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

use strict;
use Pos::Webtop::Web::ModuleLoader;
use Digest::MD5;
use URI::Escape;

# set to max number of procs you want running
my $maxProcs = 5;
my $gotLock = 0;
my $lockDir = "/tmp/WebtopRdaRegisterLocks";
my $lockHandle;

if ( ! stat($lockDir) )
{
	my @parts = split(/\//,$lockDir);
	my $path = "";

	foreach (@parts)
	{
		( defined($_) and length($_) ) or next;
		$path .= "/" . $_;

		if ( ! stat($path) )
		{
			warn "Making directory $path\n";
			mkdir $path;
		}
	}
}

if ( ! stat($lockDir) )
{
	warn "Could not access the locking directory in register.pl\n";
	exit(1);
}

for ( 1..$maxProcs )
{
	my $lockFile = $lockDir . "/lck.$_";
	open($lockHandle,">$lockFile");

	if ( flock($lockHandle,2|4) )
	{
		$gotLock = 1;
		last;
	}
}

if ( ! $gotLock )
{
	# well, there were already $maxProcs going, lets aquire a blocking lock on one of them
	my $lockFile = $lockDir . "/lck." . (int(rand($maxProcs))+1);
	warn "register.pl Doing a blocking lock on $lockFile.\n";
	open($lockHandle,">$lockFile");

	if ( ! flock($lockHandle,2) )
	{
		warn "register.pl could not aquire blocking lock on $lockFile!\n";
		exit(1);
	}
}

my $tb = Pos::Webtop::Toolbox->new(tempTableFlag=>0, useClient => 0);
my $cgi = $tb->getCgi();
my $db = $tb->getWebtopDbWriter();
#$db->{'debug'} = 1;

my $request = $cgi->param('request');
my $full = "";

{
	if(! defined $request)
	{
		warn "Malformed request";
		last;
	}
	
	if ($request eq 'register') {

		my $randNumber    = $cgi->param('randNumber');
		my $localIp       = $cgi->param('localIp');
		my $localComputerEscaped = $cgi->param('localComputer');
		my $rdAgent			= $cgi->param('rdaType');
		my $xpUserNameEscaped = $cgi->param('xpUserName');
		my $client = $tb->getClient();
		my $userId;
		my $rdaId  = $cgi->param('id');

		# Create a session if user information was provided
		my $usernameEscaped = $cgi->param('username');
		my $passwordEscaped = $cgi->param('password');
		my $username = uri_unescape($usernameEscaped);
		my $password = uri_unescape($passwordEscaped);
		my $si;

		$username =~ s/%plus/+/g;
		$password =~ s/%plus/+/g;
		
		if (defined($username) and defined($password))
		{
			# Strip leading and trailing slashes
			$username =~ s/^\s+//g;
			$username =~ s/\s+$//g;
		
			$si = $client->createSession( userName => $username, password=> $password);
		}
		
		$userId = $client->getUserId;

		$localComputerEscaped =~ s/%plus/+/g;
		$xpUserNameEscaped =~ s/%plus/+/g;
		$rdAgent =~ s/\D//g;
		
		my $localComputer = uri_unescape($localComputerEscaped);
		my $xpUserName = uri_unescape($xpUserNameEscaped);
	
		if(not defined($userId) and defined($client))
		{
			my $expired = $client->isPasswordExpired();
			if(defined($expired) and ($expired eq '1'))
			{
				$full .= "<WebTopRDA><Action failure=\"Password has expired. Please log on to WebTop to change your password.\" allowRepeat=\"true\">$request</Action></WebtopRDA>";
				last;
			}
			else
			{
         	warn "Failed to create session (invalid auth probably?)";
			   $full .= "<WebTopRDA><Action failure=\"The authentication credentials you specified were invalid.\" allowRepeat=\"true\">$request</Action></WebTopRDA>";
				last;
			}
		}
		elsif(not defined($userId))
		{
			warn "Failed to create session (invalid auth probably?)";
			$full .= "<WebTopRDA><Action failure=\"The authentication credentials you specified were invalid.\" allowRepeat=\"true\">$request</Action></WebTopRDA>";
			last;
		}	

		# But if we get here, everything is kosher, we shall insert into the database.
		
		my ($w_user_computer_id) = $db->query(sql => "
				select
					w_user_computer_id
				from
					w_user_computers
				where
					computer_name = '" . $db->escape(dirty => $localComputer) . "'
					AND user_id = $userId
				for update
			");

		if (defined($w_user_computer_id) and ($w_user_computer_id > 0)) {

			# A computer by the requested name already exists, we can't allow stupid people to overwrite computers.

			$full .= "<WebTopRDA><Action failure=\"A computer with the name you're requesting is already registered.\" allowRepeat=\"true\">$request</Action></WebTopRDA>";
			warn "duplicate name requested";
				
		} else {

			my $md5 = Digest::MD5->new();
			$md5->add($password . $randNumber);

			my $authKey = $md5->hexdigest();

			my ($id) = $db->getNextSequenceValue( sequence => "w_user_computers_pk");

			$db->do(sql => "
				insert into
					w_user_computers
				(
					w_user_computer_id,
					user_id,
					computer_ip,
					computer_name,
					last_update,
				   " . ( (Pos::defaults::isPostgresDb()) ? "\"authorization\"" : "authorization") . ",
					rda_software_id,
					xp_user_name
				) values(
					$id,
					$userId,
					DOTTED_QUAD_TO_RAWIP32('" . $db->escape(dirty => $localIp) . "'),
					'" . $db->escape(dirty => $localComputer) . "',
					" . $db->getCurrentTimeStampString() . ",
					'" . $db->escape(dirty => $authKey) . "',
					$rdAgent,
					'" . $db->escape(dirty => $xpUserName) . "'
				)");
			
			$full .= "<WebTopRDA><Action>$request</Action><RDAId>$id</RDAId><RDAAuthorization>$authKey</RDAAuthorization></WebTopRDA>";
		
		}

	} elsif ($request eq 'newIp') {

		my $rdaId            = $cgi->param('id');
		my $rdaAuthorization = $cgi->param('authorization');
		my $localIp          = $cgi->param('ip');

		my ($authorization)  = $db->query(sql => "
				select
					wuc.authorization
				from
					w_user_computers wuc
				where
					w_user_computer_id = '" . $db->escape(dirty => $rdaId) . "'
				");

		if ($authorization ne $rdaAuthorization) {

			$full .= "<WebTopRDA><Action failure=\"Your authentication credentials are invalid.\" short=\"BADAUTH\">$request</Action></WebTopRDA>";

		} else {

			# Successfully auth'd

			$db->do(sql => "
				update
					w_user_computers
				set
					computer_ip = DOTTED_QUAD_TO_RAWIP32('" . $db->escape(dirty => $localIp) . "')
				where
					w_user_computer_id = '" . $db->escape(dirty => $rdaId) . "'
				");

			$full .= "<WebTopRDA><Action>$request</Action></WebTopRDA>";

		}

	} elsif ($request eq 'changeAgent') {
		my $rdaId 				=	$cgi->param('id');
		my $rdaAuthorization	=	$cgi->param('authorization');
		my $agentId				=	$cgi->param('agentType');

		my ($authorization)	=	$db->query(sql	=> "
				select
					wuc.authorization
				from
					w_user_computers wuc
				where
					w_user_computer_id = '" . $db->escape(dirty => $rdaId) . "'
				");

				if ($authorization ne $rdaAuthorization)
				{
					$full .= "<WebTopRDA><Action failure=\"Your authentication credentials are invalid.\" short=\"BADAUTH\">$request</Action></WebTopRDA>";
				}
				else
				{
					$db->do(sql => "
						update
							w_user_computers
						set
							rda_software_id = '" . $db->escape(dirty => $agentId) . "'
						where
							w_user_computer_id = '" . $db->escape(dirty => $rdaId) . "'
						");

					$full .= "<WebTopRDA><Action>$request</Action></WebTopRDA>";
					
				}
	
	} elsif ($request eq 'ping') {

		my $rdaId            = $cgi->param('id');
		my $rdaAuthorization = $cgi->param('authorization');
		my $localIp          = $cgi->param('ip');

		my ($authorization)  = $db->query(sql => "
				select
					wuc.authorization
				from
					w_user_computers wuc
				where
					w_user_computer_id = '" . $db->escape(dirty => $rdaId) . "'
				");

		if ($authorization ne $rdaAuthorization) {

			$full .= "<WebTopRDA><Action failure=\"Your authentication credentials are invalid.\" short=\"BADAUTH\">$request</Action></WebTopRDA>";

		} else {

			# Successfully auth'd

			$db->do(sql => "
				update
					w_user_computers
				set
					last_update = " . $db->getCurrentTimeStampString() . "
				where
					w_user_computer_id = '" . $db->escape(dirty => $rdaId) . "'
				");

			$full .= "<WebTopRDA><Action>$request</Action></WebTopRDA>";

		}

	} elsif ($request eq 'checkUpdate') {

		my $rdaId            = $cgi->param('id');
		my $rdaAuthorization = $cgi->param('authorization');

		my ($authorization)  = $db->query(sql => "
				select
					wuc.authorization
				from
					w_user_computers wuc
				where
					w_user_computer_id = '" . $db->escape(dirty => $rdaId) . "'
				");

		if ($authorization ne $rdaAuthorization) {

			$full .= "<WebTopRDA><Action failure=\"Your authentication credentials are invalid.\" short=\"BADAUTH\">$request</Action></WebTopRDA>";

		} else {

			my ($currentVersion) = $db->query(sql => "
					select
						version_string
					from
						w_rda_version
					");

			$full .= "<WebTopRDA><Action>$request</Action><Version>$currentVersion</Version></WebTopRDA>";

		}

	} elsif ($request eq 'getResDll') {

		my $usernameEscaped = $cgi->param('username');
		$usernameEscaped =~ s/%plus/+/g;

		my $username = uri_unescape($usernameEscaped);

		if (defined($username)) {

			my ($oemId) = $db->query(sql => "
					select
						oem_id
					from
						oems
					where
						oem_id = (
							select
								oem_id
							from
								customers
							where
								customer_id = (
									select 
										customer_id
									from
										groups
									where
										group_id = (
											select
												group_id
											from
												users
											where
												user_name = '" . $db->escape(dirty => $username) . "'
									)
							)
					)");
		
			if (not defined($oemId)) {
				$oemId = 1;
			}

			$oemId =~ s/(\W)/\\$1/g;

			my $f;
			
			open($f, "</usr/local/positive/WebInterface/LocalWebLib/OEM/$oemId/rdares.dll");

			if (defined($f)) {
				my $buf;
				my $len;

				while (($len = sysread($f, $buf, 8192)) != 0) {
					$full .= $buf;
				}
			}

			close($f);

		}

	} else {

		$full .= "<WebTopRDA><Action failure=\"Your client sent a request that the server could not understand.\" short=\"INCOMPAT\">$request</Action></WebTopRDA>";

	}
}

$db->commit;
$db->disconnect();
close($lockHandle);

if (defined($full)) {
	print "Content-type: text/plain\r\n";
	print "Content-Length: " . length($full) . "\r\n";
	print "\r\n";

	print $full;
}

