From 089f8899c11c964c0a546216adff2e1acdc4249d Mon Sep 17 00:00:00 2001 From: Xavier Date: Wed, 20 Nov 2019 20:39:57 +0100 Subject: [PATCH] Don't stop parsing on bad session --- Build.PL | 2 +- Changes | 3 ++ META.json | 6 +-- META.yml | 2 +- lib/Apache/Session/Browseable.pm | 2 +- lib/Apache/Session/Browseable/DBI.pm | 56 +++++++++++++--------- lib/Apache/Session/Browseable/File.pm | 37 ++++++++------ lib/Apache/Session/Browseable/MySQLJSON.pm | 34 +++++++------ lib/Apache/Session/Browseable/PgHstore.pm | 14 ++++-- lib/Apache/Session/Browseable/PgJSON.pm | 56 ++++++++++++++-------- lib/Apache/Session/Browseable/Redis.pm | 54 +++++++++++++-------- 11 files changed, 164 insertions(+), 102 deletions(-) diff --git a/Build.PL b/Build.PL index ac0efa8..43896df 100644 --- a/Build.PL +++ b/Build.PL @@ -8,7 +8,7 @@ Module::Build->new( requires => { 'Apache::Session' => 0, 'JSON' => 0, }, recommends => { 'DBI' => 0, 'Net::LDAP' => 0.38, }, test_requires => { DBI => 0, 'DBD::SQLite' => 0, }, - dist_version => '1.3.3', + dist_version => '1.3.4', autosplit => [qw(lib/Apache/Session/Browseable/_common.pm)], configure_requires => { 'Module::Build' => 0, }, meta_merge => { diff --git a/Changes b/Changes index 2dd3ddc..f0f32c5 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,8 @@ Revision history for Perl extension Apache::Session::Browseable. +1.3.4 + - Don't stop parsing sessions when one is bad + 1.3.3 - LDAP: Add ldapRaw parameter (#20) diff --git a/META.json b/META.json index 1d99410..f8de59b 100644 --- a/META.json +++ b/META.json @@ -4,13 +4,13 @@ "Xavier Guimard, Ex.guimard@free.frE" ], "dynamic_config" : 1, - "generated_by" : "Module::Build version 0.4224", + "generated_by" : "Module::Build version 0.4229", "license" : [ "perl_5" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", - "version" : "2" + "version" : 2 }, "name" : "Apache-Session-Browseable", "prereqs" : { @@ -156,5 +156,5 @@ } }, "version" : "v1.3.3", - "x_serialization_backend" : "JSON::PP version 2.27400_02" + "x_serialization_backend" : "JSON::PP version 2.97001" } diff --git a/META.yml b/META.yml index 5709f58..eff1043 100644 --- a/META.yml +++ b/META.yml @@ -8,7 +8,7 @@ build_requires: configure_requires: Module::Build: '0' dynamic_config: 1 -generated_by: 'Module::Build version 0.4224, CPAN::Meta::Converter version 2.150010' +generated_by: 'Module::Build version 0.4229, CPAN::Meta::Converter version 2.150010' license: perl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html diff --git a/lib/Apache/Session/Browseable.pm b/lib/Apache/Session/Browseable.pm index 92c5687..8ea2766 100644 --- a/lib/Apache/Session/Browseable.pm +++ b/lib/Apache/Session/Browseable.pm @@ -1,6 +1,6 @@ package Apache::Session::Browseable; -our $VERSION = '1.3.2'; +our $VERSION = '1.3.4'; print STDERR "Use a sub module of Apache::Session::Browseable such as Apache::Session::Browseable::File"; diff --git a/lib/Apache/Session/Browseable/DBI.pm b/lib/Apache/Session/Browseable/DBI.pm index 6e69365..5e121b2 100644 --- a/lib/Apache/Session/Browseable/DBI.pm +++ b/lib/Apache/Session/Browseable/DBI.pm @@ -6,7 +6,7 @@ use DBI; use Apache::Session; use Apache::Session::Browseable::_common; -our $VERSION = '1.2.7'; +our $VERSION = '1.3.4'; our @ISA = qw(Apache::Session Apache::Session::Browseable::_common); sub searchOn { @@ -29,7 +29,7 @@ sub searchOnExpr { my ( $args, $selectField, $value, @fields ) = @_; # Escape quotes - $value =~ s/'/''/g; + $value =~ s/'/''/g; $selectField =~ s/'/''/g; if ( $class->_fieldIsIndexed( $args, $selectField ) ) { $value =~ s/\*/%/g; @@ -74,12 +74,18 @@ sub _query { no strict 'refs'; my $self = eval "&${class}::populate();"; my $sub = $self->{unserialize}; - my $tmp = &$sub( { serialized => $row[1] } ); - if (@fields) { - $res{ $row[0] }->{$_} = $tmp->{$_} foreach (@fields); - } - else { - $res{ $row[0] } = $tmp; + eval { + my $tmp = &$sub( { serialized => $row[1] } ); + if (@fields) { + $res{ $row[0] }->{$_} = $tmp->{$_} foreach (@fields); + } + else { + $res{ $row[0] } = $tmp; + } + }; + if ($@) { + print STDERR "Error in session $row[0]: $@\n"; + delete $res{ $row[0] }; } } } @@ -156,29 +162,35 @@ sub get_key_from_all_sessions { ? sub { require Storable; return Storable::thaw( pack( 'H*', $_[0] ) ); - } + } : $args->{DataSource} =~ /^mysql/i ? sub { require MIME::Base64; require Storable; return Storable::thaw( MIME::Base64::decode_base64( $_[0] ) ); - } + } : undef ); while ( my @row = $sth->fetchrow_array ) { no strict 'refs'; my $self = eval "&${class}::populate();"; - my $sub = $self->{unserialize}; - my $tmp = &$sub( { serialized => $row[1] }, $next ); - if ( ref($data) eq 'CODE' ) { - $tmp = &$data( $tmp, $row[0] ); - $res{ $row[0] } = $tmp if ( defined($tmp) ); - } - elsif ($data) { - $data = [$data] unless ( ref($data) ); - $res{ $row[0] }->{$_} = $tmp->{$_} foreach (@$data); - } - else { - $res{ $row[0] } = $tmp; + eval { + my $sub = $self->{unserialize}; + my $tmp = &$sub( { serialized => $row[1] }, $next ); + if ( ref($data) eq 'CODE' ) { + $tmp = &$data( $tmp, $row[0] ); + $res{ $row[0] } = $tmp if ( defined($tmp) ); + } + elsif ($data) { + $data = [$data] unless ( ref($data) ); + $res{ $row[0] }->{$_} = $tmp->{$_} foreach (@$data); + } + else { + $res{ $row[0] } = $tmp; + } + }; + if ($@) { + print STDERR "Error in session $row[0]: $@\n"; + delete $res{ $row[0] }; } } return \%res; diff --git a/lib/Apache/Session/Browseable/File.pm b/lib/Apache/Session/Browseable/File.pm index 7268cf6..c102c72 100644 --- a/lib/Apache/Session/Browseable/File.pm +++ b/lib/Apache/Session/Browseable/File.pm @@ -11,7 +11,7 @@ use Apache::Session::Browseable::_common; use constant SL => ( $^O and $^O =~ /(?:MSWin|Windows)/i ? '\\' : '/' ); -our $VERSION = '1.2.3'; +our $VERSION = '1.3.4'; our @ISA = qw(Apache::Session Apache::Session::Browseable::_common); sub populate { @@ -48,20 +48,27 @@ sub get_key_from_all_sessions { closedir DIR; my %res; for my $f (@t) { - open F, $args->{Directory} . SL . $f; - my $row = join '', ; - if ( ref($data) eq 'CODE' ) { - $res{$f} = - &$data( &Apache::Session::Serialize::JSON::_unserialize($row), - $f ); - } - elsif ($data) { - $data = [$data] unless ( ref($data) ); - my $tmp = &Apache::Session::Serialize::JSON::_unserialize($row); - $res{$f}->{$_} = $tmp->{$_} foreach (@$data); - } - else { - $res{$f} = &Apache::Session::Serialize::JSON::_unserialize($row); + eval { + open F, $args->{Directory} . SL . $f or die $!; + my $row = join '', ; + if ( ref($data) eq 'CODE' ) { + $res{$f} = + &$data( &Apache::Session::Serialize::JSON::_unserialize($row), + $f ); + } + elsif ($data) { + $data = [$data] unless ( ref($data) ); + my $tmp = &Apache::Session::Serialize::JSON::_unserialize($row); + $res{$f}->{$_} = $tmp->{$_} foreach (@$data); + } + else { + $res{$f} = + &Apache::Session::Serialize::JSON::_unserialize($row); + } + }; + if ($@) { + print STDERR "Error in session $f: $@\n"; + delete $res{$f}; } } return \%res; diff --git a/lib/Apache/Session/Browseable/MySQLJSON.pm b/lib/Apache/Session/Browseable/MySQLJSON.pm index 2d03215..5bffb0f 100644 --- a/lib/Apache/Session/Browseable/MySQLJSON.pm +++ b/lib/Apache/Session/Browseable/MySQLJSON.pm @@ -9,7 +9,7 @@ use Apache::Session::Generate::SHA256; use Apache::Session::Serialize::JSON; use Apache::Session::Browseable::DBI; -our $VERSION = '1.2.7'; +our $VERSION = '1.3.4'; our @ISA = qw(Apache::Session::Browseable::DBI Apache::Session); sub populate { @@ -36,7 +36,7 @@ sub searchOn { sub searchOnExpr { my ( $class, $args, $selectField, $value, @fields ) = @_; $selectField =~ s/'/''/g; - $value =~ s/\*/%/g; + $value =~ s/\*/%/g; my $query = { query => qq'a_session->>"\$.$selectField" like ?', values => [$value] }; return $class->_query( $args, $query, @fields ); @@ -123,18 +123,24 @@ sub get_key_from_all_sessions { while ( my @row = $sth->fetchrow_array ) { no strict 'refs'; my $self = eval "&${class}::populate();"; - my $sub = $self->{unserialize}; - my $tmp = &$sub( { serialized => $row[1] } ); - if ( ref($data) eq 'CODE' ) { - $tmp = &$data( $tmp, $row[0] ); - $res{ $row[0] } = $tmp if ( defined($tmp) ); - } - elsif ($data) { - $data = [$data] unless ( ref($data) ); - $res{ $row[0] }->{$_} = $tmp->{$_} foreach (@$data); - } - else { - $res{ $row[0] } = $tmp; + eval { + my $sub = $self->{unserialize}; + my $tmp = &$sub( { serialized => $row[1] } ); + if ( ref($data) eq 'CODE' ) { + $tmp = &$data( $tmp, $row[0] ); + $res{ $row[0] } = $tmp if ( defined($tmp) ); + } + elsif ($data) { + $data = [$data] unless ( ref($data) ); + $res{ $row[0] }->{$_} = $tmp->{$_} foreach (@$data); + } + else { + $res{ $row[0] } = $tmp; + } + }; + if ($@) { + print STDERR "Error in session $row[0]: $@\n"; + delete $res{ $row[0] }; } } return \%res; diff --git a/lib/Apache/Session/Browseable/PgHstore.pm b/lib/Apache/Session/Browseable/PgHstore.pm index 02947d8..8fcde1b 100644 --- a/lib/Apache/Session/Browseable/PgHstore.pm +++ b/lib/Apache/Session/Browseable/PgHstore.pm @@ -8,7 +8,7 @@ use Apache::Session::Browseable::Store::Postgres; use Apache::Session::Generate::SHA256; use Apache::Session::Serialize::Hstore; -our $VERSION = '1.3.0'; +our $VERSION = '1.3.4'; our @ISA = qw(Apache::Session); sub populate { @@ -36,7 +36,7 @@ sub searchOn { sub searchOnExpr { my ( $class, $args, $selectField, $value, @fields ) = @_; $selectField =~ s/'/''/g; - $value =~ s/\*/%/g; + $value =~ s/\*/%/g; my $query = { query => "a_session -> '$selectField' like ?", values => [$value] }; return $class->_query( $args, $query, @fields ); @@ -74,8 +74,14 @@ sub _query { my $self = eval "&${class}::populate();"; my $sub = $self->{unserialize}; foreach my $s ( keys %$res ) { - my $tmp = &$sub( { serialized => $res->{$s}->{a_session} } ); - $res->{$s} = $tmp; + eval { + my $tmp = &$sub( { serialized => $res->{$s}->{a_session} } ); + $res->{$s} = $tmp; + }; + if ($@) { + print STDERR "Error in session $s: $@\n"; + delete $res->{$s}; + } } } return $res; diff --git a/lib/Apache/Session/Browseable/PgJSON.pm b/lib/Apache/Session/Browseable/PgJSON.pm index 1bca68c..cf762fe 100644 --- a/lib/Apache/Session/Browseable/PgJSON.pm +++ b/lib/Apache/Session/Browseable/PgJSON.pm @@ -8,7 +8,7 @@ use Apache::Session::Browseable::Store::Postgres; use Apache::Session::Generate::SHA256; use Apache::Session::Serialize::JSON; -our $VERSION = '1.2.9'; +our $VERSION = '1.3.4'; our @ISA = qw(Apache::Session); sub populate { @@ -36,7 +36,7 @@ sub searchOn { sub searchOnExpr { my ( $class, $args, $selectField, $value, @fields ) = @_; $selectField =~ s/'/''/g; - $value =~ s/\*/%/g; + $value =~ s/\*/%/g; my $query = { query => "a_session ->> '$selectField' like ?", values => [$value] }; return $class->_query( $args, $query, @fields ); @@ -74,8 +74,14 @@ sub _query { my $self = eval "&${class}::populate();"; my $sub = $self->{unserialize}; foreach my $s ( keys %$res ) { - my $tmp = &$sub( { serialized => $res->{$s}->{a_session} } ); - $res->{$s} = $tmp; + eval { + my $tmp = &$sub( { serialized => $res->{$s}->{a_session} } ); + $res->{$s} = $tmp; + }; + if ($@) { + print STDERR "Error in session $s: $@\n"; + delete $res->{$s}; + } } } return $res; @@ -86,16 +92,19 @@ sub deleteIfLowerThan { my $query; if ( $rule->{or} ) { $query = join ' OR ', - map { "cast(a_session ->> '$_' as bigint) < $rule->{or}->{$_}" } keys %{ $rule->{or} }; + map { "cast(a_session ->> '$_' as bigint) < $rule->{or}->{$_}" } + keys %{ $rule->{or} }; } elsif ( $rule->{and} ) { $query = join ' AND ', - map { "cast(a_session ->> '$_' as bigint) < $rule->{or}->{$_}" } keys %{ $rule->{or} }; + map { "cast(a_session ->> '$_' as bigint) < $rule->{or}->{$_}" } + keys %{ $rule->{or} }; } if ( $rule->{not} ) { $query = "($query) AND " . join( ' AND ', - map { "a_session ->> '$_' <> '$rule->{not}->{$_}'" } keys %{ $rule->{not} } ); + map { "a_session ->> '$_' <> '$rule->{not}->{$_}'" } + keys %{ $rule->{not} } ); } return 0 unless ($query); my $dbh = $class->_classDbh($args); @@ -116,7 +125,8 @@ sub get_key_from_all_sessions { # Special case if all wanted fields are indexed if ( $data and ref($data) ne 'CODE' ) { $data = [$data] unless ( ref($data) ); - my $fields = join ',', map { s/'//g; "a_session ->> '$_' AS $_" } @$data; + my $fields = join ',', + map { s/'//g; "a_session ->> '$_' AS $_" } @$data; $sth = $dbh->prepare("SELECT $fields from $table_name"); $sth->execute; return $sth->fetchall_hashref('id'); @@ -127,18 +137,24 @@ sub get_key_from_all_sessions { while ( my @row = $sth->fetchrow_array ) { no strict 'refs'; my $self = eval "&${class}::populate();"; - my $sub = $self->{unserialize}; - my $tmp = &$sub( { serialized => $row[1] } ); - if ( ref($data) eq 'CODE' ) { - $tmp = &$data( $tmp, $row[0] ); - $res{ $row[0] } = $tmp if ( defined($tmp) ); - } - elsif ($data) { - $data = [$data] unless ( ref($data) ); - $res{ $row[0] }->{$_} = $tmp->{$_} foreach (@$data); - } - else { - $res{ $row[0] } = $tmp; + eval { + my $sub = $self->{unserialize}; + my $tmp = &$sub( { serialized => $row[1] } ); + if ( ref($data) eq 'CODE' ) { + $tmp = &$data( $tmp, $row[0] ); + $res{ $row[0] } = $tmp if ( defined($tmp) ); + } + elsif ($data) { + $data = [$data] unless ( ref($data) ); + $res{ $row[0] }->{$_} = $tmp->{$_} foreach (@$data); + } + else { + $res{ $row[0] } = $tmp; + } + }; + if ($@) { + print STDERR "Error in session $row[0]: $@\n"; + delete $res{ $row[0] }; } } return \%res; diff --git a/lib/Apache/Session/Browseable/Redis.pm b/lib/Apache/Session/Browseable/Redis.pm index 379d127..42f6e18 100644 --- a/lib/Apache/Session/Browseable/Redis.pm +++ b/lib/Apache/Session/Browseable/Redis.pm @@ -9,7 +9,7 @@ use Apache::Session::Lock::Null; use Apache::Session::Serialize::JSON; use Apache::Session::Browseable::_common; -our $VERSION = '1.3.2'; +our $VERSION = '1.3.4'; our @ISA = qw(Apache::Session); our $redis = $Apache::Session::Browseable::Store::Redis::redis; @@ -43,17 +43,23 @@ sub searchOn { if ( grep { $_ eq $selectField } @$index ) { my $redisObj = $class->_getRedis($args); - my @keys = $redisObj->smembers("${selectField}_$value"); + my @keys = $redisObj->smembers("${selectField}_$value"); foreach my $k (@keys) { next unless ($k); my $tmp = $redisObj->get($k); next unless ($tmp); - $tmp = unserialize($tmp); - if (@fields) { - $res{$k}->{$_} = $tmp->{$_} foreach (@fields); - } - else { - $res{$k} = $tmp; + eval { + $tmp = unserialize($tmp); + if (@fields) { + $res{$k}->{$_} = $tmp->{$_} foreach (@fields); + } + else { + $res{$k} = $tmp; + } + }; + if ($@) { + print STDERR "Error in session $k: $@\n"; + delete $res{$k}; } } } @@ -86,21 +92,27 @@ sub get_key_from_all_sessions { my %res; my $redisObj = $class->_getRedis($args); - my @keys = $redisObj->keys('*'); + my @keys = $redisObj->keys('*'); foreach my $k (@keys) { next if ( !$k or $k =~ /_/ ); - my $v = $redisObj->get($k); - my $tmp = unserialize($v); - if ( ref($data) eq 'CODE' ) { - $tmp = &$data( $tmp, $k ); - $res{$k} = $tmp if ( defined($tmp) ); - } - elsif ($data) { - $data = [$data] unless ( ref($data) ); - $res{$k}->{$_} = $tmp->{$_} foreach (@$data); - } - else { - $res{$k} = $tmp; + eval { + my $v = $redisObj->get($k); + my $tmp = unserialize($v); + if ( ref($data) eq 'CODE' ) { + $tmp = &$data( $tmp, $k ); + $res{$k} = $tmp if ( defined($tmp) ); + } + elsif ($data) { + $data = [$data] unless ( ref($data) ); + $res{$k}->{$_} = $tmp->{$_} foreach (@$data); + } + else { + $res{$k} = $tmp; + } + }; + if ($@) { + print STDERR "Error in session $k: $@\n"; + delete $res{$k}; } } return \%res;