From: John Graham-C. <jgr...@us...> - 2005-02-16 13:59:45
|
Update of /cvsroot/popfile/engine/UI In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv30946/UI Modified Files: HTML.pm Log Message: Implement logout for users, add the client IP into the cookie to prevent someone stealing a cookie, put the search/sort/filter/negate information in the session Index: HTML.pm =================================================================== RCS file: /cvsroot/popfile/engine/UI/HTML.pm,v retrieving revision 1.339 retrieving revision 1.340 diff -C2 -d -r1.339 -r1.340 *** HTML.pm 15 Feb 2005 04:23:51 -0000 1.339 --- HTML.pm 16 Feb 2005 13:59:33 -0000 1.340 *************** *** 121,126 **** # maps an API session to the last time this entry was used. # ! # lastused When this cookie was last read or written ! # user The database user id $self->{sessions__} = (); --- 121,127 ---- # maps an API session to the last time this entry was used. # ! # lastused When this cookie was last read or written ! # user The database user id ! # search/sort/filter/negate History page options $self->{sessions__} = (); *************** *** 161,166 **** # Controls whether or not we die if a template variable is missing ! # when we try to set it. Setting it to 1 can be useful for debugging ! # purposes $self->config_( 'strict_templates', 0 ); --- 162,167 ---- # Controls whether or not we die if a template variable is missing ! # when we try to set it. Setting it to 1 can be useful for ! # debugging purposes $self->config_( 'strict_templates', 0 ); *************** *** 284,287 **** --- 285,289 ---- # # $cookie The decrypted cookie string + # $client The client from which we received the cookie # # Returns undef for a bad cookie, or bad session. *************** *** 290,297 **** sub handle_cookie__ { ! my ( $self, $cookie ) = @_; ! $cookie =~ /^([^ ]+) (\d+) ([^ ]+) ([^ ]+)$/; ! my ( $garbage, $timeset, $session, $checksum ) = ( $1, $2, $3, $4 ); if ( !defined( $checksum ) ) { --- 292,299 ---- sub handle_cookie__ { ! my ( $self, $cookie, $client ) = @_; ! $cookie =~ /^([^ ]+) (\d+) ([^ ]+) ([^ ]+) ([^ ]+)$/; ! my ( $garbage, $timeset, $session, $client_name, $checksum ) = ( $1, $2, $3, $4, $5 ); if ( !defined( $checksum ) ) { *************** *** 299,312 **** } ! $self->log_( 2, "Received cookie: [$cookie] [$garbage] [$timeset] [$session] [$checksum]" ); # First check that the checksum is valid. This will check the # cookie has not been tampered with and the decryption worked ! if ( md5_hex( "$garbage $timeset $session " ) ne $checksum ) { $self->log_( 0, "Invalid cookie received, checksum failed" ); return undef; } # Now see if this session has been recorded in the current # sessions, if so then return it, because we can assume that it is --- 301,335 ---- } ! $self->log_( 2, "Received cookie: [$cookie] [$garbage] [$timeset] [$session] [$client_name] [$checksum]" ); # First check that the checksum is valid. This will check the # cookie has not been tampered with and the decryption worked ! if ( md5_hex( "$garbage $timeset $session $client_name " ) ne $checksum ) { $self->log_( 0, "Invalid cookie received, checksum failed" ); return undef; } + # Check that the cookie came from the peer that we expect it from + # to prevent someone from being able to steal a cookie and reuse + # it + + my $peer = $client->peername; + my ($peer_port, $peer_addr) = sockaddr_in($peer); + my $peer_name = inet_ntoa($peer_addr); + + if ( $client_name ne $peer_name ) { + $self->log_( 0, "Rejecting cookie because of invalid client $client_name for $peer_name" ); + return undef; + } + + # Now see if this cookie is just old and should be rejected anyway + # (more than two weeks old) + + if ( $timeset < time - 2*7*24*60*60 ) { + $self->log_( 0, "Rejecting old cookie" ); + return undef; + } + # Now see if this session has been recorded in the current # sessions, if so then return it, because we can assume that it is *************** *** 318,321 **** --- 341,351 ---- } + # Let's see if the session key is the magic string LOGGED-OUT + # in which case there's no session + + if ( $session eq 'LOGGED-OUT' ) { + return undef; + } + # Otherwise check that the session ID is still valid in the API. *************** *** 325,328 **** --- 355,363 ---- $self->{sessions__}{$session}{lastused} = time; $self->{sessions__}{$session}{user} = $user; + $self->{sessions__}{$session}{sort} = ''; + $self->{sessions__}{$session}{filter} = ''; + $self->{sessions__}{$session}{search} = ''; + $self->{sessions__}{$session}{negate} = ''; + return $session; } else { *************** *** 335,346 **** # set_cookie__ # ! # $session Valid session key # ! # Returns a Set-Cookie: header from a session ke # #---------------------------------------------------------------------------- sub set_cookie__ { ! my ( $self, $session ) = @_; if ( !defined( $session ) ) { --- 370,382 ---- # set_cookie__ # ! # $session Valid session key ! # $client The client we are sending the cookie to # ! # Returns a Set-Cookie: header from a session # #---------------------------------------------------------------------------- sub set_cookie__ { ! my ( $self, $session, $client ) = @_; if ( !defined( $session ) ) { *************** *** 354,357 **** --- 390,394 ---- # Time this cookie is being set # Value of the $session variable + # The IP address of the client that set the cookie # MD5 checksum of the data (hex encoded) *************** *** 364,367 **** --- 401,408 ---- $cookie_string .= $session; $cookie_string .= ' '; + my $peer = $client->peername; + my ($peer_port, $peer_addr) = sockaddr_in($peer); + my $peer_name = inet_ntoa($peer_addr); + $cookie_string .= "$peer_name "; $cookie_string .= md5_hex( $cookie_string ); *************** *** 409,413 **** if ( $cookie ne '' ) { ! $session = $self->handle_cookie__( $cookie ); } --- 450,454 ---- if ( $cookie ne '' ) { ! $session = $self->handle_cookie__( $cookie, $client ); } *************** *** 447,451 **** # prevent caching ! if ( defined( $session ) && ( $url =~ /skins\/(([^\/]+)\/(([^\/]+\/)+)?)?([^\/]+)$/ ) ) { my $path = ( $1 || ''); my $path_skin = ( $2 || ''); --- 488,493 ---- # prevent caching ! if ( $url =~ /skins\/(([^\/]+)\/(([^\/]+\/)+)?)?([^\/]+)$/ ) { ! my $user = 1; my $path = ( $1 || ''); my $path_skin = ( $2 || ''); *************** *** 453,457 **** my $filename = ( $5 || '' ); ! my $config_skin = $self->user_config_( $self->{sessions__}{$session}{user}, 'skin' ); my %mime_extensions = qw( gif image/gif --- 495,503 ---- my $filename = ( $5 || '' ); ! if ( defined( $session ) ) { ! $user = $self->{sessions__}{$session}{user}; ! } ! ! my $config_skin = $self->user_config_( $user, 'skin' ); my %mime_extensions = qw( gif image/gif *************** *** 576,580 **** } ! if ( $url eq '/shutdown' ) { my $http_header = "HTTP/1.1 200 OK\r\n"; $http_header .= "Connection: close\r\n"; --- 622,633 ---- } ! if ( $url eq '/logout' ) { ! $self->http_redirect_( $client, '/', 'LOGGED-OUT' ); ! return 1; ! } ! ! if ( ( $url eq '/shutdown' ) && ! ( $self->user_global_config_( $self->{sessions__}{$session}{user}, ! 'can_admin' ) ) ) { my $http_header = "HTTP/1.1 200 OK\r\n"; $http_header .= "Connection: close\r\n"; *************** *** 582,586 **** $http_header .= "Expires: 0\r\n"; $http_header .= "Cache-Control: no-cache\r\n"; ! $http_header .= $self->set_cookie__( $session ); $http_header .= "Content-Type: text/html"; $http_header .= "; charset=$self->{language__}{LanguageCharset}\r\n"; --- 635,639 ---- $http_header .= "Expires: 0\r\n"; $http_header .= "Cache-Control: no-cache\r\n"; ! $http_header .= $self->set_cookie__( $session, $client ); $http_header .= "Content-Type: text/html"; $http_header .= "; charset=$self->{language__}{LanguageCharset}\r\n"; *************** *** 701,705 **** } - if ( $color =~ /^([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/ ) { my $bmp = '424d3a0000000000000036000000280000000100000001000000010018000000000004000000eb0a0000eb0a00000000000000000000' . "$3$2$1" . '00'; --- 754,757 ---- *************** *** 793,797 **** # session then clear the cookie ! $http_header .= $self->set_cookie__( $session ); $http_header .= "Content-Type: text/html"; $http_header .= "; charset=$self->{language__}{LanguageCharset}\r\n"; --- 845,849 ---- # session then clear the cookie ! $http_header .= $self->set_cookie__( $session, $client ); $http_header .= "Content-Type: text/html"; $http_header .= "; charset=$self->{language__}{LanguageCharset}\r\n"; *************** *** 1613,1617 **** foreach my $current_mtext (@mtexts) { ! # Skip mangnet definition if it consists only of white spaces if ( $current_mtext =~ /^[ \t]*$/ ) { --- 1665,1670 ---- foreach my $current_mtext (@mtexts) { ! # Skip magnet definition if it consists only of ! # white spaces if ( $current_mtext =~ /^[ \t]*$/ ) { *************** *** 2384,2393 **** if ( defined( $self->{form_}{change} ) ) { ! # Look for all entries in the form of the form ! # reclassify_X and see if they have values, those ! # that have values indicate a reclassification ! # Set up %messages to map a slot ID to the new ! # bucket my %messages; --- 2437,2445 ---- if ( defined( $self->{form_}{change} ) ) { ! # Look for all entries in the form of the form reclassify_X ! # and see if they have values, those that have values indicate ! # a reclassification ! # Set up %messages to map a slot ID to the new bucket my %messages; *************** *** 2423,2429 **** my( $self, $session ) = @_; ! # Look for all entries in the form of the form ! # undo_X and see if they have values, those ! # that have values indicate a reclassification foreach my $key (keys %{$self->{form_}}) { --- 2475,2481 ---- my( $self, $session ) = @_; ! # Look for all entries in the form of the form undo_X and see if ! # they have values, those that have values indicate a ! # reclassification foreach my $key (keys %{$self->{form_}}) { *************** *** 2475,2481 **** # values later on in the function ! $self->{form_}{sort} = $self->{old_sort__} || '-inserted' if ( !defined( $self->{form_}{sort} ) ); ! $self->{form_}{search} = (!defined($self->{form_}{setsearch})?$self->{old_search__}:'') || '' if ( !defined( $self->{form_}{search} ) ); ! $self->{form_}{filter} = (!defined($self->{form_}{setfilter})?$self->{old_filter__}:'') || '' if ( !defined( $self->{form_}{filter} ) ); # If the user hits the Reset button on a search then we need to --- 2527,2533 ---- # values later on in the function ! $self->{form_}{sort} = $self->{sessions__}{$session}{sort} || '-inserted' if ( !defined( $self->{form_}{sort} ) ); ! $self->{form_}{search} = (!defined($self->{form_}{setsearch})?$self->{sessions__}{$session}{search}:'') || '' if ( !defined( $self->{form_}{search} ) ); ! $self->{form_}{filter} = (!defined($self->{form_}{setfilter})?$self->{sessions__}{$session}{filter}:'') || '' if ( !defined( $self->{form_}{filter} ) ); # If the user hits the Reset button on a search then we need to *************** *** 2501,2510 **** # is re-accessed without parameters ! $self->{old_sort__} = $self->{form_}{sort}; ! # We are using a checkbox for negate, so we have to ! # use an empty hidden input of the same name and ! # check for multiple occurences or any of the name ! # being defined if ( !defined( $self->{form_}{negate} ) ) { --- 2553,2561 ---- # is re-accessed without parameters ! $self->{sessions__}{$session}{sort} = $self->{form_}{sort}; ! # We are using a checkbox for negate, so we have to use an empty ! # hidden input of the same name and check for multiple occurences ! # or any of the name being defined if ( !defined( $self->{form_}{negate} ) ) { *************** *** 2513,2517 **** # this is a "clean" access of the history ! $self->{form_}{negate} = $self->{old_negate__} || ''; } elsif ( defined( $self->{form_}{negate_array} ) ) { --- 2564,2568 ---- # this is a "clean" access of the history ! $self->{form_}{negate} = $self->{sessions__}{$session}{negate} || ''; } elsif ( defined( $self->{form_}{negate_array} ) ) { *************** *** 2519,2530 **** if ($_ ne '') { $self->{form_}{negate} = 'on'; ! $self->{old_negate__} = 'on'; last; } } } else { ! # We have a negate form, but no array.. this is likely ! # the hidden input, so this is not a "clean" visit ! $self->{old_negate__} = $self->{form_}{negate}; } --- 2570,2583 ---- if ($_ ne '') { $self->{form_}{negate} = 'on'; ! $self->{sessions__}{$session}{negate} = 'on'; last; } } } else { ! ! # We have a negate form, but no array.. this is likely the ! # hidden input, so this is not a "clean" visit ! ! $self->{sessions__}{$session}{negate} = $self->{form_}{negate}; } *************** *** 2534,2543 **** # Set setsearch if search changed and setsearch is undefined ! $self->{form_}{setsearch} = 'on' if ( ( ( !defined($self->{old_search__}) && ($self->{form_}{search} ne '') ) || ( defined($self->{old_search__}) && ( $self->{old_search__} ne $self->{form_}{search} ) ) ) && !defined($self->{form_}{setsearch} ) ); ! $self->{old_search__} = $self->{form_}{search}; # Set setfilter if filter changed and setfilter is undefined ! $self->{form_}{setfilter} = 'Filter' if ( ( ( !defined($self->{old_filter__}) && ($self->{form_}{filter} ne '') ) || ( defined($self->{old_filter__}) && ( $self->{old_filter__} ne $self->{form_}{filter} ) ) ) && !defined($self->{form_}{setfilter} ) ); ! $self->{old_filter__} = $self->{form_}{filter}; # Set up the text that will appear at the top of the history page --- 2587,2598 ---- # Set setsearch if search changed and setsearch is undefined ! ! $self->{form_}{setsearch} = 'on' if ( ( ( !defined($self->{sessions__}{$session}{search}) && ($self->{form_}{search} ne '') ) || ( defined($self->{sessions__}{$session}{search}) && ( $self->{sessions__}{$session}{search} ne $self->{form_}{search} ) ) ) && !defined($self->{form_}{setsearch} ) ); ! $self->{sessions__}{$session}{search} = $self->{form_}{search}; # Set setfilter if filter changed and setfilter is undefined ! ! $self->{form_}{setfilter} = 'Filter' if ( ( ( !defined($self->{sessions__}{$session}{filter}) && ($self->{form_}{filter} ne '') ) || ( defined($self->{sessions__}{$session}{filter}) && ( $self->{sessions__}{$session}{filter} ne $self->{form_}{filter} ) ) ) && !defined($self->{form_}{setfilter} ) ); ! $self->{sessions__}{$session}{filter} = $self->{form_}{filter}; # Set up the text that will appear at the top of the history page *************** *** 2556,2566 **** # # clearpage is defined: this will delete everything on the page ! # which means we will call delete_slot in the history with the ! # ID of ever message displayed. The IDs are encoded in the ! # hidden rowid_* form elements. # # clearchecked is defined: this will delete the messages that are ! # checked (i.e. the check box has been clicked). The check box ! # is called remove_* in the form_ hash once we get here. # # The third possibility is clearall which is handled below and --- 2611,2621 ---- # # clearpage is defined: this will delete everything on the page ! # which means we will call delete_slot in the history with the ID ! # of ever message displayed. The IDs are encoded in the hidden ! # rowid_* form elements. # # clearchecked is defined: this will delete the messages that are ! # checked (i.e. the check box has been clicked). The check box is ! # called remove_* in the form_ hash once we get here. # # The third possibility is clearall which is handled below and *************** *** 2812,2818 **** } } ! # Replace any entities from the language files with ! # the corresponding character (\xa0). Otherwise HTML::Template ! # would escape the & with & $v =~ s/ /\xA0/g; --- 2867,2876 ---- } } ! ! # Replace any entities from the language ! # files with the corresponding character ! # (\xa0). Otherwise HTML::Template would escape ! # the & with & ! $v =~ s/ /\xA0/g; *************** *** 2903,2907 **** my $header = "HTTP/1.0 302 Found\r\n"; $header .= "Location: $url\r\n"; ! $header .= $self->set_cookie__( $session ); $header .= "\r\n"; --- 2961,2965 ---- my $header = "HTTP/1.0 302 Found\r\n"; $header .= "Location: $url\r\n"; ! $header .= $self->set_cookie__( $session, $client ); $header .= "\r\n"; *************** *** 2942,2947 **** } ! # If a format change was requested for the word matrix, record it in the ! # configuration and in the classifier options. $self->classifier_()->wmformat( $self->{form_}{format} ); --- 3000,3005 ---- } ! # If a format change was requested for the word matrix, record it ! # in the configuration and in the classifier options. $self->classifier_()->wmformat( $self->{form_}{format} ); *************** *** 3069,3086 **** # TODO: This code is now useless because the magnet itself ! # doesn't contain the information about which header we are ! # looking for. Ultimately, we need to fix this but I decided ! # for v0.22.0 release to not make further changes and leave this ! # code as unfixed. # if ( $line =~ /^([A-Za-z-]+): ?([^\n\r]*)/ ) { # my $head = $1; # my $arg = $2; ! # if ( $head =~ /\Q$header\E/i ) { ! # $text =~ s/</</g; # $text =~ s/>/>/g; ! # if ( $arg =~ /\Q$text\E/i ) { # my $new_color = $self->classifier_()->get_bucket_color( $session, $bucket ); --- 3127,3144 ---- # TODO: This code is now useless because the magnet itself ! # doesn't contain the information about which header we ! # are looking for. Ultimately, we need to fix this but I ! # decided for v0.22.0 release to not make further changes ! # and leave this code as unfixed. # if ( $line =~ /^([A-Za-z-]+): ?([^\n\r]*)/ ) { # my $head = $1; # my $arg = $2; ! # # if ( $head =~ /\Q$header\E/i ) { ! # # $text =~ s/</</g; # $text =~ s/>/>/g; ! # # if ( $arg =~ /\Q$text\E/i ) { # my $new_color = $self->classifier_()->get_bucket_color( $session, $bucket ); *************** *** 3279,3290 **** # Localize the template in use. # ! # Templates are automatically localized. Any TMPL_VAR that begins with ! # Localize_ will be fixed up automatically with the appropriate string ! # for the language in use. For example if you write # # <TMPL_VAR name="Localize_Foo_Bar"> # ! # this will automatically be converted to the string associated with ! # Foo_Bar in the current language file. my @vars = $templ->param(); --- 3337,3349 ---- # Localize the template in use. # ! # Templates are automatically localized. Any TMPL_VAR that begins ! # with Localize_ will be fixed up automatically with the ! # appropriate string for the language in use. For example if you ! # write # # <TMPL_VAR name="Localize_Foo_Bar"> # ! # this will automatically be converted to the string associated ! # with Foo_Bar in the current language file. my @vars = $templ->param(); *************** *** 3486,3491 **** # configure_item( 'foo', loaded foo-bar.thtml, language hash ) # ! # and needs to fill the template variables. Then it will receive ! # a call to its # # validate_item( 'foo', loaded foo-bar.thtml, language hash, form hash ) --- 3545,3550 ---- # configure_item( 'foo', loaded foo-bar.thtml, language hash ) # ! # and needs to fill the template variables. Then it will receive a ! # call to its # # validate_item( 'foo', loaded foo-bar.thtml, language hash, form hash ) *************** *** 3584,3589 **** # shutdown_page__ # ! # Determines the text to send in response to a click on the ! # shutdown link. # #---------------------------------------------------------------------------- --- 3643,3648 ---- # shutdown_page__ # ! # Determines the text to send in response to a click on the shutdown ! # link. # #---------------------------------------------------------------------------- *************** *** 3622,3627 **** my $text = $templ->output(); ! # Replace the reference to the favicon, we won't be able ! # to handle that request $text =~ s/<link rel="icon" href="favicon\.ico">//; --- 3681,3686 ---- my $text = $templ->output(); ! # Replace the reference to the favicon, we won't be able to handle ! # that request $text =~ s/<link rel="icon" href="favicon\.ico">//; |