| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package CGI::AIS::Session; | 
| 2 |  |  |  |  |  |  |  | 
| 3 | 1 |  |  | 1 |  | 773 | use strict; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 39 |  | 
| 4 |  |  |  |  |  |  |  | 
| 5 | 1 |  |  | 1 |  | 5 | use vars qw{ *SOCK @ISA @EXPORT $VERSION }; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 151 |  | 
| 6 |  |  |  |  |  |  |  | 
| 7 |  |  |  |  |  |  | require Exporter; | 
| 8 |  |  |  |  |  |  |  | 
| 9 |  |  |  |  |  |  | @ISA = qw(Exporter); | 
| 10 |  |  |  |  |  |  | @EXPORT = qw(Authenticate); | 
| 11 |  |  |  |  |  |  |  | 
| 12 |  |  |  |  |  |  | $VERSION = '0.02'; | 
| 13 |  |  |  |  |  |  |  | 
| 14 | 1 |  |  | 1 |  | 6 | use Carp; | 
|  | 1 |  |  |  |  | 10 |  | 
|  | 1 |  |  |  |  | 96 |  | 
| 15 |  |  |  |  |  |  |  | 
| 16 |  |  |  |  |  |  |  | 
| 17 | 1 |  |  | 1 |  | 1066 | use Socket qw(:DEFAULT :crlf); | 
|  | 1 |  |  |  |  | 5850 |  | 
|  | 1 |  |  |  |  | 1269 |  | 
| 18 | 1 |  |  | 1 |  | 1100 | use IO::Handle; | 
|  | 1 |  |  |  |  | 10048 |  | 
|  | 1 |  |  |  |  | 1845 |  | 
| 19 |  |  |  |  |  |  | sub miniget($$$$){ | 
| 20 | 0 |  |  | 0 | 0 |  | my($HostName, $PortNumber, $Desired, $agent)  = @_; | 
| 21 | 0 |  | 0 |  |  |  | $PortNumber ||= 80; | 
| 22 | 0 |  | 0 |  |  |  | my $iaddr	= inet_aton($HostName)	|| die "Cannot find host named $HostName"; | 
| 23 | 0 |  |  |  |  |  | my $paddr	= sockaddr_in($PortNumber,$iaddr); | 
| 24 | 0 |  |  |  |  |  | my $proto	= getprotobyname('tcp'); | 
| 25 |  |  |  |  |  |  |  | 
| 26 | 0 | 0 |  |  |  |  | socket(SOCK, PF_INET, SOCK_STREAM, $proto)  || die "socket: $!"; | 
| 27 | 0 | 0 |  |  |  |  | connect(SOCK, $paddr)    || die "connect: $!"; | 
| 28 | 0 |  |  |  |  |  | SOCK->autoflush(1); | 
| 29 |  |  |  |  |  |  |  | 
| 30 | 0 |  |  |  |  |  | print SOCK | 
| 31 |  |  |  |  |  |  | "GET $Desired HTTP/1.1$CRLF", | 
| 32 |  |  |  |  |  |  | # Do we need a Host: header with an "AbsoluteURI?" | 
| 33 |  |  |  |  |  |  | # not needed: http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.2 | 
| 34 |  |  |  |  |  |  | # but this is trumped by an Apache error message invoking RFC2068 sections 9 and 14.23 | 
| 35 |  |  |  |  |  |  | "Host: $HostName$CRLF", | 
| 36 |  |  |  |  |  |  | "User-Agent: $agent$CRLF", | 
| 37 |  |  |  |  |  |  | "Connection: close$CRLF", | 
| 38 |  |  |  |  |  |  | $CRLF; | 
| 39 |  |  |  |  |  |  |  | 
| 40 | 0 |  |  |  |  |  | join('',); | 
| 41 |  |  |  |  |  |  |  | 
| 42 |  |  |  |  |  |  | }; | 
| 43 |  |  |  |  |  |  |  | 
| 44 |  |  |  |  |  |  |  | 
| 45 |  |  |  |  |  |  |  | 
| 46 |  |  |  |  |  |  | sub Authenticate{ | 
| 47 |  |  |  |  |  |  |  | 
| 48 | 0 |  |  | 0 | 0 |  | my %Param = (agent => 'AISclient', @_); | 
| 49 | 0 |  |  |  |  |  | my %Result; | 
| 50 |  |  |  |  |  |  | my $AISXML; | 
| 51 |  |  |  |  |  |  |  | 
| 52 |  |  |  |  |  |  |  | 
| 53 | 0 |  |  |  |  |  | print STDERR "$$ Session coox: $ENV{HTTP_COOKIE}\n"; | 
| 54 | 0 |  |  |  |  |  | my (@Cookies) = ($ENV{HTTP_COOKIE} =~  /AIS_Session=(\w+)/g); | 
| 55 | 0 | 0 |  |  |  |  | tie my %Session, $Param{tieargs}->[0], | 
| 56 |  |  |  |  |  |  | $Param{tieargs}->[1],$Param{tieargs}->[2],$Param{tieargs}->[3], | 
| 57 |  |  |  |  |  |  | $Param{tieargs}->[4],$Param{tieargs}->[5],$Param{tieargs}->[6], | 
| 58 |  |  |  |  |  |  | $Param{tieargs}->[7],$Param{tieargs}->[8],$Param{tieargs}->[9] | 
| 59 | 0 |  |  |  |  |  | or croak "failed to tie @{$Param{tieargs}}"; | 
| 60 |  |  |  |  |  |  |  | 
| 61 | 0 |  |  |  |  |  | print STDERR "Session database has ",scalar(keys %Session)," keys\n"; | 
| 62 |  |  |  |  |  |  |  | 
| 63 | 0 |  |  |  |  |  | my $Cookie; | 
| 64 |  |  |  |  |  |  |  | 
| 65 |  |  |  |  |  |  | # make Cookie imply its validity | 
| 66 | 0 |  |  |  |  |  | push @Cookies, undef; | 
| 67 | 0 |  |  |  |  |  | while ($Cookie = shift @Cookies){ | 
| 68 |  |  |  |  |  |  | #$Session{$Cookie} and last; | 
| 69 | 0 | 0 |  |  |  |  | if($Session{$Cookie}){ | 
| 70 | 0 |  |  |  |  |  | print STDERR "Session $Cookie exists\n"; | 
| 71 | 0 |  |  |  |  |  | last; | 
| 72 |  |  |  |  |  |  | }else{ | 
| 73 | 0 |  |  |  |  |  | print STDERR "Session <$Cookie> false\n"; | 
| 74 |  |  |  |  |  |  |  | 
| 75 |  |  |  |  |  |  | }; | 
| 76 |  |  |  |  |  |  | }; | 
| 77 |  |  |  |  |  |  |  | 
| 78 | 0 |  |  |  |  |  | my $OTUkey; | 
| 79 |  |  |  |  |  |  | my $SessionKey; | 
| 80 | 0 |  |  |  |  |  | my ($PostKey) = ($ENV{QUERY_STRING} =~ /AIS_POST_key=(\w+)/); | 
| 81 |  |  |  |  |  |  |  | 
| 82 |  |  |  |  |  |  | # if (!$Cookie and $ENV{REQUEST_METHOD} eq 'POST' ){ | 
| 83 |  |  |  |  |  |  | # in general, whenever we've got the wrong name for the | 
| 84 |  |  |  |  |  |  | # server, it won't work.  So we need to redirect ourselves | 
| 85 |  |  |  |  |  |  | # back to here with the right name for the server, and | 
| 86 |  |  |  |  |  |  | # then we'll get our cookie, if we have one. | 
| 87 | 0 | 0 | 0 |  |  |  | if (!$Cookie and !defined($PostKey) ){ | 
| 88 |  |  |  |  |  |  | # print STDERR "$$ Cookieless POST caught early\n"; | 
| 89 | 0 |  |  |  |  |  | print STDERR "$$ possible wrong SERVER_NAME\n"; | 
| 90 | 0 | 0 |  |  |  |  | if ($ENV{REQUEST_METHOD} eq 'POST' ){ | 
| 91 | 0 |  |  |  |  |  | $PostKey = join('',time,(map {("A".."Z")[rand 26]}(0..9))); | 
|  | 0 |  |  |  |  |  |  | 
| 92 | 0 |  |  |  |  |  | $Session{$PostKey} = join('',(<>)); | 
| 93 |  |  |  |  |  |  | }else{ | 
| 94 | 0 |  |  |  |  |  | $PostKey = ''; | 
| 95 |  |  |  |  |  |  | }; | 
| 96 |  |  |  |  |  |  |  | 
| 97 | 0 |  |  |  |  |  | print "Location: http://$ENV{SERVER_NAME}$ENV{REQUEST_URI}?AIS_POST_key=$PostKey&$ENV{QUERY_STRING}$CRLF$CRLF"; | 
| 98 | 0 |  |  |  |  |  | exit; | 
| 99 |  |  |  |  |  |  | }; | 
| 100 |  |  |  |  |  |  |  | 
| 101 | 0 | 0 |  |  |  |  | if ($PostKey){	# will be defined but false '' when servicing a GET | 
| 102 | 0 | 0 |  |  |  |  | pipe(POSTREAD,POSTWRITE) or die "Cannot create pipe: $!"; | 
| 103 | 0 | 0 |  |  |  |  | if (fork){ | 
| 104 |  |  |  |  |  |  | # we are in parent | 
| 105 | 0 |  |  |  |  |  | close POSTWRITE; | 
| 106 | 0 |  |  |  |  |  | open STDIN, "<&POSTREAD"; | 
| 107 | 0 |  |  |  |  |  | $ENV{REQUEST_METHOD} = 'POST'; | 
| 108 |  |  |  |  |  |  |  | 
| 109 |  |  |  |  |  |  | }else{ | 
| 110 |  |  |  |  |  |  | # in child -- write POSTdata to pipe and exit | 
| 111 | 0 |  |  |  |  |  | close STDOUT; | 
| 112 | 0 |  |  |  |  |  | close STDIN; | 
| 113 | 0 |  |  |  |  |  | close POSTREAD; | 
| 114 | 0 |  |  |  |  |  | print POSTWRITE '&',$Session{$PostKey}; | 
| 115 | 0 | 0 |  |  |  |  | close POSTWRITE or die "$$: Error closing POSTWRITE\n"; | 
| 116 | 0 | 0 |  |  |  |  | $Cookie and delete $Session{$PostKey}; | 
| 117 |  |  |  |  |  |  | # exit; | 
| 118 |  |  |  |  |  |  | #POSIX:_exit(0); # perldoc -f exit | 
| 119 | 0 |  |  |  |  |  | exec '/usr/bin/true'; | 
| 120 |  |  |  |  |  |  | }; | 
| 121 |  |  |  |  |  |  | }; | 
| 122 |  |  |  |  |  |  |  | 
| 123 | 0 | 0 |  |  |  |  | if ($ENV{QUERY_STRING} =~ /AIS_OTUkey=(\w+)/){ | 
|  |  | 0 |  |  |  |  |  | 
| 124 | 0 |  |  |  |  |  | $OTUkey = $1; | 
| 125 | 0 | 0 |  |  |  |  | my ($method, $host, $port, $path) = | 
| 126 |  |  |  |  |  |  | ($Param{aissri} =~ m#^(\w+)://([^:/]+):?(\d*)(.+)$#) | 
| 127 |  |  |  |  |  |  | or die "Could not get meth,hos,por,pat from <$Param{aissri}>"; | 
| 128 | 0 | 0 |  |  |  |  | unless ($method eq 'http'){ | 
| 129 | 0 |  |  |  |  |  | croak "aissri parameter must begin 'http://' at this time"; | 
| 130 |  |  |  |  |  |  | }; | 
| 131 |  |  |  |  |  |  |  | 
| 132 |  |  |  |  |  |  | # my $Response = `lynx -source $Param{aissri}query?$OTUkey$CRLF$CRLF` | 
| 133 | 0 |  |  |  |  |  | my $Response = miniget $host, $port, | 
| 134 |  |  |  |  |  |  | "$Param{aissri}query?$OTUkey", $Param{agent}; | 
| 135 |  |  |  |  |  |  |  | 
| 136 | 0 |  |  |  |  |  | $SessionKey = join('',time,(map {("A".."Z")[rand 26]}(0..19))); | 
|  | 0 |  |  |  |  |  |  | 
| 137 |  |  |  |  |  |  | # print "Set-Cookie: AIS_Session=$SessionKey; path=$ENV{SCRIPT_NAME};$CRLF"; | 
| 138 | 0 |  |  |  |  |  | print "Set-Cookie: AIS_Session=$SessionKey; path=/; expires=$CRLF"; | 
| 139 | 0 | 0 |  |  |  |  | ($AISXML) = | 
| 140 |  |  |  |  |  |  | $Response =~ m#(.+)#si | 
| 141 |  |  |  |  |  |  | or die "no  element from $Param{aissri}query?$OTUkey\n"; | 
| 142 | 0 |  |  |  |  |  | $Session{$SessionKey} = $AISXML; | 
| 143 |  |  |  |  |  |  |  | 
| 144 |  |  |  |  |  |  | }elsif (!$Cookie){ | 
| 145 | 0 |  |  |  |  |  | my $PostString = ''; | 
| 146 |  |  |  |  |  |  | # if ($ENV{REQUEST_METHOD} eq 'POST' and !eof){ | 
| 147 | 0 | 0 |  |  |  |  | if ($ENV{REQUEST_METHOD} eq 'POST' ){ | 
| 148 | 0 |  |  |  |  |  | print STDERR "$$ Cookieless POST\n"; | 
| 149 | 0 |  |  |  |  |  | my $PostKey = join('',time,(map {("A".."Z")[rand 26]}(0..9))); | 
|  | 0 |  |  |  |  |  |  | 
| 150 | 0 |  |  |  |  |  | $Session{$PostKey} = join('',(<>)); | 
| 151 | 0 |  |  |  |  |  | $PostString = "AIS_POST_key=$PostKey&"; | 
| 152 |  |  |  |  |  |  |  | 
| 153 |  |  |  |  |  |  | }; | 
| 154 | 0 |  |  |  |  |  | print "Location: $Param{aissri}present?http://$ENV{SERVER_NAME}$ENV{REQUEST_URI}?${PostString}AIS_OTUkey=\n\n"; | 
| 155 | 0 |  |  |  |  |  | exit; | 
| 156 |  |  |  |  |  |  | }else{ # We have a cookie | 
| 157 | 0 |  |  |  |  |  | $AISXML = $Session{$Cookie}; | 
| 158 | 0 | 0 |  |  |  |  | delete  $Session{$Cookie} if $ENV{QUERY_STRING} eq 'AIS_LOGOUT'; | 
| 159 |  |  |  |  |  |  | }; | 
| 160 |  |  |  |  |  |  |  | 
| 161 | 0 |  |  |  |  |  | foreach (qw{ | 
|  | 0 |  |  |  |  |  |  | 
| 162 |  |  |  |  |  |  | identity | 
| 163 |  |  |  |  |  |  | error | 
| 164 |  |  |  |  |  |  | aissri | 
| 165 |  |  |  |  |  |  | user_remote_addr | 
| 166 |  |  |  |  |  |  | }, | 
| 167 |  |  |  |  |  |  | @{$Param{XML}} | 
| 168 |  |  |  |  |  |  | ){ | 
| 169 | 0 | 0 |  |  |  |  | $AISXML =~ m#<$_>(.+)$_>#si or next; | 
| 170 | 0 |  |  |  |  |  | $Result{$_} = $1; | 
| 171 |  |  |  |  |  |  | }; | 
| 172 |  |  |  |  |  |  |  | 
| 173 | 0 | 0 |  |  |  |  | if ( defined($Param{timeout})){ | 
| 174 | 0 |  |  |  |  |  | my $TO = $Param{timeout}; | 
| 175 | 0 |  |  |  |  |  | delete @Session{ grep { time - $_ > $TO } keys %Session }; | 
|  | 0 |  |  |  |  |  |  | 
| 176 |  |  |  |  |  |  |  | 
| 177 |  |  |  |  |  |  | }; | 
| 178 |  |  |  |  |  |  |  | 
| 179 |  |  |  |  |  |  | #Suppress caching NULL and ERROR | 
| 180 | 0 | 0 | 0 |  |  |  | if( $Result{identity} eq 'NULL' or $Result{identity} eq 'ERROR'){ | 
| 181 | 0 |  |  |  |  |  | print "Set-Cookie: AIS_Session=$CRLF"; | 
| 182 | 0 | 0 |  |  |  |  | $SessionKey and delete $Session{$SessionKey} ; | 
| 183 |  |  |  |  |  |  |  | 
| 184 | 0 | 0 |  |  |  |  | $Param{nodie} or die "AIS: $Result{identity} identity $Result{error} error"; | 
| 185 |  |  |  |  |  |  |  | 
| 186 |  |  |  |  |  |  | }; | 
| 187 | 0 |  |  |  |  |  | return \%Result; | 
| 188 |  |  |  |  |  |  | }; | 
| 189 |  |  |  |  |  |  |  | 
| 190 |  |  |  |  |  |  |  | 
| 191 |  |  |  |  |  |  | # Preloaded methods go here. | 
| 192 |  |  |  |  |  |  |  | 
| 193 |  |  |  |  |  |  | 1; | 
| 194 |  |  |  |  |  |  | __END__ |