This is irking me. $state preserves information about the request and so on. Now, $r->whatever_method works just fine.. EXCEPT for sending headers. When I visit my site, I get my nifty login page, and that is all. Always the login page.
I telnetted into the thing to see what kinds of cookie strings I was getting back and... NO HEADERS! No Content-type: 's or nothing. $r->send_http_header; must be broken, eh? How to fix?? =P I'll spare all of your eyes by not sending complete source, but here's the basic idea. #!/usr/bin/perl package RequestHandler; use strict; # snipped out a lot of use vars qw();'s and $val = blah. sub handler { my $r = shift; my $result = undef; eval { $result = inner_handler($r) }; return $result unless $@; warn "Uncaught Exception: $@"; return SERVER_ERROR; } sub inner_handler { my $r = shift; my %q = ($r->args, $r->content); my %state = (r => $r, q => \%q); $state{login_user} = ''; $state{login_pass} = ''; $state{title} = ''; $state{template} = ''; $state{auth_status} = password_boxes(\%state); validate_auth_cookie(\%state); my $function = $r->uri; $function = '/login.html' if $state{login_user} eq ''; my $func = $Dispatch{$function} || $Dispatch{DEFAULT}; return $func->(\%state); } sub output_html { my $state = shift; my %args = @_; my $title = $state->{title}; my $r = $state->{r}; $r->status(200); my $template = HTML::Template->new( filename => "$Template_Dir/$state->{template}", die_on_bad_params => 0, ); $template->param(TITLE => $title); eval { foreach (keys %args) { $template->param($_ => $args{$_}); }}; $template->param(ERRORS => $@) if $@; $r->header_out( 'Set-Cookie' => $state->{cookie_out} ) if $state->{cookie_out}; $r->send_http_header('text/html'); print $template->output(); } sub get_password { my $state = shift; my $row = $Sql->select_hashref('DECODE(PWORD,\'blah\')', 'techs', "TECH=\"$state->{ q}->{login_user}\""); return $row->{"DECODE(PWORD,'blah')"}; } sub build_auth_string { my $state = shift; my $ip = shift || $ENV{REMOTE_ADDR}; my $time = shift || time; my $login = $state->{login_user}; my $password = $state->{login_pass}; my $val = join "::", $login, $ip, $password, $time; # Iterate thru by 8 byte hunks. # with the added 8 spaces, do not do the last hunk # which will be all spaces my $blown; my $pos; for ( $pos = 0; (($pos + 8) < length($val) ) ; $pos+=8 ) { $blown .= $cipher->encrypt(substr($val, $pos, 8)); # encrypt this without temp vars } my $enc = encode_base64($blown,""); $enc; } sub parse_auth_string { my $state = shift; my $cookie = shift; return unless $cookie; return if $cookie =~ /logged_out/; my $unenc= decode_base64($cookie); my $unblown; # start at 8, take 8 bytes at a time # $unenc should be exactly a multiple of 8 bytes. my $pos; for ( $pos = 0; $pos<length($unenc); $pos += 8) { $unblown .= $cipher->decrypt(substr($unenc, $pos, 8)); } my ($login, $ip, $password, $time)=split ( /::/, $unblown, 4); } sub get_auth_cookie { my $state=shift; my $cookie = TTMSCGI->parse_cookie($ENV{HTTP_COOKIE})->{ttms_user}; my($login, $ip, $password, $time) = parse_auth_string($state, $cookie); ($login, $ip, $password, $time); } sub set_auth_cookie { my $state = shift; my $val = build_auth_string($state); my $c = TTMSCGI->build_cookie( name => 'ttms_user', value => $val, expires => time + 86400*30*7, domain => $Cookie_Domain, path => '/', ); $state->{cookie_out} = $c; } sub build_logout_cookie { TTMSCGI->build_cookie( name => 'ttms_user', value => "logged_out", expires=> time - 86400, domain => $Cookie_Domain, path => '/' ); } sub set_logout_cookie { my $state = shift; $state->{cookie_out} = build_logout_cookie($state); } sub validate_auth_cookie { my $state = shift; my ($login, $ip, $pass, $time) = get_auth_cookie($state); return unless $login && $pass; my $checkpass = get_password($state); if ($pass eq $checkpass) { $state->{login_user} = $login; $state->{login_pass} = $pass; $state->{auth_status} = "Logged in as $state->{login_user}"; return; } return; }