Apache2-ClickPath
view release on metacpan or search on metacpan
lib/Apache2/ClickPath/Decode.pm view on Meta::CPAN
package Apache2::ClickPath::Decode;
use strict;
use warnings;
no warnings qw{uninitialized};
use Apache2::ClickPath::_parse;
use MIME::Base64 ();
use Crypt::CBC ();
use Crypt::Blowfish ();
use Digest::MD5 ();
use Digest::CRC ();
use Class::Member qw{friendly_session
tag
server_map
secret
secret_iv
session
remote_session_host remote_session
server_id
server_name
creation_time
server_pid
seq_number
connection_id
debug};
our $VERSION='1.900';
sub new {
my $class=shift;
my $I={};
my %o=@_;
if( ref( $class ) ) {
bless $I=>ref( $class );
$I->friendly_session=$class->friendly_session;
$I->tag=$class->tag;
$I->server_map=$class->server_map;
} else {
bless $I=>$class;
}
foreach my $m (qw{friendly_session tag server_map session secret secret_iv}) {
$I->$m=$o{$m} if( exists $o{$m} );
}
if( length $I->session ) {
return $I->parse;
}
return $I;
}
sub parse {
my $I=shift;
$I->session=shift if( @_ );
my $session=$I->session;
if( length $I->tag ) {
my $tag=$I->tag;
return unless( $session=~m~\Q$tag\E([^/]+)~ );
$I->session=$session=$1;
}
return unless( length $session );
if( defined $I->friendly_session and ref($I->friendly_session) ne 'HASH' ) {
lib/Apache2/ClickPath/Decode.pm view on Meta::CPAN
defined $I->friendly_session and
exists $I->friendly_session->{$l[1]} ) {
my %h=('**'=>'*', '*!'=>'!', '*.'=>'=', '!'=>"\n");
$l[2]=~s/(\*[*!.]|!)/$h{$1}/ge;
$I->remote_session_host=$I->friendly_session->{$l[1]};
$I->remote_session=$l[2];
} else {
undef $I->remote_session_host;
undef $I->remote_session;
}
# extract session start time
$l[0]=~tr[@\-][+/];
@l=split /:/, $l[0], 2; # $l[0]: IP Addr, $l[1]: session
return unless( @l==2 );
$I->server_name=$l[0];
if( defined $I->server_map ) {
if( length $I->server_map ) {
unless( ref( $I->server_map ) eq 'HASH' ) {
my $map=eval $I->server_map;
if( ref( $map ) eq 'HASH' ) {
$I->server_map=$map;
} else {
(undef, $I->server_map)=
Apache2::ClickPath::_parse::MachineTable( $I->server_map );
}
}
$I->server_id=$I->server_map->{$l[0]}->[0]
if( ref( $I->server_map ) eq 'HASH' and
exists $I->server_map->{$l[0]} );
} else {
$I->server_id=$l[0];
}
} else {
my $len4=do {use integer; (length( $l[0] )+3)/4;};
$len4*=4;
$I->server_id=
join
( '.',
unpack("C*",
MIME::Base64::decode_base64($l[0].
('='x($len4-length( $l[0] ))))) );
}
my $len4=do {use integer; (length( $l[1] )+3)/4;};
$len4*=4;
$l[1]=MIME::Base64::decode_base64( $l[1].('='x($len4-length( $l[1] ))) );
if( $I->secret ) {
my $secret=Apache2::ClickPath::_parse::Secret( $I->secret );
my $iv;
if( length $I->secret_iv ) {
$iv=substr( Digest::MD5::md5( $I->secret_iv ), 0, 8 );
} else {
$iv="abcd1234";
}
my $crypt=Crypt::CBC->new(
-key=>$secret,
-keysize=>length($secret),
-cipher=>'Crypt::Blowfish',
-literal_key=>1,
-header=>'none',
-iv=>$iv,
);
$l[1]=$crypt->decrypt( $l[1] );
}
my $crc;
if( length( $l[1] ) ) {
$crc=Digest::CRC::crc8( substr( $l[1], 1 ) );
} else {
$crc=-1; # invalid value
}
@l=unpack( "CNNnN", $l[1] );
die "Invalid session: CRC checksum failed" if( $crc!=$l[0] );
(undef,
$I->creation_time,
$I->server_pid,
$I->seq_number,
$I->connection_id)=@l;
return $I;
}
1;
__END__
=head1 NAME
Apache2::ClickPath::Decode - Decode Apache2::ClickPath session IDs
=head1 SYNOPSIS
use Apache2::ClickPath::Decode;
my $decoder=Apache2::ClickPath::Decode->new;
$decoder->tag='-';
my $time=$decoder
->parse( 'http://bla.com/-PtVOR9:dxAredNNqtcus9NNNOdM/' )
->creation_time;
=head1 DESCRIPTION
C<Apache2::ClickPath::Decode> provides an OO interface for decoding
C<Apache2::ClickPath> session identifiers.
=head2 Methods
This module uses L<Class::Member(3)> to implement member functions. Thus,
all member functions are lvalues, eg C<< $decoder->tag='-' >>.
=over 4
=item B<new>
( run in 1.255 second using v1.01-cache-2.11-cpan-df04353d9ac )