2009-01-03 09:49:30 +01:00
|
|
|
## @file
|
|
|
|
# Session explorer
|
|
|
|
|
|
|
|
## @class
|
|
|
|
# Session explorer.
|
2010-04-28 21:57:16 +02:00
|
|
|
# Synopsis:
|
|
|
|
# * build a new Lemonldap::NG::Manager::Sessions object
|
|
|
|
# * insert tree() result in HTML
|
|
|
|
#
|
|
|
|
# tree() loads on of the tree methods.
|
|
|
|
# new() manage ajax requests (inserted in HTML tree)
|
2008-11-04 17:35:16 +01:00
|
|
|
package Lemonldap::NG::Manager::Sessions;
|
|
|
|
|
|
|
|
use strict;
|
|
|
|
use Lemonldap::NG::Handler::CGI qw(:globalStorage :locationRules);
|
2010-03-01 21:32:28 +01:00
|
|
|
use Lemonldap::NG::Common::Apache::Session; #inherits
|
|
|
|
use Lemonldap::NG::Common::Conf; #link protected conf Configuration
|
|
|
|
use Lemonldap::NG::Common::Conf::Constants; #inherits
|
2010-04-28 21:57:16 +02:00
|
|
|
require Lemonldap::NG::Manager::_i18n; #inherits
|
2009-02-16 19:01:40 +01:00
|
|
|
|
2009-02-03 10:36:13 +01:00
|
|
|
#inherits Apache::Session
|
2008-11-04 17:35:16 +01:00
|
|
|
|
2009-02-16 19:01:40 +01:00
|
|
|
our $whatToTrace;
|
|
|
|
*whatToTrace = \$Lemonldap::NG::Handler::_CGI::whatToTrace;
|
|
|
|
|
2009-06-08 18:29:13 +02:00
|
|
|
our $VERSION = '0.11';
|
2008-11-04 17:35:16 +01:00
|
|
|
|
2010-04-28 21:57:16 +02:00
|
|
|
our @ISA = qw(
|
|
|
|
Lemonldap::NG::Handler::CGI
|
|
|
|
Lemonldap::NG::Manager::_i18n
|
|
|
|
);
|
2008-11-04 17:35:16 +01:00
|
|
|
|
2009-01-03 09:49:30 +01:00
|
|
|
## @cmethod Lemonldap::NG::Manager::Sessions new(hashRef args)
|
|
|
|
# Constructor.
|
2010-04-28 21:57:16 +02:00
|
|
|
# @param $args Arguments for Lemonldap::NG::Handler::CGI::new()
|
2009-01-03 09:49:30 +01:00
|
|
|
# @return New Lemonldap::NG::Manager::Sessions object
|
2008-11-04 17:35:16 +01:00
|
|
|
sub new {
|
|
|
|
my ( $class, $args ) = @_;
|
|
|
|
my $self = $class->SUPER::new($args)
|
2008-12-03 17:05:27 +01:00
|
|
|
or $class->abort( 'Unable to start ' . __PACKAGE__,
|
|
|
|
'See Apache logs for more' );
|
2009-12-07 10:52:19 +01:00
|
|
|
|
2010-04-28 21:57:16 +02:00
|
|
|
# Try to get configuration values from global configuration
|
2009-12-07 10:52:19 +01:00
|
|
|
my $config = Lemonldap::NG::Common::Conf->new( $self->{configStorage} );
|
2009-12-30 15:22:24 +01:00
|
|
|
unless ($config) {
|
2009-12-07 10:52:19 +01:00
|
|
|
$self->abort( "Unable to start",
|
2010-03-01 21:32:28 +01:00
|
|
|
"Configuration not loaded\n" . $Lemonldap::NG::Common::Conf::msg );
|
2009-12-07 10:52:19 +01:00
|
|
|
}
|
2010-04-28 21:57:16 +02:00
|
|
|
|
|
|
|
# Load parameters from lemonldap-ng.ini.
|
2009-12-30 15:22:24 +01:00
|
|
|
my $localconf = $config->getLocalConf(MANAGERSECTION);
|
2009-12-07 10:52:19 +01:00
|
|
|
|
2010-04-28 21:57:16 +02:00
|
|
|
# Local args prepends global args
|
2009-12-30 15:22:24 +01:00
|
|
|
if ($localconf) {
|
|
|
|
$self->{$_} = $args->{$_} || $localconf->{$_}
|
|
|
|
foreach ( keys %$localconf );
|
2009-12-07 10:52:19 +01:00
|
|
|
}
|
|
|
|
|
2010-04-30 10:02:27 +02:00
|
|
|
# Load default skin if no other specified
|
|
|
|
$self->{managerSkin} ||= 'default';
|
|
|
|
|
2010-04-28 21:57:16 +02:00
|
|
|
# Now try to load Apache::Session module
|
2008-11-04 17:35:16 +01:00
|
|
|
eval "use $globalStorage";
|
2008-11-11 16:21:31 +01:00
|
|
|
$class->abort( "Unable to load $globalStorage", $@ ) if ($@);
|
2010-03-18 18:44:19 +01:00
|
|
|
|
2010-04-28 21:57:16 +02:00
|
|
|
# Check if we use X-FORWARDED-FOR header for IP
|
|
|
|
$self->{ipField} =
|
|
|
|
$self->{useXForwardedForIP} ? "xForwardedForAddr" : "ipAddr";
|
2010-04-15 13:20:42 +02:00
|
|
|
|
2010-04-28 21:57:16 +02:00
|
|
|
# Now we're ready to display sessions. Choose display type
|
|
|
|
foreach my $k ( $self->param() ) {
|
|
|
|
|
|
|
|
# Case ajax request : execute corresponding sub and quit
|
|
|
|
if ( grep { $_ eq $k } qw(delete session id uidByIp uid letter p) ) {
|
|
|
|
print $self->header( -type => 'text/html;charset=utf-8' );
|
|
|
|
print $self->$k( $self->param($k) );
|
|
|
|
$self->quit();
|
|
|
|
}
|
|
|
|
|
|
|
|
# Case else : store tree type choosen to use it later in tree()
|
|
|
|
elsif ( grep { $_ eq $k } qw(doubleIp fullip fulluid ipclasses) ) {
|
|
|
|
$self->{_tree} = $k;
|
|
|
|
last;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
# default display : list by uid
|
|
|
|
$self->{_tree} ||= 'list';
|
2010-04-15 13:20:42 +02:00
|
|
|
|
2008-11-04 17:35:16 +01:00
|
|
|
return $self;
|
|
|
|
}
|
|
|
|
|
2010-04-28 21:57:16 +02:00
|
|
|
## @method string tree()
|
|
|
|
# Launch required tree builder. It can be one of :
|
|
|
|
# * doubleIp()
|
|
|
|
# * fullip()
|
|
|
|
# * fulluid()
|
|
|
|
# * ipclasses()
|
|
|
|
# * list() (default)
|
|
|
|
# @return string XML tree
|
|
|
|
sub tree {
|
2008-11-04 17:35:16 +01:00
|
|
|
my $self = shift;
|
|
|
|
|
2010-04-28 21:57:16 +02:00
|
|
|
my $sub = $self->{_tree};
|
|
|
|
$self->lmLog( "Building chosen tree : $sub", 'debug' );
|
|
|
|
my ( $r, $legend ) = $self->$sub( $self->param($sub) );
|
|
|
|
return
|
|
|
|
qq{<ul class="simpleTree"><li class="root" id="root"><span>$legend</span><ul>$r</ul></li></ul>};
|
|
|
|
}
|
2008-11-04 17:35:16 +01:00
|
|
|
|
2010-04-28 21:57:16 +02:00
|
|
|
################
|
|
|
|
# TREE METHODS #
|
|
|
|
################
|
2009-05-20 11:29:52 +02:00
|
|
|
|
2010-04-28 21:57:16 +02:00
|
|
|
## @method protected string list()
|
|
|
|
# Build default tree (by letter)
|
|
|
|
# @return string XML tree
|
|
|
|
sub list {
|
|
|
|
my $self = shift;
|
|
|
|
my ( $byUid, $count, $res );
|
|
|
|
$count = 0;
|
|
|
|
|
|
|
|
# Parse all sessions to store first letter
|
|
|
|
$globalStorage->get_key_from_all_sessions(
|
|
|
|
$globalStorageOptions,
|
|
|
|
sub {
|
|
|
|
my $entry = shift;
|
|
|
|
next if ( $entry->{_httpSessionType} );
|
|
|
|
$entry->{$whatToTrace} =~ /^(\w)/ or return undef;
|
|
|
|
$byUid->{$1}++;
|
|
|
|
$count++;
|
|
|
|
undef;
|
|
|
|
}
|
|
|
|
);
|
2008-11-04 17:35:16 +01:00
|
|
|
|
2010-04-28 21:57:16 +02:00
|
|
|
# Build tree sorted by first letter
|
|
|
|
foreach my $letter ( sort keys %$byUid ) {
|
|
|
|
$res .= $self->ajaxNode(
|
|
|
|
|
|
|
|
# ID
|
|
|
|
"li_$letter",
|
|
|
|
|
|
|
|
# Legend
|
|
|
|
"$letter <i><small>($byUid->{$letter} "
|
|
|
|
. (
|
|
|
|
$byUid->{$letter} == 1
|
|
|
|
? $self->translate('session')
|
|
|
|
: $self->translate('sessions')
|
|
|
|
)
|
|
|
|
. ")</small></i>",
|
|
|
|
|
|
|
|
# Next request
|
|
|
|
"letter=$letter"
|
2008-11-04 17:35:16 +01:00
|
|
|
);
|
2010-04-28 21:57:16 +02:00
|
|
|
}
|
|
|
|
return (
|
|
|
|
$res,
|
|
|
|
"$count "
|
|
|
|
. (
|
|
|
|
$count == 1
|
|
|
|
? $self->translate('session')
|
|
|
|
: $self->translate('sessions')
|
2008-11-04 17:35:16 +01:00
|
|
|
)
|
2010-04-28 21:57:16 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
## @method protected string doubleIp()
|
|
|
|
# Build tree with users connected from more than 1 IP
|
|
|
|
# @return string XML tree
|
|
|
|
sub doubleIp {
|
|
|
|
my $self = shift;
|
|
|
|
my ( $byUid, $byIp, $res, $count );
|
|
|
|
|
|
|
|
# Parse all sessions
|
|
|
|
$globalStorage->get_key_from_all_sessions(
|
|
|
|
$globalStorageOptions,
|
|
|
|
sub {
|
|
|
|
my $entry = shift;
|
|
|
|
my $id = shift;
|
|
|
|
next if ( $entry->{_httpSessionType} );
|
|
|
|
push @{ $byUid->{ $entry->{$whatToTrace} }
|
|
|
|
->{ $entry->{ $self->{ipField} } } },
|
2010-08-18 13:14:05 +02:00
|
|
|
{ id => $id, startTime => $entry->{startTime} };
|
2010-04-28 21:57:16 +02:00
|
|
|
undef;
|
2008-11-04 17:35:16 +01:00
|
|
|
}
|
2010-04-28 21:57:16 +02:00
|
|
|
);
|
2008-11-04 17:35:16 +01:00
|
|
|
|
2010-04-28 21:57:16 +02:00
|
|
|
# Build tree sorted by uid (or other field chosen in whatToTrace parameter)
|
|
|
|
foreach my $uid (
|
|
|
|
sort { ( keys %{ $byUid->{$b} } ) <=> ( keys %{ $byUid->{$a} } ) }
|
|
|
|
keys %$byUid
|
|
|
|
)
|
|
|
|
{
|
|
|
|
|
|
|
|
# Parse only uid that are connected from more than 1 IP
|
|
|
|
last if ( ( keys %{ $byUid->{$uid} } ) == 1 );
|
|
|
|
$count++;
|
|
|
|
|
|
|
|
# Build UID node with IP as sub node
|
|
|
|
$res .= "<li id=\"di$uid\" class=\"closed\"><span>$uid</span><ul>";
|
|
|
|
foreach my $ip ( sort keys %{ $byUid->{$uid} } ) {
|
|
|
|
$res .= "<li class=\"open\" id=\"di$ip\"><span>$ip</span><ul>";
|
|
|
|
|
|
|
|
# For each IP node, store sessions sorted by start time
|
2010-08-18 13:14:05 +02:00
|
|
|
foreach my $session ( sort { $a->{startTime} <=> $b->{startTime} }
|
2010-04-28 21:57:16 +02:00
|
|
|
@{ $byUid->{$uid}->{$ip} } )
|
|
|
|
{
|
|
|
|
$res .=
|
|
|
|
"<li id=\"di$session->{id}\"><span onclick=\"displaySession('$session->{id}');\">"
|
2010-08-18 13:14:05 +02:00
|
|
|
. $self->_stToStr( $session->{startTime} )
|
2010-04-28 21:57:16 +02:00
|
|
|
. "</span></li>";
|
2008-11-04 17:35:16 +01:00
|
|
|
}
|
2010-04-28 21:57:16 +02:00
|
|
|
$res .= "</ul></li>";
|
2008-11-04 17:35:16 +01:00
|
|
|
}
|
2010-04-28 21:57:16 +02:00
|
|
|
$res .= "</ul></li>";
|
2008-11-04 17:35:16 +01:00
|
|
|
}
|
|
|
|
|
2010-04-28 21:57:16 +02:00
|
|
|
return (
|
|
|
|
$res,
|
|
|
|
"$count "
|
|
|
|
. (
|
|
|
|
$count == 1
|
|
|
|
? $self->translate('user')
|
|
|
|
: $self->translate('users')
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
## @method protected string fullip(string req)
|
|
|
|
# Build single IP tree
|
|
|
|
# @param $req Optional IP request (127* for example)
|
|
|
|
# @return string XML tree
|
|
|
|
sub fullip {
|
|
|
|
my ( $self, $req ) = splice @_;
|
|
|
|
my ( $byUid, $res );
|
|
|
|
|
|
|
|
# Build regexp based on IP request
|
|
|
|
my $reip = quotemeta($req);
|
|
|
|
$reip =~ s/\\\*/\.\*/g;
|
|
|
|
|
|
|
|
# Parse all sessions and store only if IP match regexp
|
|
|
|
$globalStorage->get_key_from_all_sessions(
|
|
|
|
$globalStorageOptions,
|
|
|
|
sub {
|
|
|
|
my $entry = shift;
|
|
|
|
my $id = shift;
|
|
|
|
next if ( $entry->{_httpSessionType} );
|
2010-08-05 18:02:30 +02:00
|
|
|
if ( $entry->{ $self->{ipField} } =~ /$reip/ ) {
|
2010-04-28 21:57:16 +02:00
|
|
|
push @{ $byUid->{ $entry->{ $self->{ipField} } }
|
|
|
|
->{ $entry->{$whatToTrace} } },
|
2010-08-18 13:14:05 +02:00
|
|
|
{ id => $id, startTime => $entry->{startTime} };
|
2008-11-04 17:35:16 +01:00
|
|
|
}
|
2010-04-28 21:57:16 +02:00
|
|
|
undef;
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
# Build tree sorted by IP
|
|
|
|
foreach my $ip ( sort keys %$byUid ) {
|
|
|
|
$res .= "<li id=\"fi$ip\"><span>$ip</span><ul>";
|
|
|
|
foreach my $uid ( sort keys %{ $byUid->{$ip} } ) {
|
|
|
|
$res .= $self->ajaxNode(
|
2008-11-04 17:35:16 +01:00
|
|
|
$uid,
|
|
|
|
$uid
|
|
|
|
. (
|
2010-04-28 21:57:16 +02:00
|
|
|
@{ $byUid->{$ip}->{$uid} } > 1
|
2008-11-04 17:35:16 +01:00
|
|
|
? " <i><u><small>("
|
2010-04-28 21:57:16 +02:00
|
|
|
. @{ $byUid->{$ip}->{$uid} }
|
2008-11-04 17:35:16 +01:00
|
|
|
. " sessions)</small></u></i>"
|
|
|
|
: ''
|
|
|
|
),
|
|
|
|
"uid=$uid"
|
|
|
|
);
|
|
|
|
}
|
2010-04-28 21:57:16 +02:00
|
|
|
$res .= "</ul></li>";
|
2008-11-04 17:35:16 +01:00
|
|
|
}
|
2010-04-28 21:57:16 +02:00
|
|
|
return $res;
|
|
|
|
}
|
|
|
|
|
|
|
|
## @method protected string fulluid(string req)
|
|
|
|
# Build single uid tree
|
|
|
|
# @param $req request (examples: foo*, foo.bar)
|
|
|
|
# @return string XML tree
|
|
|
|
sub fulluid {
|
|
|
|
my ( $self, $req ) = splice @_;
|
|
|
|
my ( $byUid, $res );
|
|
|
|
|
|
|
|
# Build regexp based on request
|
|
|
|
my $reuser = quotemeta($req);
|
|
|
|
$reuser =~ s/\\\*/\.\*/g;
|
|
|
|
|
|
|
|
# Parse all sessions to find user that match regexp
|
|
|
|
$globalStorage->get_key_from_all_sessions(
|
|
|
|
$globalStorageOptions,
|
|
|
|
sub {
|
|
|
|
my $entry = shift;
|
|
|
|
my $id = shift;
|
|
|
|
next if ( $entry->{_httpSessionType} );
|
|
|
|
if ( $entry->{$whatToTrace} =~ /^$reuser$/ ) {
|
|
|
|
push @{ $byUid->{ $entry->{$whatToTrace} } },
|
2010-08-18 13:14:05 +02:00
|
|
|
{ id => $id, startTime => $entry->{startTime} };
|
2010-04-28 21:57:16 +02:00
|
|
|
}
|
|
|
|
undef;
|
|
|
|
}
|
|
|
|
);
|
2008-11-04 17:35:16 +01:00
|
|
|
|
2010-04-28 21:57:16 +02:00
|
|
|
# Build tree sorted by uid
|
|
|
|
foreach my $uid ( sort keys %$byUid ) {
|
|
|
|
$res .= $self->ajaxNode(
|
|
|
|
$uid,
|
|
|
|
$uid
|
|
|
|
. (
|
|
|
|
@{ $byUid->{$uid} } > 1
|
|
|
|
? " <i><u><small>("
|
|
|
|
. @{ $byUid->{$uid} }
|
|
|
|
. " sessions)</small></u></i>"
|
|
|
|
: ''
|
|
|
|
),
|
|
|
|
"uid=$uid"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
## @method protected string ipclasses()
|
|
|
|
# Build IP classes tree (call _ipclasses())
|
|
|
|
# @return string XML tree
|
|
|
|
sub ipclasses {
|
|
|
|
my $self = shift;
|
|
|
|
return $self->_ipclasses();
|
|
|
|
}
|
|
|
|
|
|
|
|
##################
|
|
|
|
# AJAX RESPONSES #
|
|
|
|
##################
|
|
|
|
|
|
|
|
## @method protected string delete(string id)
|
|
|
|
# Delete a session
|
|
|
|
# @param id Session identifier
|
|
|
|
# @return string XML tree
|
|
|
|
sub delete {
|
|
|
|
my ( $self, $id ) = splice @_;
|
|
|
|
my %h;
|
|
|
|
eval { tie %h, $globalStorage, $id, $globalStorageOptions; };
|
|
|
|
if ($@) {
|
|
|
|
if ( $@ =~ /does not exist in the data store/i ) {
|
|
|
|
|
|
|
|
# TODO: display error
|
2008-11-04 17:35:16 +01:00
|
|
|
}
|
|
|
|
else {
|
2010-04-28 21:57:16 +02:00
|
|
|
$self->abort( 'Apache::Session error', $@ );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
my $uid = $h{uid};
|
|
|
|
if ( $h{_httpSession} ) {
|
|
|
|
my %h2;
|
|
|
|
eval {
|
|
|
|
tie %h2, $globalStorage, $h{_httpSession},
|
|
|
|
$globalStorageOptions;
|
|
|
|
tied(%h2)->delete();
|
|
|
|
};
|
2008-11-04 17:35:16 +01:00
|
|
|
if ($@) {
|
2010-04-28 21:57:16 +02:00
|
|
|
$self->lmLog( "Apache::Session error: $@", 'error' );
|
2008-11-04 17:35:16 +01:00
|
|
|
}
|
|
|
|
}
|
2010-04-28 21:57:16 +02:00
|
|
|
eval { tied(%h)->delete(); };
|
2008-11-04 17:35:16 +01:00
|
|
|
if ($@) {
|
2010-04-28 21:57:16 +02:00
|
|
|
$self->abort( 'Apache::Session error', $@ );
|
2008-11-04 17:35:16 +01:00
|
|
|
}
|
|
|
|
else {
|
2010-04-28 21:57:16 +02:00
|
|
|
return
|
|
|
|
"<strong>"
|
|
|
|
. $self->translate('sessionDeleted')
|
|
|
|
. "($uid)</strong>";
|
2008-11-04 17:35:16 +01:00
|
|
|
}
|
|
|
|
}
|
2010-04-28 21:57:16 +02:00
|
|
|
}
|
2008-11-04 17:35:16 +01:00
|
|
|
|
2010-04-28 21:57:16 +02:00
|
|
|
## @method protected string session()
|
|
|
|
# Build session dump.
|
|
|
|
# @return string XML tree
|
|
|
|
sub session {
|
|
|
|
my ( $self, $id ) = splice @_;
|
|
|
|
my ( %h, $res );
|
|
|
|
eval { tie %h, $globalStorage, $id, $globalStorageOptions; };
|
|
|
|
if ($@) {
|
|
|
|
$self->lmLog( 'Apache::Session error', $@ );
|
|
|
|
return "Apache::Session error: $@";
|
|
|
|
}
|
|
|
|
$res .=
|
|
|
|
"<input type=\"button\" onclick=\"del('$id');\" value=\""
|
|
|
|
. $self->translate('deleteSession')
|
|
|
|
. "\" /><p><b>"
|
|
|
|
. $self->translate('sessionStartedAt')
|
|
|
|
. ":</b> "
|
2010-08-18 13:14:05 +02:00
|
|
|
. $self->_stToStr( $h{startTime} )
|
2010-04-28 21:57:16 +02:00
|
|
|
. '</p><p><b>'
|
|
|
|
. $self->translate('memberOfSSOGroups')
|
|
|
|
. ' :</b><ul>';
|
|
|
|
$res .= "<li>$_</li>" foreach ( sort split /\s+/, $h{groups} );
|
|
|
|
$res .= '</ul></p>';
|
|
|
|
$res .=
|
|
|
|
'<p><b>'
|
|
|
|
. $self->translate('attributesAndMacros')
|
|
|
|
. ' :</b></p><table border="0" witdh="100%">';
|
2010-08-18 13:14:05 +02:00
|
|
|
foreach my $attr (
|
|
|
|
sort {
|
|
|
|
return $a cmp $b
|
|
|
|
if ( ( $a =~ /^_/ and $b =~ /^_/ )
|
|
|
|
or ( $a !~ /^_/ and $b !~ /^_/ ) );
|
|
|
|
return $b cmp $a
|
|
|
|
} keys %h
|
|
|
|
)
|
|
|
|
{
|
|
|
|
next if ( $attr =~ /^(?:groups)$/ );
|
|
|
|
|
|
|
|
my $value = htmlquote( $h{$attr} );
|
2010-04-28 21:57:16 +02:00
|
|
|
|
|
|
|
# Hide password value
|
2010-08-18 13:14:05 +02:00
|
|
|
$value = "******" if ( $attr =~ /^_password$/ );
|
|
|
|
$value .= ' <i>(' . localtime($value) . ')</i>'
|
|
|
|
if ( $attr eq '_utime' );
|
2010-04-28 21:57:16 +02:00
|
|
|
$res .=
|
|
|
|
'<tr valign="top"><th style="text-align:left;">'
|
|
|
|
. htmlquote($attr)
|
|
|
|
. '</th><td>:</td><td>'
|
2010-08-18 13:14:05 +02:00
|
|
|
. $value
|
2010-04-28 21:57:16 +02:00
|
|
|
. '</td></tr>'
|
2010-08-18 13:14:05 +02:00
|
|
|
if ($value);
|
2010-04-28 21:57:16 +02:00
|
|
|
}
|
|
|
|
$res .= '</table>';
|
|
|
|
untie %h;
|
|
|
|
return $res;
|
|
|
|
}
|
|
|
|
|
|
|
|
## @method protected string uidByIp()
|
|
|
|
# Build single IP tree
|
|
|
|
# @return string XML tree
|
|
|
|
sub uidByIp {
|
|
|
|
my ( $self, $ip ) = splice @_;
|
|
|
|
my ( $byUser, $res );
|
|
|
|
$globalStorage->get_key_from_all_sessions(
|
|
|
|
$globalStorageOptions,
|
|
|
|
sub {
|
|
|
|
my $entry = shift;
|
|
|
|
my $id = shift;
|
|
|
|
next if ( $entry->{_httpSessionType} );
|
|
|
|
if ( $entry->{ $self->{ipField} } eq $ip ) {
|
|
|
|
push @{ $byUser->{ $entry->{$whatToTrace} } },
|
2010-08-18 13:14:05 +02:00
|
|
|
{ id => $id, startTime => $entry->{startTime} };
|
2008-11-05 15:55:02 +01:00
|
|
|
}
|
2010-04-28 21:57:16 +02:00
|
|
|
undef;
|
2008-11-05 15:55:02 +01:00
|
|
|
}
|
2010-04-28 21:57:16 +02:00
|
|
|
);
|
|
|
|
foreach my $user ( sort keys %$byUser ) {
|
|
|
|
$res .= "<li id=\"ip$user\"><span>$user</span><ul>";
|
2010-08-18 13:14:05 +02:00
|
|
|
foreach my $session ( sort { $a->{startTime} <=> $b->{startTime} }
|
2010-04-28 21:57:16 +02:00
|
|
|
@{ $byUser->{$user} } )
|
|
|
|
{
|
|
|
|
$res .=
|
|
|
|
"<li id=\"ip$session->{id}\"><span onclick=\"displaySession('$session->{id}');\">"
|
2010-08-18 13:14:05 +02:00
|
|
|
. $self->_stToStr( $session->{startTime} )
|
2010-04-28 21:57:16 +02:00
|
|
|
. "</span></li>";
|
|
|
|
}
|
|
|
|
$res .= "</ul></li>";
|
2008-11-05 15:55:02 +01:00
|
|
|
}
|
2010-04-28 21:57:16 +02:00
|
|
|
return $res;
|
|
|
|
}
|
|
|
|
|
|
|
|
## @method protected string uid()
|
|
|
|
# Build single UID tree part
|
|
|
|
# @return string XML tree
|
|
|
|
sub uid {
|
|
|
|
my ( $self, $uid ) = splice @_;
|
|
|
|
my ( $byIp, $res );
|
|
|
|
$globalStorage->get_key_from_all_sessions(
|
|
|
|
$globalStorageOptions,
|
|
|
|
sub {
|
|
|
|
my $entry = shift;
|
|
|
|
my $id = shift;
|
|
|
|
next if ( $entry->{_httpSessionType} );
|
|
|
|
if ( $entry->{$whatToTrace} eq $uid ) {
|
|
|
|
push @{ $byIp->{ $entry->{ $self->{ipField} } } },
|
2010-08-18 13:14:05 +02:00
|
|
|
{ id => $id, startTime => $entry->{startTime} };
|
2008-11-04 17:35:16 +01:00
|
|
|
}
|
2010-04-28 21:57:16 +02:00
|
|
|
undef;
|
2008-11-04 17:35:16 +01:00
|
|
|
}
|
2010-04-28 21:57:16 +02:00
|
|
|
);
|
|
|
|
foreach my $ip ( sort keys %$byIp ) {
|
|
|
|
$res .= "<li class=\"open\" id=\"uid$ip\"><span>$ip</span><ul>";
|
2010-08-18 13:14:05 +02:00
|
|
|
foreach my $session ( sort { $a->{startTime} <=> $b->{startTime} }
|
2010-04-28 21:57:16 +02:00
|
|
|
@{ $byIp->{$ip} } )
|
|
|
|
{
|
|
|
|
$res .=
|
|
|
|
"<li id=\"uid$session->{id}\"><span onclick=\"displaySession('$session->{id}');\">"
|
2010-08-18 13:14:05 +02:00
|
|
|
. $self->_stToStr( $session->{startTime} )
|
2010-04-28 21:57:16 +02:00
|
|
|
. "</span></li>";
|
2008-11-04 17:35:16 +01:00
|
|
|
}
|
2010-04-28 21:57:16 +02:00
|
|
|
$res .= "</ul></li>";
|
2008-11-04 17:35:16 +01:00
|
|
|
}
|
2010-04-28 21:57:16 +02:00
|
|
|
return $res;
|
|
|
|
}
|
|
|
|
|
|
|
|
# Ajax request to list users starting by a letter
|
|
|
|
## @method protected string letter()
|
|
|
|
# Build letter XML part
|
|
|
|
# @return string XML tree
|
|
|
|
sub letter {
|
|
|
|
my $self = shift;
|
|
|
|
my $letter = $self->param('letter');
|
|
|
|
my ( $byUid, $res );
|
|
|
|
$globalStorage->get_key_from_all_sessions(
|
|
|
|
$globalStorageOptions,
|
|
|
|
sub {
|
|
|
|
my $entry = shift;
|
|
|
|
next if ( $entry->{_httpSessionType} );
|
|
|
|
$entry->{$whatToTrace} =~ /^$letter/ or return undef;
|
|
|
|
$byUid->{ $entry->{$whatToTrace} }++;
|
|
|
|
},
|
|
|
|
);
|
|
|
|
foreach my $uid ( sort keys %$byUid ) {
|
|
|
|
$res .= $self->ajaxNode(
|
|
|
|
$uid,
|
|
|
|
$uid
|
|
|
|
. (
|
|
|
|
$byUid->{$uid} > 1
|
|
|
|
? " <i><u><small>($byUid->{$uid} "
|
|
|
|
. (
|
|
|
|
$byUid->{$uid} == 1
|
|
|
|
? $self->translate('session')
|
|
|
|
: $self->translate('sessions')
|
|
|
|
)
|
|
|
|
. ")</small></u></i>"
|
|
|
|
: ''
|
|
|
|
),
|
|
|
|
"uid=$uid"
|
2008-11-05 15:55:02 +01:00
|
|
|
);
|
2010-04-28 21:57:16 +02:00
|
|
|
}
|
|
|
|
return $res;
|
|
|
|
}
|
2008-11-05 15:55:02 +01:00
|
|
|
|
2010-04-28 21:57:16 +02:00
|
|
|
## @method protected string p()
|
|
|
|
# Build IP classes sub tree (call _ipclasses())
|
|
|
|
# @return string XML tree
|
|
|
|
sub p {
|
|
|
|
my $self = shift;
|
|
|
|
my @t = $self->_ipclasses(@_);
|
|
|
|
return $t[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
## @method private string _ipclasses()
|
|
|
|
# Build IP classes (sub) tree
|
|
|
|
# @return string XML tree
|
|
|
|
sub _ipclasses {
|
|
|
|
my ( $self, $p ) = splice @_;
|
|
|
|
my $partial = $p ? "$p." : '';
|
|
|
|
my $repartial = quotemeta($partial);
|
|
|
|
my ( $byIp, $count, $res );
|
|
|
|
$globalStorage->get_key_from_all_sessions(
|
|
|
|
$globalStorageOptions,
|
|
|
|
sub {
|
|
|
|
my $entry = shift;
|
|
|
|
next if ( $entry->{_httpSessionType} );
|
|
|
|
$entry->{ $self->{ipField} } =~ /^$repartial(\d+)/ or return undef;
|
|
|
|
$byIp->{$1}++;
|
|
|
|
$count++;
|
|
|
|
undef;
|
2008-11-05 15:55:02 +01:00
|
|
|
}
|
2010-04-28 21:57:16 +02:00
|
|
|
);
|
2008-11-05 15:55:02 +01:00
|
|
|
|
2010-04-28 21:57:16 +02:00
|
|
|
foreach my $ip ( sort { $a <=> $b } keys %$byIp ) {
|
|
|
|
$res .= $self->ajaxNode(
|
|
|
|
"$partial$ip",
|
|
|
|
"$partial$ip <i><small>($byIp->{$ip} "
|
|
|
|
. (
|
|
|
|
$byIp->{$ip} == 1 ? $self->translate('session')
|
|
|
|
: $self->translate('sessions')
|
|
|
|
)
|
|
|
|
. ")</small></i>",
|
|
|
|
(
|
|
|
|
$partial !~ /^\d+\.\d+\.\d+/ ? "ipclasses=1&p=$partial$ip"
|
|
|
|
: "uidByIp=$partial$ip"
|
|
|
|
)
|
2008-11-04 17:35:16 +01:00
|
|
|
);
|
|
|
|
}
|
2010-04-28 21:57:16 +02:00
|
|
|
return (
|
|
|
|
$res,
|
|
|
|
"$count "
|
|
|
|
. (
|
|
|
|
$count == 1
|
|
|
|
? $self->translate('session')
|
|
|
|
: $self->translate('sessions')
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
|
|
|
#return $res;
|
2008-11-04 17:35:16 +01:00
|
|
|
}
|
|
|
|
|
2009-02-25 19:10:07 +01:00
|
|
|
## @fn protected string htmlquote(string s)
|
2009-01-03 09:49:30 +01:00
|
|
|
# Change <, > and & to HTML encoded values in the string
|
|
|
|
# @param $s HTML string
|
|
|
|
# @return HTML string
|
2008-11-04 17:35:16 +01:00
|
|
|
sub htmlquote {
|
|
|
|
my $s = shift;
|
2010-04-30 10:02:27 +02:00
|
|
|
$s =~ s/&/&/g;
|
2008-11-04 17:35:16 +01:00
|
|
|
$s =~ s/</</g;
|
|
|
|
$s =~ s/>/>/g;
|
|
|
|
return $s;
|
|
|
|
}
|
|
|
|
|
2010-04-28 21:57:16 +02:00
|
|
|
## @method private void ajaxnode(string id, string text, string param)
|
2009-01-03 09:49:30 +01:00
|
|
|
# Display tree node with Ajax functions inside for opening the node.
|
|
|
|
# @param $id HTML id of the element.
|
|
|
|
# @param $text text to display
|
|
|
|
# @param $param Parameters for the Ajax query
|
2008-11-04 17:35:16 +01:00
|
|
|
sub ajaxNode {
|
|
|
|
my ( $self, $id, $text, $param ) = @_;
|
2010-04-28 21:57:16 +02:00
|
|
|
return
|
2008-11-04 17:35:16 +01:00
|
|
|
"<li id=\"$id\"><span>$text</span>\n<ul class=\"ajax\"><li id=\"sub_$id\">{url:$ENV{SCRIPT_NAME}?$param}</li></ul></li>\n";
|
|
|
|
}
|
|
|
|
|
2010-08-18 13:14:05 +02:00
|
|
|
## @method private string _stToStr(string)
|
|
|
|
# Transform a utime string into readeable string (ex: "2010-08-18 13:03:13")
|
|
|
|
# @return Formated string
|
|
|
|
sub _stToStr {
|
|
|
|
shift;
|
|
|
|
return
|
|
|
|
sprintf( '%d-%02d-%02d %d:%02d:%02d', unpack( 'a4a2a2a2a2a2', shift ) );
|
|
|
|
}
|
|
|
|
|
2009-02-16 19:01:40 +01:00
|
|
|
1;
|
2008-11-04 17:35:16 +01:00
|
|
|
__END__
|
|
|
|
|
|
|
|
=head1 NAME
|
|
|
|
|
|
|
|
Lemonldap::NG::Manager::Sessions - Perl extension to manage Lemonldap::NG
|
|
|
|
sessions
|
|
|
|
|
|
|
|
=head1 SYNOPSIS
|
|
|
|
|
2008-12-03 17:05:27 +01:00
|
|
|
#!/usr/bin/perl
|
2008-11-04 17:35:16 +01:00
|
|
|
|
|
|
|
use strict;
|
|
|
|
use Lemonldap::NG::Manager::Sessions;
|
|
|
|
our $cgi ||= Lemonldap::NG::Manager::Sessions->new({
|
|
|
|
localStorage => "Cache::FileCache",
|
|
|
|
localStorageOptions => {
|
|
|
|
'namespace' => 'MyNamespace',
|
|
|
|
'default_expires_in' => 600,
|
|
|
|
'directory_umask' => '007',
|
|
|
|
'cache_root' => '/tmp',
|
|
|
|
'cache_depth' => 5,
|
|
|
|
},
|
|
|
|
configStorage => $Lemonldap::NG::Conf::configStorage,
|
|
|
|
configStorage=>{
|
|
|
|
type=>'File',
|
|
|
|
dirName=>"/tmp/",
|
|
|
|
},
|
|
|
|
https => 1,
|
|
|
|
jqueryUri => '/js/jquery/jquery.js',
|
|
|
|
imagePath => '/js/jquery.simple.tree/',
|
2009-05-20 11:29:52 +02:00
|
|
|
# Force the use of X-FORWARDED-FOR for IP
|
|
|
|
useXForwardedForIP => 1,
|
2008-11-04 17:35:16 +01:00
|
|
|
# Optionnal
|
|
|
|
protection => 'rule: $uid eq "admin"',
|
|
|
|
# Or to use rules from manager
|
2008-11-11 16:21:31 +01:00
|
|
|
protection => 'manager',
|
|
|
|
# Or just to authenticate without managing authorization
|
|
|
|
protection => 'authenticate',
|
2008-11-04 17:35:16 +01:00
|
|
|
});
|
|
|
|
$cgi->process();
|
|
|
|
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
|
|
|
|
Lemonldap::NG::Manager::Sessions provides a web interface to manage
|
|
|
|
Lemonldap::NG sessions.
|
|
|
|
|
|
|
|
It inherits from L<Lemonldap::NG::Handler::CGI>, so see this manpage to
|
|
|
|
understand how arguments passed to the constructor.
|
|
|
|
|
|
|
|
=head1 SEE ALSO
|
|
|
|
|
2008-11-11 16:21:31 +01:00
|
|
|
L<Lemonldap::NG::Handler::CGI>, L<Lemonldap::NG::Manager>
|
2008-11-04 17:35:16 +01:00
|
|
|
|
|
|
|
=head1 AUTHOR
|
|
|
|
|
|
|
|
Xavier Guimard, E<lt>x.guimard@free.frE<gt>
|
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE
|
|
|
|
|
|
|
|
Copyright (C) 2008 by Xavier Guimard
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or modify
|
|
|
|
it under the same terms as Perl itself, either Perl version 5.8.8 or,
|
|
|
|
at your option, any later version of Perl 5 you may have available.
|
|
|
|
|
|
|
|
C<jquery.simple.tree> embedded javascript library is licensed under BSD
|
|
|
|
L<http://en.wikipedia.org/wiki/BSD_License> and copyrighted (c) 2008 by Peter
|
|
|
|
Panov E<lt>panov@elcat.kgE<gt>, IKEEN Group L<http://www.ikeen.com/>
|
|
|
|
|
|
|
|
=cut
|