# ================================================================== # Gossamer Mail - enhanced email management system # # Website : http://gossamer-threads.com/ # Support : http://gossamer-threads.com/scripts/support/ # Revision : $Id: NoAuth.pm,v 1.36 2002/06/14 18:59:42 brewt Exp $ # # Copyright (c) 2001 Gossamer Threads Inc. All Rights Reserved. # Redistribution in part or in whole strictly prohibited. Please # see LICENSE file for full details. # ================================================================== # # Description: Base class for all modules that deal with users that # are not authenticated. # package GMail::NoAuth; # ================================================================== # Pragmas use strict; use vars qw/@ISA @ISA/; # Internal modules use GMail qw{:all}; # Globals @ISA = qw{GMail}; sub print_page { # ------------------------------------------------------------------------------------ # This method prints a template page. Any template printed by this have to be prefixed # by either login or join. This method gets the tags from the get_tags() method to be # inserted in the template. The first argument to this method is the file to parse and # print. The rest of the arguments are treated as tags to be passed to GT::Template # which takes an array of hashes as tags. # my ($self, $file, @opts) = @_; if (!ref $self) { $self = $self->new } # If we have cookie header to print print them print $IN->header; my $t = $self->template_set; # Only templates in the join directory can be printed my $base = "$CFG->{location}->{path}->{data}/templates/$t"; ($file =~ /^join/ or $file =~ /^login/ or $file =~ /^error/ or $file eq 'style.css') or return $self->disp_error('PAGEERR', $file); require GT::Template::Inheritance; my $tpl = GT::Template::Inheritance->get_path( file => $file, path => $base, use_local => 1, use_inheritance => 1 ); $tpl or return $self->disp_error('PAGEERR', $file); unshift @opts, $self->get_tags(); require GT::Template; GT::Template->parse("$base/$file", \@opts, { escape => 1, $IN->param('stream') ? 'stream' : 'print' => 1, # See if we should stream or not (pop_stream and header needs to stream). func_code => \&GMail::tpl_func_handler, debug_level => $CFG->{debug} }); } sub get_tags { # ------------------------------------------------------------------------------------ # Returns a very basic set of tags. Any arguments are included in the tages returned. # Remember that arguments passed in should be hash references. # my ($self, @opts) = @_; my $t = $self->template_set; # Template we are on and if the browser supports the editor my $version; if ($ENV{HTTP_USER_AGENT} and $ENV{HTTP_USER_AGENT} =~ /MSIE (\d+(?:\.\d+)?)/i) { $version = $1; } unshift @opts, { template => $t, t => $t, is_ie5 => ($version and $version >= 5.5) ? 1 : 0 }; # Config Options my $cfg = {}; for (keys %{$CFG->{location}->{url}}) { $cfg->{'url_' . $_} = $CFG->{location}->{url}->{$_}; } for (keys %{$CFG->{limits}}) { $cfg->{'limits_' . $_} = $CFG->{limits}->{$_}; } # What pop mode we are using. $cfg->{account_mode} = ($CFG->{email}->{pop} eq 'shared_pipe') ? 'shared_pop' : $CFG->{email}->{pop}; $cfg->{join_lost_password} = $CFG->{join}->{lost_password}; $cfg->{join_verify_email} = $CFG->{join}->{verify_email}; $cfg->{admin_email} = $CFG->{email}->{admin}; $cfg->{sessions_cookies} = $CFG->{sessions}->{cookies}; unshift @opts, $cfg; # Add any admin global vars if (exists $CFG->{globals}) { my $c = {}; for my $k (keys %{$CFG->{globals}}) { my $v = $CFG->{globals}->{$k}; if (ref $v) { $c->{$k} = $v; } else { $c->{$k} = \$v; } } unshift @opts, $c; } # Folders unshift @opts, { INBOX => INBOX, SENT => SENT, TRASH => TRASH }; # Add the CGI object last so all other vars can # override it. unshift @opts, $IN; if ($IN->param('username') and $IN->param('domain')) { unshift @opts, { email => $IN->param('username') . '@' . $IN->param('domain') }; } unshift @opts, { confirm => ($IN->param('confirm') || '') }; return @opts; } sub auth_failed { # ------------------------------------------------------------------------------------ # When authentication fails this function is called to print the page. The page # printed is the one in the config file for auth_error. CGI input is turned into a # set of hidden fields and passed to the error page as var hidden. This makes it # possible for a user to go back to the page they were trying to goto after # authenticating. This WILL BREAK for file uploads. It will proabably result # in an attachment with 0 size. # my ($self) = @_; my $hidden; for ($IN->param) { next if $_ eq 'password' or $_ eq 'username' or $_ eq 'user' or $_ eq 'domain' or $_ eq 't'; $hidden .= q{\n}; } $self->print_page($CFG->{templates}->{auth_error}, { error => $GMail::Auth::error, hidden => \$hidden }); return; } sub parse_params { # ------------------------------------------------------------------------------------ # Checks params for do= and page=. If a page is found that page is printed nd returns # 0, same goes for a function. This gives very limited access to pages and # functions. Returns 1 if handled and 0 if not. # my ($self) = @_; # If we are called with do param do the function specified # Limited ability to call functions my ($print_it, @tags); if ($IN->param('do')) { my $message; for ($IN->param('do')) { next unless $_; my ($page, $tags) = $self->do_func($_) or return; if ($tags and $tags->{message} and !$message) { $message++; } elsif ($message) { delete $tags->{message}; } push @tags, $tags if $tags; $print_it = $page if $page and not $print_it; } } if ($print_it) { $self->print_page($print_it, @tags); return; } elsif (my $page = $IN->param('page')) { $self->print_page($IN->param('page'), @tags); return; } return 1; } sub do_func { # ------------------------------------------------------------------------------------ # Runs a function specified by do=, The function ran by this has to be in the NoAuth # set of modules. # my ($self, $do) = @_; my ($module_key, $function); if (($do =~ /^(\w+-)(\w+)$/) or ($do =~ /^((?:\w+-)+)(\w+)$/)) { ($module_key, $function) = ($1, $2); chop $module_key; } else { return $self->disp_error('FUNCERR', $do); } if (exists $CFG->{modules}->{$module_key} and $CFG->{modules}->{$module_key} =~ m,/NoAuth,) { require $CFG->{modules}->{$module_key}; } else { return $self->disp_error('FUNCERR', $do); } # Get the class and find out if the function can be called. ($self = $CFG->{modules}->{$module_key}) =~ s,/,::,g; substr($self, index($self, '.')) = ''; if (exists $CFG->{states}->{$self}->{$function}) { my $set = $CFG->{states}->{$self}->{$function}; my ($ret, @args) = $PLG->dispatch("$self\::$function", sub { $self->$function() }); my $tags = {}; my $page; # Error state if (!$ret) { no strict 'refs'; $tags->{error} = ref (${$self . '::error'}) ? ${$self . '::error'} : \${$self . '::error'}; # Find the page we are going to display $page = $IN->param('error_page'); $page = ref($page) ? $page->[0] : $page; my @err = ([], []); if (ref($set->[FUNCTION_ERROR])) { @err = @{$set->[FUNCTION_ERROR]}; } if ($page) { shift @err } elsif ($err[0]) { $page = shift @err } while (@err) { my ($k, $v) = (shift @err, shift @err); next unless ($k and $v); $tags->{$k} = $v; } $self->print_page($page, $tags); return; } # Success state elsif (ref $ret eq 'HASH') { @{$tags}{keys %{$ret}} = (values %{$ret}); if (exists $tags->{message}) { my $msg = $tags->{message}; if (exists $CFG->{language}->{$tags->{message}}) { $msg = sprintf($CFG->{language}->{$tags->{message}}, @args); } $tags->{message} = ref($msg) ? $msg : \$msg; } elsif (exists $tags->{message}) { } $page = $IN->param('page'); $page = ref($page) ? $page->[0] : $page; my @suc = ([], []); if (ref($set->[FUNCTION_SUCCESS])) { @suc = @{$set->[FUNCTION_SUCCESS]}; } if ($page) { shift @suc } elsif ($suc[0]) { $page = shift @suc } while (@suc) { my ($k, $v) = (shift @suc, shift @suc); next unless ($k and $v); $tags->{$k} = $v; } } return ($page, $tags); } else { return $self->disp_error('FUNCERR', $do); } return 1; } sub disp_error { # -------------------------------------------------------------------- # $self->disp_error('ERROR_CODE', @args); # --------------------------------------- # This method prints the error page using the default user error # template page. The error code passed in is looked up in the # language hash and sprintf with any arguments. This method # always returns false. # my ($self, $msg, @args) = @_; ref $self or $self = $self->new; $self->error("No default error page") if $self->{tpl_safety}++ > 10; $msg = $CFG->{language}->{$msg} if (exists $CFG->{language}->{$msg}); $msg = sprintf($msg, @args) if (@args); # Try to default to the passed in error_page and fall back to the auth error page my $error_page = $IN->param('error_page') || $CFG->{templates}->{auth_error}; $error_page = $CFG->{templates}->{auth_error} if ($self->{tpl_safety} > 1); $self->print_page($error_page, { error => \$msg }); return; } 1;