--- docman.php 2000/05/12 12:01:08 1.1.1.1 +++ docman.php 2000/09/06 11:00:14 1.14 @@ -34,6 +34,42 @@ /* PHP3. Fixed bug which would send you to a non- */ /* existent address after file modifications. */ +/* + 2000-07-25 Dobrica Pavlinusic + + nuked exec calls (unsecure) + nuked writeable function (replaced by php is_writeable) + added support for https (tested with apache+mod_ssl) + added users file + date format user-selectable + cycle backup files in bak directory + support links as directoryes (for now) + support of file history logging + undelete capabilities (delete moves to .del directory) + + 2000-07-26 DbP + + added more checking on entered filename (when creating file/dir) + added rename option + + +IMPORTANT INSTALLATION NOTE: + deny serving of .* (dot-something) files in web server! + Otherwise, uses can access your log files, users and/or + deleted files! + + .htusers is in form: + login:Real Name:md5(loginpassword) + + +TODO: + mixed file/directory output (add type to each entry, + real support for links) + retrieve old versions of files (overwritten) + show last lock date + +*/ + ////////////////////////////////////////////////////////////////// // TODO : Don't let the file be modified itself. Create a hash of @@ -51,12 +87,46 @@ // username/password should not be system // usernames/passwords !! - // your (hashed) username/password here - $gblPw = "hash_of_your_username_and_password" ; - - $gblAuth = false ; // use builtin authentication +// $gblPw = "hash_of_your_username_and_password" ; + +// $gblAuth = false ; // use builtin authentication + $gblAuth = true ; // use builtin authentication $gblHash = "md5" ; // hash function to use + $gblPw = ""; + + if ($gblAuth) { + $htusers_file=dirname($SCRIPT_FILENAME)."/.htusers"; + if (! file_exists($htusers_file)) { + $htusers=fopen($htusers_file,"a+"); + fputs($htusers,"# Change owner of $htusers_file to root !!\n"); + fputs($htusers,"demo:full name:md5_hash\n"); + fclose($htusers); + } + $htusers=fopen($htusers_file,"r"); + while($user = fgetcsv($htusers,255,":")) { + if ($user[0] == $GLOBALS["PHP_AUTH_USER"]) { + $gblUserName=$user[1]; + $gblPw=$user[2]; + $gblEmail=$user[3]; + continue ; + } + } + fclose($htusers); + } + +// $gblDateFmt="D, F d, Y"; +// $gblTimeFmt="g:i:sA"; + + $gblDateFmt="Y-m-d"; + $gblTimeFmt="H:i:s"; + + // Number of backup files to keep + $gblNumBackups=3; + + // show red star if newer than ... days + $gblModDays=1; + // choose GifIcon below unless you have the M$ // WingDings font installed on your system @@ -65,7 +135,7 @@ // the directory below should be /icons/ or /icons/small/ // on Apache; a set of icons is included in the distribution - $gblIconLocation = "icons/" ; + $gblIconLocation = "/icons/" ; // files you want to be able to edit in text mode // and view with (primitive) syntax highlighting @@ -91,19 +161,19 @@ - <?php echo $host . " " . $title ?> + <?= $host . " " . $title ?> + HREF="?STYLE=get"> -

+

-
-

+ +

- - -
ANYPORTAL(php) Site Manager -- © 1999 by ANYPORTAL -- © 2000 by d@nger.org + - + - + + [?relogin=">logout] + +
ANYPORTAL(php) Site Manager +
+© 1999 by ANYPORTAL, +© 2000 by d@nger.org, +© 2000 by DbP +

-


+
+ +

-BODY,TD,P,H1,H2,H3 { font-family:Helvetica,Arial,sans-serif; } +BODY,TD,P,H1,H2,H3 { font-family:Verdana,Helvetica,Arial,sans-serif; } .BLK { color:black; } .RED { color:red; } .TOP { color:red; font-size:70%; } /* table headings */ @@ -164,11 +243,12 @@ $exists = file_exists($fsPath) ; $ext = strtolower(strrchr($relPath,".")) ; $editable = ( $ext=="" || strstr(join(" ",$gblEditable),$ext)) ; - $writable = Writeable($fsPath) ; + $writable = is_writeable($fsPath) ; + $file_lock = CheckLock($fsPath); if (!$editable && !$exists) Error("Creation unsupported for type",$relPath) ; - if (!exists && !Writeable($fsDir) ) + if (!exists && !is_writeable($fsDir) ) Error("Creation denied",$relDir) ; $text = "Use this page to view, modify or " ; @@ -179,20 +259,21 @@ echo "

" . $relDir . "/" . $fn . "

" ; if ($exists) { // get file info - $fsize = filesize($fsPath) ; - $fmodified = date("d/M/y G:i:s", filemtime($fsPath)) ; - $faccessed = date("d/M/y G:i:s", fileatime($fsPath)) ; - echo "
    file size: " . $fsize . " Bytes
" ; - echo "last modified: " . $fmodified . "
" ; - echo "last accessed: " . $faccessed . "
" ; - echo " owner: " . fileowner($fsPath) . "
" ; - echo " group: " . filegroup($fsPath) . "
" ; - echo " permissions: " ; - echo printf( "%o", fileperms($fsPath) ) . "" ; - echo "
" ; + $fsize = filesize($fsPath) ; + $fmodified = date("$GLOBALS[gblDateFmt] $GLOBALS[gblTimeFmt]", filemtime($fsPath)) ; + $faccessed = date("$GLOBALS[gblDateFmt] $GLOBALS[gblTimeFmt]", fileatime($fsPath)) ; + echo "
    file size: " . $fsize . " Bytes
" ; + echo "last modified: " . $fmodified . "
" ; + echo "last accessed: " . $faccessed . "
" ; + echo " owner: " . fileowner($fsPath) . "
" ; + echo " group: " . filegroup($fsPath) . "
" ; + echo " permissions: " ; + echo printf( "%o", fileperms($fsPath) ) . "" ; + echo "
" ; + } - if ( $editable && ($writable || !$exists) ) { + if ( $editable && ($writable || !$exists) && !$file_lock ) { $fh = fopen($fsPath,"a+") ; rewind($fh) ; $fstr = fread($fh,filesize($fsPath)) ; @@ -200,49 +281,119 @@ $fstr = htmlentities( $fstr ) ; ?> -
+ DOCUMENT CONTENTS
- - + + - - + +
+
" ; - echo htmlentities($tstr) . "

" . $tstr ; + if ( !$file_lock && $ext!="" && strstr(join(' ',$gblImages),$ext) ) { + $info = getimagesize($fsPath) ; + $tstr = "\""" ; +// echo htmlentities($tstr) . "

" . $tstr ; + echo $tstr ; } + ?> -
- - + + +
+
+ +OK TO FORCE LOCK REMOVAL ON "" HELD BY ? + + + -
-OK TO DELETE ""? +
+ + +OK TO ""? + + + +
+
+ +OK TO RENAME "" TO + +? - + +
+
+NOTE FOR "": + + + + + + +
CHANGES TO THIS FILE
\n"; + $bakcount = 0; // start from 0, skip fist backup (it's current) + while ($e = array_shift($logarr)) { + if (strstr($e[4],"upload")) { + if (file_exists("$bakdir/$bakcount/$name")) { + $e[4]="$e[4]"; + } + $bakcount++; + } + print "$e[1]$e[2]$e[3]$e[4]\n"; + } + print "
"; } - echo "" ; + EndHTML() ; } // end function DetailPage @@ -472,6 +623,18 @@ case "blank" : $d = "blank.gif" ; break ; + case "checkout": + $d = "box2.gif"; + break; + case "checkin": + $d = "hand.up.gif"; + break; + case "locked": + $d = "screw2.gif"; + break; + case "note": + $d = "quill.gif"; + break; default : $d = "generic.gif" ; } @@ -486,7 +649,11 @@ global $gblEditable, $gblIcon ; $self = $GLOBALS["PHP_SELF"] ; - $webRoot = "http://" . $GLOBALS["SERVER_NAME"] ; + if (isset($GLOBALS["HTTPS"]) && $GLOBALS["HTTPS"] == "on") { + $webRoot = "https://" . $GLOBALS["SERVER_NAME"] ; + } else { + $webRoot = "http://" . $GLOBALS["SERVER_NAME"] ; + } $fsDir = $fsRoot . $relDir . "/" ; // current directory if (!is_dir($fsDir)) Error("Dir not found",$relDir) ; @@ -495,14 +662,14 @@ if ( !($dir = @opendir($fsDir)) ) Error("Read Access denied",$relDir) ; while ($item = readdir($dir)) { - if ( $item == ".." || $item == "." ) continue ; + if ( $item == ".." || $item == "." || substr($item,0,1) == "." ) continue ; if ( is_dir($fsDir . $item) ) { $dirList[] = $item ; - } - else if ( is_file($fsDir . $item) ) { + } else if ( is_file($fsDir . $item) ) { $fileList[] = $item ; - } - else { + } else if ( is_link($fsDir . $item) ) { + $dirList[] = $item ; + } else { // unknown file type // $text = "Could not determine file type of " ; // Error("File Error", $text.$relDir."/".$item) ; @@ -510,12 +677,24 @@ } } closedir($dir) ; + + // scan deleted files + if ( $GLOBALS[show_deleted] == 1 && ($dir = @opendir("$fsDir/.del")) ) { + while ($item = readdir($dir)) { + if ( substr($item,0,1) == "." ) continue ; + $fileList[] = ".del/$item" ; + } + closedir($dir) ; + } + $emptyDir = ! (sizeof($dirList) || sizeof($fileList)) ; // start navigation page - $text = "Use this page to add, delete or " ; - $text .= "revise files on this web site." ; - + $text = "Use this page to add, delete"; + if (! isset($show_deleted)) { + $text .= ", undelete"; + } + $text .= " or revise files on this web site." ; StartHTML("(Navigate)",$text) ; echo " - + - +" . $dir . "/" ; ?> - - + + - - + + 0) { sort($fileList) ; while (list($key,$file) = each($fileList)) { - $path = $fsDir."/".$file ; - $mod = filemtime($path) ; - $sz = filesize($path) ; - - if ($sz >= 10240) { - $sz = (int)(($sz+1023)/1024) . " k" ; - } - else { - $sz .= " " ; - } // end size - - $a = $b = "" ; - - if ( ($mod + 30*86400) > time() ) { - $a = " * " ; - } - - $tstr = $webRoot . $relDir . "/" . $file ; - $tstr = "" ; - $tstr .= $file . "" . $a ; - - $ext = strtolower(strrchr($file,".")) ; - if ( $ext=="" || - strstr(join(" ",$gblEditable),$ext) ) - { - $b = "" ; - $b .= $gblIcon("view") . "" ; - } + $path = $fsDir."/".$file ; + $mod = filemtime($path) ; + $sz = filesize($path) ; + + if ($sz >= 10240) { + $sz = (int)(($sz+1023)/1024) . " k" ; + } else { + $sz .= " " ; + } // end size + + $a = $b = "" ; + + $info_url=$self."?A=E&F=".urlencode($file)."&D=".urlencode($relDir); + + if ( ($mod + $gblModDays*86400) > time() ) { + $a = " * " ; + } + + $file_lock=CheckLock($path); + + $file_url_html="" ; + + if (substr($file,0,5) != ".del/") { + $file_url_html .= $file . "" . $a ; + } else { + $file_url_html .= substr($file,5,strlen($file)-5) . " deleted "; + } + + $note_html="".$gblIcon("note")."".ReadNote($path); + + $ext = strtolower(strrchr($file,".")) ; + + if ($file_lock) { + if ($file_lock == $GLOBALS[gblUserName]) { + $b.="" ; + $file_url_html=$b; + $b.=$gblIcon("checkin")."" ; + $b.= $gblIcon("blank"); + $file_url_html.="$file $a"; + $note_html = $gblIcon("blank")."Please check-in (update) this file"; + } else { + $b = $gblIcon("locked"); + $b.= $gblIcon("blank"); + $note_html = $gblIcon("blank")."File locked by $file_lock"; + $file_url_html = "$file $a"; + } + } else { + $b.="" ; + $b.=$gblIcon("checkout")."" ; + + if ( $ext=="" || strstr(join(" ",$gblEditable),$ext) ) { + $b.="" ; + $b.=$gblIcon("view")."" ; + } else { + $b.= $gblIcon("blank"); + } + } + ?> - - - - + + + + + + + - - + - - + + + + + @@ -653,7 +878,7 @@ ////////////////////////////////////////////////////////////////// -function UploadPage($fsRoot, $relDir) { +function UploadPage($fsRoot, $relDir, $filename) { $self = $GLOBALS["PHP_SELF"] ; if ($relDir == "") $relDir = "/" ; @@ -661,21 +886,25 @@

- -
+ +

DIRECTORY NAME

DIRECTORY NAME

+

DOCUMENT NAMENOTE LAST UPDATEFILE SIZE
- -Bytes
Bytes
- + +
+ OK TO DELETE THIS EMPTY FOLDER? @@ -630,18 +846,27 @@ } // end if emptyDir ?> -


CREATE NEW +
+ +

CREATE NEW DIRECTORY -OR- FILE :    NAME - + - OR UPLOAD A FILE + OR UPLOAD A FILE
-DESTINATION DIRECTORY: + ACTION=""> +DESTINATION DIRECTORY: + +
DESTINATION FILE: + +

PATHNAME OF LOCAL FILE
- +

If the [BROWSE...] button is not displayed,
you must upgrade to an RFC1867-compliant browser.

-

Your browser:

+

Your browser:

-
-
+ +

@@ -694,27 +923,6 @@ ////////////////////////////////////////////////////////////////// -function Writeable($path) { - // fix by -mat- filid brandy, brandy@ecrc.de, 07/JUL/99 - - clearstatcache ; - $perms = @fileperms($path) ; - $owner = @fileowner($path) ; - exec("id",$id) ; - eregi( "^uid=([0-9]*)",$id[0], $regs) ; - $apacheuid = $regs[1] ; - $perms = 0777 & $perms ; - if ( $apacheuid != $owner ) { - return (06 == (06 & $perms)) ? 1 : 0 ; - } - else { - return (0600 == (0600 & $perms)) ? 1 : 0 ; - } - -} // end function Writable - -////////////////////////////////////////////////////////////////// - function CreateHash($user, $pw) { global $gblHash ; // hash function to use @@ -749,9 +957,9 @@ StartHTML($title,$text) ; ?> -
- - + + +
If you are a site administrator:

Click below to generate a password hash
from @@ -767,14 +975,143 @@ ////////////////////////////////////////////////////////////////// +function Logit($target,$msg) { + + $dir=dirname($target); + if (! file_exists($dir."/.log")) { + mkdir($dir."/.log",0700); + } + $file=basename($target); + + $log=fopen("$dir/.log/$file","a+"); + fputs($log,date("$GLOBALS[gblDateFmt]\t$GLOBALS[gblTimeFmt]"). + "\t$GLOBALS[gblUserName]\t$msg\n"); + fclose($log); + +} + + +////////////////////////////////////////////////////////////////// + +function WriteNote($target,$msg) { + + $dir=dirname($target); + if (! file_exists($dir."/.note")) { + mkdir($dir."/.note",0700); + } + $file=basename($target); + + $note=fopen("$dir/.note/$file","w"); + fputs($note,"$msg\n"); + fclose($note); + + Logit($target,"added note $msg"); + +} + +function ReadNote($target) { + + $dir=dirname($target); + $file=basename($target); + $msg=""; + if (file_exists($dir."/.note/$file")) { + $note=fopen("$dir/.note/$file","r"); + $msg=fgets($note,4096); + fclose($note); + } + return StripSlashes($msg); + +} + +////////////////////////////////////////////////////////////////// + +function MoveTo($source,$folder) { + + $file=basename($source); + if (! file_exists($folder)) { + mkdir($folder,0700); + } + if (file_exists($source)) { + rename($source,"$folder/$file"); + } +} + +////////////////////////////////////////////////////////////////// + +function Lock($target) { + + $dir=dirname($target); + if (! file_exists($dir."/.lock")) { + mkdir($dir."/.lock",0700); + } + $file=basename($target); + + if (file_exists("$dir/.lock/$file")) { + Logit($target,"attempt to locked allready locked file!"); + } else { + $lock=fopen("$dir/.lock/$file","w"); + fputs($lock,"$GLOBALS[gblUserName]\n"); + fclose($lock); + + Logit($target,"file locked"); + } + +} + +function CheckLock($target) { + + $dir=dirname($target); + $file=basename($target); + $msg=0; + if (file_exists($dir."/.lock/$file")) { + $lock=fopen("$dir/.lock/$file","r"); + $msg=fgets($lock,4096); + fclose($lock); + } + return chop($msg); + +} + +function Unlock($target) { + + $dir=dirname($target); + $file=basename($target); + if (file_exists($dir."/.lock/$file")) { + unlink("$dir/.lock/$file"); + Logit($target,"file unlocked"); + } else { + Logit($target,"attempt to unlocked non-locked file!"); + } + +} + +////////////////////////////////////////////////////////////////// + +function urlpath($url) { + $url=urlencode(StripSlashes("$url")); + $url=str_replace("%2F","/",$url); + $url=str_replace("+","%20",$url); + return($url); +} + +////////////////////////////////////////////////////////////////// + +function safe_rename($from,$to) { + if (file_exists($from) && is_writable(dirname($to))) { + rename($from,$to); + } +} + +////////////////////////////////////////////////////////////////// + // MAIN PROGRAM // ============ // query parameters: capital letters // local functions : begin with capital letters // global constants: begin with gbl - $gblFilePerms = "644" ; // default for new files - $gblDirPerms = 0755 ; // default for new dirs + $gblFilePerms = 0640 ; // default for new files + $gblDirPerms = 0750 ; // default for new dirs // phpinfo() ; // exit ; @@ -788,8 +1125,8 @@ } // authentication if $gblAuth == true - if ( $gblAuth && - $gblHash($PHP_AUTH_USER.$PHP_AUTH_PW) != $gblPw ) { + if ( $gblAuth && $gblHash($PHP_AUTH_USER.$PHP_AUTH_PW) != $gblPw || + isset($relogin) && $gblPw == $relogin ) { header("WWW-authenticate: basic realm=\"$SERVER_NAME\"") ; header("HTTP/1.0 401 Unauthorized") ; NoEntry() ; @@ -827,22 +1164,45 @@ switch ($POSTACTION) { case "UPLOAD" : - if (!Writeable($fsDir)) Error("Write denied",$relDir) ; + if (!is_writeable($fsDir)) Error("Write denied",$relDir) ; if (strstr($FN_name,"/")) Error("Non-conforming filename") ; // TODO : should rather check for escapeshellcmds // but maybe RFC 18xx asserts safe filenames .... $source = $FN ; - $target = $fsDir . "/" . $FN_name ; - exec("cp $source $target") ; - exec("chmod $gblFilePerms $target") ; + if (! isset($FILENAME)) { // from update file + $target = "$fsDir/$FN_name" ; + } else { + $target = "$fsDir/$FILENAME"; + } + + // backup old files first + $dir=dirname($target); + if (! file_exists($dir."/.bak")) { + mkdir($dir."/.bak",0700); + } + if (! file_exists($dir."/.bak/$GLOBALS[gblNumBackups]")) { + mkdir($dir."/.bak/$GLOBALS[gblNumBackups]",0700); + } + $file=basename($target); + for($i=$GLOBALS[gblNumBackups]-1;$i>0;$i--) { + MoveTo("$dir/.bak/$i/$file","$dir/.bak/".($i+1)."/"); + } + MoveTo($target,$dir."/.bak/1/"); + + copy($source,$target) ; + chmod($target,$gblFilePerms) ; clearstatcache() ; + Logit($target,"uploaded"); + if (isset($FILENAME)) { + Unlock($target); + } break ; case "SAVE" : $path = $gblFsRoot . escapeshellcmd($RELPATH) ; - $writable = Writeable($path) ; - $legaldir = Writeable(dirname($path)) ; + $writable = is_writeable($path) ; + $legaldir = is_writeable(dirname($path)) ; $exists = (file_exists($path)) ? 1 : 0 ; // check for legal extension here as well if (!($writable || (!$exists && $legaldir))) @@ -851,28 +1211,38 @@ fwrite($fh,$FILEDATA) ; fclose($fh) ; clearstatcache() ; + Logit($path,"saved changes"); break ; case "CREATE" : // we know $fsDir exists - if (!Writeable($fsDir)) Error("Write denied",$relDir) ; + if ($FN == "") break; // no filename! + if (!is_writeable($fsDir)) Error("Write denied",$relDir) ; $path = $fsDir . "/" . $FN ; // file or dir to create $relPath = $relDir . "/" . $FN ; switch ( $T ) { case "D" : // create a directory - if ( ! @mkdir($path,$gblDirPerms) ) - Error("Mkdir failed",$relPath) ; // eg. if it exists - clearstatcache() ; - break ; + if ( ! @mkdir($path,$gblDirPerms) ) + Error("Mkdir failed",$relPath) ; // eg. if it exists + clearstatcache() ; + break ; case "F" : // create a new file // this functionality is doubled in DetailView(). // better keep it here altogether // chmod perms to $gblFilePerms - if ( file_exists($path) && !Writable($path) ) - Error("File not writable", $relPath) ; - $tstr = $PHP_SELF . "?A=E&D=" . $relDir . "&F=" . $FN ; - header("Location: " . $tstr) ; - exit ; + if ( file_exists($path) && !is_writable($path) ) + Error("File not writable", $relPath) ; + $fh = fopen($path, "w+") ; + if ($fh) { + fputs($fh,"\n"); + fclose($fh) ; + LogIt($path,"file created"); + } else { + Error("Creation of file $relPath failed -- $path"); + } + $tstr = "$PHP_SELF?A=E&D=".urlencode($relDir)."&F=".urlencode($FN) ; + header("Location: " . $tstr) ; + exit ; } break ; @@ -883,11 +1253,25 @@ $tstr .= "insufficient privileges: " ; if ( $FN != "") { // delete file - $path = $fsDir . "/" . $FN ; - if ( ! @unlink($path) ) { - Error("File delete failed", $tstr . $path) ; - exit ; - } + $path = $fsDir . "/" . $FN ; + + $dir=dirname($path); + $file=basename($path); + if (! file_exists("$dir/.del")) { + mkdir("$dir/.del",0700); + } + +// if ( ! @unlink($path) ) { + if ( ! rename($path,"$dir/.del/$file") ) { + Error("File delete failed", $tstr . $path) ; + Logit($path,"file delete failed"); + exit ; + } else { + Logit($path,"file deleted"); + MoveTo("$dir/.log/$file","$dir/.del/.log/"); + MoveTo("$dir/.note/$file","$dir/.del/.note/"); + MoveTo("$dir/.lock/$file","$dir/.del/.lock/"); + } } else { // delete directory if ( ! @rmdir($fsDir) ) { @@ -899,6 +1283,43 @@ } break ; + case "UNDELETE" : + if ( $CONFIRM != "on" ) break ; + + if (substr($FN,0,4) != ".del") break ; + $file=substr($FN,4,strlen($FN)-4); + + Logit("$fsDir/.del/$file","undeleted"); + MoveTo("$fsDir/.del/$file","$fsDir/"); + MoveTo("$fsDir/.del/.log/$file","$fsDir/.log/"); + MoveTo("$fsDir/.del/.note/$file","$fsDir/.note/"); + MoveTo("$fsDir/.del/.lock/$file","$fsDir/.lock/"); + + break ; + + case "RENAME" : + if ( $CONFIRM != "on" ) break ; + + Logit("$fsDir/$FN","renamed $FN to $NEWNAME"); + safe_rename("$fsDir/$FN","$fsDir/$NEWNAME"); + safe_rename("$fsDir/.log/$FN","$fsDir/.log/$NEWNAME"); + safe_rename("$fsDir/.note/$FN","$fsDir/.note/$NEWNAME"); + safe_rename("$fsDir/.lock/$FN","$fsDir/.lock/$NEWNAME"); + for($i=0;$i<=$GLOBALS[gblNumBackups];$i++) { + safe_rename("$fsDir/.bak/$i/$FN","$fsDir/.bak/$i/$NEWNAME"); + } + + break ; + + case "NOTE" : + WriteNote("$fsDir/$FN","$NOTE"); + break ; + + case "UNLOCK" : + if ( $CONFIRM != "on" ) break ; + Unlock("$fsDir/$FN"); + break ; + default : // user hit "CANCEL" or undefined action } @@ -914,12 +1335,15 @@ // $A=U : upload to path given in $D // $A=E : display detail of file $D/$F and edit // $A=C : display code in file $D/$F + // $A=Co : checkout file $D/$F + // $A=Ci : checkin file $D/$F + // $A=V : view file (do nothing except log) // default : display directory $D switch ($A) { case "U" : // upload to $relDir - if (!Writeable($gblFsRoot . $relDir)) + if (!is_writeable($gblFsRoot . $relDir)) Error("Write access denied",$relDir) ; $text = "Use this page to upload a single " ; $text .= "file to $SERVER_NAME." ; @@ -929,12 +1353,34 @@ exit ; case "E" : // detail of $relDir/$F - DetailPage($gblFsRoot, $relDir, $F) ; + if (is_file("$gblFsRoot/$relDir/$F")) DetailPage($gblFsRoot, $relDir, $F) ; exit ; case "C" : // listing of $relDir/$F DisplayCode($gblFsRoot, $relDir, $F) ; exit ; + case "Co" : + // checkout + Lock("$gblFsRoot/$relDir/$F"); + header("Content-Disposition: attachment; filename=$F" ); + Header("Location: ".urlpath("$relDir/$F")); + exit; + case "Ci" : + // upload && update to $relDir + if (!is_writeable($gblFsRoot . $relDir)) + Error("Write access denied",$relDir) ; + $text = "Use this page to update a single " ; + $text .= "file to $SERVER_NAME." ; + StartHTML("(Update file Page)", $text) ; + UploadPage($gblFsRoot, $relDir, $F) ; + EndHTML() ; + exit ; + case "V" : + // view + LogIt("$gblFsRoot/$relDir/$F","viewed"); + header("Content-Disposition: attachment; filename=$F" ); + Header("Location: ".urlpath("$relDir/$F")); + exit; } // default: display directory $relDir