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

use strict;
use CGI qw/:standard/;
use Digest::MD5();
use Pos::Webtop::Web::ModuleLoader;
use Pos::Webtop::Web::OEMLoader;
use CGI qw/:standard/;
use CGI::Cookie ();
use Pos::WebService::Modules::MyCalls;
use Pos::WebService::Modules::ParseServerXmlResponse;
use LWP::UserAgent;
use HTTP::Request;
#use Apache2::Cookie ();
use APR::Request::Cookie;
use MIME::Base64;
use HTML::Entities;
use URI::Escape;
use Config::General;

my $httpHost = uc($ENV{'HTTP_HOST'});
my $tb = Pos::Webtop::Toolbox->new();
my $client = $tb->getClient();
my $cgi = $tb->getCgi();
my $oem = $tb->getOem;
my $isMobile = $client->isMobileWebtop();
my $myCallsObj = Pos::WebService::Modules::MyCalls->new();
my $xmlResponseParserObj = Pos::WebService::Modules::ParseServerXmlResponse->new();
my $effectiveOemId = Pos::Webtop::Web::OEMLoader::getSkinOemId( oemId=> $tb->getOemId() );
my $challenge = $cgi->param('challenge');

my $userId = 0;
my $isTrialExpired = 0;
my $expired = 0;
my $uslId = 0;

my $si = "";
my $sh = "";

my $mode = $cgi->param('mode');
$mode = "" unless( defined( $mode ) && length( $mode ) );

my $uerrDivStyle = "display: none;";
my $uDivStyle = "display: block;";

my $signinMsg = "Sign in to continue to WebTop.";
$signinMsg = "Sign in to download the installer." unless( length( $mode ) == 0 );

my $a = $cgi->param('a');
my $z = $cgi->param('z');

#my $msg = "You have entered an incorrect user name or password. Please try again.";
my $msg;
my $demoMsg = "WARNING: YOU ARE IN DEMO MODE";
my $oemDetected = $cgi->param('testOemId');

my $customerServicePhone;
my $conf   = new Config::General("/usr/local/positive/conf/PosPerl.conf");
my %config = $conf->getall;

my $q = $cgi->param('q');
$q = "" unless( defined( $q ) && length( $q ) );

my $s = $cgi->param('s');
$s = "" unless( defined( $s ) && length( $s ) );

my $imageDirectory = "LocalWebLib/OEM/1";
my $isL2tp = 0;

# This is used to close the session window if it's open when someone logs out.
my @anxParms;

sub setIsL2tp
{
	my $db = $tb->getWebtopDbReader();
	warn "DEBUG : Inside setIsL2tp \n";

	if( defined( $mode ) && ( $mode eq 'vpn' || $mode eq 'netcon' ) ) {
		$isL2tp = 0;
	}
	else {
		my( $internetAccessMethodId ) = $db->query( sql=> "
						SELECT
        						wuiam.intranet_access_method_id
						FROM
        					w_user_intranet_access_method AS wuiam
        					JOIN w_intranet_access_methods AS wiam ON wuiam.intranet_access_method_id = wiam.intranet_access_method_id
						WHERE user_id = $userId 
			");

		if( $internetAccessMethodId == 2 || $internetAccessMethodId == 3 ) {
			$isL2tp = 1;
		}
		else {
			$isL2tp = 0;
		}
	}
	warn "DEBUG : Leaving setIsL2tp \n";
}

sub reloadPage
{
	my( $reason, $param ) = @{{@_}}{qw/reason param/};

	my $db = $tb->getWebtopDbReader();
	my( $epoch ) = $db->query( sql=> "
                                      		SELECT
                                                	ROUND( EXTRACT(epoch FROM NOW()) / 60 )
						" );

	$param = ( $epoch * 2 ) unless( defined( $param ) && length( $param ) );

	my $url = "loginwt.pl?q=$config{'webtopLoginAgain'}&p=$param&r=$reason&u=" . $cgi->param('username');

	print "Content-Type: text/html\nCache-Control: no-cache\n\n

		<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
		<head>
		<meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
		<meta http-equiv=refresh content=\'0; url=${url}\' />
		</head>
		</html>
	";

	exit(0);
}

sub checkCredentials
{
	my $db = $tb->getWebtopDbReader();

	my $username = $cgi->param('username');
	my $password = $cgi->param('password');

	#showCheckCredentialsModal( active=>"1" );
	#sleep(2);

	$username =~ s/^ *//g;
	$username =~ s/ *$//g;

	my $encodedPassword = HTML::Entities::encode( $password );
        $encodedPassword = encode_base64( $encodedPassword );
        $encodedPassword = uri_escape( $encodedPassword );

	my $r = "<root>
			<type>Request</type>
			<remoteRequestor>
				<ipAddress></ipAddress>
				<datetime></datetime>
				<key></key>
				<sessionId></sessionId>
			</remoteRequestor>
			<command>
				<operation>UserOperator</operation>
				<method>checkUser</method>
			</command>
			<parameters>
				<parameterCount>2</parameterCount>
				<parameter>
					<name>uslId</name>
					<value></value>
				</parameter>
				<parameter>
					<name>uUserName</name>
					<value><![CDATA[$username]]></value>
				</parameter>
				<parameter>
					<name>uPwd</name>
					<value><![CDATA[$encodedPassword]]></value>
				</parameter>
			</parameters>
		</root>
	";

	my $request = HTTP::Request->new(GET => $config{webtopWebserviceUrl} . "?r=$r" );
	my $ua = LWP::UserAgent->new;
	#my $ua = LWP::UserAgent->new(ssl_opts => {verify_hostname => 0, SSL_hostname=> '${hostName}', SSL_version => 'TLSv12'});
	my $response = $ua->request( $request );

warn "DEBUG: URL=".$config{webtopWebserviceUrl}." r=$r\n";

	if($response) {
		warn "DEBUG: Going to ParseResponse .... \n";
		$xmlResponseParserObj->parseResponse( response => $response->content ) or warn "COULD NOT PARSE XML FROM CHECKUSER()\n\n";	
		warn "DEBUG: ParseResponse successful.... \n";
	}
	else {
		warn "COULD NOT PARSE XML FROM CHECKUSER()\n\n";
	}

	if( lc( $xmlResponseParserObj->getMessageInfoText() ) eq "ok") {
		$isTrialExpired = $xmlResponseParserObj->getMessageInfoTrialExpired();
		$expired = $xmlResponseParserObj->getMessageInfoExpired();
		$challenge = $xmlResponseParserObj->getMessageInfoChallenge();
		$uslId = $xmlResponseParserObj->getParameter( parameter => "uslId" );

		($userId) = $db->query( sql => "
			SELECT 
				user_id
			FROM 
				users
			WHERE
				UPPER(user_name) = '" . uc( $db->escape( dirty => $username ) ) . "'
			");
	}

	showCheckCredentialsModal( active=>"0" );

	if( ! $userId ) {
		reloadPage( reason=>$config{'webtopIncorrectCredentials'} );
	}

	warn "DEBUG: Check Credentials successful for userid $userId .... \n";
	return( $userId );
}

sub createTunnel
{
	warn "DEBUG : Inside createTunnel ... isL2tp : $isL2tp \n";
	my $rc = 0;
	my $db = $tb->getWebtopDbReader();

	my( $publicIpAddress ) = $db->query( sql=> "
		SELECT rawip32_to_dotted_quad(public_ip_address) 
			FROM client_sessions
			WHERE user_id = $userId AND client_session_type_id IN (1,4)
						
	");
	warn "DEBUG : Inside createTunnel ... Got PubIP : $publicIpAddress \n";

	if( length( $publicIpAddress ) ) {
		reloadPage( reason=>$config{'webtopExistingSignin'}, param=>$publicIpAddress );
	}

	#$isL2tp = 1 unless( defined( $mode ) && ( $mode eq 'vpn' || $mode eq 'netcon' ) );

	showTunnelModal( active=>"1" ) unless( ! $isL2tp );
	warn "DEBUG : Inside createTunnel ... Got PubIP : $publicIpAddress \n";
	#sleep(2);

	my $username = $cgi->param('username');
	my $password = $cgi->param('password');

	$password =~ s/^ *//g;
	$password =~ s/ *$//g;

	if( $isL2tp ) {
		my $remoteAddr = $ENV{'REMOTE_ADDR'};
		my $tunnelName = $username;
		$tunnelName =~ s/[^a-zA-Z0-9,]+//g;		

		my $md5 = Digest::MD5->new();
		$md5->add( $password );
		my $digest = $md5->hexdigest();

		my $url = $config{'l2tpWebserviceUrl'} . "?c=0&t=$tunnelName";
		my $request = HTTP::Request->new(GET => $url );
		my $ua = LWP::UserAgent->new;
		my $response = $ua->request( $request );

		$url = $config{'l2tpWebserviceUrl'} . "?c=1&u=$username&p=$digest&t=$tunnelName&i=$remoteAddr&l=" . $config{'l2tpLns'};
	warn "DEBUG : L2tp createTunnel url : $url \n";
		$request = HTTP::Request->new(GET => $url );
		$request->header('content-type' => 'application/text');	
		$response = $ua->request( $request );

		if( $response->is_success ) {
			$client->createSession( userId=>$userId, userName=>$username, passwd=>$password, uslId=>$xmlResponseParserObj->getParameter( parameter => "uslId" ), a=>$a, z=>$z, isL2tp=>$isL2tp );

			$si = $client->getSessionId();
			$sh = $client->getSessionHash();

			$client->setRestrictionSetId( tb=>$tb );	
			$db->do( sql=> "UPDATE client_sessions SET restrict_set_id=1, captive_portalized=1 WHERE client_session_id=$si" );
			$db->commit();

			$rc = 1;
		}
		else {
			warn "HTTP GET error code: " .  $response->code . "\n";
			warn "HTTP GET error message: " . $response->message . "\n";
                	
			reloadPage( reason=>$config{'webtopNoBrideConnection'} );
		}
	}
	else {
		$client->createSession( userId=>$userId, userName=>$username, passwd=>$password, uslId=>$xmlResponseParserObj->getParameter( parameter => "uslId" ), a=>$a, z=>$z, isL2tp=>$isL2tp );

		$si = $client->getSessionId();
		$sh = $client->getSessionHash();

		$client->setRestrictionSetId( tb=>$tb );	
		$db->do( sql=> "UPDATE client_sessions SET restrict_set_id=1, captive_portalized=1 WHERE client_session_id=$si" );
		$db->commit();

		$rc = 1;
	}

	my $cookieWsi = new CGI::Cookie(-name=>'wsi', -value=>$si);
        my $cookieWsh = new CGI::Cookie(-name=>'wsh', -value=>$sh);

        print "Set-Cookie: $cookieWsi\n";
        print "Set-Cookie: $cookieWsh\n";
	
	#my $r = Apache2::RequestUtil->request();
	#my $sessionIdEncoded = MIME::Base64::encode_base64( $si );
	#Apache2::Cookie->freeze( $sessionIdEncoded );
	#my $sessionIdCookie = Apache2::Cookie->new($r,-name=>'wsi',-value=>$sessionIdEncoded);

	#my $buf = Apache2::Cookie->freeze( $sh );
	#my $sessionHashCookie = Apache2::Cookie->new($r,-name=>'wsh',-value=>$buf);

	#$sessionIdCookie->bake($r);
	#$sessionHashCookie->bake($r);
	warn "DEBUG : Leaving createTunnel ... isL2tp : $isL2tp \n";

	return( $rc );
}

sub showDashboard
{
	my $db = $tb->getWebtopDbReader();
	my $startUrl = "defaultLanding.pl?q=$config{'webtopLanding'}";

	if( defined( $mode ) && ( $mode eq 'vpn' || $mode eq 'netcon') ) {
		if( $mode eq "netcon" ) {
			$mode = $config{'webtopNetconDownload'};
		}
		else {
			$mode = $config{'webtopVPNDownload'};
		}
		$startUrl .= "&Vwsi=$si&m=$mode";
		#$startUrl .= "&m=$mode";
	}
	else {
		$startUrl .= "&pVwsh=$sh&c=1&pVwsi=$si";
		#$startUrl .= "&c=1";

		#my( $d ) = $db->query( sql=> "
		#			SELECT 
		#				webtop_login_date 
		#			FROM 
		#				user_enrollment_metrics 
		#			WHERE 
		#				user_id = " . $client->getUserId() );
	}

	showTunnelModal( active=>"0" ) unless( ! $isL2tp );

	print "Content-Type: text/html\nCache-Control: no-cache\n\n

		<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
		<head>
		<meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
		<meta http-equiv=refresh content=\'0; url=${startUrl}\' />
		</head>
		</html>
	";
}

sub showCheckCredentialsModal
{
	my( $active ) = @{{@_}}{qw/active/};

        my $modalActive = "ot-modal";
        $modalActive = "ot-modal ot-modal--is-active" unless( $active == 0 );

	print "
		<div class='$modalActive' style='z-index: 1500;'>
			<div class='ot-modal__body'>
				<div class='ot-m-1' style='background: #white; width: 400px; height: 325px;'>
					<div class='ot-section ot--has-bg-grey-lightest'>
						<div class='ot-progress-container'>
							<div id='ot-spinner' class='ot-progress ot-progress--is-spinner ot-progress--is-spinner-has-text'>
								<div class='ot-progress__outer'>
									<div class='ot-progress__meter'>
									</div>
								</div>
								<div class='ot-progress__text'>Checking credentials...</div>
							</div>
						</div>
					</div>
				</div>
			</div>
		</div>
	";
}

sub showTunnelModal
{
	my( $active ) = @{{@_}}{qw/active/};

        my $modalActive = "ot-modal";
        $modalActive = "ot-modal ot-modal--is-active" unless( $active == 0 );

	print "
		<div class='$modalActive' style='z-index: 1501;'>
			<div class='ot-modal__body'>
				<div class='ot-m-1' style='background: #white; width: 400px; height: 325px;'>
					<div class='ot-section ot--has-bg-grey-lightest'>
						<div class='ot-progress-container'>
							<div id='ot-spinner' class='ot-progress ot-progress--is-spinner ot-progress--is-spinner-has-text'>
								<div class='ot-progress__outer'>
									<div class='ot-progress__meter'>
									</div>
								</div>
								<div class='ot-progress__text'>Building tunnel...</div>
							</div>
						</div>
					</div>
				</div>
			</div>
		</div>
	";
}

if( $q eq $config{'webtopLoginAgain'} ) {
	my $r = $cgi->param('r');
	my $p = $cgi->param('p');

	if( $r eq $config{'webtopExistingSignin'} ) {
		$msg = "You are already signed-in";

		if( defined( $p ) && length( $p ) ) {
 			$msg .= " from ${p}";
		}

		$msg .= ".";
	}
	elsif( $r eq $config{'webtopNoBrideConnection'} ) {
		$msg = "Unable to build tunnel. Please try again later.";
	}
	elsif( $r eq $config{'webtopIncorrectCredentials'} ) {
		$msg = "You have entered an incorrect user name or password. Please try again.";
	}
	else {
		$msg = $signinMsg;
	}

	$uerrDivStyle = "display: block;";
	$uDivStyle = "display: none;";
}
elsif( $q eq $config{'webtopSignoff'} || $q eq $config{'webtopTimedout'} ) {

	my $db = $tb->getWebtopDbWriter();
	my $si = $client->getSessionId();

        $si =~ s/^\s+//;
        $si =~ s/\s+$//;

	if( !defined( $si ) || ! length( $si ) ) {
		my $sql;
		$userId = $client->getUserIdDB( db=> $db );	

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

		($si) = $db->query( sql=> $sql );
	}

	if( length( $si ) ) { 
		my( $tunnelName ) = $db->query( sql=> "
							SELECT tunnel_name 
								FROM client_sessions	
								WHERE client_session_id = " . $si
						);
		
		#					
		# Disconnect L2TP/IPsec tunnel
		#					
		setIsL2tp();

		if( $isL2tp ) {
			my $url = $config{'l2tpWebserviceUrl'} . "?c=0&u=&t=$tunnelName";
			my $request = HTTP::Request->new(GET => $url );
			my $ua = LWP::UserAgent->new;
			my $response = $ua->request( $request );
		}

		(@anxParms) = $db->query( sql=> "SELECT a_param,z_param FROM anx_portal_sessions WHERE client_session_id = $si" );

		foreach my $anxparms(@anxParms)
		{
			my($anxA,$anxZ) = @{$anxparms};
			my $response = $myCallsObj->checkUserSession( a => $anxA, z => $anxZ ) ;
			
			if($response) {
				$xmlResponseParserObj->parseResponse( response => $response ) or warn "COULD NOT PARSE XML FROM CHECKUSERSESSION() on logout\n\n";	
			}
			else {
				warn "COULD NOT PARSE XML FROM CHECKUSERSESSION() on logout\n\n";
			}
			
			if(lc($xmlResponseParserObj->getMessageInfoText()) eq "ok") {
				$db->do( sql=> "DELETE FROM anx_portal_sessions WHERE client_session_id = $si" );
			}
		}
	
		$db->do( sql=> "DELETE FROM client_sessions WHERE client_session_id = $si" );
		$db->do( sql=> "DELETE FROM client_session_share_info WHERE client_session_id = $si" );
		$db->commit();
	}

	if( $cgi->param('q') eq $config{'webtopTimedout'} && $cgi->param('s') eq $config{'webtopLanding'} ) {
		$msg = "You have been signed out due to freshing your browser or inactivity.<br>Please sign in again.";
	}
	elsif( $cgi->param('q') eq $config{'webtopSignoff'} ) {
		$msg = "You have been logged out.<br>Completely close your browser to ensure privacy of recently-viewed data.";
	}
	else {
		$msg = "You have been signed out due to inactivity. Please sign in again.";
	}
	
	$uerrDivStyle = "display: block;";
	$uDivStyle = "display: none;";
}

if( defined( $cgi->param('go') && ( ! length( $cgi->param('password') ) || ! length( $cgi->param('username') ) ) ) ) {
	$msg = "Please enter a valid username and password.";
	$uerrDivStyle = "display: block;";
	$uDivStyle = "display: none;";
}

print "Content-Type: text/html\nCache-Control: no-cache\n\n

	<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
	<head>
		<meta name='robots' content='noindex, nofollow'>
		<meta http-equiv='Content-Type' content='text/html; charset=utf-8'>
		<link rel=stylesheet type='text/css' href='$imageDirectory/otcss.css'> 

		<style type='text/css'>
			\@font-face {
			font-family: 'Open Sans';
  			font-style: normal;
  			font-weight: 400;
  			font-stretch: normal;
  			src: url(https://fonts.gstatic.com/s/opensans/v26/memSYaGs126MiZpBA-UvWbX2vVnXBbObj2OVZyOOSr4dVJWUgsjZ0C4n.ttf) format('truetype');
		}
    		</style>

		<title>$config{'webtopRelease'}</title>
	</head>

	<body scroll='no' class='ot--has-bg-navy' style='overflow: hidden;'> 

	<div id='mainPanel' class='ot--has-bg-gradient' style='width: 100%; height: 100%; opacity: 1;'>  

	<div style='width: 100%; height: 120px; opacity: 1;'></div>
	<div class='ax_default ot_background_signin'> 
	<center>

	<form autocomplete=\"off\" method=POST name='loginPage'>
	<div> 
		<center>
			<img src='$imageDirectory/headerWebtop.svg' style='height: 45px; width: 344px'> 
		</center>
	</div>                                    

	<div style='width: 100%; height: 32px; opacity: 1;'></div>
";

if( $config{'webtopDemo'} == 1 ) {
print "
	<div id='dmDiv'>
		<div class='text'>
			<p style='color: white; font-size: 18px; line-height: 24px; background: rgba(255, 255, 255, 0.1); border-radius: 4px; min-height: 40px; min-width: 400px; max-width: 600px;'>
				<span>$demoMsg</span>
			</p>
		</div>
";
}

print "
	<div id='uerrDiv' style='$uerrDivStyle'>
		<div class='text'>
			<p style='color: white; font-size: 18px; line-height: 24px; background: rgba(255, 255, 255, 0.1); border-radius: 4px; min-height: 80px; min-width: 400px; max-width: 600px;'>
				<span>$msg</span>
			</p>
		</div>
	</div>
	<div id='uDiv' style='$uDivStyle' class='text'>
		<p style='color: white; font-size: 18px; line-height: 24px;'>
			<span class='ot-text --ot-white' >$signinMsg</span>
		</p>
	</div>
";

my $brokeLoginUserName = $cgi->param('u') || "";

print "
	<div style='width: 100%; height: 32px; opacity: 1;'></div>
	<div class='ot-input'>
		<input placeholder='User name' type=text id='userName' name='username' value=\"" . HTML::Entities::encode($brokeLoginUserName) . "\" maxlength='80' style='border-radius: 6px; height: 46px; width:395px; font-size: 18px;'>
	</div>

	<div style='width: 100%; height: 26px; opacity: 1;'></div>
	<div class='ot-input'>
		<input placeholder='Password' type='password' id='password' name='password' maxlength='80' style='border-radius: 6px; height: 46px; width:395px; font-size: 18px;'>
       	</div>
";

if( $brokeLoginUserName eq '' ) {
	print "
		<script type=\"text/javascript\">
			document.getElementById('userName').focus();
		</script>
		";
}
else {

	print "
		<script type=\"text/javascript\">
			document.getElementById('password').focus();
		</script>
		";
}

print "
	<div style='width: 100%; height: 52px; opacity: 1;'></div>
	<div style='width: 100%'>
		<center>
			<button role='button' id='go' name='go' title='' class='ot-btn ot-btn--is-sign-in' style='border-radius: 26px; height: 45px; width:130px;'>Sign in
			</button>
		</center>
	</div>

	<div style='width: 100%; bottom: 0; position: absolute;'>
		<div class='text'>
			<p style='color: white;'>
				<span>Copyright © 2023 Open Text. All Rights Reserved. Trademarks owned by Open Text.</span>
			</p>
		</div> 
	</div>

	<p hidden>
		<input type='password' name='mode' id='mode' length='0' value='${mode}'>
	</p>
	
	</form>
	</center>
	</div>
	</div>
</body>
</html>
";

#$client->clearSession();

if( defined( $cgi->param('go') ) && length( $cgi->param('password') ) && length( $cgi->param('username') ) ) {
	#
	# check credentials via ws, if isl2tp then show modal while creating tunnel otherwise just redirect
	#
	#
	if( checkCredentials() ) {
		warn "DEBUG : Done checkCredentials.... \n";
		setIsL2tp();
		warn "DEBUG : Done setIsL2tp .... \n";
		my $rc = createTunnel(); 
		warn "DEBUG : Done createTunnel .... \n";
		showDashboard() unless( ! $rc );
	}
}
