handle firebird events asynchronously with perl - perl

I'm creating an info board app with data taken from firebird 1.5 database.
I would like not to use polling but events.
I've created sample trigger which fires up an event in firebird database.
Now I need a client to listen for and handle the event.
I've decided to go with perl.
Here is the doc DBD::Firebird.
I'm trying to go with async events.
Here's the code, I give the skeleton which won't work anyway.
The event won't fire up in perl. What am I doing wrong. Please help, thanks!
#!/usr/bin/perl
use DBI;
$dsn =<< "DSN";
dbi:Firebird:dbname=/home/firebird/dev/db.gdb;
host=localhost;
port=3050;
ib_dialect=3;
DSN
$dbh = DBI->connect($dsn, "user", "password");
# events of interest
#event_names = ("schedule_event");
$evh = $dbh->func(#event_names, 'ib_init_event');
my $cb = sub {.
print "got event";
};
$dbh->func($evh, $cb, 'ib_register_callback');
while (1) {
}
UPDATE:
ok here's the php script I'm going with right now, just leave it here maybe it helps someone:
<?php
declare(ticks = 1);
$username = "user";
$password = "password";
$host = 'localhost:/home/firebird/base/base.gdb';
$sockets = array();
$dbh = ibase_connect($host, $username, $password);
function event_handler($event_name, $link) {
echo $event_name . "\n";
send_message($event_name);
}
# we need to unregister event in firebird before exit
function terminate($signal) {
global $event;
if (is_null($event)) {
die ( "no event has been registered yet, exiting" );
} else {
ibase_free_event_handler($event);
die ( "unregistered evented and exiting\n" );
}
}
function send_message($msg)
{
$localsocket = 'tcp://127.0.0.1:8010';
$instance = stream_socket_client ($localsocket, $errno, $errstr);
fwrite($instance, json_encode(['message' => $msg, 'userId' => 824]) . \n");
}
$event = ibase_set_event_handler($dbh, "event_handler", "schedule_update");
pcntl_signal(SIGTERM, "terminate");
while (true) {
sleep(1);
}
?>

Related

Authen::PAM login doesn't work after Vintela flush

I have a perl script that gets the username and password from an external process and then does user authentication using Vintela. Everything works perfectly until someone forces Vintela to flush it's cache. After the cache is flushed, the Authen::PAM module returns code 10, which means that it couldn't find the username.
If I run the "id $username" command in the shell and then run the script then everything returns to normal for that user. Or if the user SSH's into the system then Authen::PAM works perfectly.
On the production server user's don't SSH into the server and hence after Vintela flush, user's can't login anymore. I don't want to run the "id" command for every user before I authenticate them. Is there a way I can force the script or PAM module to look for user and then authenticate them ?
Script --
BEGIN {
unshift(#INC, "..", "/usr/local/staf/bin", "/usr/local/staf/lib", "C:/STAF/Bin");
}
use strict;
use PLSTAF;
require Authen::PAM;
my $GlobalUserName = <STDIN>;
my $GlobalPasswd = <STDIN>;
my $result = -1;
$GlobalPasswd = STAF::RemovePrivacyDelimiters($GlobalPasswd);
my $pamHandle = Authen::PAM->new("login", $GlobalUserName, \&conversionFunction);
$result = $pamHandle->pam_authenticate();
# force the destructor execution for PAM
$pamHandle = 0;
# When $result is 0 then user has been authenticated
if ($result == 0) {
print $result;
exit $result;
}
else {
exit $result;
}
sub conversionFunction {
my #response = ();
# PAM constants
my $pamEchoOn = Authen::PAM->PAM_PROMPT_ECHO_ON();
my $pamEchoOff = Authen::PAM->PAM_PROMPT_ECHO_OFF();
my $pamSuccess = Authen::PAM->PAM_SUCCESS();
while ( #_ ) {
my $code = shift;
my $msg = shift;
my $answer = "";
if ($code == $pamEchoOn) {
$answer = $GlobalUserName;
}
if ($code == $pamEchoOff) {
$answer = $GlobalPasswd;
}
# response is always in pairs, response code and the actual answer
push(#response, $pamSuccess, $answer);
}
push(#response, $pamSuccess);
return #response;
}

using Net::LDAPs with Net::LDAP::Control::Paged

I'm trying to use Net::LDAPs with Net::LDAP::CONTROL::PAGED to return many records via a privlidged bind, but so far I have failed, miserably. I've used this Net::LDAPs extensively in the past, but I've never been able to find any documentation suggesting that it is compatible with Net::LDAP:Control::Paged. Everything I find is related to Net::LDAP.
The error message I get is: Undefined subroutine &main::process_entry called at /usr/local/share/perl/5.20.2/Net/LDAP/Search.pm line 55, line 755
Here is my code:
sub Ldap636{
my ($filter) = $_[0];
my $USERNAME = 'username';
my $PASSWORD = 'password';
my $LDAP_SERVER = 'directory.domain.edu';
my $LDAP_SSL_PORT = '636';
my $LDAP_BASE = 'ou=people,dc=domain,dc=edu';
my $userDN = "uid=$USERNAME,ou=identities,ou=special,dc=domain,dc=edu";
my $ldap = Net::LDAPS->new($LDAP_SERVER, port => $LDAP_SSL_PORT) or die "Could not create LDAP object because:\n$!";
my $ldapMsg = $ldap->bind($userDN, password => $PASSWORD);
die $ldapMsg->error if $ldapMsg->is_error;
my $page = Net::LDAP::Control::Paged->new( size => 100 );
#args = (base => "$LDAP_BASE",
callback => \&process_entry,
filter => $filter,
control => [ $page ],
);
my $cookie;
while (1) {
my $result = $ldap->search(#args);
"LDAP error: server says ",$result->error,"\n" if $result->code;
foreach my $entry ($result->entries ) {
my $cn = $entry->get_value('cn');
my $desc = $entry->get_value('description');
print "$cn - $desc\n";
}
# Get cookie from paged control
my($resp) = $result->control( LDAP_CONTROL_PAGED ) or last;
$cookie = $resp->cookie or last;
$page->cookie($cookie);
}
$ldap->unbind;
}
The error message I get is: Undefined subroutine &main::process_entry
called at /usr/local/share/perl/5.20.2/Net/LDAP/Search.pm line 55,
line 755
You have written process_entry as a callback but you didn't write that subroutine. That's why you are getting the above error.

How to set the expiration time for a cookie managed by Plack::Middleware::Session?

Now my app.psgi contains (simplified):
builder {
enable 'Session', store => 'File'; #default uses Plack::Session::State::Cookie
$app;
};
Later, in the $app I'm using:
my $req = Plack::Request->new($env);
my $session = $req->session(); #returns env->{'psgix.session'}
$session->{user} = "name";
It works ok, e.g.:
when the user logged in, I store his name in the server-side stored session-file, and the Plack::Middleware::Session sets an simple session-state-cookie,
and when the user closing the browser, the cookie is automatically cleared (because the Plack::Session::State::Cookie by default didn't set any expiration for the cookie).
Now, I want implement the "Remember me" feature in my login-panel. In this case, the sesion-state-cookie should-not be removed automatically from the browser. This can be done, by using the expires method from the Plack::Session::State::Cookie.
The question:
How I can change the cookie expiration (managed by the Session middleware) from my $app. With other words, how to call the expire method somewhat here:
my $req = Plack::Request->new($env);
my $session = $req->session(); #returns env->{'psgix.session'}
$session->{user} = "name";
my $cookie_state = WHAT_TO_DO_HERE_TO_GET; #the current Plack::Session::State::Cookie object
$cookie_state->expire(86400*14); #expire in two weeks
If someone needs, here is an working example.
use strict;
use warnings;
use Plack::Request;
use Plack::Response;
use Plack::Builder;
use Data::Dumper;
my $app = sub {
my $env = shift;
my $req = Plack::Request->new($env);
my $session = $req->session;
my $res = Plack::Response->new(200);
$res->content_type('text/html');
my $link = $session->{user}
? q{ logout}
: q{ login}
;
$res->body(["Session user:", $session->{user}, "<br>$link"]);
return $res->finalize;
};
my $login = sub {
my $env = shift;
my $req = Plack::Request->new($env);
my $session = $req->session;
$session->{user} = "some";
#how to set here the session-state-cookie expiration?
my $res = Plack::Response->new();
$res->redirect("/", 302);
return $res->finalize;
};
my $logout = sub {
my $env = shift;
my $req = Plack::Request->new($env);
my $session = $req->session;
delete $session->{user};
my $res = Plack::Response->new();
$res->redirect("/", 302);
return $res->finalize;
};
builder {
enable 'Session', store => 'File';
mount "/login" => $login;
mount "/logout" => $logout;
mount "/favicon.ico" => sub { return [ 404, ['Content-Type' => 'text/html'], [ '404 Not Found' ] ] };
mount "/" => $app;
};
You can't change the expiration date directly, but you can force the session middleware to create a new session with a new expiration date like this:
$env->{'psgix.session.options'}{change_id} = 1;
$env->{'psgix.session.options'}{expires} = $my_expires;
If a user logs in, you should change the ID anyway to prevent session fixation attacks. See Cookie::Baker for supported expiration date formats.
EDIT: If you want to set the default expiration timeout globally, you can build the state object manually and pass the expires parameter to the constructor:
builder {
enable 'Session',
state => Plack::Session::State->new(
expires => $timeout_in_seconds,
);
$app;
};

Managing session state with html::mason

I'm using HTML::Mason with Apache2 mod_perl2 for a project and am unsure what's a good way to manage session state easily.
Please don't say use Catalyst. I normally do, but not on this occasion.
After struggling with this for a long time I finally have a working solution:
This is using mysql to store session data so that no matter which front-end server you hit, you will get the same session data.
You will need a db with a table called sessions made with this:
CREATE TABLE sessions (id char(32), length int, a_session text);
This is in MySession.pm in my INC path.
package MySession;
use DBI();
use Apache::Session::MySQL;
use Apache2::Cookie;
sub start_session($){
my ($r) = #_;
my $cookie_name = 'mysite-session';
my $cookie_domain = '.mysite.com';
my $dsn = "DBI:mysql:database=db;host=host.com";
my $dbuser = 'admin';
my $dbpass = 'password';
my $dbh = DBI->connect($dsn, $dbuser, $dbpass, {'RaiseError' => 1});
my $session_cookie = Apache2::Cookie->fetch($r)->{$cookie_name};
my %cookie_hash;
if(defined($session_cookie)){
%cookie_hash = $session_cookie->value();
}
tie my %session, 'Apache::Session::MySQL', $cookie_hash{SessionID}, {
Handle => $dbh,
LockHandle => $dbh
};
my $cookie = Apache2::Cookie->new($r,
-name => $cookie_name,
-domain => $cookie_domain,
-value => {SessionID => $session{_session_id}}
);
$cookie->bake($r);
return \%session;
}
1;
Then on any page you wish to use/modify session data:
% use MySession;
% my $session = MySession::start_session($r);
% $session->{variable} = "Wow, I have a cookie";
Looks like I've found the answer in
MasonX::Request::WithApacheSession

Why does Perl's Net::Msmgr hang when I try to authenticate?

There's Net::Msmgr module on CPAN. It's written clean and the code looks trustworthy at the first glance. However this module seems to be beta and there is little documentation and no tests :-/
Has anyone used this module in production? I haven't managed to make it run by now, because it requires all event loop processing to be done in the application and as I've already said there is little documentation and no working examples to study.
That's where I've gone so far:
#!/usr/bin/perl
use strict;
use warnings;
use Event;
use Net::Msmgr::Object;
use Net::Msmgr::Session;
use Net::Msmgr::User;
use constant DEBUG => 511;
use constant EVENT_TIMEOUT => 5; # seconds
my ($username, $password) = qw/my.username#live.com my.password/;
my $buddy = 'your.username#live.com';
my $user = Net::Msmgr::User->new(user => $username, password => $password);
my $session = Net::Msmgr::Session->new;
$session->debug(DEBUG);
$session->login_handler(\&login_handler);
$session->user($user);
my $conv;
sub login_handler {
my $self = shift;
print "LOGIN\n";
$self->ui_state_nln;
$conv = $session->ui_new_conversation;
$conv->invite($buddy);
}
our %watcher;
sub ConnectHandler {
my ($connection) = #_;
warn "CONNECT\n";
my $socket = $connection->socket;
$watcher{$connection} = Event->io(fd => $socket,
cb => [ $connection, '_recv_message' ],
poll => 're',
desc => 'recv_watcher',
repeat => 1);
}
sub DisconnectHandler {
my $connection = shift;
print "DISCONNECT\n";
$watcher{$connection}->cancel;
}
$session->connect_handler(\&ConnectHandler);
$session->disconnect_handler(\&DisconnectHandler);
$session->Login;
Event::loop();
That's what it outputs:
Dispatch Server connecting to: messenger.hotmail.com:1863
Dispatch Server connected
CONNECT
Dispatch Server >>>VER 1 MSNP2 CVR0
--> VER 1 MSNP2 CVR0
Dispatch Server >>>USR 2 MD5 I my.username#live.com
--> USR 2 MD5 I my.username#live.com
Dispatch Server <<<VER 1 CVR0
<-- VER 1 CVR0
And that's all, here it hangs. The handler on login is not being triggered. What am I doing wrong?
Hope these documents will help you out
1) Net::Msmgr documentation
2) Net::Msmgr::Session