#!/usr/local/bin/perl -w

# PHP File Uploader with progress bar Version 1.02
# Copyright (C) Raditha Dissanyake 2003
# http://www.raditha.com

# Licence:
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
# 
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
# 
# The Initial Developer of the Original Code is Raditha Dissanayake.
# Portions created by Raditha are Copyright (C) 2000-2003
# Raditha Dissanayake. All Rights Reserved.
# 

#
# CHANGES
# As of version 1.00 this file no longer uses cookies. This has two
# major benefits; the first being that minority of users who do not
# like cookies are not inconvinienced. Secondly there is one less
# dependecy and this would lead to a smoother setup for most people.
#
# added a cache control header in version 1.02

use CGI;
use Fcntl qw(:DEFAULT :flock);

# use Carp;		
# Carp is only needed if you want debugging. Uncomment the above line
# if you comment out any of the carp statements in the body of the 
# script.


#
# the most obvious issue that we will face is file locking.
# if two threads read and write from the same file at the same
# time only one of them will be allowed to finish the operation.
# Since we are storing our temporary data in a file we are likely to
# run into that exact same problem.
# We can't overcome it but we can make sure the progress bar does
# not display junk when that happens.
#
#
# status codes = 0-uploading, 1-started, 2- complete


$query = new CGI();
$sessionid = $query->param('sessionid');
$iTotal = $query->param('iTotal');
$iRead = $query->param('iRead');
$status =  $query->param('iStatus');
$thisUrl = $query->url;

# The values for iStatus are
#	0 - in progress
#	1 - New upload
#	2 - Complete

#carp "iTotal = $iTotal, iRead = $iRead, status = $status, sessionId = $sessionid";

require("./header.cgi");


sub readFlength()
{
	#carp 	"$user_dir/flength";
	
	if(open (STAT,"$user_dir/flength"))
	{
		#flock(STAT, LOCK_SH);
		
		#$bRead = <STAT>;
		#close STAT;
		sysopen(STAT, "$user_dir/flength", O_RDONLY)
				or die "can't open numfile: $!";
		$ofh = select(STAT); $| = 1; select ($ofh);
		#flock(STAT, LOCK_EX)
		#	or die "can't write-lock numfile: $!";
		$iTotal = <STAT>;

		#carp "trying to read the stuff in $iTotal";
		if(defined($iTotal) && $iTotal ne "")
		{
			return 1;
		
		}
		else
		{
			return 0;
		}
	}
}

# many thanx to Terrence Johnson who pointed out the fact that i should have added 
# cache control header.

print "Pragma: no-cache\n";
print "Content-type: text/html\n\n ";
	
if($status == 1)
{
	#new upload starting
	show_starting();
}
elsif($status ==0)
{
	# in progress
	# we will try to read in the total size of data to be transfered from the
	# shared file. It will also tell us how much data has been transfered upto
	# now.

	$bRead = -s "$user_dir/postdata";
	
	if(defined $bRead)
	{
		# We have  been able to read in it from the file.

		$percent = $bRead * 100 / $iTotal;
		$iRead=$bRead;
		
	}
	else
	{
		&show_error();
		exit();
	}

	# division results in truncation errors at times so don't compare percentage
	if(($iTotal == $bRead) && $bRead != 0)
	{
		if($status == 1)
		{
			$bRead=0;
			$status=0;
			&get_last_values();
		}
		else
		{
			show_complete();
			unlink "$user_dir/flength";
			unlink "$user_dir/postdata";
			rmdir $user_dir;
			
			exit;
		}
	}
	else
	{
		$kachal = "$bRead , $iTotal";
	}


	&make_progress_bar();
	exit;
}
else 
{
	show_complete();
}

#
# Since the progress bar is in html, so it needs to refresh itself periodicaly to
# obtain new values. The refresh url with the query string is generated by this 
# function.

sub make_url
{

	#print "Content-type: text/html\n\n ";
	#print "hellow $iTotal $iStatus $sessionid $iRead <br>\n" ;

	$url= "$thisUrl?iTotal=$iTotal&iRead=$iRead&iStatus=$status&sessionid=$sessionid";
	$url =~ s/\n//;
	#print $url;
	return $url;

}

sub make_progress_bar
{


	$url = make_url();
	

	print <<__PART1__
	<html>
	<head>
	 <title>file Upload Status</title>
 	 <meta HTTP-EQUIV=Refresh CONTENT="$interval; URL=$url"></head>
	 </head>
	<body bgcolor="#eeeeee">
		<table border=0 width="100%">
		  <tr><TD align="center"  bgcolor="#ecf8ff">File Upload In Progress</td></tr></table>
		  <tr><td>
		    <table border=0 width='100%'>
			<tr><td>
			 <table border=0 width='$percent%' bgcolor='red'>
 			  <tr><td width='100%' style="height: 20px"> </td></tr>
		         </table>
			</td></tr>
		     </table>
		   </td></tr>
	           <tr><td>$bRead bytes out of $iTotal uploaded</td></tr>
		</table>
	</body>
	</html>
__PART1__

}


sub show_complete
{
	
	$status=2;
	$url = make_url();


	print <<__PART2__;
		<html><head><title>File Upload Complete</title>
			<!meta HTTP-EQUIV=Refresh CONTENT="$interval; URL=$url">
		</head>
		<body  bgcolor="#eeeeee">
		  <table align="center">
		   <tr><td align="center">File Upload Complete</td></tr>
		   <tr><td align="center"><a href="javascript:parent.window.close();">close</a></td></tr>
		  </table>
		</body>
		</html>
__PART2__

}

sub show_starting
{
	#carp "starting";
	if(readFlength() == 1)
	{
		$status=0;
	}
	$url = make_url();


	print <<__PART2__;
		<html><head><title>File Upload Complete</title>
			<meta HTTP-EQUIV=Refresh CONTENT="$interval; URL=$url">
		</head>
		<body bgcolor="#eeeeee">
		 <table align="center"><tr><td>File Upload in progress</td></tr></table>
		</body>
		</html>
__PART2__
}

sub show_error
{
	$url = make_url();

	print <<__PART2__;
		<html><head><title>File Upload Complete</title>
		<meta HTTP-EQUIV=Refresh CONTENT="$interval; URL=$url"></head>
		<body>File Upload in progress, total file size uncertain.</body>
		</html>
__PART2__

}

# this function may not return;
sub get_last_values()
{
	if($status == 1)
	{

		#print "Content-type: text/html\n\n ";
		#print " in get last values";
		show_starting();
		exit;
	}
	else
	{

	 	if($status == 2)
		{

			
			show_complete();
			exit;
		}
		else
		{

			#
			# we have done everything possible to try to retrieve the data
			# now try to calculate the percentage once again
			#
			$iTotal = $iTotal;
			$bRead = $iRead;

			if(defined($iTotal) && $iTotal != 0)
			{
				$percent = $bRead * 100 / $iTotal;
				$kachal="1";
			}
			else
			{
				&show_error();
				exit;
			}
		}
	}
}
