| 1 | #!/usr/bin/perl -w
 | 
|---|
| 2 | ###############################################################################
 | 
|---|
| 3 | ## Fancy Speed Test - Easily measure your upload and download speeds
 | 
|---|
| 4 | ## Home Page:   http://www.brandonchecketts.com/speedtest/
 | 
|---|
| 5 | ## Author:      Brandon Checketts
 | 
|---|
| 6 | ## File:        upload.cgi
 | 
|---|
| 7 | ## Version:     1.1
 | 
|---|
| 8 | ## Date:        2006-02-06
 | 
|---|
| 9 | ## Purpose:     Time the upload progress, forward to results.php (or back to
 | 
|---|
| 10 | ##              download.php if using auto_size)
 | 
|---|
| 11 | ###############################################################################
 | 
|---|
| 12 | 
 | 
|---|
| 13 | use strict;
 | 
|---|
| 14 | use File::Basename;         ## for dirname();
 | 
|---|
| 15 | use Time::HiRes qw(gettimeofday tv_interval);
 | 
|---|
| 16 | ## Time::HiRes should be included with most Perl distributions
 | 
|---|
| 17 | ## use "perl -MCPAN -e install Time::HiRes" if it isn't installed
 | 
|---|
| 18 | 
 | 
|---|
| 19 | my $dirname = dirname($0);
 | 
|---|
| 20 | my $config_file = "$dirname/speedtest.cfg";
 | 
|---|
| 21 | ## NOTE: 
 | 
|---|
| 22 | ## If you have to move upload.cgi to another directory (ie: /cgi-bin) then
 | 
|---|
| 23 | ## you will have to change the path for $config_file to point to the
 | 
|---|
| 24 | ## correct directory.  
 | 
|---|
| 25 | # my $config_file = "/home/brandonchecketts.com/speedtest/speedtest.cfg";
 | 
|---|
| 26 | 
 | 
|---|
| 27 | 
 | 
|---|
| 28 | 
 | 
|---|
| 29 | ## Make sure we read in the config file
 | 
|---|
| 30 | my $config = &ReadConfig($config_file);
 | 
|---|
| 31 | DieNicely("Unable to read configuration settings") if(! $config);
 | 
|---|
| 32 | 
 | 
|---|
| 33 | ## This is what PHP can't do .......
 | 
|---|
| 34 | my $content_length = $ENV{'CONTENT_LENGTH'} ? $ENV{'CONTENT_LENGTH'} : 1;
 | 
|---|
| 35 | 
 | 
|---|
| 36 | ## Don't buffer output
 | 
|---|
| 37 | $|=1;
 | 
|---|
| 38 | 
 | 
|---|
| 39 | ## Start the timer
 | 
|---|
| 40 | Debug("Starting to read");
 | 
|---|
| 41 | Debug("len is $content_length");
 | 
|---|
| 42 | my $t0 = [gettimeofday];
 | 
|---|
| 43 | 
 | 
|---|
| 44 | ## Read all of the STDIN (HTTP POST data)
 | 
|---|
| 45 | my $bytes_read = 0;
 | 
|---|
| 46 | while (read (STDIN ,my $line, 4096) && $bytes_read < $content_length ) {
 | 
|---|
| 47 |         $bytes_read += length($line);
 | 
|---|
| 48 | }
 | 
|---|
| 49 | ## Stop the timer
 | 
|---|
| 50 | my $t1 = [gettimeofday];
 | 
|---|
| 51 | Debug("Done reading");
 | 
|---|
| 52 | 
 | 
|---|
| 53 | 
 | 
|---|
| 54 | 
 | 
|---|
| 55 | ## Calculate the speed
 | 
|---|
| 56 | my $elapsed = sprintf("%.2f",tv_interval ( $t0, $t1 ));
 | 
|---|
| 57 | 
 | 
|---|
| 58 | my $upload_speed;
 | 
|---|
| 59 | if($elapsed != 0) {
 | 
|---|
| 60 |     $upload_speed = sprintf("%.2f",$bytes_read / $elapsed * 8 / 1024);
 | 
|---|
| 61 | } else {
 | 
|---|
| 62 |     $upload_speed="undefined";
 | 
|---|
| 63 | }
 | 
|---|
| 64 | my $uploadsize = $bytes_read / 1024;
 | 
|---|
| 65 | 
 | 
|---|
| 66 | Debug("\$upload_size is $uploadsize");
 | 
|---|
| 67 | Debug("\$bytes_read is $bytes_read");
 | 
|---|
| 68 | Debug("\$elapsed is $elapsed");
 | 
|---|
| 69 | Debug("\$upload_speed is $upload_speed");
 | 
|---|
| 70 | 
 | 
|---|
| 71 | 
 | 
|---|
| 72 | ## If we're using auto_size, then forward back to download.php with the
 | 
|---|
| 73 | ## speed values from out initial test.  
 | 
|---|
| 74 | ## Otherwise forward to result.php to display the results
 | 
|---|
| 75 | 
 | 
|---|
| 76 | my $url;
 | 
|---|
| 77 | if( $ENV{'QUERY_STRING'} =~ m/auto_size=1/) {
 | 
|---|
| 78 |     $url = $config->{'general'}->{'base_url'} . "download.php?".$ENV{'QUERY_STRING'}."&uptime=$elapsed&upsize=$uploadsize&upspeed=$upload_speed";
 | 
|---|
| 79 | } else {
 | 
|---|
| 80 |     $url = $config->{'general'}->{'base_url'} . "results.php?".$ENV{'QUERY_STRING'}."&uploadtime=$elapsed&uploadsize=$uploadsize&upspeed=$upload_speed";
 | 
|---|
| 81 | }
 | 
|---|
| 82 | 
 | 
|---|
| 83 | Log("Redirecting to $url");
 | 
|---|
| 84 | print "Location: $url\n\n";
 | 
|---|
| 85 | 
 | 
|---|
| 86 | 
 | 
|---|
| 87 | ## My standard Log() function
 | 
|---|
| 88 | sub Log {
 | 
|---|
| 89 |     my $message = shift;
 | 
|---|
| 90 |     my $logfile = $config->{'general'}->{'logfile'};
 | 
|---|
| 91 |     return if(! $logfile);
 | 
|---|
| 92 | 
 | 
|---|
| 93 |     (my $sec, my $min, my $hour, my $year, my $jdate)=(localtime())[0,1,2,5,7];
 | 
|---|
| 94 |     if($sec < 10) {
 | 
|---|
| 95 |         $sec="0$sec";
 | 
|---|
| 96 |     }
 | 
|---|
| 97 |     if($min < 10) {
 | 
|---|
| 98 |         $min="0$min";
 | 
|---|
| 99 |     }
 | 
|---|
| 100 |     if($hour < 10) {
 | 
|---|
| 101 |         $hour="0$hour";
 | 
|---|
| 102 |     }
 | 
|---|
| 103 | 
 | 
|---|
| 104 |     if($jdate < 100) {
 | 
|---|
| 105 |         if($jdate < 10) {
 | 
|---|
| 106 |             $jdate="0$jdate";
 | 
|---|
| 107 |         }
 | 
|---|
| 108 |         $jdate="0$jdate";
 | 
|---|
| 109 |     }
 | 
|---|
| 110 | 
 | 
|---|
| 111 |     $year=$year+1900;
 | 
|---|
| 112 |     if($jdate == "365" || ($jdate == "364" && ($year % 4 == 0))) {
 | 
|---|
| 113 |         $jdate++;
 | 
|---|
| 114 |     }
 | 
|---|
| 115 |     open(LOGFILE,">> $logfile") ||
 | 
|---|
| 116 |         DieNicely("Couldn't open $logfile");
 | 
|---|
| 117 |     print LOGFILE "$year $jdate $hour:$min:$sec $message\n";
 | 
|---|
| 118 |     close(LOGFILE);
 | 
|---|
| 119 | }
 | 
|---|
| 120 | 
 | 
|---|
| 121 | ## Display a nice error message if we have to die
 | 
|---|
| 122 | sub DieNicely {
 | 
|---|
| 123 |     my $message = shift();
 | 
|---|
| 124 |     print "Content-type: text/html\n\n<h1>A critical error occurred: $message</h1>\n";
 | 
|---|
| 125 |     Log("Dying: $message");
 | 
|---|
| 126 |     exit 1;
 | 
|---|
| 127 | }
 | 
|---|
| 128 | 
 | 
|---|
| 129 | ## Debug to the log file if the config file says to
 | 
|---|
| 130 | sub Debug {
 | 
|---|
| 131 |     Log(@_) if($config->{'general'}->{'debug'});
 | 
|---|
| 132 | }
 | 
|---|
| 133 | 
 | 
|---|
| 134 | 
 | 
|---|
| 135 | 
 | 
|---|
| 136 | ## Read in the configuration file into our $config variable
 | 
|---|
| 137 | sub ReadConfig() {
 | 
|---|
| 138 |     my $config;
 | 
|---|
| 139 |     $config_file = shift;
 | 
|---|
| 140 |     open(CONF,"<$config_file") ||
 | 
|---|
| 141 |         DieNicely("Unable to read configuration file: $config_file\n\n");
 | 
|---|
| 142 |     my $section;
 | 
|---|
| 143 |     while(<CONF>) {
 | 
|---|
| 144 |         chomp($_);
 | 
|---|
| 145 |         s/\r//g;        ## Remove DOS EOL Symbols
 | 
|---|
| 146 |         s/\#.*//g;      ## Remove comments
 | 
|---|
| 147 |         next if(! $_);
 | 
|---|
| 148 | 
 | 
|---|
| 149 |         if (substr($_,0,1) eq "[") {
 | 
|---|
| 150 |             $section = $_;
 | 
|---|
| 151 |             $section =~ s/\[//g;
 | 
|---|
| 152 |             $section =~ s/\]//g;
 | 
|---|
| 153 |             next;
 | 
|---|
| 154 |         }
 | 
|---|
| 155 |         next if($_ !~ m/=/);
 | 
|---|
| 156 |         
 | 
|---|
| 157 |         if($section) {
 | 
|---|
| 158 |             my ($item,$value) = split('=',$_);
 | 
|---|
| 159 |             ## Remove un-necessary speces
 | 
|---|
| 160 |             $item =~ s/ +$//g;
 | 
|---|
| 161 |             $value =~ s/^ $//g;
 | 
|---|
| 162 |             $config->{$section}->{$item} = $value;
 | 
|---|
| 163 |         }
 | 
|---|
| 164 |     }
 | 
|---|
| 165 |     close(CONF);
 | 
|---|
| 166 |     return $config;
 | 
|---|
| 167 | }
 | 
|---|
| 168 | 
 | 
|---|
| 169 | 
 | 
|---|
| 170 | 
 | 
|---|
| 171 | 
 | 
|---|
| 172 | 
 | 
|---|
| 173 | 
 | 
|---|