%# BEGIN BPS TAGGED BLOCK {{{
%# 
%# COPYRIGHT:
%#  
%# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC 
%#                                          <jesse@bestpractical.com>
%# 
%# (Except where explicitly superseded by other copyright notices)
%# 
%# 
%# LICENSE:
%# 
%# This work is made available to you under the terms of Version 2 of
%# the GNU General Public License. A copy of that license should have
%# been provided with this software, but in any event can be snarfed
%# from www.gnu.org.
%# 
%# This work is distributed in the hope that it will be useful, but
%# WITHOUT ANY WARRANTY; without even the implied warranty of
%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
%# General Public License for more details.
%# 
%# You should have received a copy of the GNU General Public License
%# along with this program; if not, write to the Free Software
%# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
%# 
%# 
%# CONTRIBUTION SUBMISSION POLICY:
%# 
%# (The following paragraph is not intended to limit the rights granted
%# to you to modify and distribute this software under the terms of
%# the GNU General Public License and is only of importance to you if
%# you choose to contribute your changes and enhancements to the
%# community by submitting them to Best Practical Solutions, LLC.)
%# 
%# By intentionally submitting any modifications, corrections or
%# derivatives to this work, or any other work intended for use with
%# Request Tracker, to Best Practical Solutions, LLC, you confirm that
%# you are the copyright holder for those contributions and you grant
%# Best Practical Solutions,  LLC a nonexclusive, worldwide, irrevocable,
%# royalty-free, perpetual, license to use, copy, create derivative
%# works based on those contributions, and sublicense and distribute
%# those contributions and any derivatives thereof.
%# 
%# END BPS TAGGED BLOCK }}}
<%INIT>

# Roll back any dangling transactions from a previous failed connection
$RT::Handle->ForceRollback() if $RT::Handle->TransactionDepth;


local *session unless $m->is_subrequest; # avoid reentrancy, as suggested by masonbook

# Disable AutoFlush using an attribute
if ($m->request_comp->attr_exists('AutoFlush')) {
    $m->autoflush($m->request_comp->attr('AutoFlush'));
}

%ARGS = map {
    # if they've passed multiple values, they'll be an array. if they've 
    # passed just one, a scalar whatever they are, mark them as utf8
    my $type = ref($_);
    (!$type)
	? Encode::is_utf8($_) ? $_ : Encode::decode(utf8 => $_, Encode::FB_PERLQQ) :
	($type eq 'ARRAY')
	? [ map { (ref($_) or Encode::is_utf8($_)) ? $_ : Encode::decode(utf8 => $_, Encode::FB_PERLQQ) } @$_ ] :
	($type eq 'HASH')
	? { map { (ref($_) or Encode::is_utf8($_)) ? $_ : Encode::decode(utf8 => $_, Encode::FB_PERLQQ) } %$_ } : $_
    } %ARGS;

$m->{'rt_base_time'} = [Time::HiRes::gettimeofday()];
        
$m->comp('/Elements/SetupSessionCookie', %ARGS);

unless ($session{'CurrentUser'} && $session{'CurrentUser'}->Id) {
    $session{'CurrentUser'} = RT::CurrentUser->new();
}

# Set the proper encoding for the current language handle
$r->content_type("text/html; charset=utf-8");

# If it's a noauth file, don't ask for auth.
if ($m->base_comp->path =~ $RT::WebNoAuthRegex )
{
    $m->call_next(%ARGS);
    $m->abort();
}

# If RT is configured for external auth, let's go through and get REMOTE_USER
elsif ( $RT::WebExternalAuth ) {

    # do we actually have a REMOTE_USER equivlent?
    if ( RT::Interface::Web::WebCanonicalizeInfo() ) {

	my $orig_user = $user;
	
	$user = RT::Interface::Web::WebCanonicalizeInfo();
	$session{'CurrentUser'} = RT::CurrentUser->new();
	my $load_method = $RT::WebExternalGecos ? 'LoadByGecos' : 'Load';
	
	if ($^O eq 'MSWin32' and $RT::WebExternalGecos) {
	    my $NodeName = Win32::NodeName();
	    $user =~ s/^\Q$NodeName\E\\//i;
	}
	
	$session{'CurrentUser'}->$load_method($user);
	
	if ($RT::WebExternalAuto and !$session{'CurrentUser'}->Id() ) {
	    # Create users on-the-fly
	    
	    my $UserObj = RT::User->new(RT::CurrentUser->new('RT_System'));
	    
	    my ($val, $msg) = $UserObj->Create(
					       %{ref($RT::AutoCreate) ? $RT::AutoCreate : {}},
					       Name   => $user,
					       Gecos  => $user,
					       );
	    
	    if ($val) {
		
		# now get user specific information, to better create our user.
		my $new_user_info = RT::Interface::Web::WebExternalAutoInfo($user);
		
		# set the attributes that have been defined.
		# FIXME: this is a horrible kludge. I'm sure there's something cleaner
		foreach my $attribute ('Name', 'Comments', 'Signature', 'EmailAddress',
				       'PagerEmailAddress', 'FreeformContactInfo',
				       'Organization', 'Disabled', 'Privileged',
				       'RealName', 'NickName', 'Lang', 'EmailEncoding',
				       'WebEncoding', 'ExternalContactInfoId',
				       'ContactInfoSystem', 'ExternalAuthId', 'Gecos',
				       'HomePhone', 'WorkPhone', 'MobilePhone',
				       'PagerPhone', 'Address1', 'Address2', 'City',
				       'State', 'Zip', 'Country') {
               $m->comp('/Elements/Callback', %ARGS, _CallbackName => 'NewUser');
		    
		    my $method = "Set$attribute";
		    $UserObj->$method($new_user_info->{$attribute}) 
			if( defined $new_user_info->{$attribute} );
		}	    
		$session{'CurrentUser'}->Load($user);
	    }
	    else {
		# we failed to successfully create the user. abort abort abort.
		delete $session{'CurrentUser'};
		$m->abort() unless $RT::WebFallbackToInternalAuth;
		$m->comp('/Elements/Login', %ARGS, 
			 Error=> loc('Cannot create user: [_1]', $msg));
	    }
	}
	
	unless ( $session{'CurrentUser'}->Id() ) {
	    delete $session{'CurrentUser'};
	    $user = $orig_user;
	    
	    if ( $RT::WebExternalOnly ) {	        
		$m->comp('/Elements/Login', %ARGS, 
			 Error=> loc('You are not an authorized user'));
		$m->abort();
	    }
	}
    }
    elsif ($RT::WebFallbackToInternalAuth) {
  	unless (defined($session{'CurrentUser'})) {
	        $m->comp('/Elements/Login', %ARGS,
                         Error=> loc('You are not an authorized user'));
                $m->abort();
	}
    } else {
	# WebExternalAuth is set, but we don't have a REMOTE_USER. abort
	delete $session{'CurrentUser'} if defined $session{'CurrentUser'};
    }
}

delete $session{'CurrentUser'}
    unless $session{'CurrentUser'} and defined $session{'CurrentUser'}->Id;


# Process per-page authentication callbacks
$m->comp('/Elements/Callback', %ARGS, _CallbackName => 'Auth');

# If the user is logging in, let's authenticate
if (!$session{'CurrentUser'} && defined ($user) && defined ($pass) ){
    $session{'CurrentUser'} = RT::CurrentUser->new();
    $session{'CurrentUser'}->Load($user);

    if (!$session{'CurrentUser'}->id() ||
        !$session{'CurrentUser'}->IsPassword($pass))
    {
        delete $session{'CurrentUser'};
	$RT::Logger->error("FAILED LOGIN for $user from $ENV{'REMOTE_ADDR'}");
        $m->comp('/Elements/Login', %ARGS,
                 Error => loc('Your username or password is incorrect'));
        $m->abort();
    }
    else {
	$RT::Logger->info("Successful login for $user from $ENV{'REMOTE_ADDR'}");
    }
}
  
# If we've got credentials, let's serve the file up.
if ( (defined $session{'CurrentUser'}) and 
     ( $session{'CurrentUser'}->Id) ) {
    
    # Process per-page global callbacks
    $m->comp('/Elements/Callback', %ARGS);

    # If the user isn't privileged, they can only see SelfService
    if ((! $session{'CurrentUser'}->Privileged) and
	($m->base_comp->path !~ '^(/+)SelfService/') ) {
	$m->comp('/SelfService/index.html');
	$m->abort();
    }
    else {
	$m->call_next(%ARGS);
    }
}

# If we have no credentials
else {
    $m->comp('/Elements/Login', %ARGS);
    $m->abort();
}
</%INIT>
<& /Elements/Footer, %ARGS &>
<%ARGS>
$user => undef
$pass => undef
$menu => undef
</%ARGS>
