# Cool Randupload # Revision history: # v1.0.0 -- 02-10-2000 -- started # v1.1.0 -- 02-11-2000 -- adding config file support # v1.2.0 -- 02-09-2002 -- Delete link and retry if link is nonexistent, # support actual files not just links # # Notes: The CFG file is a newline-delimited file of number/dir pairs # The number must be an integer and at either the beginning or end of # the line. I don't recommend using a directory name ending in a # space and number, but otherwise spaces should not confuse this code. # (No guarantees about the FTP package though!) # Install this with ppm (you may not have the complete libwin32 by default): # "install libwin32" use Win32::Shortcut; print "Cool Randupload v1.1.0\n"; (5 == @ARGV) or die "Args: RemoteHost LoginID LoginPW Path/CFGFile RemoteFile"; ($remoteHost, $loginID, $loginPW, $pathLocalOrCFGFile, $remoteFile) = @ARGV; my $localfile; $localfile = PickLocalFile($pathLocalOrCFGFile); # strip full remote filename into remote path and remote filename ($remotePath, $remoteFilename) = (($remoteFile =~ /^(.*)\/(.*)/), ($1, $2)); print "Remote path: $remotePath / $remoteFilename\n"; # upload the file use Net::FTP; $ftp = Net::FTP->new($remoteHost, Debug => 0) or die "Couldn't connect to server"; $ftp->login($loginID, $loginPW) or die "Couldn't login"; $ftp->cwd($remotePath) or die "Couldn't change dir"; ($remoteFilename =~ /(html?|txt|pl|bat|c|cpp)$/) ? $ftp->ascii() : $ftp->binary(); $ftp->put($localfile, $remoteFilename) or die "couldn't upload $remoteFilename"; $ftp->quit; exit; sub PickLocalFile { my ($pathLocalOrCFGFile) = @_; my $pathLocal; my $linkfile; my $localfile; # Randomize (Programming Perl, p. 223) #srand( time() ^ ($$ + ($$ << 15)) ); # Note that the time increments don't seem to affect the initial # value of the randomizer much. Reversing the time helps. # Also, on Windows, the process ID isn't monotonically increasing. srand( (reverse time()) ^ ($$ + ($$ << 15)) ); while (!$localfile) { # Get local path (via config file, if necessary) if (-f $pathLocalOrCFGFile) { $pathLocal = ReadCFGFile($pathLocalOrCFGFile); } else { $pathLocal = $pathLocalOrCFGFile; } print "Reading from path: $pathLocal\n"; opendir(DIR, $pathLocal) or die "can't opendir : $!"; @dircontents = readdir(DIR); closedir DIR; $nLastDirEntry = $#dircontents; $nSizeDir = @dircontents; $nSizeDir > 2 or die "No files in input directory!"; $nRndIdx = int(rand ($nSizeDir - 2)) + 2; # hack to nuke "." and ".." $linkfile = "$pathLocal\\@dircontents[$nRndIdx]"; print "Selected $linkfile\n"; # This code works with links or regular files my $LINK=new Win32::Shortcut(); if ($LINK->Load($linkfile)) { print "Shortcut to: $LINK->{'Path'} $LINK->{'Arguments'} \n"; $localfile = $LINK->{'Path'}; $LINK->Close(); if (! (-f $localfile)) { # delete the offending nonexistent link print "Nonexistent destination--deleting link!\n"; unlink ($linkfile); (! (-f $linkfile)) or die "failed to delete $linkfile!"; $localfile = ""; # make loop repeat } } else { # file is probably a real file, not a mere link $localfile = $linkfile; } } print "Returning $localfile\n"; return $localfile; } sub ReadCFGFile { my ($szCFGFile) = @_; open(CFGFILE, "+<$szCFGFile") or die "Can't open file : $!"; my (@arrDirs, @arrWeights); my $i; my $nTotalWeight; for ($i = 0; ; $i++) { if (/^(.+) +([0-9]+)$/) { # [dir] [weight] (@arrDirs[$i], @arrWeights[$i]) = ($1, $2); } elsif (/^([0-9]+) +(.+)$/) { # [weight] [dir] (@arrDirs[$i], @arrWeights[$i]) = ($2, $1); } else { die "Can't read file : $!"; } #print "Dir $arrDirs[$i]; wgt $arrWeights[$i]\n"; $nTotalWeight += @arrWeights[$i]; } my $n = $i; my $nWhich = rand $nTotalWeight; my $testn = @arrWeights; #print ("$n, $testn, $nWhich, $nTotalWeight\n"); for ($i = 0; $i < $n; $i++) { # Example: @arrWeights[0] = 10, $nWhich = 10 # first iteration: $nWeight = 0 # Should go again because rand goes [0, $nTotalWeight) #print "$i, @arrWeights[$i]\n"; if (($nWhich -= @arrWeights[$i]) < 0) { return @arrDirs[$i]; } } die "Array bounds exceeded!" }