#native_company# #native_desc#
#native_cta#

Web File Browser

By David AZOULAY
on September 2, 2002

Version: 0.4b12

Type: Full Script

Category: File Management

License: GNU General Public License

Description: Web File Browser is a simple but full featured open-source file browser written in PHP (1 single file) that allows users to create, delete, edit, copy, rename, move and upload files and directories thru a light, full-text, web-based interface

<?
//======================================================================
//
// Name        : Web File Browser
//
// Description : A web-based file browser written in PHP
//
// HomePage    : http://www.webfilebrowser.org/
//
// Author      : David AZOULAY ([email protected])
//
// History     : 02/20/2002 - Alpha version 0.1a
//               02/23/2002 - Alpha version 0.2a
//               02/25/2002 - Alpha version 0.3a
//               02/26/2002 - Beta version 0.4b1
//               03/02/2002 - Beta version 0.4b2
//               03/04/2002 - Beta version 0.4b3
//               03/05/2002 - Beta version 0.4b3
//               03/13/2002 - Beta version 0.4b5
//               04/05/2002 - Beta version 0.4b6
//               05/22/2002 - Beta version 0.4b7
//               05/23/2002 - Beta version 0.4b8
//               05/24/2002 - Beta version 0.4b9
//               06/14/2002 - Beta version 0.4b10
//               06/26/2002 - Beta version 0.4b11
//               07/04/2002 - Beta version 0.4b12
//
// Credits :     Thanks to Albert LOMBARTE for the spanish and catalan version
//               Thanks to Johannes EDER for the german version
//               Thanks to Mikael WANBERG for the swedish version
//               Thanks to Dmytro KOVALOV for the ukrainian version
//               Thanks to Larry CHAFFIN for some ideas
//
// TODO list   : Images for actions (edit view and download)
//               Zip and unzip files and directories
//               Use constants instead of variables for customization
//               Multiple file upload (not simple stuff !)
//               Comments ;-)
//
// Knowns BUGS : Reported problems with some web browsers (such as Opera), I only
//               tested it on IE 6.0, NS 4.75 and NS 7.0.
//               Setting $basedir to other directory does not always work well
//               depending on the web server configuration (in fact it's not a bug
//               but lot of people are amazed by the results so I indicate it here)
//
// Legal stuff : 
//
// 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
// 
// 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.
//
// For US citizens : This program is not suitable for feeding pets, cannot
// be used to sail on the ocean, must not be put in a microwave oven
// etc... The author absolutely declines any responsability for whatever
// usage that would give the idea to the user to sue him ;-)
//
//======================================================================

// ---------------- Things that can be customized... -------------------

$title = "Web File Browser 0.4b12";// Title (may contain HTML tags)
$windowtitle = $title;             // Window title (text only)

$thbgcolor = "#D0D0D0";            // Background color of table headers
$thfgcolor = "#000000";            // Foreground color of table headers
$tdbgcolor = "#F0F0F0";            // Background color of table cells
$tdfgcolor = "#000000";            // Foreground color of table cells

$editcols = 80;                    // Number of columns for edit area
$editrows = 24;                    // Number of rows for edit area
$defaultfileformat = "dos";        // Default file format when editing and saving (dos/unix)

$trashcan = "wfbtrash";            // Trash can (must be located in base directory)
$allowbrowsetrashcan = true;       // Allowing to browse trash can
$allowemptytrashcan = true;        // Allowing to empty trash can
$allowrestorefromtrashcan = true;  // Allowing to restore files from trash can
$trashcaninfofileext = "wfbinfo";  // Extension of information file in trash can

$allowmove = true;                 // Allowing file and directory moving
$allowrename = true;               // Allowing file and directory renaming
$allowcopy = true;                 // Allowing file copying
$allowdelete = true;               // Allowing file and directory deletion
$allowcreatefile = true;           // Allowing file creation
$allowcreatedir = true;            // Allowing directory creation
$allowupload = true;               // Allowing file uploads
$allowurlupload = true;            // Allowing file uploads from URL

$filealiases = true;               // File aliasing feature
$filealiasext = "wfbalias";        // File alias extension
$allowalias = true;                // Allowing file aliasing

$defaultsortby = "name";           // Default sort mode (name/size/date)
$hidedotfiles = true;              // Hide dot-files (obsolete : use $hidefilepattern instead)
$hidefilepattern = "^..*$";       // All files matching that pattern will be hidden
$filemode = 0664;                  // Create mode for files (UNIX)
$dirmode = 0775;                   // Create mode for directories (UNIX)
$showunixattrs = false;            // Show perms / owner / group (UNIX)
$uploadmaxsize = 2097152;          // Max file size for uploads (check your php.ini)
$filelinks = true;                 // Links on files (inhibited with a custom $basedir)

$readmefile = "wfbreadme.html";    // README file name (empty means no README file)
$showreadmefile = false;           // Allowing README file to be in file list

$allowdownload = true;             // Allow file download

$allowedit = true;                 // Allowing file edition
$allowshow = true;                 // Allowing file viewing (useful only if allowedit is false)
$viewextensions = array(           // Viewable extensions (empty array means every file is viewable)
   "txt",
   "php",
   "php3",
   "jsp",
   "htm",
   "html",
   "shtml",
   "xml",
   "wml",
   "js",
   "css"
);

$builtinauth = false;              // Use builtin authentication (needs PHP to be running as module)
$authuser = "user";                // Builtin authentication user
$authpassword = "password";        // Builtin authentication password
$realmname = "Web File Browser";   // Realm name

$useimages = false;                // Use images (pages are lighter without images), set to false by default
                                   // to respect the philosophy "all in one single file"
$imagesdir = "wfbimages";          // Images directory (must be located in base directory)
$showimagesdir = false;            // Show images directory
$trashcanimage = "trashcan.gif";   // Image for trash can
$upperdirimage = "upperdir.gif";   // Image for upper and main directory
$opendirimage = "opendir.gif";     // Image for open directory
$dirimage = "dir.gif";             // Image for simple directory
$fileimage = "file.gif";           // Image for file directory

$allowsearch = true;               // Allow searches
$searchmaxlevels = 10;             // Search levels (max depth in sub directories for searches, 0 means no limits)
$allowregexpsearch = true;         // Allow optionnal use of regular expressions in searches

// ---- Locales --------------------------------------------------------

// Date format
$dateformat = "m-d-Y H:i:s";       // Date format. Here are some other examples (that you can combine) :
                                   // "M D, Y"   = Dec Fri, 2002
                                   // "m/d/y"    = 12/20/02
                                   // "m-d-y"    = 12-20-02
                                   // "l M d, Y" = Friday Dec 20, 2002
                                   // "F dS, Y"  = December 20th, 2002
                                   // "H:i:s"    = 24 hour time with seconds
                                   // "h:i a"    = 12 hour time with am,pm
                                   // etc...

// Charset
$charset = "iso-8859-1";

// Messages
//  If you want another language just replace this array by the one
//  in your favorite language file (an include file is not done to keep
//  the whole code in 1 single file)
$messages = array(
   "rlm1"=>"Authentication required",
   "trc0"=>"Empty",
   "trc1"=>"Trash can emptied",
   "trc2"=>"Trash can was not fully emptied",
   "trc3"=>"Unable to read trash can",
   "trc9"=>"Empty trash can",
   "rst0"=>"Restore",
   "rst1"=>"Bad name for file to restore",
   "rst2"=>"Restore only works in trash can",
   "rst3"=>"File %VAR1% restored",
   "rst4"=>"Unable to restore file %VAR1%",
   "rst5"=>"No name for file to restore",
   "rst9"=>"Restore <b>selected</b> file",
   "mov0"=>"Move",
   "mov1"=>"Bad name for file to move",
   "mov2"=>"Bad destination folder for file to move",
   "mov3"=>"File %VAR1% moved to %VAR2%",
   "mov4"=>"Unable to move file %VAR1% to %VAR2%",
   "mov5"=>"Destination folder %VAR1% is not a valid folder",
   "mov6"=>"No name or destination folder for file to move",
   "mov9"=>"Move <b>selected</b> file or folder to <b>selected</b> destination folder",
   "ren0"=>"Rename",
   "ren1"=>"Bad name for file to rename",
   "ren2"=>"Bad new name for file to rename",
   "ren3"=>"File %VAR1% renamed to %VAR2%",
   "ren4"=>"Unable to rename file %VAR1% to %VAR2%",
   "ren5"=>"No name or new name for file to rename",
   "ren9"=>"Rename <b>selected</b> file or folder to",
   "cpy0"=>"Copy",
   "cpy1"=>"Bad name for file to copy",
   "cpy2"=>"Bad copy name for file to copy",
   "cpy3"=>"File %VAR1% copied to %VAR2%",
   "cpy4"=>"Unable to copy file %VAR1% to %VAR2%",
   "cpy5"=>"Can't copy directories",
   "cpy6"=>"No name or copy name for file to copy",
   "cpy9"=>"Copy <b>selected</b> file to",
   "als0"=>"Alias",
   "als1"=>"Bad name for file to alias",
   "als2"=>"File %VAR1% aliased",
   "als3"=>"Unable to alias file %VAR1%",
   "als4"=>"File %VAR1% was un-aliased",
   "als5"=>"File %VAR1% was not aliased",
   "als6"=>"Can't alias directories",
   "als7"=>"No name for file to alias",
   "als9"=>"Alias <b>selected</b> file with",
   "cre0"=>"Create file",
   "cre1"=>"Bad name for file to create",
   "cre2"=>"File %VAR1% created",
   "cre3"=>"Unable to create file %VAR1%",
   "cre4"=>"No name for file to create",
   "cre9"=>"Create new file",
   "sav1"=>"Bad name for file to save",
   "sav2"=>"Unable to save file %VAR1%",
   "sav3"=>"No name for file to save",
   "sav4"=>"Save",
   "sav5"=>"Cancel",
   "sav6"=>"DOS / WINDOWS format",
   "sav7"=>"UNIX format",
   "del0"=>"Delete",
   "del1"=>"Bad name for file to delete",
   "del2"=>"Folder %VAR1% deleted",
   "del3"=>"Unable to delete folder %VAR1% (not empty ?)",
   "del4"=>"File %VAR1% moved to trash can",
   "del5"=>"Unable to move file %VAR1% to trash can",
   "del6"=>"No name for file or folder to delete",
   "del9"=>"Delete <b>selected</b> file or folder",
   "fup0"=>"Upload",
   "fup1"=>"Bad name for file to upload",
   "fup2"=>"Upload of file %VAR1% succeeded",
   "fup3"=>"Upload of file %VAR1% aborted",
   "fup4"=>"No name for file to upload",
   "fup9"=>"Upload file",
   "uup0"=>"URL Upload",
   "uup1"=>"Bad URL to upload",
   "uup2"=>"URL %VAR1% uploaded to %VAR2%",
   "uup3"=>"Unable to upload %VAR1%",
   "uup4"=>"No URL to upload",
   "uup9"=>"Upload file from URL",
   "mkd0"=>"Create folder",
   "mkd1"=>"Bad name for folder to create",
   "mkd2"=>"Folder %VAR1% created",
   "mkd3"=>"Unable to create folder %VAR1%",
   "mkd4"=>"No name for folder to create",
   "mkd9"=>"Create new folder",
   "edt1"=>"Bad name for file to edit",
   "edt2"=>"Bad name for file to view",
   "edt3"=>"Bad extension for file to edit",
   "edt4"=>"Bad extension for file to view",
   "edt5"=>"Unable to read file %VAR1%",
   "edt6"=>"No name for file to edit",
   "edt7"=>"No name for file to view",
   "edt8"=>"Edit file",
   "edt9"=>"View file",
   "edt10"=>"E", // Edit action
   "edt11"=>"V", // View action
   "edt12"=>"Return to file list",
   "dir1"=>"Unable to read folder",
   "dir2"=>"Main folder",
   "dir3"=>"Upper folder",
   "dir4"=>"Trash can",
   "dir5"=>"Sub-folder",
   "tab1"=>"Sel",
   "tab2"=>"To",
   "tab3"=>"Name",
   "tab4"=>"Size",
   "tab5"=>"Date",
   "tab6"=>"Perms",
   "tab7"=>"Owner",
   "tab8"=>"Group",
   "tab9"=>"Read<br>Only",
   "tab10"=>"Action",
   "tab11"=>"directories",
   "tab12"=>"files",
   "tab13"=>"Kb",
   "tab14"=>"Yes",
   "act1"=>"Unkown or unsuitable action",
   "act2"=>"Are you sure" ,
   "act3"=>"No file or destination folder selected",
   "act4"=>"No file selected",
   "act5"=>"No new name for file to rename",
   "act6"=>"No copy name for file to copy",
   "sch1"=>"Search file(s) from the current folder",
   "sch2"=>"Search",
   "sch3"=>"No files found matching %VAR1%",
   "sch4"=>"Search results for %VAR1%",
   "sch5"=>"Searched folder",
   "sch6"=>"No search pattern",
   "sch7"=>"Use regular expression",
   "sch8"=>"Go to folder of <b>selected</b> file",
   "sch9"=>"Go to folder",
   "dwn1"=>"D", // Download action
   "dwn2"=>"Bad name for file to download",
   "dwn3"=>"Unable to download file",
   "dwn4"=>"No name for file to download"
);

// ---- Things that may be customized (but without any warranty)... ----

$basedir = dirname(__FILE__);     // Base directory = local directory
//$basedir = "/foo/bar";          // Base directory = custom directory (UNIX)
//$basedir = "c:My Documents";  // Base directory = custom directory (WINDOWS)

// ---------------------------------------------------------------------

// Prevents from seeing this file
$thisfile = strtolower(basename(__FILE__));

// Inhibitate file links with custom base directory
$filelinks = ($basedir != dirname(__FILE__)) ? false : $filelinks;

// Globals
$thishost = $HTTP_SERVER_VARS["HTTP_HOST"];
$thisscript = $HTTP_SERVER_VARS["PHP_SELF"];
if (!empty($HTTP_POST_VARS)) extract($HTTP_POST_VARS);
if (!empty($HTTP_GET_VARS)) extract($HTTP_GET_VARS);

// Checks and rebuilds sub-directory
function extractSubdir($d) {
   global $basedir;

   if ($d != "") {
      $tmp = strtr(str_replace($basedir, "", realpath($d)), "", "/");
      if ($tmp[0] == '/') $tmp = substr($tmp, 1);
   } else $tmp = "";

   return $tmp;
}

// Returns full file path
function getFilePath($f, $sd = "") {
   global $basedir, $subdir;

   return $basedir."/".(($sd != "") ? $sd : $subdir)."/".basename($f);
}

// Return UNIX file perms
function getFilePerms($p) {
   if      (($p & 0xC000) === 0xC000) $type = 's';
   else if (($p & 0x4000) === 0x4000) $type = 'd';
   else if (($p & 0xA000) === 0xA000) $type = 'l';
   else if (($p & 0x8000) === 0x8000) $type = '-';
   else if (($p & 0x6000) === 0x6000) $type = 'b';
   else if (($p & 0x2000) === 0x2000) $type = 'c';
   else if (($p & 0x1000) === 0x1000) $type = 'p';
   else $type = '?';

   $u["r"] = ($p & 00400) ? 'r' : '-';
   $u["w"] = ($p & 00200) ? 'w' : '-';
   $u["x"] = ($p & 00100) ? 'x' : '-';
   $g["r"] = ($p & 00040) ? 'r' : '-';
   $g["w"] = ($p & 00020) ? 'w' : '-';
   $g["x"] = ($p & 00010) ? 'x' : '-';
   $o["r"] = ($p & 00004) ? 'r' : '-';
   $o["w"] = ($p & 00002) ? 'w' : '-';
   $o["x"] = ($p & 00001) ? 'x' : '-';

   if($p & 0x800) $u["x"] = ($u[x] == 'x') ? 's' : 'S';
   if($p & 0x400) $g["x"] = ($g[x] == 'x') ? 's' : 'S';
   if($p & 0x200) $o["x"] = ($o[x] == 'x') ? 't' : 'T';

   return $type.$u["r"].$u["w"].$u["x"].$g["r"].$g["w"].$g["x"].$o["r"].$o["w"].$o["x"];
}

// Checks file name
function checkFileName($f) {
   global $subdir, $thisfile, $hidedotfiles, $hidefilepattern, $trashcan, $trashcaninfofileext, $showimagesdir, $imagesdir, $readmefile, $showreadmefile, $filealiases, $filealiasext;
 
   $f = basename($f);

   return !(   (($subdir == "") && (strtolower($f) == $thisfile))
            || (($subdir == "") && ($f == $trashcan))
            || (!$showimagesdir && ((($subdir == "") && ($f == $imagesdir)) || ($subdir == $imagesdir)))
            || ($hidedotfiles && ($f[0] == '.'))
            || (($hidefilepattern != "") && ereg($hidefilepattern, $f))
            || ($filealiases && ereg("^.*.".strtolower($filealiasext)."$", strtolower($f)))
            || ($f == "..")
            || (!$showreadmefile && ($f == $readmefile))
            || (($subdir == $trashcan) && (($f == $readmefile) || ereg(".*.".strtolower($trashcaninfofileext)."$", strtolower($f)))) );
}

// Checks for edit extension
function checkExtension($f) {
   global $viewextensions;

   if (count($viewextensions) != 0) {
      foreach ($viewextensions as $ext) {
         if (ereg(".*.".strtolower($ext)."$", strtolower($f))) return true;
      }
      return false;
   } else {
      return true;
   }
}

// Find files matching a regexp pattern
function searchFiles($sd, $searchpattern, $level = 0) {
   global $basedir, $subdir, $searchmaxlevels, $regexpsearch;

   $count = 0;

   if (   ($searchmaxlevels == 0)
       || ($level < $searchmaxlevels)) {
      $dir = $basedir."/".$sd;

      if (!$regexpsearch && $level == 0) {
         $searchpattern = "^".str_replace("*", ".*", str_replace("?", ".", str_replace(".", ".", $searchpattern)))."$";
      }
         
      $d = @opendir($dir); 

      while (($file = @readdir($d))) { 
         if (is_dir($dir."/".$file) && ($file != ".") && ($file != "..")) {
            searchFiles($sd."/".$file, $searchpattern, $level + 1); 
         } else if (@ereg(strtolower($searchpattern), strtolower($file))) {
            $fp = getFilePath($file, $sd);
            addFileToList($file, $fp, ($subdir != "") ? str_replace($subdir."/", "", extractSubdir($fp)) : extractSubdir($fp), 9);
            $count++;
         }
      } 

      @closedir($d); 
   }

   return $count;
}

// Adds a file to file list
function addFileToList($file, $fp, $alias, $level, $image = "") {
   global $files, $subdir, $trashcan, $sortby, $showunixattrs, $dateformat, $useimages, $imagesdir, $dirimage, $fileimage;

   if ($alias == "") $alias = $file;

   $date = filemtime($fp);
   $size = filesize($fp);
   if ($showunixattrs) {
      $perms = getFilePerms(fileperms($fp));
      $uid = @posix_getpwuid(fileowner($fp));
      $owner = $uid["name"];
      $gid = @posix_getgrgid(filegroup($fp));
      $group = $gid["name"];
   } else {
      $perms = "";
      $owner = "";
      $group = "";
   }

   if ($sortby == "size") {
      $key = $level." ".str_pad($size, 20, "0", STR_PAD_LEFT)." ".$alias;
   } else if ($sortby == "date") {
      $key = $level." ".date("YmdHis", $date)." ".$alias;
   } else {
      $key = $level." ".$alias;
   }

   $files[$key] = array(
         "name"=>$file,
         "alias"=>(($useimages) ? "<img src="$imagesdir/".(($image != "") ? $image : ((is_dir($fp)) ? $dirimage : $fileimage))."" border=0 align=center>&nbsp;" : "").(($subdir == $trashcan) ? ereg_replace("(.*).[0-9]*$", "1", $alias) : $alias),
         "level"=>$level,
         "path"=>$fp,
         "size"=>$size,
         "date"=>date($dateformat, $date),
         "perms"=>$perms,
         "owner"=>$owner,
         "group"=>$group,
         "dir"=>is_dir($fp),
         "link"=>is_link($fp),
         "readonly"=>!is_writeable($fp)
         );
}

// Generates full message
function getMsg($class, $msgcode, $msgparam1 = "", $msgparam2 = "") {
   global $messages;

   $msg = str_replace("%VAR1%", $msgparam1, str_replace("%VAR2%", $msgparam2, $messages[$msgcode]));

   return (($class != "") ? "<p class=$class>" : "").htmlspecialchars($msg);
}

// Manages redirections
function redirectWithMsg($class, $msgcode, $msgparam1 = "", $msgparam2 = "", $extraparams = "") {
   global $thishost, $thisscript, $subdir, $sortby;

   $msg = getMsg($class, $msgcode, $msgparam1, $msgparam2);
   header("Location: http://$thishost$thisscript?subdir=".rawurlencode($subdir)."&sortby=$sortby&msg=".rawurlencode($msg).$extraparams);
   exit;
}

// Page header
function pageHeader() {
   global $title, $windowtitle, $thbgcolor, $thfgcolor, $tdbgcolor, $tdfgcolor, $msg;
?>
<html>
<head>
<title><?= $windowtitle ?></title>
<style type="text/css" media=screen>
<!--
body       { background-color: white; color=black; font-family: Arial, Helvetica, sans-serif; font-size: 10pt; }
p          { color=black; font-family: Arial, Helvetica, sans-serif; font-size: 10pt; }
.info      { color: green; font-family: Arial, Helvetica, sans-serif; font-size: 10pt; }
.warning   { color: orange; font-family: Arial, Helvetica, sans-serif; font-size: 10pt; }
.error     { color: red; font-family: Arial, Helvetica, sans-serif; font-size: 10pt; }
.fix       { font-family: Courier; font-size: 10pt; }
h1         { font-family: Arial, Helvetica, sans-serif; font-size: 16pt; }
h2         { font-family: Arial, Helvetica, sans-serif; font-size: 12pt; }
th         { background-color: <?= $thbgcolor ?>; color: <?= $thfgcolor ?>; font-family: Arial, Helvetica, sans-serif; font-size: 10pt; }
td         { background-color: <?= $tdbgcolor ?>; color: <?= $tdfgcolor ?>; font-family: Arial, Helvetica, sans-serif; font-size: 10pt; }
.tdlt      { background-color: white; color: black; font-family: Arial, Helvetica, sans-serif; font-size: 10pt; text-align: left; vertical-align: top; }
.tdrt      { background-color: white; color: black; font-family: Arial, Helvetica, sans-serif; font-size: 10pt; text-align: right; vertical-align: top; }
.tdcc      { background-color: white; color: black; font-family: Arial, Helvetica, sans-serif; font-size: 10pt; text-align: center; vertical-align: center; }
a:link     { color: blue; text-decoration: none; }
a:active   { color: red; text-decoration: underline; }
a:visited  { color: blue; text-decoration: none; }
a:hover    { color: red; text-decoration: underline; }
-->
</style>
</head>
<body>
<h1><?= $title ?></h1>
<?
   if (isset($msg)) echo $msg; // Displays message after redirection if required
}

// Page footer
function pageFooter() {
?>
</body>
</html>
<?
}

header("Expires: -1");
header("Pragma: no-cache");
header("Cache-Control: max-age=0");
header("Cache-Control: no-cache");
header("Cache-Control: no-store");
if ($act != "download") {
   header("Content-Type: text/html; charset=$charset");
}

if ($builtinauth) {
   if (   !isset($HTTP_SERVER_VARS["PHP_AUTH_USER"])
       || ($HTTP_SERVER_VARS["PHP_AUTH_USER"] != $authuser)
       || ($HTTP_SERVER_VARS["PHP_AUTH_PW"] != $authpassword)) {
      header("WWW-Authenticate: Basic realm="$realmname"");
      header("HTTP/1.0 401 Unauthorized");
      pageHeader();
      echo getMsg("error", "rlm1");
      pageFooter();
      exit;
   }
}

if (  !isset($subdir)
   || strstr($subdir, "..")
   || (!$allowbrowsetrashcan && ($subdir == $trashcan))) {
   $subdir = "";
}
$subdir = extractSubdir($basedir."/".$subdir);

if (!isset($sortby)) $sortby = $defaultsortby;

if (!isset($act)) $act = "";

// Array for file lists
$files = array();

// Processes actions and redirects to pages
if (($act != "edit") && ($act != "show")) {
   if ($act == "") {
      @clearstatcache();

      if ($d = @opendir($basedir."/".$subdir)) {
         // builds an indexed array for files
         if ($subdir != "") {
            addFileToList("", $basedir, "[".$messages["dir2"]."]", 0, $upperdirimage);
         }
         if ($subdir != $trashcan) {
            addFileToList("..", getFilePath(".."), "[".$messages["dir3"]."]", 2, $upperdirimage);
         }
         if ($allowbrowsetrashcan && ($subdir != $trashcan) && (is_dir($basedir."/".$trashcan))) {
            addFileToList($trashcan, $basedir."/".$trashcan, "[".$messages["dir4"]."]", 1, $trashcanimage);
         }
         while ($file = @readdir($d)) {
            if (checkFileName($file)) {
               $fp = getFilePath($file);
               $fp_alias = $fp.".".$filealiasext; 

               $alias = "";
               if ($filealiases && @is_readable($fp_alias)) {
                  $fd = @fopen($fp_alias, "r");
                  $alias = trim(@fread($fd, filesize($fp_alias)))." <i>(".(($subdir == $trashcan) ? ereg_replace("(.*).[0-9]*$", "1", $file) : $file).")</i>";
                  @fclose($fd);
               }

               addFileToList($file, $fp, $alias, 9);
            }
         }

         @closedir($d);

         // Sort the array according to indexes
         ksort($files);
      } else {
         pageHeader();
         echo getMsg("error", "dir1", $subdir);
         pageFooter();
         exit;
      }
   } else if ($allowsearch && ($act == "search")) {
      $searchpattern = trim($searchpattern);

      if ($searchpattern != "") {
         if (!isset($regexpsearch)) $regexpsearch = false;

         @clearstatcache();

         addFileToList($subdir, getFilePath("."), "[".$messages["sch5"]."]", 1, $upperdirimage);

         if (searchFiles($subdir, $searchpattern) == 0) {
            redirectWithMsg("warning", "sch3", $searchpattern, "", "&searchpattern=".rawurlencode($searchpattern).(($allowregexpsearch) ? "&regexpsearch=$regexpsearch" : ""));
         }

         ksort($files);
      } else {
         redirectWithMsg("error", "sch6");
      }
   } else if ($allowemptytrashcan && ($act == "empty") && ($subdir == $trashcan)) {
      $res = true;
      if ($d = @opendir($basedir."/".$subdir)) {
         while ($file = @readdir($d)) {
            $fp = getFilePath($file);

            if (($file != ".") && ($file != "..")) {
               if (is_dir($fp) || !@unlink($fp)) {
                  $res = false;
               }
            }
         }
         @closedir($d);

         if ($res) {
            redirectWithMsg("info", "trc1");
         } else {
            redirectWithMsg("warning", "trc2");
         }
      } else {
         redirectWithMsg("error", "trc3");
      }
   } else if ($allowrestorefromtrashcan && ($act == "restore")) {
      if (isset($file) && ($file != "")) {
         if (!checkFileName($file)) {
            redirectWithMsg("warning", "rst1");
         } else if ($subdir != $trashcan) {
            redirectWithMsg("warning", "rst2");
         } else {
            $f = ereg_replace("(.*).[0-9]*$", "1", $file);
            $fp = getFilePath($file);
            $fp_info = $fp.".".$trashcaninfofileext;

            $fpd = "";
            if ($fdi = @fopen($fp_info, "r")) {
               $fpd = trim(@fread($fdi, filesize($fp_info)));
               @fclose($fdi);
            }

            $fp_alias = $fp.".".$filealiasext;
            $fpd_alias = $fpd.".".$filealiasext;

            if (@rename($fp, $fpd)) {
               @unlink($fp_info);
               if ($filealiases && @is_readable($fp_alias)) @rename($fp_alias, $fpd_alias);
               redirectWithMsg("info", "rst3", $f);
            } else {
               redirectWithMsg("error", "rst4", $f);
            }
         }
      } else {
         redirectWithMsg("warning", "rst5");
      }
   } else if ($allowmove && ($act == "move")) {
      if (isset($file) && ($file != "") && isset($dest)) {
         if (!checkFileName($file) || (($subdir == "") && ($file == $trashcan))) {
            redirectWithMsg("warning", "mov1");
         } else if (($dest != "..") && !checkFileName($dest)) {
            redirectWithMsg("warning", "mov2");
         } else {
            $fp = getFilePath($file);
            $fpd = ($dest == "") ? $basedir : getFilePath($dest);
            $fp_alias = $fp.".".$filealiasext;
            $fpd_alias = $fpd."/".basename($file).".".$filealiasext;

            $destinfo = ($dest == "") ? "main directory" : (($dest == "..") ? "upper directory" : $dest);

            if (is_dir($fpd)) {
               if (@rename($fp, $fpd."/".basename($file))) {
                  if ($filealiases && @is_readable($fp_alias)) @rename($fp_alias, $fpd_alias);
                  redirectWithMsg("info", "mov3", $file, $destinfo);
               } else {
                  redirectWithMsg("error", "mov4", $file, $destinfo);
               }
            } else {
               redirectWithMsg("error", "mov5", $dest);
            }
         }
      } else {
         redirectWithMsg("warning", "mov6");
      }
   } else if ($allowrename && ($act == "rename") && ($subdir != $trashcan)) {
      if (isset($file) && ($file != "") && isset($renameto) && ($renameto != "")) {
         if (!checkFileName($file) || (($subdir == "") && ($file == $trashcan))) {
            redirectWithMsg("warning", "ren1");
         } else if (!checkFileName($renameto)) {
            redirectWithMsg("warning", "ren2");
         } else {
            $fp = getFilePath($file);
            $fpto = getFilePath($renameto);
            $fp_alias = $fp.".".$filealiasext;
            $fpto_alias = $fpto.".".$filealiasext;

            if (@rename($fp, $fpto)) {
               if ($filealiases && @is_readable($fp_alias)) @rename($fp_alias, $fpto_alias);
               redirectWithMsg("info", "ren3", $file, $renameto);
            } else {
               redirectWithMsg("error", "ren4", $file, $renameto);
            }
         }
      } else {
         redirectWithMsg("warning", "ren5");
      }
   } else if ($allowcopy && ($act == "copy") && ($subdir != $trashcan)) {
      if (isset($file) && ($file != "") && isset($copyto) && ($copyto != "")) {
         if (!checkFileName($file) || (($subdir == "") && ($file == $trashcan))) {
            redirectWithMsg("warning", "cpy1");
         } else if (!checkFileName($copyto)) {
            redirectWithMsg("warning", "cpy2");
         } else {
            $fp = getFilePath($file);
            $fpto = getFilePath($copyto);

            if (!is_dir($fp)) {
               if (@copy($fp, $fpto)) {
                  redirectWithMsg("info", "cpy3", $file, $copyto);
               } else {
                  redirectWithMsg("error", "cpy4", $file, $copyto);
               }
            } else {
               redirectWithMsg("error", "cpy5");
            }
         }
      } else {
         redirectWithMsg("warning", "cpy6");
      }
   } else if ($allowalias && $filealiases && ($act == "alias") && ($subdir != $trashcan)) {
      if (isset($file) && ($file != "")) {
         if (!checkFileName($file) || (($subdir == "") && ($file == $trashcan))) {
            redirectWithMsg("warning", "als1");
         } else {
            $fp = getFilePath($file);
            $fp_alias = $fp.".".$filealiasext;

            if (!is_dir($fp)) {
               if ($aliasto != "") {
                  if ($fda = @fopen($fp_alias, "w")) {
                     @fwrite($fda, $aliasto);
                     @fclose($fda);
                     redirectWithMsg("info", "als2", $file);
                  } else {
                     redirectWithMsg("error", "als3", $file);
                  }
               } else {
                  if (@is_readable($fp_alias)) {
                     @unlink($fp_alias);
                     redirectWithMsg("info", "als4", $file);
                  } else {
                     redirectWithMsg("info", "als5", $file);
                  }
               }
            } else {
               redirectWithMsg("error", "als6");
            }
         }
      } else {
         redirectWithMsg("warning", "als7");
      }
   } else if ($allowcreatefile && ($act == "create") && ($subdir != $trashcan)) {
      if (isset($file) && ($file != "")) {
         if (!checkFileName($file) || (($subdir == "") && ($file == $trashcan))) {
            redirectWithMsg("warning", "cre1");
         } else {
            $fp = getFilePath($file);

            if (@touch($fp)) {
               @chmod($fp, $filemode);
               redirectWithMsg("info", "cre2", $file);
            } else {
               redirectWithMsg("error", "cre3", $file);
            }
         }
      } else {
         redirectWithMsg("warning", "cre4");
      }
   } else if ($allowedit && ($act == "save") && ($subdir != $trashcan)) {
      if (isset($file) && ($file != "")) {
         if (!checkFileName($file) || (($subdir == "") && ($file == $trashcan))) {
            redirectWithMsg("warning", "sav1");
         } else {
            $fp = getFilePath($file);

            if ($fd = @fopen($fp, "w")) {
               if (!isset($fileformat)) $fileformat = $defaultfileformat;

               $data = stripslashes($data); // Strips doubled backslashes
               $data = str_replace("rn", "n", $data); // Remove LF => UNIX format
               if ($fileformat == "dos") $data = str_replace("n", "rn", $data); // Add LF => DOS format

               @fwrite($fd, $data);
               @fclose($fd);

               redirectWithMsg("File $file saved (".strtoupper($fileformat)." format)", "info");
            } else {
               $msg = getMsg("error", "sav2", $file);
               $data = stripslashes($data);
               $act = "edit"; // To re-edit file (no redirection)
            }
         }
      } else {
         redirectWithMsg("warning", "sav3");
      }
   } else if ($allowdelete && ($act == "delete") && ($subdir != $trashcan)) {
      if (isset($file) && ($file != "")) {
         if (!checkFileName($file) || (($subdir == "") && ($file == $trashcan))) {
            redirectWithMsg("warning", "del1");
         } else {
            $fp = getFilePath($file);

            if (is_dir($fp) && !is_link($fp)) {
               if (@rmdir($fp)) {
                  redirectWithMsg("info", "del2", $file);
               } else {
                  redirectWithMsg("error", "del3", $file);
               }
            } else {
               $tr = $basedir."/".$trashcan;
               $fpd = $tr."/".basename($file).".".date("YmdHis");
               $fpd_info = $fpd.".".$trashcaninfofileext;
               $fp_alias = $fp.".".$filealiasext;
               $fpd_alias = $fpd.".".$filealiasext;

               if (is_dir($tr) && ($fdi = @fopen($fpd_info, "w")) && @rename($fp, $fpd)) {
                  @fwrite($fdi, $fp);
                  @fclose($fdi);
                  if ($filealiases && @is_readable($fp_alias)) @rename($fp_alias, $fpd_alias);

                  redirectWithMsg("info", "del4", $file);
               } else {
                  redirectWithMsg("error", "del5", $file);
               }
            }
         }
      } else {
         redirectWithMsg("warning", "del6");
      }
   } else if ($allowupload && ($act == "upload") && ($subdir != $trashcan)) {
      if (isset($HTTP_POST_FILES['file']) && ($HTTP_POST_FILES['file']['size'] > 0)) {
         if (!checkFileName($HTTP_POST_FILES['file']['name']) || (($subdir == "") && ($HTTP_POST_FILES['file']['name'] == $trashcan))) {
            redirectWithMsg("warning", "fup1");
         } else {
            $fp = getFilePath($HTTP_POST_FILES['file']['name']);

            if (@copy($HTTP_POST_FILES['file']['tmp_name'], $fp)) {
               @unlink($HTTP_POST_FILES['file']['tmp_name']);
               @chmod($fp, $filemode);
               redirectWithMsg("info", "fup2", $HTTP_POST_FILES['file']['name']);
            } else {
               redirectWithMsg("error", "fup3", $HTTP_POST_FILES['file']['name']);
            }
         }
      } else {
         redirectWithMsg("warning", "fup4");
      }
   } else if ($allowurlupload && ($act == "urlupload") && ($subdir != $trashcan)) {
      if (isset($file) && ($file != "")) {
         $url = $file;
         $file = basename(ereg_replace("^[a-zA-Z]*:/(.*)$", "1", $url));
         if (!checkFileName($file) || (($subdir == "") && ($file == $trashcan))) {
            redirectWithMsg("warning", "uup1");
         } else {
            $fp = getFilePath($file);

            if (($fd = @fopen($url, "r")) && ($fdd = @fopen($file, "w"))) {
               while (! @feof($fd)) {
                  @fwrite($fdd, fread($fd, 1024));
               }
               @fclose($fd);
               @fclose($fdd);
               redirectWithMsg("info", "uup2", $url, $file);
            } else {
               redirectWithMsg("error", "uup3", $url);
            }
         }
      } else {
         redirectWithMsg("warning", "uup4");
      }
   } else if ($allowcreatedir && ($act == "mkdir") && ($subdir != $trashcan)) {
      if (isset($file) && ($file != "")) {
         if (!checkFileName($file) || (($subdir == "") && ($file == $trashcan))) {
            redirectWithMsg("warning", "mkd1");
         } else {
            $fp = getFilePath($file);

            if (@mkdir($fp, $dirmode)) {
               @chmod($fp, $dirmode); // mkdir sometimes fails to set permissions
               redirectWithMsg("info", "mkd2", $file);
            } else {
               redirectWithMsg("error", "mkd3", $file);
            }
         }
      } else {
         redirectWithMsg("warning", "mkd4");
      }
      redirectWithMsg($msg);
   } else if ($allowdownload && ($act == "download") && ($subdir != $trashcan)) {
      if (isset($file) && ($file != "")) {
         $subdir = dirname($file);

         if (!checkFileName($file) || (($subdir == "") && ($file == $trashcan))) {
            redirectWithMsg("warning", "dwn2");
         } else {
            $fp = getFilePath($file);

            if (@is_readable($fp)) {
               @clearstatcache();

               header("Content-Type: application/force-download");
               header("Content-Transfer-Encoding: binary");
               header("Content-Length: ".filesize($fp));
               header("Content-Disposition: attachment; filename="".basename($file).""");

               @readfile($fp);

               exit;
            } else {
               redirectWithMsg("error", "dwn3", $file);
            }
         }
      } else {
         redirectWithMsg("warning", "dwn4");
      }
   } else {
      redirectWithMsg("error", "act1");
   }
}

pageHeader();

if ($allowsearch) echo "<form action=$thisscript method=get name=searchForm>";
echo "<table border=0 cellspacing=0 cellpadding=2><tr><td width=".(($showunixattrs) ? 310 : 360)."><b>";
if ($useimages) {
   echo "<img src="$imagesdir/$opendirimage" align=center> ";
}

if ($act == "search") {
   echo getMsg("", "sch4", $searchpattern)." (";
}
if ($subdir == "") {
   echo $messages["dir2"];
} else if ($subdir == $trashcan) {
   echo $messages["dir4"];
} else {
   echo $messages["dir5"]." : ".htmlspecialchars($subdir);
}
if ($act == "search") echo ")";

echo "</b><br>".date($dateformat)."</td>";

if ($allowsearch && (($act == "") || ($act == "search"))) {
   echo "<td width=20 class=tdlt>&nbsp;</td>";
   echo "<td class=tdlt>";
   echo "<input name=act type=hidden value=search>";
   echo "<input name=subdir type=hidden value="$subdir">";
   echo "<input name=sortby type=hidden value=$sortby>";
   echo "<input name=searchpattern type=text size=15 value="$searchpattern"> ";
   echo "<input type=button value="".$messages["sch2"]."" onClick='submitActForm(document.searchForm, "".$messages["sch6"]."")'>";
   if ($allowregexpsearch) {
      echo "<br><input type=checkbox value=true name=regexpsearch".(($regexpsearch) ? " checked" : "")."> ".$messages["sch7"];
   }
}

echo"</tr></table>";
if ($allowsearch) echo "</form>";

// Edit or show page
if (($allowedit && ($act == "edit")) || ($allowshow && ($act == "show")) && ($subdir != $trashcan)) {
   if (isset($file) && ($file != "")) {
      if (!checkFileName($file) || (($subdir == "") && ($file == $trashcan))) {
         echo getMsg("warning", ($act == "edit") ? "edt1" : "edt2");
      } else if (!checkExtension($file)) {
         echo getMsg("warning", ($act == "edit") ? "edt3" : "edt4");
      } else {
         if (!isset($data)) {
            $fp = getFilePath($file);

            if ($fd = @fopen($fp, "r")) {
               $data = @fread($fd, filesize($fp));
               @fclose($fd);
            } else {
               echo getMsg("error", "edt5");
            }
         }

         if ($act == "edit") {
            echo "<p><b>".$messages["edt8"]." : </b>".htmlspecialchars($file);
?>
<script language=javascript>
<!--
function cancelEdit() {
   f = document.editForm;
   f.act.value = "";
   f.file.value = "";
   f.data.value = "";
   f.method = "get";
   f.submit();
}
//-->
</script>
<form action=<?= $thisscript ?> method=post name=editForm>
<input name=act type=hidden value=save>
<input name=subdir type=hidden value="<?= $subdir ?>">
<input name=sortby type=hidden value=<?= $sortby ?>>
<input name=file type=hidden value="<?= $file ?>">
<p><table border=0 cellspacing=0 cellpadding=10>
<tr>
<td colspan=3>
<?
            echo "<textarea name=data cols=$editcols rows=$editrows>";
            echo htmlspecialchars($data);
            echo "</textarea>";
?>
</td>
</tr>
<tr>
<td align=left>
<input type=radio name=fileformat value=dos<?= (($defaultfileformat == "dos") ? " checked" : "") ?>><?= $messages["sav6"] ?>
<br><input type=radio name=fileformat value=unix<?= (($defaultfileformat == "unix") ? " checked" : "") ?>><?= $messages["sav7"] ?>
</td>
<td align=center>
<input type=submit value="<?= $messages["sav4"] ?>">
</td>
<td align=right>
<input type=button value="<?= $messages["sav5"] ?>" onClick='cancelEdit()'>
</td>
</tr>
</table>
</form>
<?
         } else {
            echo "<p><b>".$messages["edt9"]." : </b>".htmlspecialchars($file);
?>
<p><table border=0 cellspacing=0 cellpadding=10>
<tr><td width=700><pre><?= htmlspecialchars($data) ?></pre>&nbsp;</td></tr>
</table>
<p><a href=<?= $thisscript?>?subdir=<?= rawurlencode($subdir) ?>&sortby=<?= $sortby ?>><?= $messages["edt12"] ?></a>.
<?
         }
      }
   } else {
      echo getMsg("warning", ($act == "edit") ? "edt6" : "edt7");
   }
// File list page
} else {
?>
<script language=javascript>
<!--
function submitListForm(action) {
   f = document.listForm;
   filechecked = false;
<?
   if ($act == "search") {
      echo "subdir = '';";
      echo "filesubdir = new Array();";
      reset($files);
      $i = 0;
      while (list($key, $file) = each($files)) {
         if (!is_dir($file["path"])) echo "filesubdir[".$i++."] = "".extractSubdir(dirname($file["path"]))."";";
      }
   }
?>
   if (f.file) {
      if (f.file.length > 1) {
         for (i = 0; i < f.file.length; i++) {
            if (f.file[i].checked) {
               filechecked = true;
<?
   if ($act == "search") echo "subdir = filesubdir[i];";
?>
               break;
            }
         }
      } else {
         filechecked = f.file.checked;
<?
   if ($act == "search") echo "subdir = filesubdir[0];";
?>
      }
   }
<?
   if ($act != "search") {
?>
   destchecked = false;
   if (f.dest) {
      if (f.dest.length > 1) {
         for (i = 0; i < f.dest.length; i++) {
            if (f.dest[i].checked) {
               destchecked = true;
               break;
            }
         }
      } else {
         destchecked = f.dest.checked;
      }
   }
   if ((action == "empty") && confirm("<?= $messages["act2"] ?> ?")) {
      f.act.value = action;
      f.submit();
   } else if ((action == "move") && (!filechecked || !destchecked)) {
      alert("<?= $messages["act3"] ?>");
   } else if (!filechecked) {
      alert("<?= $messages["act4"] ?>");
   } else if ((action == "rename") && (f.renameto.value == "")) {
      alert("<?= $messages["act5"] ?>");
   } else if ((action == "copy") && (f.copyto.value == "")) {
      alert("<?= $messages["act6"] ?>");
   } else if ((action == "delete") && confirm("<?= $messages["act2"] ?> ?")) {
      f.act.value = action;
      f.submit();
   } else if (action != "delete") {
      f.act.value = action;
      f.submit();
   }
<?
   } else {
?>
   f.subdir.value = subdir;
   f.act.value = "";
   f.submit();
<?
   }
?>
}
function submitActForm(f, m) {
   if (f.elements[3].value == "") {
      alert(m);
   } else {
      f.submit();
   }
}
//-->
</script>
<?
   if (!empty($files)) {
?>
<form action=<?= $thisscript ?> method=post name=listForm>
<input name=act type=hidden value="">
<input name=subdir type=hidden value='<?= $subdir ?>'>
<input name=sortby type=hidden value=<?= $sortby ?>>
<table border=0 cellspacing=2 cellpadding=2>
<tr>
<td width=25 height=0 class=tdcc></td>
<td width=25 height=0 class=tdcc></td>
<td width=<?= ($showunixattrs) ? 250 : 300 ?> height=0 class=tdcc></td>
<td width=100 height=0 class=tdcc></td>
<td width=130 height=0 class=tdcc></td>
<?
   if ($showunixattrs) {
      $nbcols = 9;
?>
<td width=100 height=0 class=tdcc></td>
<td width=75 height=0 class=tdcc></td>
<td width=75 height=0 class=tdcc></td>
<?
   } else {
?>
<td width=50 height=0 class=tdcc></td>
<?
      $nbcols = 7;
   }
?>
<td width=50 height=0 class=tdcc></td>
</tr>
<?
   if (($readmefile != "") && @is_readable(getFilePath($readmefile)) && ($act != "search")) {
      echo "<tr><td colspan=$nbcols>";
      @include(getFilePath($readmefile));
      echo "</td></tr>";
   }
?>
<tr>
<th><?= $messages["tab1"] ?></th>
<th><?= $messages["tab2"] ?></th>
<?
   echo "<th>";
   echo "<a href=$thisscript?subdir=".rawurlencode($subdir)."&sortby=name".(($act == "search") ? "&act=search&searchpattern=".rawurlencode($searchpattern) : "").">".$messages["tab3"]."</a>";
   echo "</th>";
   echo "<th>";
   echo "<a href=$thisscript?subdir=".rawurlencode($subdir)."&sortby=size".(($act == "search") ? "&act=search&searchpattern=".rawurlencode($searchpattern) : "").">".$messages["tab4"]."</a>";
   echo "</th>";
   echo "<th>";
   echo "<a href=$thisscript?subdir=".rawurlencode($subdir)."&sortby=date".(($act == "search") ? "&act=search&searchpattern=".rawurlencode($searchpattern) : "").">".$messages["tab5"]."</a>";
   echo "</th>";
?>
<?
   if ($showunixattrs) {
?>
<th><?= $messages["tab6"] ?></th>
<th><?= $messages["tab7"] ?></th>
<th><?= $messages["tab8"] ?></th>
<?
   } else {
?>
<th><?= $messages["tab9"] ?></th>
<?
   }
?>
<th><?= $messages["tab10"] ?></th>
</tr>
<?
      // Display files
      $total = 0;
      $nbfiles = 0;
      $nbdirs = 0;
      reset($files);
      while (list($key, $file) = each($files)) {
         if ($file["dir"]) {
            if (($subdir != "") || ($file["name"] != "..")) {
               echo "<tr>";
               if (($file["level"] != 0) && ($file["level"] != 1) && ($file["level"] != 2) && ($allowmove || $allowrename || $allowdelete)) {
                  echo "<td><input type=radio name=file value='".$file["name"]."'></td>";
               } else {
                  echo "<td>&nbsp;</td>";
               }
               if (($file["level"] != 1) && $allowmove && ($subdir != $trashcan)) {
                  echo "<td><input type=radio name=dest value='".$file["name"]."'></td>";
               } else {
                  echo "<td>&nbsp;</td>";
               }
               echo "<td>";
               if ($file["link"]) {
                  echo "<i><b>".htmlspecialchars($file["name"])."</b></i>";
               } else {
                  echo "<a href=$thisscript?subdir=".rawurlencode(extractSubdir($file["path"]))."&sortby=$sortby>";
                  echo "<b>".$file["alias"]."</b>";
                  echo "</a>";
               }
               echo "</td>";
               echo "<td>&nbsp;</td>";
               echo "<td align=right>".$file["date"]."</td>";
               if ($showunixattrs) {
                  echo "<td align=center><span class=fix>".$file["perms"]."</span></td>";
                  echo "<td align=right>".$file["owner"]."</td>";
                  echo "<td align=right>".$file["group"]."</td>";
               } else {
                  echo "<td align=center>".(($file["readonly"]) ? $messages["tab14"] : "&nbsp;")."</td>";
               }
               echo "<td>&nbsp;</td>";
               echo "</tr>";

               if ($file["name"] != "..") $nbdirs++;
            }
         } else {
            echo "<tr>";
            if ($allowmove || $allowrename || $allowcopy || $allowdelete) {
               echo "<td><input type=radio name=file value='".$file["name"]."'>&nbsp;</td>";
            } else {
               echo "<td>&nbsp;</td>";
            }
            echo "<td>&nbsp;</td>";
            echo "<td>".(($file["link"]) ? "<i>" : "");
            if ($filelinks) {
               echo "<a href=".str_replace("%2F", "/", rawurlencode(extractSubdir($file["path"]))).">";
               echo $file["alias"];
               echo "</a>";
            } else {
               echo htmlspecialchars($file["name"]);
            }
            echo (($file["link"]) ? "</i>" : "")."</td>";
            echo "<td align=right>".$file["size"]."</td>";
            echo "<td align=right>".$file["date"]."</td>";
            if ($showunixattrs) {
               echo "<td align=center><span class=fix>".$file["perms"]."</span></td>";
               echo "<td align=right>".$file["owner"]."</td>";
               echo "<td align=right>".$file["group"]."</td>";
            } else {
               echo "<td align=center>".(($file["readonly"]) ? $messages["tab14"] : "&nbsp;")."</td>";
            }
            echo "<td align=center>&nbsp;";
            if (($act != "search") && ($allowedit || $allowshow) && checkExtension($file["name"]) && ($subdir != $trashcan)) {
               if (!$file["readonly"] && $allowedit) {
                  echo "<a href=$thisscript?act=edit&subdir=".rawurlencode($subdir)."&sortby=$sortby&file=".rawurlencode($file["name"]).">".$messages["edt10"]."</a> ";
               }
               echo "<a href=$thisscript?act=show&subdir=".rawurlencode($subdir)."&sortby=$sortby&file=".rawurlencode($file["name"]).">".$messages["edt11"]."</a> ";
            } 
            if (($allowdownload) && ($subdir != $trashcan)) {
               echo "<a href=$thisscript?act=download&subdir=".rawurlencode($subdir)."&sortby=$sortby&file=".str_replace("%2F", "/", rawurlencode(extractSubdir($file["path"]))).">".$messages["dwn1"]."</a> ";
            }
            echo "</td>";
            echo "</tr>";
            
            $total += $file["size"];
            $nbfiles++;
         }
      }
      echo "<th colspan=$nbcols>$nbdirs ".$messages["tab11"].", $nbfiles ".$messages["tab12"]." (".round($total/1024)." ".$messages["tab13"].")</th>";
?>
</tr>
<?
         if ($allowsearch && ($act == "search")) {
?>
<tr>
<td class=tdrt colspan=3>
<br><?= $messages["sch8"] ?> :&nbsp;
</td>
<td class=tdlt colspan=<?= $nbcols - 3 ?>>
<br><input type=button value="<?= $messages["sch9"] ?>" onClick='submitListForm("goto")'>
<?
         }
      if (  ($act != "search")
         && $allowmove 
         && ($subdir != $trashcan)
         && (  (($subdir != "") && (($nbfiles > 0) || ($nbdirs > 0)))
            || (($subdir == "") && ($nbfiles > 0) && ($nbdirs > 0)) ) ) {
?>
<tr>
<td class=tdrt colspan=3>
<br><?= $messages["mov9"] ?> :&nbsp;
</td>
<td class=tdlt colspan=<?= $nbcols - 3 ?>>
<br><input type=button value="<?= $messages["mov0"] ?>" onClick='submitListForm("move")'>
</td>
</tr>
<?
      }
      if (   ($act != "search")
          && $allowdelete
          && ($subdir != $trashcan)