#!/usr/bin/perl
#############################################################################
# fm.cgi
# File/Directory Management Program (FileManager)
#
# Author: Steve Horsburgh  (fm@horsburgh.com)
# Version: 0.9
#
#############################################################################
# Full support for Microsoft Internet Explorer 4 and greater.
# Context menus are unavailable in other browsers.
#############################################################################
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#
#############################################################################
$|=1;
require 5.002;
require "./preferences.pl";
require "$Cgilib";
#------------------------------------------------------------------#
#-- Main Program --------------------------------------------------#
#------------------------------------------------------------------#

# Setup initial stuff

    $isMac = ($ENV{'HTTP_USER_AGENT'} =~ /Mac/) ? 1 : 0;
    $isIE  = ($ENV{'HTTP_USER_AGENT'} =~ /MSIE/) ? 1 : 0;
    if (!$isMac && $isIE) {
      ($IEversion = $ENV{'HTTP_USER_AGENT'}) =~ s/^.*MSIE (\d+).*$/$1/;
    }
    $isIE = ($IEversion >= 4) ? 1 : 0;
    $User = $ENV{'REMOTE_USER'} || getpwuid($<) || "";

    &ReadParse();
    &GetCookie();
    &ReadOptions();

    print &SetCookie(),&PrintHeader();

    if ($in{'help'}) {
        print &Header(),&Help(),&Footer();
        exit;
    }

# Get the original relative path and change to the absolute directory

    $Basedir = "/" . $Basedir unless $Basedir =~ /^\//;
    $rPath = $in{'path'} || "/";
    $aPath = &CatDirs($Basedir, $rPath);
    $rPath =~ s/^$Basedir//;
    $rPath = '/' . $rPath unless $rPath =~ /^\//;
    &Error("Invalid directory: $rPath") unless chdir($aPath);

# If we have a QuickDir request then check it out and then change to the directory

    if ($in{'npath'}) {
      if ($in{'npath'} =~ /^\//) { $npath = &CatDirs($Basedir, $in{'npath'}); }
      else { $npath = &CatDirs($Basedir, $rPath, $in{'npath'}); }
      &Error("Invalid directory: $in{'npath'}") unless $npath =~ /^$Basedir/;
      &Error("Invalid directory : $in{'npath'}") unless chdir($npath);
      $aPath = $npath;
      ($rPath = $aPath) =~ s/^$Basedir//;
      $rPath = '/' . $rPath unless $rPath =~ /^\//;
    }

# Set parameters

    $SortBy      = $in{'sort'} || "name";
    $Reverse     = ($in{'rs'} eq $SortBy) ? ($Reverse ? 0 : 1) : $Reverse;
    $Reverse     = 0 if ($in{'rs'} and ($in{'rs'} ne $SortBy));
    $SortBy      = $in{'rs'} || $SortBy;

    print &Header();

# Handle Options Page

    if ($in{'getoptions'}) {
      print &GetOptions($NoCookie,$Fmurl,$IconMode,$DirsFirst,$AllowDotFiles,$AllowMode,$AllowOwnGrp,
                        $Rows,$Cols,$Divheight,$MaxCols,$FontSize,$LogoWidth,$MainTableWidth,
                        $rPath,$DisableMode,$DisableOwnGrp);
      print &Footer();
      exit;
    }

    $cmd = &FixCommand($AllowCmd,$Basedir,$aPath,$rPath,$in{'command'});
#   print "<pre>cmd = $cmd</pre>\n" if $cmd;

# Handle File Uploads

    if ($in{'upload'}) {
      if ($AllowUpload) {
        &Error("Unable to upload \"$in{'upload'}\"") unless &GetFile($in{'upload'},$aPath);
      }
      $cmd = "";
    }

# Handle Properties Command

    elsif ($cmd =~ /^properties /) {
      print &GetProperties($aPath,$cmd,$Imgprefix,$Basedir,$Fss);
      $cmd = "";
    }

# Handle Commands

    print &HandleCmd($User,$cmd,$BaseLink,$Basedir,$aPath,$Tmpdir,$Rows,$Cols,$MainTableWidth,$rPath,$isIE,$ENV{'HTTP_HOST'},$Fss) if $cmd;

# Display command area

    print &GenCmdArea($ShowCmdArea,$MainTableWidth-14,$Imgprefix,$Fmurl,$Edurl,$rPath,
                      $AllowCmd,$AllowUpload,$AllowEdits);

# Generate and Display Files Area

    print &GenFilesArea($ShowDirArea,$MainTableWidth-14,$Imgprefix,$Fmurl,$rPath,
                        &CreateFileInfo($rPath,$aPath,$SortBy,$Reverse,$AllowDotFiles,$IconMode,
                                        $Fmurl,$DirsFirst,$AllowMode,$AllowOwnGrp,$MaxCols,
                                        $Imgprefix,$MainTableWidth-14,@Months
                                       )
                        );
# Wrap things up

    print &Footer();
	exit;

# Avoid warning messages

 @Months      = @Months;
 $Cgilib      = $Cgilib;
 $Basedir     = $Basedir;
 $Tmpdir      = $Tmpdir;
 $Logo        = $Logo;
 $BaseLink    = $BaseLink;
 $Fsl         = $Fsl;
 $AllowEdits  = $AllowEdits;
 $RealOS      = $RealOS;
 $RealOSVer   = $RealOSVer;
 $ShowWebUser = $ShowWebUser;

#------------------------------------------------------------------#
#-- CreateFileInfo ------------------------------------------------#
#------------------------------------------------------------------#

sub CreateFileInfo {
    use strict;
    my($rPath,$aPath,$SortBy,$Reverse,$AllowDotFiles,$IconMode,$Fmurl,$DirsFirst,
                    $AllowMode,$AllowOwnGrp,$MaxCols,$Imgprefix,$MainTableWidth,@Months) = @_;
    my($totalbytes,$itemid,$item,$fitem,$extension,$ritem,$icon,$lnk,$href,$itm,$stats,$temp);
    my($dev,$ino,$mode,$nlink,$uid,$gid,$rdec,$size,$atime,$mtime,$ctime,$blksize,$blocks);
    my($m,$u,$g,$s,$t,$f,$e,$h);
    my(@mymode,@myuname,@mygname,@mysize,@mythisday,@myndate,@myhref,@myname,@myfname,@myext);

    local(*DIR);

    opendir(DIR,"$aPath") || &Error("Unable to open directory: $rPath");
	my @allfiles = readdir(DIR);
	closedir(DIR);

    $totalbytes = $itemid = 0;

    foreach $item (@allfiles) {
      next if (($item eq ".") or ($item eq ".."));
      next if (!$AllowDotFiles and ($item =~ /^\./));

      $fitem = &CreateFileSpec($aPath,$item);
      if ($item =~ /^.+\..+/) {
        ($extension = lc($item)) =~ s/^.+\.(.+)$/$1/;
      } else {
        $extension = "";
      }
      $ritem = &CreateFileSpec($rPath,$item);
      $itemid++;
      $icon = &SetIcon($fitem);

      ($dev,$ino,$mode,$nlink,$uid,$gid,$rdec,$size,$atime,$mtime,$ctime,$blksize,$blocks) = stat($fitem);
      $totalbytes += $size;

      $lnk = (-l $fitem) ? 1 : 0;
	  if (-d $fitem) {  # Directory
        $temp = "showpopup('$item','$ritem','item$itemid','".($lnk?"link":"dir")."',event)";
	    $href  = "<a href=\"\" onMouseOver=\"$temp\" onMouseOut=\"hidepopups()\" onClick=\"return false\">".
                 "<img border=0 name=item".$itemid." src=\"".$Imgprefix;
        if ($IconMode) {
          $href .= "/".$icon.".gif\" title=\"\" alt=\"\"></a><br>";
        } else {
          $href .= "/dirtool.gif\" height=15 width=15 title=\"\" alt=\"\"></a>";
        }
        $href .= "<a href=\"".$Fmurl."?path=".$ritem.&GenOptions("a")."\">".($lnk?"<em>":"").
                  $item.($lnk?"</em>":"")."</a>";
      } 
      else {  # File
        $temp = "showpopup('$item','$ritem','item$itemid','file',event)";
	    $href  = "<a href=\"\" onMouseOver=\"$temp\" onMouseOut=\"hidepopups()\" onClick=\"return false\">".
                 "<img border=0 name=item".$itemid." src=\"".$Imgprefix;
        if ($IconMode) {
          $href .= "/".$icon.".gif\" title=\"\" alt=\"\"></a><br>";
        } else {
          $href .= "/filetool.gif\" height=15 width=15 title=\"\" alt=\"\"></a>";
        }
        $href .= ($lnk?"<em>":"").$item.($lnk?"</em>":"");
      }

	  push(@mymode,    &SetMode($mode,$fitem));
	  push(@myuname,   ((getpwuid($uid))[0]||$uid));
	  push(@mygname,   ((getgrgid($gid))[0]||$gid));
	  push(@mysize,    sprintf("%9d",$size));
	  push(@mythisday, &SetTime($mtime,@Months));
	  push(@myndate,   &SetNTime($mtime));
	  push(@myhref,    $href);
	  push(@myname,    $item);
      push(@myfname,   $fitem);
      push(@myext,     $extension);
    }

	my $out  = &SetPathSpec($rPath,$Fmurl) . "</div>\n".
               "    <table width=".($MainTableWidth-9)." border=0 cellspacing=0 cellpadding=0>\n".
               "     <tr>\n".
               "      <td width=\"30%\" class=hh>\&nbsp;<tt>Total: ".&SetTotalBytes($totalbytes)."</tt></td>\n".
               "      <td width=\"70%\" align=\"right\" class=hh>";

    if ($IconMode) {
      $out .= "<font color=\"white\">|</font> Sort by ";
      $out .= ($SortBy eq "name") ? "<b>Name</b>, " : "<a href=\"".$Fmurl."?path=".$rPath.&GenOptions("a","sort")."\&sort=name\">Name</a>, ";
      $out .= ($SortBy eq "date") ? "<b>Date</b>, " : "<a href=\"".$Fmurl."?path=".$rPath.&GenOptions("a","sort")."\&sort=date\">Date</a>, ";
      $out .= ($SortBy eq "type") ? "<b>Type</b>"   : "<a href=\"".$Fmurl."?path=".$rPath.&GenOptions("a","sort")."\&sort=type\">Type</a>";
      $out .= " <font color=\"white\">|</font>".
              " <a href=\"\" onClick=\"doCommand('New Folder Name:','mkdir',0);return false\">".
              "<img src=\"".$Imgprefix."/newfolder.gif\" width=16 height=16 border=0 alt=\"New Folder\" title=\"New Folder\"></a>".
              " <a href=\"\" onClick=\"doCommand('Find which file or folder?','find',0);return false\">".
              "<img src=\"".$Imgprefix."/find.gif\" width=16 height=16 border=0 alt=\"Find\" title=\"Find\"></a>".
              " <a href=\"".$Fmurl."?path=".$rPath."\&im=0".&GenOptions("a","im")."\">".
              "<img src=\"".$Imgprefix."/listview.gif\" width=16 height=16 border=0 alt=\"List View\" title=\"List View\"></a>".
              " <img src=\"".$Imgprefix."/iconviewon.gif\" width=16 height=16 border=0 alt=\"Icon View\" title=\"Icon View\">".
              " <a href=\"".$Fmurl."?getoptions=1\&path=".$rPath.&GenOptions("a")."\">".
              "<img src=\"".$Imgprefix."/options.gif\" width=16 height=16 border=0 alt=\"Preferences\" title=\"Preferences\"></a>".
              " <a href=\"".$Fmurl."?help=1\&path=".$rPath.&GenOptions("a")."\">".
              "<img src=\"".$Imgprefix."/help.gif\" width=16 height=16 border=0 alt=\"Help\" title=\"Help\"></a>".
              "</td>\n     </tr>\n    </table>\n    <table cellpadding=0 cellspacing=8>\n";
    } else {
      $out .= "<font color=\"white\">|</font>".
              " <a href=\"\" onClick=\"doCommand('New Folder Name:','mkdir',0);return false\">".
              "<img src=\"".$Imgprefix."/newfolder.gif\" width=16 height=16 border=0 alt=\"New Folder\" title=\"New Folder\"></a>".
              " <a href=\"\" onClick=\"doCommand('Find which file or folder?','find',0);return false\">".
              "<img src=\"".$Imgprefix."/find.gif\" width=16 height=16 border=0 alt=\"Find\" title=\"Find\"></a>".
              " <img src=\"".$Imgprefix."/listviewon.gif\" width=16 height=16 border=0 alt=\"List View\" title=\"List View\">".
              " <a href=\"".$Fmurl."?path=".$rPath."\&im=1".&GenOptions("a","im")."\">".
              "<img src=\"".$Imgprefix."/iconview.gif\" width=16 height=16 border=0 alt=\"Icon View\" title=\"Icon View\"></a>".
              " <a href=\"".$Fmurl."?getoptions=1\&path=".$rPath.&GenOptions("a")."\">".
              "<img src=\"".$Imgprefix."/options.gif\" width=16 height=16 border=0 alt=\"Preferences\" title=\"Preferences\"></a>".
              " <a href=\"".$Fmurl."?help=1\&path=".$rPath.&GenOptions("a")."\">".
              "<img src=\"".$Imgprefix."/help.gif\" width=16 height=16 border=0 alt=\"Help\" title=\"Help\"></a>".
              "</td>\n     </tr>\n    </table>\n    <table>\n     <tr align=\"center\">\n";
    }

    if(!$IconMode) {
      $href = $Fmurl."?path=".$rPath.&GenOptions("a")."\&rs=";
	  $out .= "      <td bgcolor=\"#ccccea\" align=\"left\"><tt>\&nbsp;</tt><a href=\"".$href.
              "name\"><tt>Name</tt></a><tt>\&nbsp;\&nbsp;(</tt><a href=\"".$href.
              "type\"><tt>type</tt></a><tt>)</tt></td>\n";
      $out .= "      <td bgcolor=\"#ccccea\" align=\"right\"><a href=\"".$href."size\"><tt>Bytes</tt></a></td>\n";
	  $out .= "      <td bgcolor=\"#ccccea\"><a href=\"".$href."date\"><tt>Date</tt></a></td>\n";
      $out .= "      <td bgcolor=\"#ccccea\"><a href=\"".$href."owner\"><tt>Owner</tt></a></td>\n" .
		      "      <td bgcolor=\"#ccccea\"><a href=\"".$href."group\"><tt>Group</tt></a></td>\n" if $AllowOwnGrp;
      $out .= "      <td bgcolor=\"#ccccea\"><a href=\"".$href."mode\"><tt>Mode</tt></a></td>\n" if $AllowMode;
      $out .= "     </tr>\n";
    }

    my $tdcount = 0;
    my $tdwidth = "width=\"".int(100/$MaxCols)."%\"";

    if ($DirsFirst) {
      foreach $itm (&SortList($Reverse,$SortBy,$IconMode,\@mymode,\@myuname,\@mygname,
                              \@mysize,\@mythisday,\@myndate,\@myhref,\@myname,\@myfname,
                              \@myext,@Months)) {
	    ($m,$u,$g,$s,$t,$f,$e,$h) = split(/\t/,$itm);
        next unless (-d $f);
        if (!$IconMode) {
          $stats  = "";
          $stats .= "      <td align=right nowrap><tt>\&nbsp;".$s."</tt></td>\n".
                    "      <td nowrap><tt>\&nbsp;".$t."</tt></td>\n";
          $stats .= "      <td nowrap><tt>\&nbsp;".$u."</tt></td>\n".
                    "      <td nowrap><tt>\&nbsp;".$g."</tt></td>\n" if $AllowOwnGrp;
	      $stats .= "      <td nowrap><tt>\&nbsp;".$m."</tt></td>\n" if $AllowMode;
	      $out   .= "     <tr valign=top>\n      <td nowrap><tt>".$h."</tt></td>\n".$stats."     </tr>\n";
        } else {
          $out .= "     <tr align=\"center\">\n" if $tdcount++ == 0;
          $out .= "      <td ".$tdwidth.">".$h."</td>\n";
          if($tdcount >= $MaxCols) {
            $tdcount = 0;
            $out .= "     </tr>\n";
          }
        }
      }

      foreach $itm (&SortList($Reverse,$SortBy,$IconMode,\@mymode,\@myuname,\@mygname,
                              \@mysize,\@mythisday,\@myndate,\@myhref,\@myname,\@myfname,
                              \@myext,@Months)) {
	    ($m,$u,$g,$s,$t,$f,$e,$h) = split(/\t/,$itm);
        next if (-d $f);
        if (!$IconMode) {
          $stats  = "";
          $stats .= "      <td align=right nowrap><tt>\&nbsp;".$s."</tt></td>\n".
                    "      <td nowrap><tt>\&nbsp;".$t."</tt></td>\n";
          $stats .= "      <td nowrap><tt>\&nbsp;".$u."</tt></td>\n".
                    "      <td nowrap><tt>\&nbsp;".$g."</tt></td>\n" if $AllowOwnGrp;
	      $stats .= "      <td nowrap><tt>\&nbsp;".$m."</tt></td>\n" if $AllowMode;
	      $out   .= "     <tr valign=top>\n      <td nowrap><tt>".$h."</tt></td>\n".$stats."     </tr>\n";
        } else {
          $out .= "     <tr align=\"center\">\n" if $tdcount++ == 0;
          $out .= "      <td ".$tdwidth.">".$h."</td>\n";
          if($tdcount >= $MaxCols) {
            $tdcount = 0;
            $out .= "     </tr>\n";
          }
        }
      }
      $out .= "     </tr>\n" if ($IconMode and ($tdcount > 0));
      
    } else {
      foreach $itm (&SortList($Reverse,$SortBy,$IconMode,\@mymode,\@myuname,\@mygname,
                              \@mysize,\@mythisday,\@myndate,\@myhref,\@myname,\@myfname,
                              \@myext,@Months)) {
	    ($m,$u,$g,$s,$t,$f,$e,$h) = split(/\t/,$itm);
        if (!$IconMode) {
          $stats  = "";
          $stats .= "      <td align=right nowrap><tt>\&nbsp;".$s."</tt></td>\n".
                    "      <td nowrap><tt>\&nbsp;".$t."</tt></td>\n";
          $stats .= "      <td nowrap><tt>\&nbsp;".$u."</tt></td>\n".
                    "      <td nowrap><tt>\&nbsp;".$g."</tt></td>\n" if $AllowOwnGrp;
	      $stats .= "      <td nowrap><tt>\&nbsp;".$m."</tt></td>\n" if $AllowMode;
	      $out   .= "     <tr valign=top>\n      <td nowrap><tt>".$h."</tt></td>\n".$stats."     </tr>\n";
        } else {
          $out .= "     <tr align=\"center\">\n" if $tdcount++ == 0;
          $out .= "      <td ".$tdwidth.">".$h."</td>\n";
          if($tdcount >= $MaxCols) {
            $tdcount = 0;
            $out .= "     </tr>\n";
          }
        }
      }
      $out .= "     </tr>\n" if ($IconMode and ($tdcount > 0));
    }

	$out .= "    </table>\n";

    return $out;
 }

#------------------------------------------------------------------#
#-- GenCmdArea ----------------------------------------------------#
#------------------------------------------------------------------#

sub GenCmdArea {
    use strict;
    my($ShowCmdArea,$MainTableWidth,$Imgprefix,$Fmurl,$Edurl,$rPath,$AllowCmd,$AllowUpload,$AllowEdits) = @_;
    my($sheight,$swidth,$ret);

    my $foptions = &GenOptions("f");
    
    if ($ShowCmdArea) {
      $sheight = 22;
      $swidth  = 9
    } else {
      $sheight = 9;
      $swidth  = 36;
    }
    my $twidth = $MainTableWidth - $swidth;

    $ret = <<EE0;
 <table border=0 cellspacing=0 cellpadding=0 width=$MainTableWidth>
  <tr><td colspan=2 bgcolor="#cccccc"><img src="$Imgprefix/dot.gif" width=$MainTableWidth height=1 border=0></td></tr>
  <tr valign="top">
   <td width=$swidth bgcolor="#cccccc">
EE0

    if ($ShowCmdArea) {
      $ret .= "    <a href=\"".$Fmurl."?path=".$rPath.&GenOptions("a","sc").
              "\&sc=0\" alt=\"Hide Command Area\" title=\"Hide Command Area\">".
              "<img src=\"".$Imgprefix."/tb.gif\" border=0 width=".$swidth." height=".$sheight."></a>".
              "</td>\n   <td width=".$twidth.">\n".
              "    <table border=0 cellspacing=0 cellpadding=0>\n";
      $ret .= <<EOT2 if $AllowCmd;
     <tr>
      <td colspan=2>
       <form method=post action=$Fmurl>
       <input type=hidden name=path value="$rPath">
       $foptions
       <table border=0 cellspacing=0 cellpadding=0>
        <tr>
         <td width=90 align="right">Command:</td> 
         <td><input type=text name=command size=50><input type=submit name=submit value="Submit"></td>
        </tr>
       </table>
       </form>
      </td>
     </tr>
EOT2
      $ret .= <<EOT3 if $AllowUpload;
     <tr>
      <td colspan=2>
       <form enctype="multipart/form-data" method=post action=$Fmurl>
       <input type=hidden name=path value="$rPath">
       $foptions
       &nbsp;&nbsp;Upload&nbsp;a&nbsp;file:
       <input type=file name=upload size=37><input type=submit value="Upload">
       </form>
      </td>
     </tr>
EOT3
      $ret .= <<EOT4;
     <tr>
      <td>
       <form method=post action=$Fmurl>
       <input type=hidden name=path value="$rPath">
       $foptions
       &nbsp;&nbsp;QuickDir: 
       <input type=text name=npath size=18><input type=submit name=submit value="Go">
       </form>
      </td>
      <td>
EOT4
      $ret .= <<EOT5 if $AllowEdits;
       <form method=post action=$Edurl>
       <input type=hidden name=path value="$rPath">
       $foptions
       &nbsp;Edit/Create&nbsp;a&nbsp;file:
       <input type=text name=filename size=15><input type=submit name=submit value="Edit">
       </form>
EOT5
      $ret .= <<EOT6;
      </td>
     </tr>
    </table>
EOT6
    }
    else {
      $ret .= "    <a href=\"".$Fmurl."?path=".$rPath.&GenOptions("a","sc").
            "\&sc=1\" alt=\"Show Command Area\" title=\"Show Command Area\"><img src=\"".
            $Imgprefix."/ctb.gif\" border=0 width=36 height=9></a></td>\n".
            "   <td bgcolor=\"#cccccc\" width=".$twidth.">".
            "<img src=".$Imgprefix."/dot.gif width=".$twidth." height=1 border=0>";
    }

    $ret .= <<EOT7;
   </td>
  </tr>
 </table>
EOT7
    return $ret;
}

#------------------------------------------------------------------#
#-- GenFilesArea --------------------------------------------------#
#------------------------------------------------------------------#

sub GenFilesArea {
    use strict;
    my($ShowDirArea,$MainTableWidth,$Imgprefix,$Fmurl,$rPath,$out) = @_;
    my($sheight,$swidth,$ret);

    if ($ShowDirArea) {
      $sheight = 22;
      $swidth  = 9
    } else {
      $sheight = 9;
      $swidth  = 36;
    }
    my $twidth = $MainTableWidth - $swidth;

    $ret = <<EE1;
 <table border=0 cellspacing=0 cellpadding=0 width=$MainTableWidth>
  <tr>
   <td colspan=2 bgcolor="#cccccc"><img src="$Imgprefix/dot.gif" width=$MainTableWidth height=1></td>
  </tr>
  <tr valign="top">
   <td width=$swidth bgcolor="#cccccc">
EE1

    if ($ShowDirArea) {
      $ret .= "    <a href=\"".$Fmurl."?path=".$rPath.&GenOptions("a","sd").
              "\&sd=0\" alt=\"Hide Files Area\" title=\"Hide Files Area\">".
              "<img src=\"".$Imgprefix."/tb.gif\" border=0 width=".$swidth." height=".$sheight.
              "></a></td>\n   <td width=".$twidth.">\n    ".$out."   </td>\n  </tr>\n </table>\n";
    } else {
      $ret .= "    <a href=\"".$Fmurl."?path=".$rPath.&GenOptions("a","sd").
              "\&sd=1\" alt=\"Show Files Area\" title=\"Show Files Area\">".
              "<img src=\"".$Imgprefix."/ctb.gif\" border=0 width=".$swidth." height=".$sheight.
              "></a></td>\n   <td width=".$twidth." bgcolor=\"#cccccc\"><img src=\"".$Imgprefix.
              "/dot.gif\" width=".$twidth." height=1 border=0></td>\n  </tr>\n </table>\n";
    }

    return $ret;
}

#------------------------------------------------------------------#
#-- HandleCmd -----------------------------------------------------#
#------------------------------------------------------------------#

sub HandleCmd {
    use strict;
    my ($User,$cmd,$BaseLink,$Basedir,$aPath,$Tmpdir,$Rows,$Cols,$MainTableWidth,$rPath,$isIE,$host,$Fss) = @_;
    my($ext,$file,$line,$url,@lines,$sycmd);
    local(*F);
    my $ret = "";

    $cmd =~ s/^view/cat/ if (($cmd =~ /^view /) and (!$BaseLink));

    if (($cmd =~ /^view /) and $BaseLink) {
      ($file = $cmd) =~ s/^view //;
      $file =~ s/^$Basedir//;
      $file = "/".$file unless $file =~ /^\//;
      $file = &CreateFileSpec($BaseLink,$file);
      &Error("Invalid file specification: $file") unless $file =~ /^\/$BaseLink/;
      ($ext = lc($file)) =~ s/^.*\.(.*)$/$1/;

      if ($ext =~ /js|cgi|pl|css|jav|java|htm|html/) {    # intercept some extensions
        $cmd =~ s/^view/cat/;
      } else {
        $url = "http://".$host.$file;
        $ret .= <<EOS;
        <script language="JavaScript">
        <!--
          newWindow = window.open("$url","view","scrollbars,resizable,height=400,width=400")
          newWindow.focus();
        // -->
        </script>
EOS
        $cmd = "";
      }
    }

    if ($cmd) {
      system("cd $aPath;$cmd 1>$Tmpdir/msg$$ 2>&1");

      if (-f "$Tmpdir/msg$$") {
        open(F, "<$Tmpdir/msg$$");
        my $nrows = 1;
        my $ntext = "";
        while (<F>) { 
	      $line = $_;
	      chomp $line; #next unless $line;
	      $line =~ s/\&/\&amp;/g;
	      $line =~ s/\</\&lt;/g;
	      $line =~ s/\>/\&gt;/g;
          push(@lines,$line);
	      $nrows++;
	    }
	    close(F);

	    unlink("$Tmpdir/msg$$");

        if ($nrows > 1) {
          
          if ($isIE) {
            $nrows = $Rows if $nrows > $Rows;
            $ret .= "<div class=big>Command Result</div>\n";
	        $ret .= "<div id=\"source\" style=\"overflow:auto;height:" . $nrows * 16 . 
		          ";width:".$MainTableWidth.";border:2px solid black;\"><pre>".join("\n",@lines)."</pre></div>\n<hr>\n";
          } elsif ($nrows <= $Rows) {
            $ret .= "<div class=big>Command Result</div>\n";
	        $ret .= "<div id=\"source\" style=\"height:" . $nrows * 16 . 
		          ";width:".$MainTableWidth.";border:2px solid black;\"><pre>".join("\n",@lines)."</pre></div>\n<hr>\n";
          } elsif ($nrows <= 1000) {
            $ret .= "<div class=big>Command Result</div>\n";
            $ret .= "<form><textarea rows=$Rows cols=$Cols nowrap>";
            foreach (@lines) { $ret .= $_."\n"; }
	        $ret .= "</textarea></form>\n<hr>\n";
          } else {
             $ret .= <<EOS2;
             <script language="JavaScript">
             <!--
               newWindow = window.open("","view","scrollbars,resizable,height=400,width=500")
               newWindow.document.writeln('<html>')
               newWindow.document.writeln('<head><title>ViewPort</title><meta http-equiv="Expires" content="-1"><style type="text/css">PRE {$Fss;color:black}</style></head>')
               newWindow.document.writeln('<body bgcolor="white" text="black"><pre>')
EOS2
             foreach (@lines) {
               ($ntext = $_) =~ s/'/\\'/g;
               $ntext =~ s/&/&amp;/g;
               $ntext =~ s/\\n/\\\\n/g;
               $ret .= "newWindow.document.writeln('$ntext')\n";
             }
             $ret .= <<EOS3
               newWindow.document.writeln('</pre></body>')
               newWindow.document.writeln('</html>')
               newWindow.document.close()
               newWindow.focus();
             // -->
             </script>
EOS3
          }
        }
      }
	}
    return $ret;
}

#------------------------------------------------------------------#
#-- SetIcon -------------------------------------------------------#
#------------------------------------------------------------------#

sub SetIcon {
    use strict;
    my $fitem = shift;
    my %types = (
        'htm'   => 'html',
        'html'  => 'html',
        'htmls' => 'html',
        'htx'   => 'html',
        'shtml' => 'html',
        'acgi'  => 'script',
        'asp'   => 'script',
        'c'     => 'script',
        'cc'    => 'script',
        'cgi'   => 'script',
        'cpp'   => 'script',
        'css'   => 'script',
        'cxx'   => 'script',
        'f'     => 'script',
        'f90'   => 'script',
        'for'   => 'script',
        'jav'   => 'script',
        'java'  => 'script',
        'js'    => 'script',
        'p'     => 'script',
        'pas'   => 'script',
        'pl'    => 'script',
        'boz'   => 'zip',
        'bz'    => 'zip',
        'bz2'   => 'zip',
        'cpt'   => 'zip',
        'gz'    => 'zip',
        'gzip'  => 'zip',
        'sit'   => 'zip',
        'tgz'   => 'zip',
        'Z'     => 'zip',
        'zip'   => 'zip',
        'art'   => 'pict',
        'bm'    => 'pict',
        'bmp'   => 'pict',
        'dwg'   => 'pict',
        'dxf'   => 'pict',
        'fif'   => 'pict',
        'flo'   => 'pict',
        'fpx'   => 'pict',
        'g3'    => 'pict',
        'gif'   => 'pict',
        'ico'   => 'pict',
        'ief'   => 'pict',
        'iefs'  => 'pict',
        'jfif'  => 'pict',
        'jpe'   => 'pict',
        'jpeg'  => 'pict',
        'jpg'   => 'pict',
        'jps'   => 'pict',
        'jut'   => 'pict',
        'nap'   => 'pict',
        'nif'   => 'pict',
        'niff'  => 'pict',
        'pbm'   => 'pict',
        'pct'   => 'pict',
        'pcx'   => 'pict',
        'pgm'   => 'pict',
        'pic'   => 'pict',
        'pict'  => 'pict',
        'png'   => 'pict',
        'pnm'   => 'pict',
        'ppm'   => 'pict',
        'qif'   => 'pict',
        'qti'   => 'pict',
        'qtif'  => 'pict',
        'ras'   => 'pict',
        'rast'  => 'pict',
        'rf'    => 'pict',
        'rgb'   => 'pict',
        'rp'    => 'pict',
        'svf'   => 'pict',
        'tif'   => 'pict',
        'tiff'  => 'pict',
        'wbmp'  => 'pict',
        'xbm'   => 'pict',
        'xif'   => 'pict',
        'xpm'   => 'pict',
        'xwd'   => 'pict',
    );
    my($ext);

    ($ext = $fitem) =~ s/^.*\.(.*)$/$1/;

    my $type = (-d $fitem)        ? "dir"            :
               ($types{lc($ext)}) ? $types{lc($ext)} :
               (-T $fitem)        ? "text"           :
               "binary";
    $type = "l".$type if (-l $fitem);
    return $type;
}

#------------------------------------------------------------------#
#-- SetMode -------------------------------------------------------#
#------------------------------------------------------------------#

sub SetMode {
    use strict;
    my($mode,$fitem) = @_;

# There's probably a better way to do this, but for now ...

    my $owner = ("---","--x","-w-","-wx","r--","r-x","rw-","rwx")[int(($mode & 0777) / 64)];
	my $group = ("---","--x","-w-","-wx","r--","r-x","rw-","rwx")[int((($mode & 0777) % 64)/8)];
	my $world = ("---","--x","-w-","-wx","r--","r-x","rw-","rwx")[int(($mode & 0777) % 8)];

    $owner =~ s/.$/s/ if (($mode & 04000) == 04000);
    $group =~ s/.$/s/ if (($mode & 02000) == 02000);
    $world =~ s/.$/t/ if (($mode & 01000) == 01000);

    my $lead = ( (-l $fitem) ? "l" :
                 (-d $fitem) ? "d" :
                 (($mode & 0140000) == 0140000) ? "s" :
                 (($mode & 060000)  ==  060000) ? "b" :
                 (($mode & 020000)  ==  020000) ? "c" :
                 (($mode & 010000)  ==  010000) ? "p" :
                 "-"
               );
    return $lead . $owner . $group . $world;
}

#------------------------------------------------------------------#
#-- SetTime -------------------------------------------------------#
#------------------------------------------------------------------#

sub SetTime {
    use strict;
    my $mtime = shift;
    my @Months = @_;
    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =  localtime($mtime);
	my $thisday = $Months[$mon] . " " . ($mday<10 ? "0" . $mday : $mday) . " ";
	
    if($year == (localtime)[5]) {
      $hour = "0" . $hour if $hour < 10;
      $min  = "0" . $min  if $min  < 10;
      $sec  = "0" . $sec  if $sec  < 10;
      $thisday .= $hour . ":" . $min . ":" . $sec;
    } else {
      $thisday .= 1900 + $year;
    }

    return $thisday;
}

#------------------------------------------------------------------#
#-- SetNTime ------------------------------------------------------#
#------------------------------------------------------------------#

sub SetNTime {
    use strict;
    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =  localtime(shift);
    return (1900 + $year) . 
           ($mon <=9?"0".$mon :$mon)  . 
           ($mday<=9?"0".$mday:$mday) . 
           ($hour<=9?"0".$hour:$hour) . 
           ($min <=9?"0".$min :$min)  . 
           ($sec <=9?"0".$sec :$sec);
}

#------------------------------------------------------------------#
#-- SetTotalBytes -------------------------------------------------#
#------------------------------------------------------------------#

sub SetTotalBytes {
    use strict;
    my $bytes = shift;
    my $mbytes = $bytes/1024/1024;
    my $kbytes = $bytes/1024;
    my $string = ($mbytes >= 1) ? int($mbytes).".".int(($mbytes-int($mbytes))*100)." MB"
               : ($kbytes >= 1) 
                                ? int($kbytes).".".int(($kbytes-int($kbytes))*100)." KB"
               : $bytes." Bytes";

    $string =~ s/\.0 / /;
    return $string;
}

#------------------------------------------------------------------#
#-- SetPathSpec ---------------------------------------------------#
#------------------------------------------------------------------#

sub SetPathSpec {
    use strict;
    my ($path,$url) = @_;
	my $pathspec = "\&nbsp;<div class=big>Directory: <a href=\"".$url."?path=/".&GenOptions("a")."\">/</a>";
	my $p = "";
	foreach (split(/\//,$path)) {
	  next unless $_;
	  $p .= "/".$_;
	  $pathspec .= "<a href=\"".$url."?path=".$p.&GenOptions("a")."\">".$_."</a>/";
	}
    return $pathspec;
}

#------------------------------------------------------------------#
#-- SortList ------------------------------------------------------#
#------------------------------------------------------------------#

sub SortList {
    use strict;
    my($reverse,$sortby,$IconMode,$mymode,$myuname,$mygname,$mysize,$mythisday,$myndate,
       $myhref,$myname,$myfname,$myext,@Months) = @_;

    if ($IconMode) {
      $reverse = 0;
      $sortby = "name" unless (($sortby eq "date") or ($sortby eq "type"));
      $reverse = 1 if $sortby eq "date";
    }
	my($i,$item,$n,$m,$u,$g,$s,$t,$f,$e,$h,$mon,$mday,$yearorhms,@templist,@returnlist);
	foreach $i (0..$#{$myname}) {
	  if ($sortby =~ /name/i) {
	    push(@templist, $$myname[$i] .  "\t" . $$mymode[$i] . "\t" . $$myuname[$i] . "\t" . $$mygname[$i] . "\t" . $$mysize[$i] .  "\t" . $$mythisday[$i] . "\t" . $$myfname[$i] .   "\t" . $$myext[$i] .   "\t" . $$myhref[$i]);
	  } elsif ($sortby =~ /mode/i) {
	    push(@templist, $$mymode[$i] .  "\t" . $$myname[$i] . "\t" . $$myuname[$i] . "\t" . $$mygname[$i] . "\t" . $$mysize[$i] .  "\t" . $$mythisday[$i] . "\t" . $$myfname[$i] .   "\t" . $$myext[$i] .   "\t" . $$myhref[$i]);
	  } elsif ($sortby =~ /owner/i) {
	    push(@templist, $$myuname[$i] . "\t" . $$myname[$i] . "\t" . $$mymode[$i] .  "\t" . $$mygname[$i] . "\t" . $$mysize[$i] .  "\t" . $$mythisday[$i] . "\t" . $$myfname[$i] .   "\t" . $$myext[$i] .   "\t" . $$myhref[$i]);
	  } elsif ($sortby =~ /group/i) {
	    push(@templist, $$mygname[$i] . "\t" . $$myname[$i] . "\t" . $$mymode[$i] .  "\t" . $$myuname[$i] . "\t" . $$mysize[$i] .  "\t" . $$mythisday[$i] . "\t" . $$myfname[$i] .   "\t" . $$myext[$i] .   "\t" . $$myhref[$i]);
	  } elsif ($sortby =~ /size/i) {
	    push(@templist, $$mysize[$i] .  "\t" . $$myname[$i] . "\t" . $$mymode[$i] .  "\t" . $$myuname[$i] . "\t" . $$mygname[$i] . "\t" . $$mythisday[$i] . "\t" . $$myfname[$i] .   "\t" . $$myext[$i] .   "\t" . $$myhref[$i]);
	  } elsif ($sortby =~ /date/i) {
	    push(@templist, $$myndate[$i] . "\t" . $$myname[$i] . "\t" . $$mymode[$i] .  "\t" . $$myuname[$i] . "\t" . $$mygname[$i] . "\t" . $$mysize[$i] .    "\t" . $$myfname[$i] .   "\t" . $$myext[$i] .   "\t" . $$myhref[$i]);
	  } elsif ($sortby =~ /type/i) {
	    push(@templist, $$myext[$i] .   "\t" . $$myname[$i] . "\t" . $$mymode[$i] .  "\t" . $$myuname[$i] . "\t" . $$mysize[$i]  . "\t" . $$mygname[$i] .   "\t" . $$mythisday[$i] . "\t" . $$myfname[$i] . "\t" . $$myhref[$i]);
	  } else {
	    push(@templist, $$myname[$i] .  "\t" . $$mymode[$i] . "\t" . $$myuname[$i] . "\t" . $$mygname[$i] . "\t" . $$mysize[$i] .  "\t" . $$mythisday[$i] . "\t" . $$myfname[$i] .   "\t" . $$myext[$i] .   "\t" . $$myhref[$i]);
	  }
	}

	foreach $item (sort @templist) {
	  if ($sortby =~ /name/i) {
	    ($n,$m,$u,$g,$s,$t,$f,$e,$h) = split(/\t/,$item);
	  } elsif ($sortby =~ /mode/i) {
	    ($m,$n,$u,$g,$s,$t,$f,$e,$h) = split(/\t/,$item);
	  } elsif ($sortby =~ /owner/i) {
	    ($u,$n,$m,$g,$s,$t,$f,$e,$h) = split(/\t/,$item);
	  } elsif ($sortby =~ /group/i) {
	    ($g,$n,$m,$u,$s,$t,$f,$e,$h) = split(/\t/,$item);
	  } elsif ($sortby =~ /size/i) {
	    ($s,$n,$m,$u,$g,$t,$f,$e,$h) = split(/\t/,$item);
	  } elsif ($sortby =~ /type/i) {
	    ($e,$n,$m,$u,$s,$g,$t,$f,$h) = split(/\t/,$item);
	  } elsif ($sortby =~ /date/i) {
	    ($t,$n,$m,$u,$g,$s,$f,$e,$h) = split(/\t/,$item);
	    $mon = substr($t,4,2);
	    $mday = substr($t,6,2);
	    $yearorhms = substr($t,0,4);
		$yearorhms = substr($t,8,2) . ":" . substr($t,10,2) . ":" . substr($t,12,2) if($yearorhms == (localtime)[5] + 1900);
	    $t = $Months[$mon] . " " . $mday . " ". $yearorhms;
	  } else {
	    ($n,$m,$u,$g,$s,$t,$f,$e,$h) = split(/\t/,$item);
	  }
	  push(@returnlist, $m . "\t" . $u . "\t" . $g . "\t" . int($s) . "\t" . $t . "\t" . $f . "\t" . $e . "\t" . $h);
	}

	return ($reverse ? reverse @returnlist : @returnlist);
}

#------------------------------------------------------------------#
#-- FixCommand ----------------------------------------------------#
#------------------------------------------------------------------#

sub FixCommand {
  use strict;
  my($AllowCmd,$Basedir,$aPath,$rPath,$cmd) = @_;
  my($arg1,$arg2,$command,$farg1,$farg2,$status1,$status2);

  $cmd =~ s/[`;&]//g;
  $cmd =~ s/\s+$//;

  if ($AllowCmd) {
    $cmd =~ s/^(..)-/$1 -/;
    return $cmd;
  }

  return unless $cmd;

  my %Cmds = (
        'cp'     => 2,
        "$::DirCpCmd"   => 2,
        'cat'    => 1,
        'mv'     => 2,
        'rm'     => 1,
        'rm-r'   => 1,
        'ln-s'   => 2,
        'rmdir'  => 1,
        'chmod'  => 2,
        'chown'  => 2,
        'gzip'   => 1,
        'gunzip' => 1,
        'mkdir'  => 1,
        'view'   => 1,
        'find'   => 1,
        'properties' => 1,
  );

  my @items = split(/ /,$cmd);

# See if we know this command

  if ((exists $Cmds{$items[0]}) and ($#items == $Cmds{$items[0]})) {
    ($command = $items[0]) =~ s/-/ -/;

# Handle "command scalar file/dir" commands

    if (($command eq "chown") or ($command eq "chmod")) {
      $farg1 = $items[1];
      $farg2 = &CreateFileSpec($aPath,$items[2]);
      return $command . " " . $farg1 . " " . $farg2 if (($farg2 =~ /^$Basedir/) and (-e $farg2));

# Handle the find command

    } elsif ($command eq "find") {
      return $command . " . -name '*" . $items[1] . "*' -print" unless $items[1] =~ /[^a-zA-Z0-9_\.]/;

# Handle all other commands (note the exception for mkdir)

    } else {

      $farg1 = &CreateFileSpec($aPath,$items[1]);
      if (($farg1 =~ /^$Basedir/) and (($command eq "mkdir") or (-e $farg1))) {

        if ($items[2]) {
          $farg2 = &CreateFileSpec(($items[2] =~ /^\// ? $Basedir : $aPath),$items[2]);
          return $command . " " . $farg1 . " " . $farg2 if $farg2 =~ /^$Basedir/;
        } else {
          return $command . " " . $farg1;
        }

      }
    }
  }
  &Error("Invalid command: $cmd [\$command, \$farg1, \$farg2 = $command , $farg1, $farg2]");
  &Error("Invalid command: $cmd");
}

#------------------------------------------------------------------#
#-- ConstructFileSpec ---------------------------------------------#
#------------------------------------------------------------------#

sub ConstructFileSpec {
# Given a file specification and base directory (optional) return
# the absolute file specification and relative file specification
# This handles such contructs as "../"
# Return (0) if error.
    use strict;
    use Cwd;
    my($fspec,$Basedir) = @_;
    my($path,$file,$origdir,$abspath,$relpath,$status);

    if ($fspec =~ /\//) {
      ($path,$file) = $fspec =~ m/^(.*)\/(.*)$/;     # Get path and file
    } else {
      $path = "";                                    # Relative path
      $file = $fspec;                                # Filename
    }

    ($status,$abspath,$relpath) = &ConstructPathSpec($path,$Basedir);
    return $status,$abspath.$file,$relpath.$file;
}

#------------------------------------------------------------------#
#-- ConstructPathSpec ---------------------------------------------#
#------------------------------------------------------------------#

sub ConstructPathSpec {
    use strict;
    my($opath, $Basedir) = @_;
    $Basedir .= "/" unless $Basedir =~ /\/$/;
    my $path = $Basedir;
    my $relpath = "";

    if ($opath) {
      my $origdir = cwd();
      if ($opath =~ /^\//) {            # Relative to the Basedir
        ($path = $opath) =~ s/^\///;
        $path = $Basedir . $path;
      } elsif ($opath =~ /^\.\//) {     # Relative to the current dir
        ($path = $opath) =~ s/^\.//;
        $path = $origdir . $path;
      } else {                          # Relative to the current dir also
        $path = $origdir . "/" . $opath;
      }

      return 0 unless chdir($path);
      $path = cwd();
      chdir($origdir);
    }

    $path .= "/" unless $path =~ /\/$/;
    $path =~ s/\/\//\//g;
    ($relpath = $path) =~ s/^$Basedir//;
    return 1,$path,$relpath;
}

#------------------------------------------------------------------#
#-- CatDirs -------------------------------------------------------#
#------------------------------------------------------------------#

sub CatDirs {
    use strict;
    my(@args) = @_;
    my(@list,@nlist,$path);

# Get all the dir elements in order
    foreach (@args) { push(@list,split /\//); }

# Now build path elements
    foreach (@list) {
      next unless $_;
      if ($_ eq "..") {
        pop @nlist;
      } elsif ($_ eq ".") {
        # skip
      } else {
        push(@nlist,$_);
      }
    }

# Construct path string
    $path  = '/'.join('/',@nlist);
    $path .= '/' unless $path =~ /\/$/;

# Return the new path
    return $path;
}

#------------------------------------------------------------------#
#-- CreateFileSpec ------------------------------------------------#
#------------------------------------------------------------------#

sub CreateFileSpec {
    use strict;
    my(@args) = @_;
    my(@list,$filename,$path);

# Get all the elements in order
    foreach (@args) { push(@list,split /\//); }

# Pop off the filename
    $filename = pop @list;

# Construct the path
    $path = &CatDirs("/",@list);

# Return the file spec
    return $path . $filename;
}

#------------------------------------------------------------------#
#-- GetOptions ----------------------------------------------------#
#------------------------------------------------------------------#

sub GetOptions {
  use strict;
  my($NoCookie,$Fmurl,$IconMode,$DirsFirst,$AllowDotFiles,$AllowMode,
     $AllowOwnGrp,$Rows,$Cols,$Divheight,$MaxCols,$FontSize,$LogoWidth,
     $MainTableWidth,$rPath,$DisableMode,$DisableOwnGrp) = @_;

  my($im0, $im1)   = $IconMode      ? ("","checked") : ("checked","");
  my($df0, $df1)   = $DirsFirst     ? ("","checked") : ("checked","");
  my($adf0,$adf1)  = $AllowDotFiles ? ("","checked") : ("checked","");
  my($am0, $am1)   = $AllowMode     ? ("","checked") : ("checked","");
  my($aog0,$aog1)  = $AllowOwnGrp   ? ("","checked") : ("checked","");

  my $minTableWidth = 307 + $LogoWidth;

  my $out = "";

  $out = <<EOO;
  <form method="post" action="$Fmurl">
  <input type=hidden name=path value="$rPath">
  <p><strong>Options</strong></p>
EOO
  if ($NoCookie) {
    $out .= "<p>The following options will be used for this session only. ".
            "[Cookie support has been disabled.]</p>";
  } else {
    $out .= "<p>The following options will be used for this session. ".
            "If you have enabled cookies on your browser, these settings ".
            "will be saved for later sessions.</p>";
  }
  $out .= <<EOO2;
  <table>
   <tr>
    <td>
     <input type=radio name=im value=0 $im0>View Files as a List<br>
     <input type=radio name=im value=1 $im1>View Files as Icons
    </td>
    <td>
     <input type=radio name=df value=1 $df1>Show Folders First<br>
     <input type=radio name=df value=0 $df0>Mix Files and Folders
    </td>
    <td>
     <input type=radio name=adf value=1 $adf1>Show Files starting with a period (.)<br>
     <input type=radio name=adf value=0 $adf0>Hide Files starting with a period (.)
    </td>
   </tr>
   <tr><td colspan=3><hr></td></tr>
   <tr>
    <td>
EOO2
  $out .= <<EOO3 unless $DisableMode;
     <input type=radio name=am value=1 $am1>Show 'Mode' in List View<br>
     <input type=radio name=am value=0 $am0>Hide 'Mode' in List View
EOO3
  $out .= <<EOO4;
    </td>
    <td colspan=2>
EOO4
  $out .= <<EOO5 unless $DisableOwnGrp;
     <input type=radio name=aog value=1 $aog1>Show 'Owner' &amp; 'Group' in List View<br>
     <input type=radio name=aog value=0 $aog0>Hide 'Owner' &amp; 'Group' in List View<br>
EOO5
  $out .= <<EOO6;
    </td>
   </tr>
   <tr><td colspan=3><hr></td></tr>
  </table>
  <table>
   <tr>
    <td>Editor Window Size:</td>
    <td><input type=text name=rows size=4 value="$Rows">Rows,
        <input type=text name=cols size=4 value="$Cols">Columns</td>
   </tr>
   <tr>
    <td>Command Viewport Height:</td>
    <td><input type=text name=dh size=4 value="$Divheight">pixels</td>
   </tr>
   <tr>
    <td>Icon View Columns:</td>
    <td><input type=text name=mc size=4 value="$MaxCols"></td>
   </tr>
   <tr>
    <td>Base Font Size:</td>
    <td><input type=text name=bf size=4 value="$FontSize">points</td>
   </tr>
   <tr>
    <td>Main Table Width:</td>
    <td><input type=text name=mtw size=4 value="$MainTableWidth">points
    (minimum: $minTableWidth)</td>
   </tr>
  </table>
  
  <input type=submit name=saveoptions value="Save">
  <input type=reset value="Reset">
EOO6
    $out .= "<input type=button value=\"Cancel\" onClick=\"javascript:location='".$Fmurl."?path=".$rPath.&GenOptions("a")."'\">".
            "</form>";
    return $out;
}

#------------------------------------------------------------------#
#-- ReadOptions ---------------------------------------------------#
#------------------------------------------------------------------#

sub ReadOptions {

# This routine sets GLOBAL values

  $IconMode       = exists $in{'im'}  ? ($in{'im'}  ? 1 : 0) : $IconMode;
  $DirsFirst      = exists $in{'df'}  ? ($in{'df'}  ? 1 : 0) : $DirsFirst;
  $AllowDotFiles  = exists $in{'adf'} ? ($in{'adf'} ? 1 : 0) : $AllowDotFiles;
  $AllowMode      = exists $in{'am'}  ? ($in{'am'}  ? 1 : 0) : $AllowMode;
  $AllowMode      = 0 if $DisableMode;
  $AllowOwnGrp    = exists $in{'aog'} ? ($in{'aog'} ? 1 : 0) : $AllowOwnGrp;
  $AllowOwnGrp    = 0 if $DisableOwnGrp;

  $ShowCmdArea    = exists $in{'sc'} ? ($in{'sc'} ? 1 : 0) : 1;
  $ShowDirArea    = exists $in{'sd'} ? ($in{'sd'} ? 1 : 0) : 1;

  $MainTableWidth = exists $in{'mtw'} ? (int($in{'mtw'}) < (307+$LogoWidth) ?
                    (307+$LogoWidth) : int($in{'mtw'})) : $MainTableWidth;

  $SortBy    = exists $in{'sort'} ? $in{'sort'} : "name";
  $Reverse   = exists $in{'rev'}  ? $in{'rev'}  : 0;

  $Rows      = exists $in{'rows'} ? (int($in{'rows'}) < 3  ? 3  : int($in{'rows'})) : $Rows;
  $Cols      = exists $in{'cols'} ? (int($in{'cols'}) < 3  ? 3  : int($in{'cols'})) : $Cols;
  $Divheight = exists $in{'dh'}   ? (int($in{'dh'})   < 20 ? 20 : int($in{'dh'}))   : $Divheight;
  $MaxCols   = exists $in{'mc'}   ? (int($in{'mc'})   < 1  ? 1  : int($in{'mc'}))   : $MaxCols;

  $FontSize         = exists $in{'bf'} ? (int($in{'bf'}) < 4  ? 4 : int($in{'bf'})) : $FontSize;
  $Fontsize_normal  = int($FontSize) > 8 ? int($FontSize) : 10;
  $Fontsize_xsmall  = int($Fontsize_normal * 0.7 + 0.5);
  $Fontsize_small   = int($Fontsize_normal * 0.8 + 0.5);
  $Fontsize_large   = int($Fontsize_normal * 1.2 + 0.5);
  $Fontsize_huge    = int($Fontsize_normal * 1.6 + 0.5);
  $Fxs              = "font-size:".$Fontsize_xsmall .'pt';
  $Fss              = "font-size:".$Fontsize_small  .'pt';
  $Fsn              = "font-size:".$Fontsize_normal .'pt';
  $Fsl              = "font-size:".$Fontsize_large  .'pt';
  $Fsh              = "font-size:".$Fontsize_huge   .'pt';
}

#------------------------------------------------------------------#
#-- GenOptions ---------------------------------------------------#
#------------------------------------------------------------------#

sub GenOptions {

# This routine generates an options list for links and forms using GLOBAL values
    
    my $type = shift;
    my $omit = shift || "";
    my $out  = "";

    if ($type eq "f") {
      $out .= "<input type=hidden name=im   value=\"".$IconMode."\">"       unless $omit eq "im";
      $out .= "<input type=hidden name=sort value=\"".$SortBy."\">"         unless $omit eq "sort";
      $out .= "<input type=hidden name=rev  value=\"".$Reverse."\">"        unless $omit eq "rev";
      $out .= "<input type=hidden name=df   value=\"".$DirsFirst."\">"      unless $omit eq "df";
      $out .= "<input type=hidden name=adf  value=\"".$AllowDotFiles."\">"  unless $omit eq "adf";
      $out .= "<input type=hidden name=am   value=\"".$AllowMode."\">"      unless ($DisableMode or ($omit eq "am"));
      $out .= "<input type=hidden name=aog  value=\"".$AllowOwnGrp."\">"    unless ($DisableGrpOwn or ($omit eq "aog"));
      $out .= "<input type=hidden name=rows value=\"".$Rows."\">"           unless $omit eq "rows";
      $out .= "<input type=hidden name=cols value=\"".$Cols."\">"           unless $omit eq "cols";
      $out .= "<input type=hidden name=dh   value=\"".$Divheight."\">"      unless $omit eq "dh";
      $out .= "<input type=hidden name=mc   value=\"".$MaxCols."\">"        unless $omit eq "mc";
      $out .= "<input type=hidden name=bf   value=\"".$FontSize."\">"       unless $omit eq "bf";
      $out .= "<input type=hidden name=mtw  value=\"".$MainTableWidth."\">" unless $omit eq "mtw";
      $out .= "<input type=hidden name=sc   value=\"".$ShowCmdArea."\">"    unless $omit eq "sc";
      $out .= "<input type=hidden name=sd   value=\"".$ShowDirArea."\">"    unless $omit eq "sd";
   } else {
      $out .= "\&im=".  $IconMode       unless $omit eq "im";
      $out .= "\&df=".  $DirsFirst      unless $omit eq "df";
      $out .= "\&adf=". $AllowDotFiles  unless $omit eq "adf";
      $out .= "\&am=".  $AllowMode      unless ($DisableMode or ($omit eq "am"));
      $out .= "\&aog=". $AllowOwnGrp    unless ($DisableGrpOwn or ($omit eq "aog"));
      $out .= "\&rows=".$Rows           unless $omit eq "rows";
      $out .= "\&cols=".$Cols           unless $omit eq "cols";
      $out .= "\&dh=".  $Divheight      unless $omit eq "dh";
      $out .= "\&mc=".  $MaxCols        unless $omit eq "mc";
      $out .= "\&bf=".  $FontSize       unless $omit eq "bf";
      $out .= "\&sort=".$SortBy         unless $omit eq "sort";
      $out .= "\&rev=". $Reverse        unless $omit eq "rev";
      $out .= "\&mtw=". $MainTableWidth unless $omit eq "mtw";
      $out .= "\&sc=".  $ShowCmdArea    unless $omit eq "sc";
      $out .= "\&sd=".  $ShowDirArea    unless $omit eq "sd";
    }

    return $out;
}


#------------------------------------------------------------------#
#-- GetCookie -----------------------------------------------------#
#------------------------------------------------------------------#

sub GetCookie {

# This routine uses GLOBAL values
    
    return if $NoCookie;
    eval "use CGI qw/:standard/";
    eval "use CGI::Cookie";

    my ($k, $v, $cookie);
    my %cookies = fetch CGI::Cookie;
    
    $cookie = $cookies{'filemanager'}->value if exists $cookies{'filemanager'};
    
    foreach (split(/\&/,$cookie)) {
      next unless $_;
      ($k,$v) = split /=/;
      $in{$k} = $v unless exists $in{$k};
    }
}

#------------------------------------------------------------------#
#-- SetCookie -----------------------------------------------------#
#------------------------------------------------------------------#

sub SetCookie {

# This routine uses GLOBAL values
    
    return if $NoCookie;
    eval "use CGI qw/:standard/";
    eval "use CGI::Cookie";

    my $cookie = &GenOptions("a","sd");

    my $c = new CGI::Cookie(-name    =>  'filemanager',
                            -value   =>  $cookie,
                            -expires =>  '+6M');

    return "Set-Cookie: $c\n";
}

#------------------------------------------------------------------#
#-- GetFile -------------------------------------------------------#
#------------------------------------------------------------------#

sub GetFile {
    use strict;
    my $file = shift || return 0;
    my $path = shift || return 0;

    $path = "" if $path eq "/";

    my($fixed,$filename);

# See if we got a file, if so, put it in the right place

    if (-f $file) {
      ($fixed = $file) =~ s/\\/\//g;
      $fixed           =~ s/^.*\/(.+)$/$1/;
      $fixed           =~ s/^FM//;
      $fixed           =~ s/\s/_/g;
      $filename        = $path . "/" . $fixed;
      $filename        =~ s/\/\//\//g;
      system("cp \"$file\" \"$filename\"");
      unlink($file);
      return (-f $filename) ? 1 : 0;
    }

    return 0;
}

#------------------------------------------------------------------#
#-- GetProperties -------------------------------------------------#
#------------------------------------------------------------------#

sub GetProperties {
    use strict;
    my ($aPath,$cmd,$Imgprefix,$Basedir,$Fss) = @_;
    my ($filename,$rpath,$ntext,$afilespec,$rfilespec,$status);
    my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdec,$size,$atime,$mtime,$ctime,$blksize,$blocks);
    my (@allitems,$filecount,$dircount,$linkcount,$temp,$sSize,$sSizeVal);
    local(*D);

    return unless ($aPath or $filename);

    ($afilespec = $cmd) =~ s/^properties //;
    return unless $afilespec =~ /^$Basedir/;
    ($filename = $afilespec) =~ s/.*\///;
    
    ($rfilespec = $afilespec) =~ s/^$Basedir//;
    $rfilespec = "/" . $rfilespec unless $rfilespec =~ /^\//;

    ($rpath = $rfilespec) =~ s/^(.*)\/.*$/$1/;
    $rpath = "/" unless $rpath;

    my $link = (-l $afilespec) ? 1 : 0;
    my $dir  = (-d $afilespec) ? 1 : 0;
    my $file = ($dir) ? 0 : 1;
    my $icon = &SetIcon($afilespec);
    my $type = $dir ? "Folder" : "File";

   ($dev,$ino,$mode,$nlink,$uid,$gid,$rdec,$size,$atime,$mtime,$ctime,$blksize,$blocks) = stat($afilespec);

    my $smode = &SetMode($mode,$afilespec);
    $mode = sprintf("%o",$mode & 07777);
    my $omode = substr($smode,1,3);
    my $gmode = substr($smode,4,3);
    my $wmode = substr($smode,7,3);

    $omode = (($omode =~ /r/) ? "Read"      : "")    . " " .
             (($omode =~ /w/) ? ", Write"   : "Only") . " " .
             (($omode =~ /x/) ? ", Execute" : "");
    $omode = "None" if $omode eq " Only ";
    $gmode = (($gmode =~ /r/) ? "Read"      : "")    . " " .
             (($gmode =~ /w/) ? ", Write"   : "Only") . " " .
             (($gmode =~ /x/) ? ", Execute" : "");
    $gmode = "None" if $gmode eq " Only ";
    $wmode = (($wmode =~ /r/) ? "Read"      : "")    . " " .
             (($wmode =~ /w/) ? ", Write"   : "Only") . " " .
             (($wmode =~ /x/) ? ", Execute" : "");
    $wmode = "None" if $wmode eq " Only ";

    $blocks *= 512;

    $uid = $uid . "/" . ((getpwuid($uid))[0] || $uid);
    $gid = $gid . "/" . ((getgrgid($gid))[0] || $gid);

    $ctime = scalar(localtime($ctime));
    $mtime = scalar(localtime($mtime));
    $atime = scalar(localtime($atime));

    if ($dir && !$link) {
      opendir(D,$afilespec);
      @allitems = grep(!/^\.\.?$/,readdir(D));
      closedir(D);
      $filecount = $dircount = $linkcount = 0;
      foreach (@allitems) {
        $temp = &CreateFileSpec($afilespec,$_);
        if (-l $temp) {
          $linkcount++;
        } elsif (-d $temp) {
          $dircount++;
        } else {
          $filecount++;
        }
      }
      $sSize = "Contents:";
      $sSizeVal = $dircount." Folder".($dircount == 1 ? "" : "s").", ".
                  $filecount." File".($filecount == 1 ? "" : "s");
      $sSizeVal .= ", ".$linkcount." Link".($linkcount == 1 ? "" : "s") if $linkcount;

    } elsif ($link) {
      $type .= " Alias" if $link;
      $sSize = "Target:";
      $sSizeVal = readlink($afilespec);
      $sSizeVal =~ s/^$Basedir//;
      $sSizeVal = "/" . $sSizeVal unless $sSizeVal =~ /^\//;

    } else {
      $sSize = "Size:";
      $sSizeVal = $size." bytes (".$blocks." allocated)";
    }

    my $body = <<EOP;
<table border=0 width=300 cellpadding=0 cellspacing=0>
 <tr>
  <td>
   <img src="$Imgprefix/$icon.gif"> <b>$filename</b>
   <table border=0>
    <tr><td nowrap><font color="#669999">Type:<br>Location:<br>$sSize</font></td><td nowrap>$type<br>$rpath<br>$sSizeVal</td></tr>
   </table>
   <hr>
   <table border=0>
    <tr><td nowrap><font color="#669999">Created on:<br>Modified on:<br>Last Access:</font></td><td nowrap align="right">$ctime<br>$mtime<br>$atime</td></tr>
   </table>
   <hr>
   <table border=0>
    <tr><td align="right" nowrap><font color="#669999">Owner ID:<br>Group ID:</font></td><td nowrap>$uid<br>$gid</td></tr>
   </table>
   <hr>
   <table border=0>
    <tr><td colspan=2 nowrap><font color="#669999">Privileges: </font>($mode / $smode)</td></tr>
    <tr><td nowrap><font color="#669999">\&nbsp;\&nbsp;\&nbsp;\&nbsp;Owner:<br>\&nbsp;\&nbsp;\&nbsp;\&nbsp;Group:<br>\&nbsp;\&nbsp;\&nbsp;\&nbsp;World:</font></td><td nowrap>$omode<br>$gmode<br>$wmode</td></tr>
   </table>
  </td>
 </tr>
</table>
EOP

    my $ret = <<EOPH;
<script language="JavaScript">
<!--
  newWindow = window.open("","Properties","scrollbars,resizable,height=380,width=350");
  newWindow.document.writeln('<html>');
  newWindow.document.writeln('<head><title>Properties of $rfilespec</title>');
  newWindow.document.writeln('<meta http-equiv="Expires" content="-1">');
  newWindow.document.writeln('<style type="text/css">TD {$Fss;color:black}</style>');
  newWindow.document.writeln('</head>');
  newWindow.document.writeln('<body bgcolor="#ffffff" text="black">');
EOPH

    foreach (split(/\n/,$body)) {
      ($ntext = $_) =~ s/'/\\'/g;
      $ntext =~ s/\\n/\\\\n/g;
      $ret .= "newWindow.document.writeln('$ntext')\n";
    }

    $ret .= <<EOPH2;
  newWindow.document.writeln('</body>')
  newWindow.document.writeln('</html>')
  newWindow.document.close()
  newWindow.focus();
// -->
</script>
EOPH2

    return $ret;
}

#------------------------------------------------------------------#
#-- Header --------------------------------------------------------#
#------------------------------------------------------------------#

sub Header {

# This routine uses GLOBAL values
  
  $DoneHeader      = 1;
  my $uname        = $ShowWebUser ? "<span class=gb>User: </span>".(getpwuid($<)||$<) : "";
  my $options      = &GenOptions("a");
  my $inTableWidth = $MainTableWidth - 14;
  my $inWidth      = $MainTableWidth - $LogoWidth - 7;
  my $inWidth2     = $MainTableWidth - 307;
  my $aref         = $isIE ? "A {text-decoration:none;color:#0000ff}\n".
                             "A:hover {text-decoration:underline;color:red}\n"
                           : "A {color:#0000ff}\n";
  my $out          = "";
  $out .= <<EOH1;
<html>
<head>
 <title>FileManager</title>
 <meta http-equiv="Expires" content="-1">  
 <style type="text/css">
    H2 {font-family:arial,helvetica,sans-serif;$Fsh;font-weight:bold}
    H3 {font-family:arial,helvetica,sans-serif;$Fsl;font-weight:bold}
    H4 {font-family:arial,helvetica,sans-serif;$Fsn;font-weight:bold}
    TT {$Fss;color:black}
    PRE {$Fss;color:black}
    P {$Fsn;color:black}
    BLOCKQUOTE {$Fsn;color:black}
    OL {$Fss}
    UL {$Fss}
    LI {$Fss;color:black}
    TD {$Fss;color:black}
    INPUT {$Fss;color:black}
    FORM {margin:0;border-width:0;padding:0;$Fss}
    .hh {$Fss;background-color:#e7e7e7}
    .im {border-width:2;border-color:white}
	.rb {font-family:arial,helvetica,sans-serif;$Fxs;color:white}
	.gb {font-family:arial,helvetica,sans-serif;$Fxs;text-decoration:none;color:#cccccc}
	.bb {font-family:arial,helvetica,sans-serif;$Fxs;text-decoration:none;color:white}
	.ti {font-family:arial,helvetica,sans-serif;$Fsh;text-decoration:none;color:white}
	.xst {font-family:arial,helvetica,sans-serif;$Fxs;text-decoration:none;color:black}
    .sp {position:absolute;top:0;left:0;width:70;font-size:8pt;font-family:arial,helvetica,sans-serif;background-color:#bdbdbd;border-style:outset;border-width:2;display:none}
    .lsp {position:absolute;top:0;left:0;width:70;font-size:8pt;font-family:arial,helvetica,sans-serif;background-color:#bdbdbd;border-width:1}
    .aa {text-decoration:none;font-size:8pt}
    .big {$Fsl;font-weight:bold}
    $aref
 </style>
 <script language="JavaScript">
 <!-- 
      var gPath = '$rPath'
      var gFile
      var gDirOn, gImgOn
      var fntSiz = '$Fontsize_small'

     NS4 = (document.layers);
     IE4 = (document.all);
    ver4 = (NS4 || IE4);
	 IE5 = (IE4 && navigator.appVersion.indexOf("5.")!=-1);
   isMac = (navigator.appVersion.indexOf("Mac") != -1);
  isMenu = (NS4 || (IE4 && !isMac) || (IE5 && isMac));

    if (!isMenu) alert("FileManager is not compatible with this browser.");

    function popUp(){return};
    function popDown(){return};
    if (!ver4) event=null;

   function doCommand(msg,cmd,numargs) {
     var arg1 = "";
     var arg2 = "";
     var newloc = "";
     var to = "";
     if (numargs == 0) {
       arg1 = escape(gFile)

       if (msg == "Delete") {
         arg1 = ""
         if (confirm('Are you sure you want to delete "'+gFile+'"?')) {
           arg1 = escape(gFile)
         }
       }
       if (msg == "QuickEdit") {
         newloc = "http://"+location.host+"$Edurl?path="+escape(gPath)+"&submit=edit&filename="+arg1+"$options"
         location.href = newloc
         return
       }
       if ((cmd == "mkdir") || (cmd == "find")) {
         to = prompt(msg,"")
         arg1 = ""
         if ((to != null) && (to != "")) {
           arg1 = escape(to)
           arg1 = arg1.replace('+','%2B')
         }
       }
       if (msg == "Open") {
         gPath = gPath + ((gPath == "/") ? "" : "/") + gFile
         newloc = "http://"+location.host+"$Fmurl?path="+escape(gPath)+"$options"
         location.href = newloc
         return
       }
     }
     if (numargs == 1) {
       to = prompt(msg+' "'+gFile+'" to',"")
       if ((to != null) && (to != "")) {
         arg1 = escape(gFile)
         arg2 = escape(to)
         arg2 = arg2.replace('+','%2B')
       }
     }
     if (numargs == 2) {
       to = prompt(msg+' "'+gFile+'" to',"")
       if ((to != null) && (to != "")) {
         arg2 = escape(gFile)
         arg1 = escape(to)
         arg1 = arg1.replace('+','%2B')
       }
     }
     if (arg1 != "" ) {
       newloc = "http://"+location.host+"$Fmurl?path="+escape(gPath)+"&command="+escape(cmd)+"+"+arg1+"+"+arg2+"$options"
       location.href = newloc
     }
   }

// MENU Arrays
//
// Item  1       Menu Width in pixels
// Items 2,3     Forced left,top position for menu rendering
// Items 4,5     Font color, mouseover Font color
// Items 6,7     Background color, mouseover background color
// Item  8       Border Color
// Item  9       Separator Color (IE only)
//
// MenuItemName, Link
//      MenuItemName        String of text
//      Link                String URL or "javascript:scriptname"
//
// Menu names are "arMenu#" where # begins at 1
//

arMenu1 = new Array(
150,
"QuickView","javascript:doCommand('QuickView','view',0)",
"QuickEdit","javascript:doCommand('QuickEdit','edit',0)",
"<hr>","",
"Duplicate","javascript:doCommand('Duplicate','cp',1)",
"Rename or Move","javascript:doCommand('Rename or Move','mv',1)",
"Delete","javascript:doCommand('Delete','rm',0)",
"<hr>","",
"Generate alias","javascript:doCommand('Generate alias','ln-s',1)",
"Compress","javascript:doCommand('Compress','gzip',0)",
"Expand","javascript:doCommand('Expand','gunzip',0)"
EOH1
    $out .= <<EOH2 unless $DisableMode;
    ,"Change mode","javascript:doCommand('Change mode','chmod',2)"
EOH2
    $out .= <<EOH3 unless $DisableOwnGrp;
    ,"Change owner:group","javascript:doCommand('Change owner:group','chown',2)"
EOH3
    $out .= <<EOH4;
    ,"<hr>","",
    "Properties","javascript:doCommand('properties','properties',0)"
)

arMenu2 = new Array(
150,
"Open","javascript:doCommand('Open','open',0)",
EOH4
    $out .= <<EOH4a if $DirCpCmd;
"Duplicate","javascript:doCommand('Duplicate','$DirCpCmd',1)",
EOH4a
    $out .= <<EOH4b;
"Rename or Move","javascript:doCommand('Rename or Move','mv',1)",
"Delete","javascript:doCommand('Delete','rm-r',0)",
"<hr>","",
"Generate alias","javascript:doCommand('Generate alias','ln-s',1)"
EOH4b
    $out .= <<EOH5 unless $DisableMode;
    ,"Change mode","javascript:doCommand('Change mode','chmod',2)"
EOH5
    $out .= <<EOH6 unless $DisableOwnGrp;
    ,"Change owner:group","javascript:doCommand('Change owner:group','chown',2)"
EOH6
    $out .= <<EOH7;
    ,"<hr>","",
    "Properties","javascript:doCommand('properties','properties',0)"
)

arMenu3 = new Array(
150,
"Open","javascript:doCommand('Open','open',0)",
EOH7
    $out .= <<EOH7a if $DirCpCmd;
"Duplicate","javascript:doCommand('Duplicate','$DirCpCmd',1)",
EOH7a
    $out .= <<EOH7b;
"Rename or Move","javascript:doCommand('Rename or Move','mv',1)",
"Delete","javascript:doCommand('Delete','rm',0)"
EOH7b
    $out .= <<EOH7c unless ($DisableMode and $DisableOwnGrp);
,"<hr>",""
EOH7c
    $out .= <<EOH8 unless $DisableMode;
    ,"Change mode","javascript:doCommand('Change mode','chmod',2)"
EOH8
    $out .= <<EOH9 unless $DisableOwnGrp;
    ,"Change owner:group","javascript:doCommand('Change owner:group','chown',2)"
EOH9
    $out .= <<EOH10;
    ,"<hr>","",
    "Properties","javascript:doCommand('properties','properties',0)"
)

// -->
</script>
</head>
<body bgcolor="#ffffff" background="$Imgprefix/bg.gif" leftmargin=0 topmargin=0 marginheight=0 marginwidth=0 text="#000000" link="#000084" vlink="#333399" alink="#ff0000">
<script language='JavaScript1.2' src='$Htmlprefix/fm_menus.js' type='text/javascript'></script>
<noscript>
   <h1>FileManager is not compatible with this browser.</h1>
</noscript>
<center>
 <table border=0 cellspacing=0 cellpadding=0 width=$MainTableWidth>
  <tr>
   <td nowrap width=$LogoWidth bgcolor="#000042" align="right"><a 
    href="$Fmurl?path=/$options"><img src="$Logo" width=$LogoWidth height=$LogoHeight 
    alt="home" border="0" align="left"></a></td>
   <td bgcolor="#000042"><img src="$Imgprefix/dot.gif" width=1 height=1></td>
   <td nowrap bgcolor="#000042" align="right"><font class="ti">FileManager</font>&nbsp;</td>
   <td nowrap width=7><img src="$Imgprefix/shadow1.gif" width=7 height=$LogoHeight alt=""></td>
  </tr>
  <tr valign="bottom">
   <td nowrap width=$inWidth2 bgcolor="#666684" colspan=2 class=rb>&nbsp;$uname</td>
   <td nowrap width=300 bgcolor="#666684" class=rb align="right">$RealOS&nbsp;$RealOSVer&nbsp;</td>
   <td nowrap width=7><img src="$Imgprefix/shadow2.gif" width=7 height=20 alt=""></td>
  </tr>
  <tr>
   <td nowrap width=$MainTableWidth colspan=4 height=7 align="right"><img 
    src="$Imgprefix/shadow3.gif" width=$MainTableWidth height=7 alt=""></td>
  </tr>
 </table>
 <table border=0 cellspacing=0 cellpadding=0 width=$inTableWidth>
 <tr valign="top">
  <td bgcolor="#ffffff">
EOH10
    return $out;
}

#------------------------------------------------------------------#
#-- Footer --------------------------------------------------------#
#------------------------------------------------------------------#

sub Footer {

# This routine uses GLOBAL values
  
  my $gendate = scalar(localtime(time));
  my $inTableWidth = $MainTableWidth - 7;
  return <<EOF;
   </td>
  </tr>
 </table>
 <table border=0 cellpadding=0 cellspacing=0 width=$MainTableWidth>
  <tr>
   <td colspan=2 height=3><img src="$Imgprefix/dot.gif" width=$MainTableWidth height=3 alt=""></td>
  </tr>
  <tr>
   <td width=$inTableWidth bgcolor="#666684" nowrap align="center"><font class="bb">This information was generated on $gendate.</font></td>
   <td nowrap><img src="$Imgprefix/shadow1.gif" width=7 height=20 alt=""></td>
  </tr>
  <tr>
   <td nowrap width=$inTableWidth bgcolor="#000042" align="center">
    <a href="http://www.horsburgh.com/" class="rb">Designed by Horsburgh.com</a>
   </td> 
   <td nowrap width=7><img src="$Imgprefix/shadow2.gif" width=7 height=20 alt=""></td>
  </tr>
  <tr>
   <td nowrap width=$MainTableWidth colspan=2 height=7 align="right"><img src="$Imgprefix/shadow3.gif" width=$MainTableWidth height=7 alt=""></td>
  </tr>
 </table>
 </center>
</body>
</html>
EOF
}

#------------------------------------------------------------------#
#-- Error ---------------------------------------------------------#
#------------------------------------------------------------------#

sub Error {

# This routine uses GLOBAL values

    my $msg = shift;
    print &Header() unless $DoneHeader;
    print "<h2>ERROR</h2>\n",$msg,"<p><a href=\"".$Fmurl."?&path=".$in{'path'}.&GenOptions("a")."\">Back</a><p>",&Footer();
    exit;
}

#------------------------------------------------------------------#
#-- Help ----------------------------------------------------------#
#------------------------------------------------------------------#

sub Help {

# This routine uses GLOBAL values

    my $return = "<a href=\"".$Fmurl."?&path=".$in{'path'}.&GenOptions("a")."\">Return</a>";

    return <<EOHLP;
    <h2>Help Information</h2>
    <p>FileManager allows remote, web-based access to a Unix/Linux file system for groups of 
    users or a single user. Below is a quick summary of the actions and commands. (Note that 
    the terms <em>directory </em>and <em>folder </em>are used interchangeably.)</p>
    <h3>CONTENTS</h3>
    <ol>
    <li><a href="#GENERAL">General Information</a></li>
    <li><a href="#COMMAND">Command Area</a></li>
    <li><a href="#DIRECTORY">Directory/File Display Area</a></li>
    <li><a href="#CONTEXT">Context-sensitive Menus</a></li>
    <li><a href="#ICON">Icon  Mode</a></li>
    <li><a href="#LIST">List Mode</a></li>
    <li><a href="#OPTIONS">Options Page</a></li>
    <li><a href="#EDITOR">Editor Page</a></li>
    </ol>
    <hr>
    <a name="GENERAL"><h3>GENERAL INFORMATION</h3></a>
    <p>The screen is divided into two sections, a <a href="#COMMAND">Command Area</a> and a 
    <a href="#DIRECTORY">Directory Area</a>. The Directory area can be viewed in either 
    <a href="#ICON">Icon Mode</a> or <a href="#LIST">List Mode</a>.</p>
    <p>There is a tab located in the upper left corner of each area. Clicking on the tab will 
    hide/show the area.</p>
    <p>In addition to these areas, there is an <a href="#OPTIONS">Options Page</a> that allows 
    you to customize how the page will appear, an <a href="#EDITOR">Editor Page</a> that provides 
    a simple, full-screen, text editor, and this Help page.
    Each area is described below.</p>
    <a name="COMMAND"><h3>COMMAND AREA</h3></a>
    <p>
    Each of the following items may or may not be present depending on the installation options 
    set by your system administrator.
    </p>
    <blockquote>
    <table border=1 cellspacing=1 cellpadding=3>
     <tr valign="top">
      <td>Command:</td><td>Allows you to issue Unix/Linux commands directly to the server. 
      The command privileges are set by the system administrator. The characters `;&amp; are not allowed.
      Note that use of this command 
      line will bypass most of the security features of FileManager, so be careful!</td>
     </tr>
     <tr valign="top">
      <td>Upload a file:</td><td>Allows you to send a file from your local computer to the server. 
      Click on the browse button to locate the file you want to send to the server and then click 
      on the Upload button.</td>
     </tr>
     <tr valign="top">
      <td>QuickDir:</td><td>Change to the directory/folder specified. This can be a quick way to 
      navigate a complex directory structure. Enter the full directory path and click on the Go 
      button.</td>
     </tr>
     <tr valign="top">
      <td nowrap>Edit/Create a file:</td><td>Starts the simple, full-screen text editor. 
      Enter a file name and click the Edit button. If the file does not exist then one is created. 
      Note that only non-binary (text) files can be edited.</td>
     </tr>
    </table>
    </blockquote>
    <a name="DIRECTORY"><h3>DIRECTORY/FILE DISPLAY AREA</h3></a>
    <ul>
    <li><strong>Directory Items:</strong> Clicking on the first '/' will change to the base (or root) 
    directory. Clicking on other parts of the directory list will change to the directory 
    clicked on.<br>&nbsp;</li>
    <li>Names in <em>italics </em>are links (shortcuts).<br>&nbsp;</li>
    <li>Clicking on a folder name will change to that directory.<br>&nbsp;</li>
    <li>Clicking on a file or folder icon will display a context-sensitive menu allowing you to 
    perform certain actions.</li>
    </ul>

    <a name="CONTEXT"><h3>CONTEXT-SENSITIVE MENUS</h3></a>
    <blockquote>
    <table border=0>
     <tr valign="top">
      <td rowspan=32>&nbsp;&nbsp;&nbsp;</td>
      <td colspan=2>&nbsp;<br><b>Folders:</b></td>
     </tr>
     <tr valign="top"><td>Open</td><td>Open the folder (change to the directory)</td></tr>
     <tr valign="top"><td>Duplicate</td><td>Make a duplicate copy of the folder and its contents (if enabled)</td></tr>
     <tr valign="top"><td>Rename or Move</td><td>Change the name of the folder or move it to a different directory</td></tr>
     <tr valign="top"><td>Delete</td><td>Delete the folder and ALL OF ITS CONTENTS</td></tr>
     <tr valign="top"><td>Generate alias</td><td>Create an alias (shortcut) to this folder</td></tr>
     <tr valign="top"><td>Change mode</td><td>Change the folder protection (if enabled)</td></tr>
     <tr valign="top"><td nowrap>Change owner:group</td><td>Change the folder ownership and group privileges (if enabled)</td></tr>

     <tr valign="top"><td colspan=2>&nbsp;<br><b>Links (shortcuts) to a folder:</b></td></tr>
     <tr valign="top"><td>Open</td><td>Open the folder pointed to by the link (change to the directory)</td></tr>
     <tr valign="top"><td>Duplicate</td><td>Make a duplicate copy of the link (if enabled)</td></tr>
     <tr valign="top"><td>Rename or Move</td><td>Change the name of the link or move it to a different directory</td></tr>
     <tr valign="top"><td>Delete</td><td>Delete the link (not the original folder)</td></tr>
     <tr valign="top"><td>Change mode</td><td>Change the link protection (if enabled)</td></tr>
     <tr valign="top"><td>Change owner:group</td><td>Change the link ownership and group privileges (if enabled)</td></tr>

     <tr valign="top"><td colspan=2>&nbsp;<br><b>Files:</b></td></tr>
     <tr valign="top"><td>QuickView</td><td>View (display) the file. Some files will bring up a separate window for viewing. If you have the application that created the file it will launch in this window.</td></tr>
     <tr valign="top"><td>QuickEdit</td><td>Edit the file with a simple full-screen editor. (Text files only)</td></tr>
     <tr valign="top"><td>Duplicate</td><td>Make a duplicate copy of the file</td></tr>
     <tr valign="top"><td>Rename or Move</td><td>Change the name of the file or move it to a different directory</td></tr>
     <tr valign="top"><td>Delete</td><td>Delete the file</td></tr>
     <tr valign="top"><td>Generate alias</td><td>Create an alias (shortcut) to this file</td></tr>
     <tr valign="top"><td>Compress</td><td>Compress the file using 'gzip'</td></tr>
     <tr valign="top"><td>Expand</td><td>Uncompress the file using 'gunzip'</td></tr>
     <tr valign="top"><td>Change mode</td><td>Change the file protection (if enabled)</td></tr>
     <tr valign="top"><td nowrap>Change owner:group</td><td>Change the file ownership and group privileges (if enabled)</td></tr>

     <tr valign="top"><td colspan=2>&nbsp;<br><b>Links (shortcuts) to file:</b></td></tr>
     <tr valign="top"><td>QuickView</td><td>View (display) the original file. Some files will bring up a separate window for viewing. If you have the application that created the file it will launch in this window.</td></tr>
     <tr valign="top"><td>QuickEdit</td><td>Edit the original file with a simple full-screen editor. (Text files only)</td></tr>
     <tr valign="top"><td>Duplicate</td><td>Make a duplicate copy of the link (not the original file)</td></tr>
     <tr valign="top"><td>Rename or Move</td><td>Change the name of the link or move it to a different directory</td></tr>
     <tr valign="top"><td>Delete</td><td>Delete the link (not the original file)</td></tr>
    </table>
    </p>
    </blockquote>
    <p>There are two directory viewing modes, List and Icon. They are described below.</p>
    <a name="ICON"><h3>ICON  MODE</h3></a>
    <blockquote>
    The express links are as follows:
    <table border=0>
     <tr valign="top">
      <td rowspan=6>&nbsp;&nbsp;&nbsp;</td>
      <td align="right" nowrap>Sort by Name:&nbsp;</td><td>Sort the files and folders by their names</td>
     </tr>
     <tr valign="top">
      <td align="right">Sort by Date:&nbsp;</td><td>Sort the files and folders by their modification
      times</td>
     </tr>
     <tr valign="top">
      <td align="right">Sort by Type:&nbsp;</td><td>Sort the files and folders by their extensions</td>
     </tr>
     <tr valign="top">
      <td align="right">New Folder:&nbsp;</td><td>Create a new folder/directory in this directory</td>
     </tr>
     <tr valign="top">
      <td align="right">List View:&nbsp;</td><td>Change to the List View</td>
     </tr>
     <tr valign="top">
      <td align="right">Options:&nbsp;</td><td>Set your personal preferences</td>
     </tr>
    </table>
    </blockquote>
    <a name="LIST"><h3>LIST MODE</h3></a>
    <blockquote>
    In LIST mode, the express links are as follows:
    <table border=0>
     <tr valign="top">
      <td rowspan=3>&nbsp;&nbsp;&nbsp;</td>
      <td align="right" nowrap>New Folder:&nbsp;</td><td>Create a new folder/directory in this 
      directory</td>
     </tr>
     <tr valign="top">
      <td align="right">Icon View:&nbsp;</td><td>Change to the Icon View</td>
     </tr>
     <tr valign="top">
      <td align="right">Options:&nbsp;</td><td>Set your personal preferences</td>
     </tr>
    </table>
    <p>To <b>sort</b> the table, click on a table heading. To <b>reverse</b> the sort, click on the same
    table heading again.</p>
    </blockquote>
    <a name="OPTIONS"><h3>OPTIONS PAGE</h3></a>
    <p>This is the page to set all of your personalization information. If you have 'cookies' enabled 
    and the system administrator has allowed it, these settings will be saved from session to session.
    If not, then your settings will only be used for the current session.</p>

    <a name="EDITOR"><h3>EDITOR PAGE</h3></a>
    <p>This is a simple, full-screen text editor. To edit/insert text, just click the mouse where you
    want in the text window and start typing. The mouse and arrow keys allow you to move around in the
    text. You can select text (using shift-arrow or click-drag with the mouse), cut, delete, copy, and
    paste text. The 'find' function works with most browsers (control-f or cmd-f for Mac users). Also, 
    the Undo function works on the newer browsers (control-z or cmd-z for Mac users).</p>
    <p>Remember to save your work by clicking on the Save button. To cancel all edits, click on the 
    Cancel button.</p>
    <ul>
    <li>If the file is readonly, the contents will be displayed, but no changes can be made.</li>
    <li>If the file is binary or does not have read privileges, it cannot be edited.</li>
    </ul>
    <hr>
    <p>If you have other questions, comments, or suggestions, please email them to 
    <a href="mailto:fm\@horsburgh.com">fm\@horsburgh.com</a>.</p>
    <p align="right">$return</p>
EOHLP
}
