#!/usr/bin/perl -Tw -I. -I/usr/local/positive/Perl

use strict;
use Pos::Web::Client;
use Pos::web;
use Digest::MD5;
use Pos::Webtop::Auth;
use Pos::Webtop::Toolbox;
#use warnings;
#use Apache2::Cookie();
use APR::Request::Cookie;

package Pos::Webtop::Web::Client;

our @ISA = qw(
	Pos::Web::Client
);

sub new 
{
	my $this = shift;
	my $class = ref($this) || $this;
	my ($self,$db) = @{{@_}}{qw/self db/};

	if ( not defined $self )
	{
		$self = {};
		bless($self,$class);
	}

	if ( not defined $db )
	{
		warn ref($self) . "::setup(): db was undef\n";
		return undef;
	}

	$self->{'webtopDb'} = $db;
	$self->{'expired'}  = 0;
	$self->{'trialExpired'} = 0;
	$self->{'challenge'} = '';

	# setup base class
	Pos::Web::Client->new( self=> $self );

	$self->setupSession();

	return $self;	
}

sub clearSession
{
	my $self = shift;

	$self->setPersistedValue( name=> "wsi", value=> undef );
	$self->setPersistedValue( name=> "wsh", value=> undef );
}

sub setupSession
{
	my $self = shift;
	my $db = $self->{'webtopDb'};

	#$self->{'persist'} = 0;
	#$self->{'userId'} = undef;
	#$self->{'sessionId'} = undef;
	#$self->{'sessionHash'} = undef;
	#$self->{'restrictionSetId'} = undef;

	# delete old sessions
	#$self->cleanupExpiredSessions();

	# find em from persisted 

	# Try to use cookies first, then fallback to CGI parameters.
	my $wsi = $self->getCookie(name => 'wsi');
	if (defined($wsi))
	{
		$self->setPersistedValue(name => "wsi", value => undef);
	}
	else
	{
		$wsi = $self->getPersistedValue( name=> "wsi" );

		# We need to re-persist our session hash and identifier.
		$self->{'persist'} = 1;
	}

	if ( defined($wsi) && length($wsi) )
	{
		$self->{'sessionId'} = Pos::web::digitize( dirty=> $wsi );
	}
	else
	{
		return; # there's not a session to setup!
	}

	# Try to use cookies if a persisted value isn't defined
	my $wsh = $self->getCookie(name => "wsh");
	if ( defined($wsh) && length($wsh) )
	{
		$self->setPersistedValue(name => "wsh", value => undef);
	}
	else
	{
		$wsh = $self->getPersistedValue( name=> "wsh" );
	}

	$self->{'sessionId'} = $wsi;
	$self->{'sessionHash'} = $wsh;

	my @si;
	
	if( (defined($self->{'sessionId'}) && length($self->{'sessionId'})) &&
		 (defined($self->{'sessionHash'}) && length($self->{'sessionHash'})))
	{
		# now we verify that it is a valid session .. 
		@si = $db->query( sql=> "
			select 
				user_id 
			from 
				client_sessions
			where 
				client_session_id = " . $db->escape( dirty=> $self->{'sessionId'} ) . "
				and
				upper(client_session_hash) = '" . $db->escape( dirty=> uc($self->{'sessionHash'}) ) . "'
		");
	}

	if( scalar( @si ) == 0 ) {
		my $raddr = $ENV{'REMOTE_ADDR'};

		( @si ) = $db->query( sql=> "
					SELECT user_id
					FROM client_sessions
					WHERE rawip32_to_dotted_quad(public_ip_address) = '$raddr'
					");
	}

	if ( @si )
	{
		# good session, save and persist, touch db
		
		$self->{'userId'} = $si[0];

		if ($self->{'persist'})
		{
			$self->setPersistedValue( name=> "wsi", value=> $self->{'sessionId'} );
			$self->setPersistedValue( name=> "wsh", value=> $self->{'sessionHash'} );
		}

		$db->do( sql=> " update client_sessions set touch_time = " . $db->getCurrentTimeStampString() .
				" where client_session_id = '" . $db->escape( dirty=> $self->{'sessionId'} ) . "'" );
	
	}
	else
	{
		# in the future, we will be checking cookies to give a 2nd chance
		# no session or bad, undef sessionId and sessionHash

		$self->{'sessionId'} = undef;
		$self->{'sessionHash'} = undef;

		$self->setPersistedValue( name=> "wsi", value=> $self->{'sessionId'} );
		$self->setPersistedValue( name=> "wsh", value=> $self->{'sessionHash'} );
	}

	$db->commit();
}

sub getUserName
{
	my $self = shift;
	my $db = $self->{'webtopDb'};
	my $userId = $self->getUserId();
	$userId = $self->getUserIdDB( db=> $db ) unless( length( $userId ) );
	my $userName;

	#if (defined $self->getUserId())
	#{
	if( length( $userId ) ) {
		($userName) = $db->query(sql => "	
						select 
							user_name
						from 
							users
						where 
							user_id = $userId 
					");
	}

	return $userName if defined $userName;
	return undef;
}

sub getCustomerId
{
	my $self = shift;
	my $db = $self->{'webtopDb'};

	if ( exists $self->{'customerId'} )
	{
		return $self->{'customerId'};
	}

	if ( not defined $self->{'userId'} )
	{
		return undef;
	}

	($self->{'customerId'}) = $db->query( sql => "
		SELECT
			customer_id
		FROM
			groups
		WHERE
			group_id = (
				SELECT
					group_id
				FROM
					users
				WHERE
					user_id = " . $self->{'userId'} . "
			)
	");

	return $self->{'customerId'};
}

sub getPwd 
{
	 my $self = shift;	
	 return $self->{'passwd'};
}

sub createSession
{
	my $self = shift;
	my ($userId, $userName, $passwd, $uslId, $a, $z, $isL2tp) = @{{@_}}{qw/userId userName passwd uslId a z isL2tp/};
	my $isExpired = 0;
	my $trialExpired = 0;
	my $challenge = '';
	$isL2tp = 0 unless( defined( $isL2tp ) && length( $isL2tp ) > 0 );
	my $db = $self->{'webtopDb'};
	
	$self->{'userId'} = $userId;
	$self->{'userName'} = $userName;
	$self->{'passwd'} = $passwd;
	$self->{'uslId'} = $uslId;
	$self->{'a_param'} = $a;
	$self->{'z_param'} = $z;
	# Create the database hashes and what not.

	$self->createSessionHashes( isL2tp=> $isL2tp );

	# persist the values also
	if ($self->{'persist'} )
	{
		$self->setPersistedValue( name=> "wsi", value=> $self->{'sessionId'} );
		$self->setPersistedValue( name=> "wsh", value=> $self->{'sessionHash'} );
	}

	$db->commit();
}

sub createInitializedSession 
{
	my $self = shift;
	my ($userId, $customerId, $launcherSession) = @{{@_}}{qw/userId customerId launcherSession/};

	$self->{'userId'}     = $userId;
	$self->{'customerId'} = $customerId;

	$self->createSessionHashes(launcherSession=> $launcherSession, isL2tp=> 0 );

	return 1;
}

sub createSessionHashes {
	my $self = shift;
	my ($launcherSession, $isL2tp) = @{{@_}}{qw/launcherSession isL2tp/};
	my $confidenceOnlinePassed = 0;
	my $newSessionId = 0;

	$isL2tp = 0 unless( defined( $isL2tp ) && length( $isL2tp ) );
	my $db = $self->{'webtopDb'};

	# Create id
	if( $isL2tp == 0 ) {
		($newSessionId) = $db->getNextSequenceValue( sequence => "client_sessions_pk");
		$self->{'sessionId'} = $newSessionId;
	
		# Create hash
		my $randStuff = rand(2**32) . rand(2**32); # two random numbers under 4 gig
		my $md5 = Digest::MD5->new();
		$md5->add( $randStuff );
		$self->{'sessionHash'} = $md5->hexdigest();
	} 
	else {
		my( @clientSession ) = $db->query( sql=> "
							SELECT client_session_id, client_session_hash
								FROM client_sessions
								WHERE client_session_type_id IN (1,4) AND user_id = " . $self->{'userId'} 
						);

		my( $sessionId, $sessionHash ) = @{ $clientSession[0] };

		$self->{'sessionId'} = $sessionId;
		$self->{'sessionHash'} = $sessionHash;
	}

	# Get remote address
	my $raddr = $ENV{'REMOTE_ADDR'};
	$raddr =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/;
	$raddr = "$1.$2.$3.$4";

	my $anxS = 0;

	if ($self->{'uslId'})
	{
		($anxS) = $db->query( sql => "
			select
				anx_session_id
			from
				anx_portal_sessions
			where
				anx_session_id = '" . $db->escape( dirty => $self->{'uslId'} ) . "'
			");
	}

	my $ssoPass;
	
	if ($anxS)
	{
		($ssoPass) = $db->query( sql => "
				select
					single_sigon_password
				from
					anx_portal_sessions
				where
					anx_session_id = " . $db->escape( dirty => $self->{'uslId'} ) . "
			");
		
		$db->do( sql => "
			update anx_portal_sessions
				set
					client_session_id = $newSessionId,
					client_session_hash = '" . $self->{'sessionHash'} . "',
					a_param = '" . $db->escape( dirty => $self->{'a_param'} ) . "',
					z_param = '" . $db->escape( dirty => $self->{'z_param'} ) . "'
				where
					anx_session_id = " . $db->escape( dirty => $self->{'uslId'} ) . "
			");
	}
	else
	{
      my ($cnt) = $db->query(sql=> "
         select count(hook_id) from w_user_single_signon_hooks
         where user_id = " . $self->{'userId'} . "");

      if ($cnt)
      {
            $ssoPass = $self->{'passwd'};
      }

	}

	if( ! $isL2tp ) {
		$db->do( sql=> "
			insert into client_sessions (
				client_session_id,
				client_session_hash,
				client_session_type_id,
				user_id,
				touch_time,
				connect_date,
				public_ip_address,
				single_signon_password
			) values (
				$newSessionId,
				'" . $self->{'sessionHash'} . "',
				1,
				" . $self->{'userId'} . ",
				" . $db->getCurrentTimeStampString() . ",
				" . $db->getCurrentTimeStampString() . ",
				dotted_quad_to_rawip32('$raddr'),
				'" . $db->escape( dirty => $ssoPass ) . "'
			)
		");
	}
}

sub setRestrictionSetId
{
	my $self = shift;
	my ($tb) = @{{@_}}{qw/tb/};

	if ( !defined($self->getRestrictionSetId()) || !length($self->getRestrictionSetId()) )
	{
		$self->{'restrictionSetId'} = $self->checkActiveRestrictionSetId(tb=> $tb);
		#$self->logger( severity=>'NORMAL', logMessage=>"WEBTOP Client: Setting restriction set id to $self->{'restrictionSetId'} " );
	}
	else
	{
		#$self->logger( severity=>'NORMAL', logMessage=>"WEBTOP Client: Restriction set id is $self->{'restrictionSetId'} " );
	}

	return $self->{'restrictionSetId'};
}

sub getRestrictionSetId
{
	return shift->{'restrictionSetId'};
}

sub checkActiveRestrictionSetId
{
	my $self = shift;
	my ($tb, $userId) = @{{@_}}{qw/tb userId/};

	# we now need to check if they have been assigned a restriction set...
	my $cdb = $tb->getWebtopDbReader();
	my $wsi = $self->getSessionId();

	$userId = $self->getUserId() unless( length( $userId ) );
	$userId = $self->getUserIdDB( db=> $cdb ) unless( length( $userId ) );

	my $activeRestrictionSetId = 0;

	if( length( $wsi ) ) {
		($activeRestrictionSetId) = $cdb->query( sql=> "select restrict_set_id from client_sessions
					where client_session_id = '" . $cdb->escape( dirty=> $wsi ) . "'
			");
	}
	elsif( length( $userId ) ) {
		($activeRestrictionSetId) = $cdb->query( sql=> "
							SELECT restrict_set_id 
							FROM client_sessions
							WHERE user_id = $userId
								AND client_session_type_id IN (1,4)
						" );
	}

	if ( !defined($activeRestrictionSetId) || !length($activeRestrictionSetId) )
	{
		# the second thing we try is to call the external program that determines the restriction set
		# for us based on a web session.
		
		my $oldPath = $ENV{'PATH'};
		$oldPath = "" unless defined $oldPath;
		my $oldLd = $ENV{'LD_LIBRARY_PATH'};
		$oldLd = "" unless defined $oldLd;
		$ENV{'PATH'} = "/bin:/usr/bin"; # we need no path!
		$ENV{'LD_LIBRARY_PATH'} = "/usr/local/positive/Library:$oldLd";
		my $wsiClean = $wsi;

		$wsiClean =~ s/(\W)/\\$1/g;
		my $command = "/usr/local/positive/Binary/WebtopDetermineActiveRestrictSetId $wsiClean";
		
		$command =~ /^(.*)$/;
		$command = $1;

		$activeRestrictionSetId = `$command`;
		$ENV{'PATH'} = $oldPath;
		$ENV{'LD_LIBRARY_PATH'} = $oldLd;
		chomp $activeRestrictionSetId;

		if ( not ( defined($activeRestrictionSetId) && length($activeRestrictionSetId) && $activeRestrictionSetId =~ /^\d+$/
			&& $activeRestrictionSetId ne "0" ) )
		{
			$activeRestrictionSetId = undef;
		}

		#$self->logger( severity=>'NORMAL', logMessage=>"WEBTOP Client: Tried the helper command for active restrict set id..." );

		if ( not defined $activeRestrictionSetId )
		{
			$self->logger( severity=>'ERROR', logMessage=>"WEBTOP Client: Could not determine the restriction set id to use for this session, giving up!" );
			exit(1);
		}

		# now we update the current restriction set id

		my $db = $tb->getWebtopDbWriter();
		#$db->do( sql=> "update client_sessions set restrict_set_id = $activeRestrictionSetId
		#	where client_session_id = $wsi and activex_disabled = '1'" );

		$db->do( sql=> "
				UPDATE client_sessions 
					SET restrict_set_id = $activeRestrictionSetId
					WHERE client_session_id = $wsi"
				 );

		$db->commit();

		#$self->logger( severity=>'NORMAL', logMessage=>"WEBTOP Client: using restriction set $activeRestrictionSetId" );
	}

	return $activeRestrictionSetId;
}

sub usingOcx
{
	my $self = shift;
	my ($tb) = @{{@_}}{qw/tb/};
	my $db = $tb->getWebtopDbWriter();

	my $webSessionId = $self->getSessionId();
	$webSessionId =~ /^(\d+)$/;
	$webSessionId = $1;

	$db->do(sql => "
		update
			client_sessions
		set
			activex_disabled = 0
		where
			client_session_id = '$webSessionId'");
	$db->commit();

}

sub notUsingOcx
{
	my $self = shift;
	my ($tb) = @{{@_}}{qw/tb/};
	my $db = $tb->getWebtopDbWriter();

	my $webSessionId = $self->getSessionId();
	$webSessionId =~ /^(\d+)$/;
	$webSessionId = $1;

	$db->do(sql => "
		update
			client_sessions
		set
			activex_disabled = 1 
		where
			client_session_id = '$webSessionId'");
	$db->commit();

}

# Checks to see if the OCX is required.  If it is not, the page may redirect
# to the main.pl when it fails to load.
sub isOcxRequired
{
	my $self = shift;
	my ($tb, $ocxFailed, $userId) = @{{@_}}{qw/tb ocxFailed userId/};
	my $db = $tb->getWebtopDbWriter();
	my $rid;

	$userId = $self->getUserId() unless( length( $userId ) );
	$userId = $self->getUserIdDB( db=> $db ) unless( length( $userId ) );

	# If the ocx failed, flag that in the database
	if ($ocxFailed)
	{
		my $webSessionId = $self->getSessionId();
		$webSessionId =~ /^(\d+)$/;
		$webSessionId = $1;

		if( length( $webSessionId ) ) {
			$db->do(sql => "
				update
					client_sessions
				set
					activex_disabled = 1
				where
					client_session_id = '$webSessionId'");
		}
		elsif( length( $userId ) ) {
			$db->do(sql => "
				UPDATE
					client_sessions
				SET
					activex_disabled = 1
				WHERE
					user_id = $userId
					AND client_session_type_id IN (1,4)
				" );
		}

		$db->commit();
	}

	$rid = $self->checkActiveRestrictionSetId(tb => $tb, userId=> $userId);
	
	# If any of the following captive portal deciders has an entry for this user and this restriction set
	# we must assume that the ActiveX control is required.  If the admin did not want to require portalization
	# for this user he would create a restriction set tab that had these requirements set to no.
	my ($isRequired) = $db->query(sql => "
		select
			1
		" . ((Pos::defaults::isPostgresDb()) ? "" : " from dual ") . "
		where
			((
				select enforce	
				from user_virus_enforce
				where
					user_id = $userId
					and restrict_set_id = '$rid'
			) = 1 AND
			(
				select enforce
				from w_user_enforce_antivirus
				where
					user_id = $userId
					and enforce = 1
			) = 1) OR
			((
				select require_distribute
				from user_spyware_enforce
				where
					user_id = $userId
					and restrict_set_id = '$rid'
			) = 1 AND
			(
				select enforce
				from w_user_enforce_spyware
				where
					user_id = $userId
					and enforce = 1
			) = 1) OR
			((
				select is_required
				from user_critical_updates_required
				where
					user_id = $userId
					and restrict_set_id = '$rid'
			) = 1 AND
			(
				select enforce
				from w_user_enforce_crit_updates
				where
					user_id = $userId
					and enforce = 1
			) = 1) OR
			((
				select enforce
				from w_user_enforce_appdist
				where
					user_id = $userId
					and enforce = 1
			) = 1 AND
			(
				select enforce
				from user_appdist_enforce
				where
					user_id = $userId
					AND restrict_set_id = $rid
			) = 1)
		");

	$isRequired = 0 if (not defined($isRequired));

	#$self->logger( severity=>'NORMAL', logMessage=>"WEBTOP Client: OCX is" . ($isRequired ? "" : " not") . " required, using rid $rid" );
	#$self->logger( severity=>'NORMAL', logMessage=>"WEBTOP Client: Plugin-in is" . ($isRequired ? "" : " not") . " required, using rid $rid" );

	return $isRequired;

#	my $agent = $ENV{'HTTP_USER_AGENT'};
#	my $required = 1;
#
#	if (!($agent =~ /MSIE/)) {
#		$required = 0;
#	}
#
#	return $required;
#	return 0; # Right now, as there is no policy, we do not require the ActiveX control to load for ANY browser.
}

# 
# Checks to see if a session is captive portalized
#
# First, it checks to see if the session should be worry about
# being captive portalized
#
sub isCaptivePortalized
{
	my $self = shift;
	my ($tb) = @{{@_}}{qw/tb/};
	my $requiresCaptivePortal = 1;
	my $portalized = 1;
	my $db = $self->{'webtopDb'};
	my $sessionId;
	my $agent = $ENV{'HTTP_USER_AGENT'};

	# Use the isOcxRequired method to tell us whether or not we need to use the captive portal
	$requiresCaptivePortal = $self->isOcxRequired(tb => $tb);
	warn "RP - Client.pm - requiresCaptivePortal = $requiresCaptivePortal\n";

	# If captive portal is not required for this session, return that the session
	# is not captive portalized.
	if (!$requiresCaptivePortal) 
	{
		return 0;
	}

	# Now check to see if the session really is captive portalized
	$sessionId = $db->escape(dirty => $self->{'sessionId'});

	if (defined($sessionId))
	{
		my ($numPortals) = $db->query(sql => "
			select
				count(*)
			from
				captive_portalized cs,
				client_sessions us
			where
				cs.user_id = us.user_id
				AND cs.computer_id = us.computer_id
				AND us.client_session_id = '" . $db->escape( dirty=> $sessionId ) . "'
			");

		# If the query returns no rows, the session is not portalized.
		if (not defined($numPortals) or $numPortals == 0) 
		{
			$portalized = 0;
		}
		else
		{
			$portalized = 1;
		}
	}
	else
	{
		# XXX: Re-evalulate this -- should a user be let out of the captive
		#      portal if their user session identifier cannot be determined?
		#      This seems like a job for restriction sets.
		$portalized = 0;
	}

	if ($portalized)
	{
		#$self->logger( severity=>'NORMAL', logMessage=>"WEBTOP SECURITY CHECKS: User is captive portalized" );
	}

	return $portalized;
}

sub isLauncherSession
{
	return 0;
}

#
# Checks to see if a user's password is expired after they have authenticated.
# A better way to implement this would be to have the radius server return whether or
# not the password was expired.
#
sub isPasswordExpired
{
	my $self = shift;
	return $self->{'expired'};
}

sub isTrialExpired
{
	my $self = shift;
	return $self->{'trialExpired'};
}

sub challenge
{
	my $self = shift;
	return $self->{'challenge'};
}

sub requiredToChangePassword
{
	my $self = shift;
	my $db = $self->{'webtopDb'};
	my $pwResetRequired;
	
	if ($self->{'userId'})
	{
		my ($authType) = $db->query( sql=> "
			select 
				upper(auth_type_name)
			from
				auth_types at,
				user_auth_types uat
			where
				at.auth_type_id = uat.auth_type_id
				and user_id = '$self->{'userId'}' 
		");

		if ($authType ne 'SECURID' && $authType ne 'PHONEFACTOR - SECURID')
		{
			if (!$self->{'expired'})
			{
				($pwResetRequired) = $db->query( sql => "
					select
						ext_password_expired
					from
						users
					where
						user_id = '$self->{'userId'}'
				");
			}
		}

		$pwResetRequired and $self->{'expired'} = 1;
	}

	return $self->{'expired'};
}

sub getUserIdDB
{
	my $self = shift;
	my $clientSessionId = $self->{'sessionId'};
	my $userId = $self->{'userId'};

	my( $db ) = @{{@_}}{qw/db/};

	my $sql;
	#my $userId = 0;

	if( ! length( $userId ) )  {
		if( length( $clientSessionId ) ) {
			$sql = "SELECT user_id FROM client_sessions WHERE client_session_id = "	. $clientSessionId . " AND client_session_type_id IN (1,4)";
		}
		else {
			my $raddr = $ENV{'REMOTE_ADDR'};
			$sql = "SELECT user_id FROM client_sessions WHERE rawip32_to_dotted_quad(public_ip_address) = '$raddr' AND client_session_type_id IN (1,4)";
		}

		if( defined( $db ) ) {	
			($userId) = $db->query( sql=> $sql );
		}
		else {
			warn "DEBUG: getUserIdDB(): No DB handle\n";
		}
	}

	return( $userId );
}

sub getUserId
{
	return shift->{'userId'};
}

# warning, setUserId should only be used when you want
# to forge a client object for backend scripts and arne't
# really online in the webtop
sub setUserId
{
	my $self = shift;
	my ($userId) = @{{@_}}{qw/userId/};
	$self->{'userId'} = $userId;
}

sub getSessionParams
{
	my $self = shift;

	if ($self->{'persist'})
	{
		return "pVwsi=" . HTML::Entities::encode($self->getSessionId()) . 
		       "&pVwsh=" . HTML::Entities::encode($self->getSessionHash());
	}
	else
	{
		return "";
	}
}

sub getSessionId
{
	return shift->{'sessionId'};
}

sub getSessionHash
{
	return shift->{'sessionHash'};
}

# we override the base class getFormGetCode and getFormInputs to do the following:
# if not persist, then we manually tack on the session vars that MUST be sent
# for the Pos::Webtop::Web::Client object.  We then call the base class methods
# based on that logic.

sub getFormGetCode
{
	my $self = shift;
	my ($persist,$values) = @{{@_}}{qw/persist values/};
	
	# base class says that it is true by default, so we do that also
	$persist = 1 unless defined $persist;

	if ( not $persist )
	{
		my %args = @_; # this is the callers param list (copy)

		# we need to call base class method with our stuff tacked on
		# note that we will make a copy and replace their parameter with ours...
		# if we just modified the $values refed hash, we might screw up the calling
		# context's data.

		# We only do this if we need to persist the session information.

		if ($self->{'persist'})
		{
			my $persistPrefix = $self->getPersistPrefix();
			
			my $newValues = [
				{
					name=> $persistPrefix . "wsi",
					value=> $self->{'sessionId'}
				},
				{
					name=> $persistPrefix . "wsh",
					value=> $self->{'sessionHash'}
				}
			];
	
			# put their values in with ours... 
			push @{ $newValues }, @{ $values };
			
			# modify our copy of the args and replace the values hash entry
			# with our new values list...
			$args{'values'} = $newValues;
		}
		else
		{
			$args{'values'} = $values;
		}

		# now call the base class method with new args hash
		return $self->Pos::Web::Client::getFormGetCode( %args );
	}
	else
	{
		# just call base class method since we persisted the wsi and wsh vars
		return $self->Pos::Web::Client::getFormGetCode(@_);
	}
}

sub getFormInputs
{
	my $self = shift;
	my ($persist,$values) = @{{@_}}{qw/persist values/};
	
	# base class says that it is true by default, so we do that also
	$persist = 1 unless defined $persist;

	if ( not $persist )
	{
		# we need to call base class method with our stuff tacked on
		# note that we will make a copy and replace their parameter with ours...
		# if we just modified the $values refed hash, we might screw up the calling
		# context's data.
		
		my $persistPrefix = $self->getPersistPrefix();

		my %args = @_; # this is the callers param list (copy)

		my $newValues = [
			{
				name=> $persistPrefix . "wsi",
				value=> $self->{'sessionId'}
			},
			{
				name=> $persistPrefix . "wsh",
				value=> $self->{'sessionHash'}
			}
		];

		# put their values in with ours... 
		push @{ $newValues }, @{ $values };
		
		# modify our copy of the args and replace the values hash entry
		# with our new values list...
		$args{'values'} = $newValues;

		# now call the base class method with new args hash
		return $self->Pos::Web::Client::getFormInputs( %args );
	}
	else
	{
		# just call base class method since we persisted the wsi and wsh vars
		return $self->Pos::Web::Client::getFormInputs(@_);
	}
}

sub checkSession
{
	my $self = shift;
	my ($ignoreAuxAuth, $forceReturn, $userId) = @{{@_}}{qw/ignoreAuxAuth forceReturn userId/};
	my $db     = $self->{'webtopDb'};
	my @si;
	my @badAuxAuths;

	$userId = $self->getUserId() unless( length( $userId ) );
	$userId = $self->getUserIdDB( db=> $db ) unless( length( $userId ) );

	$userId = 0 unless defined($userId);
	$ignoreAuxAuth = 0 unless defined( $ignoreAuxAuth );
	$forceReturn = 0 unless defined( $forceReturn );

	if( (defined($self->{'sessionId'}) && length($self->{'sessionId'})) &&
		 (defined($self->{'sessionHash'}) && length($self->{'sessionHash'})))
	{
		# now we verify that it is a valid session .. 
		@si = $db->query( sql=> "
			select 
				user_id 
			from 
				client_sessions
			where 
				client_session_id = '" . $db->escape( dirty=> $self->{'sessionId'} ) . "'
				and
				upper(client_session_hash) = '" . $db->escape( dirty=> uc($self->{'sessionHash'}) ) . "'
		");
		
		if (!$ignoreAuxAuth && scalar(@si))
		{
			@badAuxAuths = $db->query(sql=> "
				select aux_auth_id
				from client_session_aux_auths
				where client_session_id = '" . $db->escape( dirty=> $self->{'sessionId'} ) . "'
					and (passed = false or expired = true)");
		}
	}
	elsif( length( $userId ) ) {
		@si = $db->query( sql=> "
				SELECT 
					user_id 
				FROM 
					client_sessions
				WHERE 
					user_id = $userId AND client_session_type_id IN (1,4)
			" );

		my( $clientSessionId ) = $db->query( sql=> "
			SELECT 
				client_session_id	
			FROM 
				client_sessions
			WHERE 
				user_id = $userId AND client_session_type_id IN (1,4)
			");
		
		if (!$ignoreAuxAuth && length( $clientSessionId ) ) {
			@badAuxAuths = $db->query(sql=> "
				SELECT aux_auth_id
				FROM client_session_aux_auths
				WHERE client_session_id = $clientSessionId
					AND (passed = false or expired = true)");
		}
	}
	
	!$userId and $self->logger( severity=>'NORMAL', logMessage=>"WEBTOP SECURITY CHECKS: checkSession() - No userid for some reason." );
	!scalar(@si) and $self->logger( severity=>'NORMAL', logMessage=>"WEBTOP SECURITY CHECKS: checkSession() - session has and session id not found in client_sessions table...could have expired." );
	scalar(@badAuxAuths) and $self->logger( severity=>'NORMAL', logMessage=>"WEBTOP SECURITY CHECKS: checkSession() - Haven't authed with " . scalar(@badAuxAuths) . " aux auth." );

	if( $forceReturn == 0 ) {
		if ( !$userId || !scalar(@si) || scalar(@badAuxAuths))
		{
			# invalid session
			# redir to login.pl and exit

			print "Content-type: text/html\n\n";
			print "
			<html><head><meta http-equiv='pragma' content='no-cache'/>
			<script>
			setTimeout(\"top.location.href = 'login.pl'\", 0000);
			</script></head></html>
			";

			exit();
		}
	}
}

sub cleanupExpiredSessions
{
	my $self    = shift;
	my $db      = $self->{'webtopDb'};
	my $cleaned = $self->{'cleaned'};

	# Only do this once per instantiation
	if (defined($cleaned) and $cleaned == 1) {
		return;
	}

	$db->do(sql => "
		delete from
			client_sessions
		where
			touch_time < " . $db->getCurrentTimeStampString() . " - interval '1 hour'
			and concentrator_session_id is null
			and client_session_type_id = 1
		");

	$db->do(sql => "
		delete from 
			anx_portal_sessions
		where
			client_session_id is not null
			and
			client_session_id not in ( select client_session_id from client_sessions )
		");

	$db->commit;

	$self->{'cleaned'} = 1;
}

sub getUserContentModules
{
	my $self = shift;

	#
	# get the hash with the module access info
	#
	my $allowedHash = $self->getAllowedContentModules();
	my $intranet = $allowedHash->{'Intranet'}->{'m_intranet'};	
	my $applications = $allowedHash->{'Applications'}->{'m_applications'};	
	my $email = $allowedHash->{'Mail'}->{'m_email'};	
	my $fileShares = $allowedHash->{'FileShares'}->{'m_fileshares'};	
	my $remoteDesktop = $allowedHash->{'RemoteDesktop'}->{'m_remoteDesktop'};	

	#
	# so i can do the foreach down there
	#
	my @blah = ($intranet,$applications,$email,$fileShares,$remoteDesktop);

	#
	# get the number of modules that the user can see,
	# if it is 2 then we have to assign the col and rows
	# different so they can be side by side instead of on 
	# top of each other
	#
	my $numberOfModules = 0;

	foreach my $module ( @blah )
	{
		$module and $numberOfModules++;
	}

	# 
	# these are the col and row numbers, hardcoded
	# for 5 modules cause i couldnt figure out a good
	# way not to hard code it...i wasted so much time on that
	#
	my @col;
	my @row;
	my @moduleOrder = ("0,0",($numberOfModules < 3 ? "1,0" : "0,1"),"1,0","1,1","1,2");
	my @linkOrder;
	my $i = 0;

	#
	# 	if the module is ye then assign it a col, row number and link order number
	# 	else
	# 	asign it x
	#
	foreach my $yeOrNe ( @blah )
	{
		if ($yeOrNe)
		{
			my ($orderCol,$orderRow) = split(/,/,$moduleOrder[$i]);
			
			push @col, $orderCol;
			push @row, $orderRow;
			push @linkOrder, $i;

			$i++;
		}
		else
		{
			push @col, "x";
			push @row, "x";
			push @linkOrder,"x";
		}

	}
	
	my $cmi = {
		Intranet=> {
			moduleName=> "Intranet",
			shown=> $intranet,
			shownMobile=> 1,
			col=> $col[0],
			row=> $row[0],
			icon=> "intranetIcon.png",
			linkOrder=> $linkOrder[0],
			requiresActiveX=> 0
		},
		Applications=> {
			moduleName=> "Applications",
			shown=> $applications,
			shownMobile=> 0,
			col=> $col[1],
			row=> $row[1],
			icon=> "applicationsIcon.png",
			linkOrder=> $linkOrder[1],
			requiresActiveX=> 1
		},
		Mail=> {
			moduleName=> "Email",
			shown=> $email,
			shownMobile=> 1,
			col=> $col[2],
			row=> $row[2],
			icon=> "mailIcon.png",
			linkOrder=> $linkOrder[2],
			requiresActiveX=> 0
		},
		FileShares=> {
			moduleName=> "File Shares",
			shown=> $fileShares,
			shownMobile=> 1,
			col=> $col[3],
			row=> $row[3],
			icon=> "fileSharesIcon.png",
			linkOrder=> $linkOrder[3],
			requiresActiveX=> 0
		},
		RemoteDesktop=> {
			moduleName=> "Remote Desktop",
			shown=> $remoteDesktop,
			shownMobile=> 0,
			col=> $col[4],
			row=> $row[4],
			icon=> "remoteDesktopIcon.png",
			linkOrder=> $linkOrder[4],
			requiresActiveX=> 0
		},
		UserPrefs=> {
			moduleName=> "Preferences",
			shown=> 1,
			shownMobile=> 0,
			col=> "",
			row=> "",
			linkOrder=> "",
			icon=> "",
			noPreview => 1
		}
	};

	return $cmi;
}

sub getAllowedContentModules
{
	my $self = shift;
	my $db = $self->{'webtopDb'};
	my $tb = Pos::Webtop::Toolbox->new();
	#
	# get the modules and sub modules access info
	#
	# m_* is the actual module
	# sm_* is a submodule of module * or something
	#

	my $userId = $self->getUserId();
	$userId = $self->getUserIdDB( db=> $db ) unless( length( $userId ) );

	my $restrictSetId = $self->getRestrictionSetId();
	$restrictSetId = 1 unless( length( $restrictSetId ) );

	my @allowed = $db->query(sql => "
		select
			m_f_fileshares,
			sm_f_new_fileshare,
			m_i_intranet,
			m_a_applications,
			sm_a_user_defined_atp,
			sm_a_app_launcher,
			m_e_email,
			m_rd_remote_desktop,
			sm_rd_manually_connect,
			sm_rd_install_agent
		from
			w_user_module_access
		where
			user_id = $userId 
			and restrict_set_id = $restrictSetId
		");

	#
	# create mad hash of module access info
	#
	my $moduleAccess = {
		Intranet=> 
		{
			m_intranet=> ($allowed[0][2] || !defined($allowed[0][2]) ? "1" : "0") 
		},
		
		Applications=> 
		{
			m_applications=> ( ($allowed[0][3] || !defined($allowed[0][3])) && $self->isWebtopVpnConnectionEstablished(tb=> $tb, db=>$db) ? "1" : "0"),
			sm_userDefinedAtp=> ($allowed[0][4] || !defined($allowed[0][4]) ?"1" : "0"),
			sm_appLauncher=> ($allowed[0][5] || !defined($allowed[0][5]) ? "1" : "0")
		},
		
		Mail=> 
		{
			m_email=> ($allowed[0][6] || !defined($allowed[0][6]) ? "1" : "0")
		},
		
		FileShares=> 
		{
			m_fileshares=> ($allowed[0][0] || !defined($allowed[0][0])  ? "1" : "0"),
			sm_newFileshare=> ($allowed[0][1] || !defined($allowed[0][1]) ? "1" : "0")
		},

		RemoteDesktop=> 
		{
			m_remoteDesktop=> ( ($allowed[0][7] || !defined($allowed[0][7])) && ($self->isWebtopVpnConnectionEstablished(tb=> $tb, db=>$db) || ( $allowed[0][9] || !defined($allowed[0][9]) )) && !$self->isMacWebtop() ? "1" : "0"),
			sm_manuallyConnect=> ($allowed[0][8] || !defined($allowed[0][8]) ? "1" : "0"),
			sm_installAgent=> ($allowed[0][9] || !defined($allowed[0][9]) ? "1" : "0")
		}
	};

	return $moduleAccess;
}

sub isSupportAccount
{
	my $self = shift;

	my ($db, $userId) = @{{@_}}{qw/db userId/};

	my $supportAccount = 0;

	if ( defined($userId) )
	{
		($supportAccount) = $db->query(sql => "
			select
				count(user_id)
			from
				users
			where
				user_id = $userId
				AND
				is_support_account = 1
			");
	}
	
	if ( $supportAccount )
	{
		#$self->logger( severity=>'NORMAL', logMessage=>"WEBTOP SECURITY CHECKS: This user is set as the support account." );
	}

	return $supportAccount;
}

sub isSupportAccountActive
{
	my $self = shift;

	my ($db, $userId) = @{{@_}}{qw/db userId/};

	my $activeSupportAccount = 0;

	if ( defined($userId) )
	{
		($activeSupportAccount) = $db->query(sql => "
			select
				count(user_id)
			from
				users
			where
				user_id = $userId
				AND
				is_support_account = 1
				AND
				" . $db->getCurrentDateString() . " < last_password_reset " . ((Pos::defaults::isPostgresDb()) ? "+ interval '1 hour'" : "+ 1/24" ) . "
			");
	}
		
	if ( $activeSupportAccount )
	{
		#$self->logger( severity=>'NORMAL', logMessage=>"WEBTOP SECURITY CHECKS: Support account is active." );
	}
	else
	{
		#$self->logger( severity=>'NORMAL', logMessage=>"WEBTOP SECURITY CHECKS: Support account has expired." );
	}
	
	return $activeSupportAccount;
}

sub isMobileWebtop
{
	my $self = shift;
	
	my $agent = $ENV{'HTTP_USER_AGENT'};

	$agent = uc($agent);
	
	if (($agent =~ s/WINDOWS CE/$agent/ ||
			$agent =~ s/NETFRONT/$agent/ ||
			$agent =~ s/PALM OS/$agent/ ||
			$agent =~ s/BLAZER/$agent/ ||
			$agent =~ s/ELAINE/$agent/ ||
			$agent =~ s/^WAP.*$/$agent/ ||
			$agent =~ s/PLUCKER/$agent/ ||
			$agent =~ s/PPC/$agent/ ||
			$agent =~ s/SMARTPHONE/$agent/ || 
			$agent =~ s/IEMOBILE/$agent/ ||
			$agent =~ s/SYMBIAN/$agent/ ||
			$agent =~ s/BLACKBERRY/$agent/ ||
			$agent =~ s/OPERA MINI/$agent/ ||
			$agent =~ s/OPWV/$agent/ ||
			$agent =~ s/ADVANTGO/$agent/) &&
			$agent !~ s/MACINTOSH/$agent/
		)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

#
# this will return 1 if it is a handheld pc
# with something other than windows ce
#
sub isLameHandheldThatSux
{
	my $self = shift;
	my ($dow) = @{{@_}}{qw/dow/};

	if ($dow)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

sub isLameUsingOwa
{
	my $self = shift;
	my ($db, $userId) = @{{@_}}{qw/db userId/};

	my @res = $db->query(sql => "
		select
			wes.email_setting_name
		from
			w_email_settings wes,
			w_user_email_settings wues
		where
			wues.email_setting_id = wes.email_setting_id
			AND wues.user_id = $userId
		");
		
	if (scalar(@res) == 0 || $res[0] ne 'OWA') 
	{
		return 0;
	}
	else
	{
		return 1;
	}
}

sub getOwaServer
{
	my $self = shift;
	my ($db, $userId) = @{{@_}}{qw/db userId/};

	my @res = $db->query(sql => "
		select
			owa_server
		from
			w_user_email_settings_owa
		where
			user_id = $userId
		");
	
	if (scalar(@res) == 0) 
	{
		return 0;
	}
	else
	{
		return $res[0];
	}
}

sub isWebtopVpnConnectionEstablished
{
	my $self = shift;
	my ($db, $userId) = @{{@_}}{qw/db userId/};

	my $sql;
	my $clientSessionId = $self->{'sessionId'};
	if( ! length( $clientSessionId ) ) {
		if( length( $userId ) ) {
			$sql = "SELECT user_id FROM client_sessions WHERE user_id = $userId
				AND client_session_type_id IN (1,4)";
		}
		else {
			my $raddr = $ENV{'REMOTE_ADDR'};
			$sql = "SELECT user_id FROM client_sessions WHERE rawip32_to_dotted_quad(public_ip_address) = '$raddr' 
				AND client_session_type_id IN (1,4)";
		}
			
		($clientSessionId) = $db->query( sql=> $sql );
	}
	
	my ($vpnConnection) = $db->query(sql => "
		select
			control_session_id
		from
			client_sessions
		where
			client_session_id = $clientSessionId
			and
			client_session_type_id = (select client_session_type_id from client_session_types where upper(client_session_type_name) = 'WEBTOP')

		");

	if($vpnConnection)
	{
		#$self->logger( severity=>'NORMAL', logMessage=>"WEBTOP SECURITY CHECKS: Webtop VPN connection is established" );
		return 1;
	}

	#$self->logger( severity=>'NORMAL', logMessage=>"WEBTOP SECURITY CHECKS: Webtop VPN connection is not established for user" );
	
	return 0;
}

sub isActivexDisabled
{
	my $self = shift;
	my ($db, $userId) = @{{@_}}{qw/db userId/};
	my $activexDisabled;

	if( $self->getSessionId() )  {
	
		($activexDisabled) = $db->query(sql => "
			select
				activex_disabled
			from
				client_sessions
			where
				client_session_id = '" . $db->escape( dirty=> $self->getSessionId() ) . "'
			" );
	}
	elsif( length( $userId ) ) {
		($activexDisabled) = $db->query(sql => "
				SELECT 
					user_id
				FROM 
					client_sessions
				WHERE client_session_type_id IN (1,4) AND user_id = $userId
			" );		
	}
	
	if ($activexDisabled)
	{
		#$self->logger( severity=>'NORMAL', logMessage=>"WEBTOP SECUIRTY CHECKS: ActiveX is disabled for user" );
	}

	return $activexDisabled;
}

sub isPassedCaptivePortalChecks
{
	my $self = shift;
	my ($db, $userId) = @{{@_}}{qw/db userId/};

	my $hasPassedChecks;	
	if( length( $self->getSessionId() ) ) {
		($hasPassedChecks) = $db->query(sql => "
			select
				webtop_passed_checks
			from
				client_sessions
			where
				client_session_id = '" . $db->escape( dirty=>$self->getSessionId() ) . "'
			");
	}
	elsif( length( $userId ) ) {
		($hasPassedChecks) = $db->query(sql => "
			SELECT
				webtop_passed_checks
			FROM
				client_sessions
			WHERE 
				client_session_type_id IN (1,4) AND user_id = $userId
			" );
	}

	if (!$hasPassedChecks || not defined($hasPassedChecks))
	{
		#$self->logger( severity=>'NORMAL', logMessage=>"WEBTOP SECURITY CHECKS: User has not passed all captive portal checks" );
	}
	else
	{
		#$self->logger( severity=>'NORMAL', logMessage=>"WEBTOP SECURITY CHECKS: User has passed all captive portal checks" );
	}

	return $hasPassedChecks;
}

sub isPortalzOpen
{
	my $self = shift;
	my ($db, $userId) = @{{@_}}{qw/db userId/};
	my $numPortals;

	if( length( $self->getSessionId() ) ) {
		($numPortals) = $db->query(sql => "
			SELECT
				count(*)
			FROM
				captive_portalized cs,
				client_sessions us
			WHERE
				cs.user_id = us.user_id
				AND cs.computer_id = us.computer_id
				AND us.client_session_id = '" . $db->escape( dirty => $self->getSessionId() ) . "'
		");
	}
	elsif( length( $userId ) ) {
		($numPortals) = $db->query(sql => "
			SELECT
				count(*)
			FROM
				captive_portalized cs,
				client_sessions us
			WHERE
				cs.user_id = us.user_id
				AND cs.computer_id = us.computer_id
				AND client_session_type_id IN (1,4) 
				AND user_id = $userId
			" );
	}

	if (not scalar($numPortals))
	{
		warn "WEBOP SECURITY CHECKS: $numPortals portals open for user " . $self->getUserName() . "\n";
	}

	return $numPortals;
}

#
# checks to make sure the user didn't 
# get around the portal checks for ocx
# and stuff
#
sub isOcxRequiredCaptivePortalCheck
{
	my $self = shift;
	my ($db, $tb, $userId) = @{{@_}}{qw/db tb userId/};

	not defined($tb) and $tb = Pos::Webtop::Toolbox->new();

	my $hasPassedChecks = $self->isPassedCaptivePortalChecks(db=>$db, userId=> $userId); 
	$hasPassedChecks and return [0,0,1];

	if ($self->isOcxRequired(tb => $tb, userId=> $userId))
	{
		#$self->logger( severity=>'NORMAL', logMessage=>"WEBTOP SECURITY CHECK: OCX is required for user, checking for portals and activex" );
		my $portalized;
		my $numPortals = $self->isPortalzOpen(db=>$db, userId=>$userId);
		my $activexDisabled = $self->isActivexDisabled(db=>$db, userId=>$userId);
	
		not defined($activexDisabled) and $activexDisabled = 0;

		my $vpnConnection = $self->isWebtopVpnConnectionEstablished(db=>$db, userId=>$userId);
		
		# If the query returns no rows, the session is not portalized.
		if ((not defined($numPortals) or $numPortals == 0) && $activexDisabled == 0)
		{
			$portalized = 0;
		}
		else
		{
			$portalized = 1;
		}
	
		return [$portalized,$activexDisabled,$vpnConnection];
	}
	
	# if it gets here that means they are able to login so they are kew for this session

	if( length( $self->getSessionId() ) ) {
		$db->do(sql => "
			update 
				client_sessions
			set
				webtop_passed_checks = '1'
			where
				client_session_id = '" . $self->getSessionId() . "'
		");
	}
	elsif( length( $userId ) ) {
		$db->do(sql => "
			UPDATE 
				client_sessions
			SET
				webtop_passed_checks = '1'
			WHERE
				client_session_type_id IN (1,4) AND user_id = $userId
			" );
	}

	$db->commit;

	return [0,0,1]; 
}

sub isWebtopAccessEnabled
{
	my $self = shift;
	my ($tb, $db, $userId) = @{{@_}}{qw/tb db userId/};

	$userId = $self->getUserId() unless( defined( $userId ) ); 
	$userId = $self->getUserIdDB( db=> $db ) unless( length( $userId ) );

	my $restrictSetId = $self->getRestrictionSetId();
	$restrictSetId = 1 unless( length( $restrictSetId ) );

	my ($userHasAccess) = $db->query( sql => "
		select
			can_use_webtop
		from
			user_webtop_access
		where
			user_id = $userId
			and 
			can_use_webtop = 1
			and
			restrict_set_id = $restrictSetId
			limit 1
		");
		
	if (not defined($userHasAccess))
	{
		$userHasAccess = 0;
		#$self->logger( severity=>'NORMAL', logMessage=>"WEBTOP SECURITY CHECKS: Webtop access is disabled for user" );
	}

	return $userHasAccess;
}

sub isUserRegistered
{
	my $self = shift;
	my ($tb, $db) = @{{@_}}{qw/tb db/};

	my $userId = $self->getUserId();
	$userId = $self->getUserIdDB( db=> $db ) unless( length( $userId ) );

	my ($userHasRegistered) = $db->query(sql => "
		select
			case when c.trial_expiration_date is null then
				u.register_complete
			else
				1
			end as register_complete
		from
			users u
			inner join groups g on u.group_id = g.group_id
			inner join customers c on g.customer_id = c.customer_id
		where
			u.user_id = $userId
		");
	
	if (not defined($userHasRegistered))
	{
		$userHasRegistered = 0;
		#$self->logger( severity=>'NORMAL', logMessage=>"WEBTOP SECURITY CHECKS: User has not gone through the registration stuff" );
	}

	return $userHasRegistered;
}

sub isUserTryingToBeSneaky
{
	my $self = shift;
	my ($tb, $db) = @{{@_}}{qw/tb db/};
	my $userId = $self->getUserId();
	my $registered = 0;

	my $isSupportAccount = $self->isSupportAccount( db=> $db, userId=> $userId );
	
	my $hasPassedChecks = $self->isPassedCaptivePortalChecks(db=>$db); 

	$userId = $self->getUserIdDB( db=> $db ) unless( length( $userId ) );

	$hasPassedChecks and return 0;

	!$isSupportAccount and $registered = $self->isUserRegistered( tb=> $tb, db=> $db );
	my $webtopAccess = $self->isWebtopAccessEnabled( tb=> $tb, db=> $db );

	$isSupportAccount and $registered = 1;

	if(!$registered || !$webtopAccess)
	{
		#$self->logger( severity=>'NORMAL', logMessage=>"WEBTOP SECURITY CHECK: Looks like user is trying to be sneaky" );
		return 1;
	}

	return 0;
}

sub isVpnAccessEnabled
{
	my $self = shift;
	my ($db, $userId) = @{{@_}}{qw/db userId/};

	my ($vpnAccess) = $db->query( sql => "
		select
			can_use_vpn
		from
			user_vpn_access
		where
			user_id = $userId
			and 
			(can_use_vpn = 1 OR can_use_l2tp = 1)
			limit 1
		");
	
	my ($vpnDownload) = $db->query( sql => "
		select
			can_download_vpn | can_download_l2tp_ios | can_download_l2tp_macosx
		from
			user_vpn_access
		where
			user_id = $userId
			limit 1
		");

	if(not defined($vpnAccess))
	{
		$vpnAccess = 0;
		#$self->logger( severity=>'NORMAL', logMessage=>"WEBTOP SECURITY CHECKS: VPN access for user is disabled" );
	}

	if(not defined($vpnDownload))
	{
		$vpnDownload = 0;
		#$self->logger( severity=>'NORMAL', logMessage=>"WEBTOP SECURITY CHECKS: VPN client dowload for user is disabled" );
	}

	return [$vpnAccess,$vpnDownload];
}

sub getUserType
{
	my $self = shift;
	my ($db, $userId) = @{{@_}}{qw/db userId/};
	
	my ($userType) = $db->query(sql => "
				select
					user_type_name
				from
					user_types ut,
					users u
				WHERE 
					u.user_id = $userId
					and
					u.user_type_id = ut.user_type_id
			");
	
	not defined($userType) and $userType = 0;

	return $userType;
}

sub canUserChangePassword
{
	my $self = shift;
	my ($db,$userId) = @{{@_}}{qw/db userId/};

	my ($canUserChangePassword) = $db->query(sql => "
		select
			can_change_password
		from
			users
		where
			user_id = $userId
		");

	if ( $canUserChangePassword )
	{
		#$self->logger( severity=>'NORMAL', logMessage=>"WEBTOP SECURITY CHECKS: User password change'n has been enabled." );
	}
	else
	{
		#$self->logger( severity=>'NORMAL', logMessage=>"WEBTOP SECURITY CHECKS: User password change'n has been disabled." );
	}

	return $canUserChangePassword;
}

sub getMacWebtopVersion
{
	my $self = shift;
	my ($db, $userId) = @{{@_}}{qw/db userId/};
	my $releaseId;
	
	# Note that this is a different query than the one in the OCX version
	# checker.  This one's last query checks stable, not latest. (not to mention
	# actually uses the result too).
	#
	my @info = $db->query(sql => "
		select
			(
				select
					software_release_id
				from
					user_software_versions
				where
					user_id = $userId
					AND software_product_id = sp.software_product_id
			) as USER_SOFTWARE_ACTUAL_RELEASE,
			(
				select
					spb.software_release_id
				from
					software_product_branches spb,
					user_software_versions usv
				where
					spb.software_branch_type_id = usv.software_branch_type_id
					AND usv.software_product_id = sp.software_product_id
					AND spb.software_product_id = usv.software_product_id
					AND usv.user_id = $userId
			) as USER_SOFTWARE_BRANCH_RELEASE,
			(
				select
					software_release_id
				from
					software_product_branches
				where
					software_branch_type_id = (
						select
							software_branch_type_id
						from
							software_branch_types
						where
							upper(software_branch_type_name) = upper('stable')
					) AND software_product_id = sp.software_product_id
			) as GLOBAL_SOFTWARE_RELEASE	
		from
			software_products sp
		where
			sp.distribution_identifier = 'macwebtop'
		");

																															
	my ($userActualRelease, $userBranchRelease, $globalRelease) = @{ $info[0] };

	if (defined($userActualRelease)) 
	{
		$releaseId = $userActualRelease;
	} 
	elsif (defined($userBranchRelease)) 
	{
		$releaseId = $userBranchRelease;
	}
	elsif (defined($globalRelease)) 
	{
		$releaseId = $globalRelease;
	} 

	if (! (defined($releaseId) && length($releaseId)))
	{
		return [62,0];
	}
	
	# This query should already exist as an sproc -- I left it the same so
	# the sproc could be reused, even though we don't need activex_version.
	#
	@info = $db->query(sql => "
		select
			major_release_number,
			minor_release_number,
			activex_version
		from
			software_releases
		where
			software_release_id = '$releaseId'
		");

	if (! @info)
	{
		return [62,0];
	}
	
	my ($major, $minor, $activeXVersion) = @{ $info[0] };
	
	return [$major,$minor];
}

sub getWebtopOcxVersion
{
	my $self = shift;
	my ($db, $userId) = @{{@_}}{qw/db userId/};
	my $releaseId;

	my @info = $db->query(sql => "
		select
			(
				select
					software_release_id
				from
					user_software_versions
				where
					user_id = $userId
					AND software_product_id = sp.software_product_id
			) as USER_SOFTWARE_ACTUAL_RELEASE,
			(
				select
					spb.software_release_id
				from
					software_product_branches spb,
					user_software_versions usv
				where
					spb.software_branch_type_id = usv.software_branch_type_id
					AND usv.software_product_id = sp.software_product_id
					AND spb.software_product_id = usv.software_product_id
					AND usv.user_id = $userId
			) as USER_SOFTWARE_BRANCH_RELEASE,
			(
				select
					software_release_id
				from
					software_product_branches
				where
					software_branch_type_id = (
						select
							software_branch_type_id
						from
							software_branch_types
						where
							upper(software_branch_type_name) = upper('latest')
					) AND software_product_id = sp.software_product_id
			) as GLOBAL_SOFTWARE_RELEASE	
		from
			software_products sp
		where
			sp.distribution_identifier = 'webtop'
		");

		my ($branch) = $db->query(sql => "
		select
			sbt.software_branch_type_name
		from
			user_software_versions usv,
			software_product_branches spb,
			software_branch_types sbt
		where
			usv.user_id = $userId
			AND
			usv.software_branch_type_id = sbt.software_branch_type_id
		");
																															
	my ($userActualRelease, $userBranchRelease, $globalRelease) = @{ $info[0] };

	if (defined($userActualRelease)) 
	{
		$releaseId = $userActualRelease;
	} 
	elsif (defined($userBranchRelease)) 
	{
		$releaseId = $userBranchRelease;
	}
	
	@info = $db->query(sql => "
		select
			major_release_number,
			minor_release_number,
			activex_version
		from
			software_releases
		where
			software_release_id = '$releaseId'
		");
	
	my ($major, $minor, $activeXVersion) = @{ $info[0] };

	# if it isn't defined then we default to a version that is old...
	# works like this...if we are currently on 2,1,23,5 but the policy
	# is set to 2,1,23,1 and the user does not have the activex installed
	# it will grab the current cab and install it...the next time the user
	# logs in and if the policy is still set to 2,1,23,1 ie will relize that
	# it has a newer version of the activex installed and will not attempt to 
	# upgrade and will just login...if the policy gets set to 2,1,23,6 then
	# (admin) ie will upgrade the activex (non-admin) webtop will tell the user
	# that the browser doesn't support activex
	
	not defined($activeXVersion) and $activeXVersion = "2,1,23,1";
	
	return [$major,$minor,$activeXVersion];

}

sub logger
{
	my $self = shift;
	my $userName = $self->getUserName();
	my ($severity,$logMessage) = @{{@_}}{qw/severity logMessage/};

	warn "[" . localtime() . "] (" . uc($severity) . ") <" . (defined($userName) ? $userName : "USERNAME NOT AVAILABLE" ) . "> $logMessage \n";

	return 1;
}

# This is simply a test that we are in a browser that is mac webtop enhanced
# capable.  This is intended to be used by areas of code that need to disable
# enhanced features that are not available on mac yet.
#
sub isMacWebtop
{
   my $agent = $ENV{'HTTP_USER_AGENT'};
   my $ret = 0;   

   if($agent =~ /Mac OS/) {
   	if($agent =~ /Safari/ && $agent !~ /Chrome/) { 
        	#warn "Detected Safari - using compatible mode\n";
		warn "Detected Safari - testing in enhanced mode\n";
		$ret = 1;        
   	} elsif($agent =~ /Firefox/) {
                warn "Detected Firefox, using enhanced mode\n";
 		$ret = 1;
        } elsif($agent =~ /Chrome/) {
                warn  "Detected Chrome, using enhanced mode\n";
		$ret = 1;
        } else {
                warn "not sure what browswer you are running..\n";        
	}
   }

   return $ret;
}

# RP - A new subroutine to determine if OS X access is enabled
sub isOsxAccessEnabled
{
	my $self = shift;
	my ($db, $userId) = @{{@_}}{qw/db userId/};

	my $vpnAccess = 0;

	($vpnAccess) = $db->query( sql => "
		select
			can_use_l2tp
		from
			user_vpn_access
		where
			user_id = $userId
			limit 1
		");

	if(not defined($vpnAccess))
	{
		#$self->logger( severity=>'NORMAL', logMessage=>"WEBTOP SECURITY CHECKS: VPN access for user is disabled" );
	}

	return $vpnAccess;
}

1;
