#!/usr/local/bin/perl
use lib '/usr/local/rib/lib';
# NHSE Repository in a Box (RIB)
#
# The author of this software is Paul McMahan.
# Copyright (c) 1998 by the University of Tennessee.
# Permission to use, copy, modify, and distribute this software for any
# purpose without fee is hereby granted, provided that this entire notice
# is included in all copies of any software which is or includes a copy
# or modification of this software and in all copies of the supporting
# documentation for such software.
# THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
# WARRANTY.  IN PARTICULAR, NEITHER THE AUTHORS NOR UNIVERSITY OF TENNESSEE
# MAKE ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
# MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
#

use strict;
use RIB::Util ();
use Data::Dumper ();
use LWP::UserAgent;
use RIB::ConfigParser ();
use RIB::DomainParser ();
use Cwd;
$Data::Dumper::Indent = 0;

my $util = RIB::Util->new();
my %in = RIB::Util->ReadParse();
$util->PrintHeader();

my $repository = $util->GetRepoName();
if (!$repository) {
  $util->ErrorMessage("repository was not specifed in your input.");
}

my $filepath = $util->GetRibDir() . "/repositories/" . $repository;
my $urlpath  = $util->GetRibUrl() . "/repositories/" . $repository;
my $back_to_top = $util->BackToTop($repository);

my $top = "<head><title>Manage software files for "
     . "$repository</title></head>\n"
     . "<body bgcolor=#FFFFF0>"
     . "<center>"
     . "<h1>Manage software files for $repository</h1>\n"
     . "</center>"
     . "<p><hr><p>\n"
     . "<a href=" . $util->GetRibUrl() . "/help/help.html#managing_software_files>"
     . "<i>help on managing software files</i></a><p>";

my $back = "<p><hr>\n"
  . "<a href=manage_software_files.pl>Back to software file management page</a>\n"
  . "</body>\n";


# file used to store mirroring information
my $mirrorfile = $filepath . "/files/.mirror";


# create a lock file by appending ".lock" to the
# first argument and trying to create that file.
# if that file already exists then wait for a while
# first.
sub CreateLockfile {
  my $file = shift;  # file to lock
  my $timeout = shift;  # number of minutes after which $file
                        # should be assumed to be stale
  my $lockfile = $file . ".lock";

  # remove the lock file if it already exists and is more than
  # $timeout minutes old
  if ($timeout) {
    unlink $lockfile if (time - (stat($lockfile))[10]) > $timeout * 60;
  }
  my $count=0;
  while (++$count < 30) {
    if (-e $lockfile) {
      sleep 1;
    } else {
      last;
    }
  }
  if ($count == 30) {
    my $message = "The lockfile for this collection has not expired yet. ";
    if ($timeout) {
      $message .= "The lockfile will expire within the next $timeout minutes, "
                     . "so please try again after that time.";
    }
    $util->ErrorMessage($message);
  }
  unless (open(LOCK, ">$lockfile")) {
    my $dir = $file;
    $dir =~ s,/[^/]+$,,;
    $util->ErrorMessage("Couldn't open lockfile $lockfile.<br>"
                      . "Reason : $!<p>"
                      . "If there is a permissions problem then you "
                      . "need to make sure that the user "
                      . $util->GetUserName() . " has permission to create a file in $dir.");
  }
}

sub DeleteLockfile {
  my $file = shift;  # file that is locked
  my $lockfile = "$file" . ".lock";
  unless (unlink ($lockfile)) {
    print STDERR "Can't unlink $lockfile : reason $!";
  }
}
  
sub GetMirrorInfo {
  unless (-e $mirrorfile) {
    unless (open (FOO, ">$mirrorfile")) {
      $util->ErrorMessage("Can't create $mirrorfile.<br>Reason : $!<p>\n"
                        . "If there is a permissions problem then you need to "
                        . "make sure that the user " . $util->GetUserName()
                        . " has permission to create a file in $filepath/files");
    }
    close FOO;
  }
  
  # the mirror file should not be readable until this program
  # needs it.  that's because it might contain username/passwd
  # pairs used for mirroring.  after we read the file in we should
  # set the permissions back to unreadable.  this prevents people
  # from retrieving the file via http
  unless (chmod 0600, $mirrorfile) {
    $util->ErrorMessage("Can't chmod mirror file : $!");
  }
  
  &CreateLockfile($mirrorfile, 5);
  unless (open (MIRROR, "<$mirrorfile")) {
    &DeleteLockfile($mirrorfile);
    chmod 0000, $mirrorfile;
    $util->ErrorMessage("Can't read $mirrorfile.<br>Reason : $!\n<p>"
                      . "If there is a permissions problem then you need to "
                      . "make sure that the user " . $util->GetUserName()
                      . " has permission to read the file $mirrorfile");
  }
  undef ($/);
  my $buf = <MIRROR>;
  $/= "\n";
  &DeleteLockfile($mirrorfile);
  my $ptr = [];
  if ($buf) {
    $ptr = eval "my $buf";
  }
  undef $buf;
  close (MIRROR);
  # so people can't retrieve this file via http.  don't test
  # return status of call, just hope it works since call above
  # worked (this is not a good time to bug out)
  chmod 0000, $mirrorfile;
  return $ptr;
}

# this subroutine will find out whether a url is redirected
# and will follow the redirects until it finds the "root" url
sub FindRootUrl {
  my $url = shift;
  my $ua = new LWP::UserAgent;
  my $req = new HTTP::Request HEAD => $url;
  my $res = $ua->request($req); # automatically follows redirects
  $res->request->url->as_string;
}


$|=1;
print $top;
  
if ($in{update}) {
  ## start the mirroring update process
  if ($in{start}) {
    my $pid;
    $!="";
    if ($pid = fork) {
      wait;  ## parent wait on first child (should happen quickly)
      print "<strong>Mirroring process successfully started.</strong>\n";
      print "The background process ID is ", $pid+1, ".<p>\n";
      if ($in{email}) {
        print "The results of the mirroring process will be sent to $in{email}.\n";
        print "That message will tell you which files were checked and if they were\n";
        print "updated or unchanged.\n";
      } else {
        print "Since you did not specify an email address to send the results of the\n";
        print "mirroring process to, you will not be informed of the status of the upload.\n";
        print "However, you can check the date on the <a href=manage_software_files.pl>main";
        print "software management page</a> to see when the last successful update was\n";
        print "completed.\n";
      }
      print $back;
      exit (0);
    } elsif (defined $pid) {
      # 2nd fork forces child into background
      unless (fork) {   #child's child
        ## there's a bug in NCSA httpd1.3 and some netscape servers
        ## that prevents backgrounding of the child process. so the
        ## first 20 filehandles are closed.  This kills unclosed
        ## socket 
        my $SYS_close;
        if (`uname -s` =~ /irix/i) {
          # per /usr/include/sys.s
          $SYS_close = 1006;
        } else {
          $SYS_close = 6;
        }
        if (`uname -s` !~ /aix/i) {
          my $i;
          for ($i=0; $i<20; $i++) {
            eval {syscall($SYS_close, $i+0)};
          }
        }
        sleep 1 until getppid == 1;
        $in{email}=~ s/\s*(\S*)\s*/$1/;
        delete $in{email} unless $in{email} =~ /^[A-Za-z0-9\.-~]+@[A-Za-z0-9\.-~]+$/;
        if ($in{email}) {
          exec "./update_mirrors.pl", "-e", "$in{email}";
        } else {
          exec "./update_mirrors.pl";
        }
      }
      ## first child exits quickly
      exit (0);
    } else  {
      print "<strong>Mirroring not started</strong>\n";
      print "The mirroring process could not be started because of a\n";
      print "fork error : $!\n";
      print $back;
      exit(0);
    }
  }
  ## display form for mirroring update
  print "When you start the update process, all of the software which is mirrored\n";
  print "by this repository will be checked at its master site and updated if necessary.\n";
  print "Since this update process can take a long time to complete and shouldn't\n";
  print "be interrupted, the process\n";
  print "will start in the background after you press the start\n";
  print "button below.\n";
  print "<p>If you specify an email address \n";
  print "then the results of the update will be sent to that address when the process\n";
  print "has completed.  Otherwise, the process will finish its job silently. It is\n";
  print "recommended that you specify an email address.\n<p>\n";
  print "<form method=post action=manage_software_files.pl>\n";
  print "<input type=hidden name=update value=1>\n";
  print "<input type=hidden name=start value=1>\n";
  print "Email results of update to : <input name=email size=40> (optional)<p>\n";
  print "<input type=submit value=\"Start the Update Process\">\n";
  print "</form>\n";
  print $back;
  exit;
}

if ($in{rename}) {
  if ($in{filename} && $in{newname} && $in{verified}) {
    if ($in{newname} =~ m,/,) {
      $util->ErrorMessage("new filename can't contain &quot;/&quot;");
    }
    if (-e "$filepath/files/$in{filename}") {
      unless (rename ("$filepath/files/$in{filename}", "$filepath/files/$in{newname}")) {
        $util->ErrorMessage("Couldn't rename $filepath/files/$in{filename} "
                          . "to $filepath/files/$in{newname}.<p>Reason: $!");
      }
    }

    ## if this file is set up for mirroring then update the mirror info file
    if (-f $mirrorfile) {
      unless (chmod 0600, $mirrorfile) {
        $util->ErrorMessage("Can't chmod mirror file : $!");
      }
      &CreateLockfile($mirrorfile, 5);
      unless (open (MIRROR, "+<$mirrorfile")) {
        &DeleteLockfile($mirrorfile);
        chmod 0000, $mirrorfile;
        $util->ErrorMessage("Can't open $mirrorfile<br>Reason : $!\n<p>"
                          . "If there is a permissions problem then you need to "
                          . "make sure that the user " . $util->GetUserName()
                          . " has permission to read the file $mirrorfile");
      }
      undef ($/);
      my $buf = <MIRROR>;
      $/= "\n";
      my @mirror_list;
      if ($buf) {
        my $tmp = eval "my $buf";
        @mirror_list = @$tmp;
        undef $tmp;
      }
      undef $buf;
      my @new_mirror_list;
      foreach (@mirror_list) {
        if ($_->{filename} eq $in{filename}) {
          $_->{filename} = $in{newname};
        }
        push (@new_mirror_list, $_);
      }
      seek (MIRROR, 0, 0);
      truncate (MIRROR, 0);
      print MIRROR Data::Dumper::Dumper(\@new_mirror_list);
      close (MIRROR);
      &DeleteLockfile($mirrorfile);
      chmod 0000, $mirrorfile;
    }
    print "<h2>Success</h2>\n";
    print "The file has been renamed.\n";
    print $back;
    exit;
  }
  elsif ($in{filename} && $in{newname}) {
    $in{newname} =~ s/^\s*(\S+)\s*$/$1/m;
    if ($in{newname} !~ /^[A-Za-z0-9\.,_-]+$/) {
      $util->ErrorMessage("The new filename that you choose can only have "
                        . "alphanumeric characters.  The following characters "
                        . "are also acceptable :<br>. , _ -\n<p>Please back "
                        . "up and try your submission again.");
    }
    if ($in{newname} eq $in{filename}) {
      $util->ErrorMessage("You did not choose a new filename but instead repeated the "
                        . "current one.<P>Please back up and try your submission again.");
    }
    unless (opendir (DIR, "$filepath/files")) {
      $util->ErrorMessage("Can't opendir $filepath/files : $!");
    }
    my $file;
    foreach $file (readdir(DIR)) {
      if ($in{newname} eq $file) {
        $util->ErrorMessage("The new filename that you chose is already being "
                          . "used in this repository's upload directory.  Please "
                          . "back up and choose a different name.<p>Alternatively, "
                          . "you can <a href=manage_software_files.pl?delete=1"
                          . "&filename=$in{newname}>delete</a> the file that is "
                          . "already using this name.");
      }
    }
    print "Are you sure that you want to rename the file &quot;$in{filename}&quot; ";
    print "to &quot;$in{newname}&quot;?<p>";
    print "<form method=post action=manage_software_files.pl>\n";
    print "<input type=hidden name=verified value=1>\n";
    print "<input type=hidden name=filename value=$in{filename}>\n";
    print "<input type=hidden name=newname value=$in{newname}>\n";
    print "<input type=hidden name=rename value=1>\n";
    print "<input type=submit value=Yes>\n";
    print "</form>\n";
    print $back;
    exit;
  }
  elsif ($in{filename}) {
    print "Please choose a new name for the file <i>$in{filename}</i> :\n";
    print "<p><form method=post action=manage_software_files.pl>\n";
    print "<input type=hidden name=filename value=$in{filename}>\n";
    print "<input type=hidden name=rename value=1>\n";
    print "<input name=newname value=$in{filename} size=40>\n";
    print "<input type=submit value=Submit>\n";
    print $back;
    exit;
  }
  else {
    print "Please choose the file that you would like to rename :<ul>\n";
    my $mirror_list = &GetMirrorInfo();
    # get list of uploaded files (non-mirrored files).
    # just push them onto the end of the mirror_list.
    opendir (DIR,"$filepath/files");
    foreach (grep /^[^\.]/, readdir(DIR)) {
      my $tmp;
      my $found=0;
      foreach $tmp (@$mirror_list) {
        $found = 1 if $tmp->{filename} eq $_;
      }
      push @$mirror_list, { filename=>$_, URL=>"-" } unless $found;
    }
    closedir DIR;
    foreach (@$mirror_list) {
      print "<li><a href=manage_software_files.pl?rename=1&filename=", $_->{filename}, ">";
      print $_->{filename}, "</a>\n";
    }
    print "</ul>\n";
    print $back;
    exit;
  }
}


if ($in{delete}) {
  if ($in{filename} && $in{verified}) {
    unlink ("$filepath/files/$in{filename}");
    if ($mirrorfile) {
      ## don't forget to make sure the mirror file gets the info removed
      ## or the file will reappear during the next mirror update.
      unless (chmod 0600, $mirrorfile) {
        $util->ErrorMessage("Can't chmod mirror file : $!");
      }
      &CreateLockfile($mirrorfile, 5);
      unless (open (MIRROR, "+<$mirrorfile")) {
        &DeleteLockfile($mirrorfile);
        chmod 0000, $mirrorfile;
        $util->ErrorMessage("Can't open $mirrorfile<br>Reason : $!\n<p>"
                          . "If there is a permissions problem then you need to "
                          . "make sure that the user " . $util->GetUserName()
                          . " has permission to read the file $mirrorfile");
      }
      undef ($/);
      my $buf = <MIRROR>;
      $/= "\n";
      my @mirror_list;
      if ($buf) {
        my $tmp = eval "my $buf";
        @mirror_list = @$tmp;
        undef $tmp;
      }
      undef $buf;
      my @new_mirror_list;
      foreach (@mirror_list) {
        next if $_->{filename} eq $in{filename}; # this entry will be replaced
        push (@new_mirror_list, $_);
      }
      seek (MIRROR, 0, 0);
      truncate (MIRROR, 0);
      print MIRROR Data::Dumper::Dumper(\@new_mirror_list);
      close (MIRROR);
      &DeleteLockfile($mirrorfile);
      chmod 0000, $mirrorfile;
    }
    print "<h2>Success</h2>\n";
    print "The file has been deleted.\n";
    print $back;
    exit;
  } elsif ($in{filename}) {
    print "Are you sure that you wish to delete the following file :\n";
    print "<dl><dd>$in{filename}</dl>\n";
    print "<form method=post action=manage_software_files.pl>\n";
    print "<input type=hidden name=delete value=1>\n";
    print "<input type=hidden name=filename value=$in{filename}>\n";
    print "<input type=hidden name=verified value=1>\n";
    print "<input type=submit value=Yes>\n";
    print "</form>\n";
    print $back;
    exit;
  } else {
    print "Please choose the software that you wish to delete from the list\n";
    print "below :\n<ul>";
    my $mirror_list = &GetMirrorInfo();
    # get list of uploaded files (non-mirrored files).
    # just push them onto the end of the mirror_list.
    opendir (DIR,"$filepath/files");
    foreach (grep /^[^\.]/, readdir(DIR)) {
      my $tmp;
      my $found=0;
      foreach $tmp (@$mirror_list) {
        $found = 1 if $tmp->{filename} eq $_;
      }
      push @$mirror_list, { filename=>$_, URL=>"-" } unless $found;
    }
    closedir DIR;
    foreach (sort {$a->{filename} cmp $b->{filename}} @$mirror_list) {
      print "<li><a href=manage_software_files.pl?delete=1&filename=", $_->{filename}, ">";
      print $_->{filename}, "</a>\n";
    }
    print "</ul>\n";
    print $back;
    exit;
  }
}

if ($in{upload}) {
  if ($in{url}) {
    $in{url} =~ s/\s*(\S+)\s*/$1/s;
    unless ($in{url} =~ /^(http|ftp|gopher):\/\//i) {
      $util ->ErrorMessage("The url that you specified : &quot;$in{url}&quot; "
                         . "cannot be uploaded.  Urls should be of the form :<ul>"
                         . "<li>http://hostname/path/to/file "
                         . "<li>ftp://hostname/path/to/file"
                         . "<li>gopher://hostname/path/to/file</ul>\n");
    }

    my $root_url = &FindRootUrl($in{url});
    if ($root_url ne $in{url}) {
      print "<p>The url that you specified, $in{url}, is server redirected to the\n";
      print "url ", $root_url, ".  The url which is the target of the redirect will\n";
      print "be used to upload the software instead of the url that you specified.<p>\n";
      $in{url} = $root_url;
    }

    my $basename;
    ($basename) = $in{url} =~ m,/([^/]+)$,;
    unless ($basename) {
      $util->ErrorMessage("The url that you specified : &quot;$in{url}&quot; "
                        . "does not point to a file, but instead points at a\n"
                        . "directory.  The url that you specify should point to\n"
                        . "to a file.");
    }

    if (!($in{overwrite})) {
      my $mirror_list = &GetMirrorInfo();

      # get list of uploaded files (non-mirrored files).
      # just push them onto the end of the mirror_list.
      opendir (DIR,"$filepath/files");
      foreach (grep /^[^\.]/, readdir(DIR)) {
        my $tmp;
        my $found=0;
        foreach $tmp (@$mirror_list) {
          $found = 1 if $tmp->{filename} eq $_;
        }
        push @$mirror_list, { filename=>$_, URL=>"-" } unless $found;
      }
      closedir DIR;

      foreach (@$mirror_list) {
        if ($_->{URL} eq $in{url}) {
          print "The url that you specified (<i>$in{url}</i>) is already\n";
          print "mirrored by this repository.<p>\n";
          print "If you would like for the currently mirrored copy of this file ";
          print "to be uploaded again then you can ";
          print "<a href=manage_software_files.pl?update=1>update the mirrored files ";
          print "in this repository</a>.\n";
          print $back;
          exit;
        }
        if ($_->{filename} eq $basename) {
          print "The url that you specified (<i>$in{url}</i>) points to a file whose\n";
          print "name ($basename) is already taken in this repository's ";
          print "upload directory.\n";
          print "<p>Since two files in a directory cannot have the ";
          print "same name, if you still want to upload this file then\n";
          print "your choices are :<br>\n";

          #replace the file
          print "<form method=post action=manage_software_files.pl>";
          print "<input type=hidden name=password value=$in{password}>";
          print "<input type=hidden name=username value=$in{username}>";
          print "<input type=hidden name=mirror value=$in{mirror}>";
          print "<input type=hidden name=url value=$in{url}>";
          print "<input type=hidden name=email value=$in{email}>";
          print "<input type=hidden name=upload value=1>";
          print "<input type=hidden name=overwrite value=1>";
          print "<input type=submit value=\"Replace the local file\">";
          print "</form><br>\n";

          #delete the file
          print "<form method=post action=manage_software_files.pl>";
          print "<input type=hidden name=filename value=\"", $_->{filename}, "\">";
          print "<input type=hidden name=delete value=1>";
          print "<input type=submit value=\"Delete the local file\">\n";
          print "</form><br>\n";

          #rename the file
          print "<form method=post action=manage_software_files.pl>";
          print "<input type=hidden name=filename value=\"", $_->{filename}, "\">";
          print "<input type=hidden name=rename value=1>";
          print "<input type=submit value=\"Rename the local file\">\n";
          print "</form><br>\n";
          print $back;
          exit;
        }
      }
    }

    # go ahead and overwrite the file, if it exists
    if ($in{mirror}) {
      unless (-f $mirrorfile) {
        open (MIRRORFILE, ">$mirrorfile") ||
          $util->ErrorMessage("Can't open new mirror file : $!");
        close MIRRORFILE;
      }
      unless (chmod 0600, $mirrorfile) {
        $util->ErrorMessage("Can't chmod mirror file : $!");
      }
      &CreateLockfile($mirrorfile, 5);
      unless (open (MIRROR, "+<$mirrorfile")) {
        &DeleteLockfile($mirrorfile);
        chmod 0000, $mirrorfile;
        $util->ErrorMessage("Can't open $mirrorfile<br>Reason : $!\n<p>"
                          . "If there is a permissions problem then you need to "
                          . "make sure that the user " . $util->GetUserName()
                          . " has permission to read the file $mirrorfile");
      }
      undef ($/);
      my $buf = <MIRROR>;
      $/= "\n";
      my @mirror_list;
      if ($buf) {
        my $tmp = eval "my $buf";
        @mirror_list = @$tmp;
        undef $tmp;
      }
      undef $buf;
      my @new_mirror_list;
      foreach (@mirror_list) {
        next if $_->{filename} eq $basename; # this entry will be replaced
        push (@new_mirror_list, $_);
      }
      push (@new_mirror_list, {URL=>$in{url}, filename=>$basename,
                               username=>$in{username}, password=>$in{password}});
      seek (MIRROR, 0, 0);
      truncate (MIRROR, 0);
      print MIRROR Data::Dumper::Dumper(\@new_mirror_list);
      close (MIRROR);
      &DeleteLockfile($mirrorfile);
      chmod 0000, $mirrorfile;
    }

    #get the file with the mirroring script
    my $pid;
    $!="";
    if ($pid = fork) {
      wait;  ## parent wait on first child (should happen quickly)
      print "<h2>Success</h2>\n";
      print "The upload process has been started. The file will be saved to the location :\n";
      print "<dl><dd>$filepath/files/$basename</dl>\n";
      if ($in{email}) {
        print "The results of the upload process will be sent to $in{email}.\n";
        print "That message will tell you if the upload was successful or if there\n";
        print "were any problems with the upload.\n";
      } else {
        print "Since you did not specify an email address to send the results of the\n";
        print "upload process to, you will not be informed of the status of the upload.\n";
        print "However, you can check the date on the <a href=manage_software_files.pl>main";
        print "software management page</a> to view information about the software files\n";
        print "currently in this repository.\n";
      }
      print $back;
      exit (0);
    } elsif (defined $pid) {
      # 2nd fork forces child into background
      unless (fork) {   #child's child
        ## there's a bug in NCSA httpd1.3 and some netscape servers
        ## that prevents backgrounding of the child process. so the
        ## first 20 filehandles are closed.  This kills unclosed
        ## socket
        my $SYS_close;
        if (`uname -s` =~ /irix/i) {
          # per /usr/include/sys.s
          $SYS_close = 1006;
        } else {
          $SYS_close = 6;
        }
        if (`uname -s` !~ /aix/i) {
          my $i;
          for ($i=0; $i<20; $i++) {
            eval {syscall($SYS_close, $i+0)};
          }
        }
        sleep 1 until getppid == 1;
        $in{email}=~ s/\s*(\S*)\s*/$1/;
        delete $in{email} unless $in{email} =~ /^[\w\-\.~:,]+@[\w\-\.~:,]+$/;
        my $script = Cwd::cwd() . "/lwp-download.pl";
        unless (chdir ("$filepath/files")) {
          print STDERR "Can't chdir $filepath/files : $!\n";
          exit (1);
        }
        if ($in{password} or $in{username}) {
          if ($in{email}) {
            exec $script, '-C', "$in{username}:::::$in{password}", '-e', $in{email}, $in{url};
          }
          exec $script, '-C', "$in{username}:::::$in{password}", $in{url};
        }
        if ($in{email}) {
            exec $script, '-e', $in{email}, $in{url};
        }
        exec $script, $in{url};
      }
      ## first child exits quickly
      exit (0);
    } else  {
      print "<strong>Upload not started</strong>\n";
      print "The upload  process could not be started because of a\n";
      print "fork error : $!\n";
      print $back;
      exit(0);
    }
  } else {
    print "Please specify the url for the file that you want to upload.  When you\n";
    print "press the Submit button below the file will start uploading in a background\n";
    print "process (you won't have to wait for the file to finish uploading).\n";
    print "<p>You can specify an email address that the results of the upload should be\n";
    print "sent to.  It is recommended that you specify an email address because\n";
    print "otherwise you wouldn't know if an error had occurred during the upload.\n";
    print "<form method=post action=manage_software_files.pl>\n";
    print "<table border=0>\n";
    print "<tr><td>URL</td><td><input name=url size=50>\n</td></tr>\n";
    print "<tr><td>&nbsp;</td><td><input type=checkbox name=mirror>";
    print "Set up a mirror for this file</td></tr>\n";
    print "<tr><td>Email</td><td><input name=email size=25> (optional)</td></tr>\n";
    print "<tr><td colspan=2>&nbsp;<p>\n";
    print "<i>(You don't need to specify username or password unless they ";
    print "are required to access the url above)</i></td></tr>\n";
    print "<tr><td>Username</td><td><input name=username size=25> (optional)</td></tr>\n";
    print "<tr><td>Password</td><td><input name=password type=password size=25>";
    print " (optional)</td></tr>\n";
    print "<tr><td colspan=2>&nbsp;<p>";
    print "<input type=hidden name=upload value=1>\n";
    print "<input type=submit value=Submit>\n";
    print "<input type=reset value=Reset>\n";
    print "</tr>\n";
    print "</table>\n";
    print "</form>\n";
    print $back;
    exit;
  }
}

# get list of mirrored files
my $mirror_list = &GetMirrorInfo();

my $mirror_check = 0;
$mirror_check++ if @$mirror_list;

# find out whether this repository supports the Element class.
# If not then find out if its Asset class supports the File
# attribute.  If one of these are supported then we can allow
# them to jump from this html page straight into the Asset or
# Element page with the appropriate field filled in.
my $cp = RIB::ConfigParser->new();
$cp->load_config($filepath."/conf/BIDM.conf");
my $class='';
my $attribute='';
if (grep /^Element$/, $cp->Classes()) {
  my $object = $cp->InstanceOf('','Element');
  if (grep /^UniqueID$/, $object->Fields()) {
    $class='Element';
    $attribute='UniqueID';
  } else {  # Asset class is always present (er... it better be!)
    $object = $cp->InstanceOf('','Asset');
    if (grep /^File$/, $object->Fields()) {
      $class='Asset';
      $attribute='File';
    }
  }
} else {
  my $object = $cp->InstanceOf('','Asset');
  if (grep /^File$/, $object->Fields()) {
    $class='Asset';
    $attribute='File';
  }
}

# get list of uploaded files (non-mirrored files).
# just push them onto the end of the mirror_list.
opendir (DIR,"$filepath/files");
foreach (grep /^[^\.]/, readdir(DIR)) {
  my $tmp;
  my $found=0;
  foreach $tmp (@$mirror_list) {
    $found = 1 if $tmp->{filename} eq $_;
  }
  push @$mirror_list, { filename=>$_, URL=>"-" } unless $found;
}
closedir DIR;

if (@$mirror_list) {
  print "<center>\n";
  print "<h2>Files currently stored in this repository</h2>\n";
  print "<table border=5 cellpadding=5>\n";
  print "<tr bgcolor=#FFFFFF>\n";
  print "<th>Filename</th>\n";
  print "<th>Upload Date</th>\n";
  print "<th>Size</th>\n";
  if ($mirror_check) {
    print "<th>Master Copy (if mirrored)</th>\n";
  }
  if ($class) {
    print "<th>Create $class Description For This File</th>\n";
  }
  print "</tr>\n";
  my ($filename,$lastupdate, $filesize);
  foreach (sort {$a->{filename} cmp $b->{filename}} @$mirror_list) {
    $filename = $filepath . "/files/" . $_->{filename};
    if (-f $filename) {
      $lastupdate = localtime ((stat($filename))[9]);
      $filesize = (stat($filename))[7];
      if ($filesize > 999) {
        $filesize =~ s/\d\d\d$//;
        $filesize =~ s/(\d)(\d\d\d)$/$1,$2/;
        1 while $filesize =~ s/(\d)(\d\d\d),/$1,$2,/;
      } else {
        $filesize = '> 1';
      }
      $filesize .= 'k';
    } else {
      $filesize = '-';
      $lastupdate = "<font color=red><i>not uploaded - click update link below</i></font>";
    }
    print "<tr bgcolor=#FFFFFF>\n";
    print "<td align=left><a href=$urlpath/files/" , $_->{filename} , ">",
          $_->{filename}, "</a></td>\n";
    print "<td align=center>$lastupdate</td>\n";
    print "<td align=right>$filesize</td>\n";
    if ($mirror_check) {
      if ($_->{URL} ne '-') {
        print "<td align=center><a href=", $_->{URL}, ">", $_->{URL}, "</a></td>\n";
      } else {
        print "<td align=center>-</td>\n";
      }
    }
    if ($class) {
      print "<td align=center><form action=create_object.pl method=post>";
      print "<input type=hidden name=class value=$class>";
      # must prepend "1" to attribute name because that's how create_object.pl wants it
      print "<input type=hidden name=1", $attribute, " value=$urlpath/files/";
      print $_->{filename}, "><input type=submit value=Create></form>\n";
    }
    print "</tr>\n";
  }
  print "</table>\n";
  print "</center>\n";
  print "<p>\n";
}

print "<strong>Options available</strong>\n";
print "<ul>\n";
print "<li><a href=manage_software_files.pl?upload=1>Upload a file</a>\n";
if (@$mirror_list) {
  print "<li><a href=manage_software_files.pl?delete=1>Delete a file</a>\n";
  print "<li><a href=manage_software_files.pl?rename=1>Rename a file</a>\n";
}
print "<p>\n";
if ($mirror_check) {
  print "<li><a href=manage_software_files.pl?update=1>Update the mirrored ";
  print "files in this repository</a>\n";
  if (-f "$filepath/files/.last_check") {
    my $lastupdate = localtime((stat(_))[9]);
    print "<dl><dd>(<i>last check was $lastupdate</i>)</dl>";
  }
}
print "<li><a href=check_disk_space.pl>Check disk space</a>\n";
print "</ul>\n";

if (@$mirror_list) {
  print "The url prefix for files in this repository is $urlpath/files\n";
}

print $back_to_top;
exit;
