/***Copyright and coded by Dakusan, please do not steal code, but you may study and learn from it... Free to use and redistribute - See https://www.castledragmire.com/Copyright for more information. ***/
/***Dakusan's Directory Manager v1.1 - https://www.castledragmire.com/Projects/Other_Web_Scripts ***/
DetectFileName();
//---User options---
//Password protection information
$PassFileName='.htpasswd'; //Can be put in another directory - if path is not relative, it must start with a "/"
$OnlyProtectIndexFile=false; //User authentication only requires access for this script ($MyFileName) [or a directory listing at /]
$PasswordHashFunction='crypt'; //Usually "crypt", Windows' IIS might need "md5"
//Allowable files and types
$DoNotShowList=Array($MyFileName, $PassFileName, '.htaccess');
$DisallowedExtensions=Array('php', 'php3', 'cgi', 'pl'); //Cannot upload or rename to these extensions
$DissalowedExtensionsAppend='.txt'; //Disallowed extensions have the following appended to them
//Basic permissions - Set options to either true or false
$AllowFileList=true;
$AllowDeleting=true;
$AllowRenaming=true;
$AllowUploading=true;
$AllowUserEdit=false; //Edit other users
$AllowPasswordEdit=true; //Edit own password
$IgnoreDisallowedExtensions=false;
//[Admin] Permission state modifiers - Comment out line or set to FALSE to ignore option
$AdminUsers=Array('admin'); //When logged in, these user(s) have all "AdminPermissions" set to true
$PermissionsIfNoPassFileFound=Array('FileList','Deleting','Renaming','Uploading','UserEdit','PasswordEdit'); //Permissions set to true when no password file is found - Default is all permissions but IgnoreDisallowedExtensions
$AdminPermissions=Array('FileList','Deleting','Renaming','Uploading','UserEdit','PasswordEdit','IgnoreDisallowedExtensions'); //Permissions set to true when in admin mode - Default is all permissions
//Default sorting options
$SortBy='Name'; //Default SortBy, options include "Name", "Size", and "ModTime" (Last Modified Time)
$SortDesc=false; //Sort Ascending (false) or descending (true)
//---END of User Options---
//---File header and footer sections - Used for incorperating into a design layout---
function HeaderSection()
{
header('Content-Type: text/html; charset=utf-8');
print
'
File Manager
';
}
function FooterSection()
{
print '';
}
//---DO NOT EDIT PAST HERE---
//Get the script's location information
function DetectFileName()
{
global $MyFileName, $MyDir, $MyURL;
$MyScriptName=str_replace('\\', '/', $_SERVER['SCRIPT_NAME']); //The script URL - Replace "\" [windows] with "/" [standard]
$LastSlash=strrpos($MyScriptName, '/'); //Determine the location between the path and filename
$MyFileName=substr($MyScriptName, $LastSlash+1); //Determine the filename
$MyDir=substr($MyScriptName, 0, $LastSlash); //Determine the directory name
$MyURL=str_replace('%2F', '/', urlencode($MyDir)); //URL encoded path to directory
}
//Output informational messages
function ReturnMessage($P) //Function parameters are in STATIC_MESSAGE, VARIABLE, STATIC_MESSAGE2, VARIABLE2, ... format
{
print '';
foreach(func_get_args() as $i => $Arg)
if($i&1) //variable
print '"'.htmlentities(substr($Arg, 0, 1)=='!' ? substr($Arg, 1) : $_REQUEST[$Arg]).'" '; //If the variable starts with an exclamation mark, it is an actual value, otherwise, it is a variable name found in $_REQUEST
else
print "$Arg ";
print ' ';
}
//Confirm valid files names
function IsFileNameOK(&$FN, $IsModifying) //Filename we are checking (updated inside the function if needed), and checking if file exists if modifying, or does not exist if creating (IsModifying=false)
{
if(!isset($FN)) //Confirm variable is even set
{
$FN='NOT SPECIFIED';
return FALSE;
}
//Check against DoNotShowList, for invalid characters ('/')
global $DoNotShowList;
if(in_array($FN, $DoNotShowList) || strpos($FN, '/'))
{
if(in_array($FN, $DoNotShowList))
ReturnMessage('This specific filename is restricted.');
if(strpos($FN, '/'))
ReturnMessage('', '!/', 'character is not allowed in filenames.');
return FALSE;
}
//Modify name according to allowed extensions
global $IgnoreDisallowedExtensions, $DisallowedExtensions, $DissalowedExtensionsAppend;
if(!$IgnoreDisallowedExtensions)
{
$MyExt=strrchr($FN, '.'); //Get the extension from the last dot
$MyExt=($MyExt==FALSE || $MyExt=='.' ? '' : substr($MyExt, 1)); //Remove the dot - Set to blank if no extension is found
if(in_array($MyExt, $DisallowedExtensions)) //If an invalid extension, append ending
{
ReturnMessage('Non allowed file extension ', "!$MyExt", 'detected. Changing file name from', "!$FN", 'to', "!$FN$DissalowedExtensionsAppend", '.');
$FN.=$DissalowedExtensionsAppend; //Update filename
}
}
if($IsModifying) //If deleting/renaming from, return if file currently exists
return file_exists($FN);
//If creating/renaming to, update name accordingly until name does not conflict
$NewFN=$FN;
$CurNum=0;
while(file_exists($NewFN)) //Append .v# until a file name conflict is not found
$NewFN="$FN.v".++$CurNum;
if($CurNum)
ReturnMessage('File name ', "!$FN", 'already exists. File being named as ', "!$NewFN", '.');
$FN=$NewFN;
return true;
}
//Create the password and access file
function UpdatePassFile(&$User, $Pass)
{
global $PassFileName;
//Read in previous password information
$MyUsersO=(file_exists($PassFileName) ? explode("\n",file_get_contents($PassFileName)) : Array()); //Get basic user list in format x=>"user:pass"
$MyUsers=Array();
foreach($MyUsersO as $U) //Get user list in format user=>"user:pass"
$MyUsers[substr($U, 0, strpos($U,':'))]=$U;
//Fix username to valid characters and non blank
$User=preg_replace('/[^A-Za-z0-9_]/','',$User);
$User=($User=='' ? 'Default' : $User);
//Perform action
if($Pass!='') //If password is not empty, modify user
{
global $PasswordHashFunction;
$MyMessage=Array('User', 'UserName', isset($MyUsers[$User]) ? 'modified' : 'created');
$MyUsers[$User]="$User:".eval("return $PasswordHashFunction(\$Pass);");
}
else //Otherwise, delete user
{
$MyMessage=Array('User', 'UserName', isset($MyUsers[$User]) ? 'deleted' : 'non existant');
unset($MyUsers[$User]);
}
if(!count($MyUsers)) //If no more users, delete existing password files
{
if(file_exists('.htaccess')) unlink('.htaccess');
if(file_exists($PassFileName)) unlink($PassFileName);
call_user_func_array('ReturnMessage', $MyMessage);
return;
}
if(($HTPasswd=fopen($PassFileName, 'w'))===FALSE) //Attempt to write out new password file
{
ReturnMessage('Password file cannot be accessed.');
return;
}
fwrite($HTPasswd, implode("\n", $MyUsers));
fclose($HTPasswd);
call_user_func_array('ReturnMessage', $MyMessage);
if(!file_exists('.htaccess')) //Write out permissions file, if it doesn't exist, to require access credentials, and deny access to itself and the password file
{
if(($HTAccess=fopen('.htaccess', 'w'))===FALSE) //Attempt to open for writing
{
ReturnMessage('Directory access file cannot be accessed.');
return;
}
global $OnlyProtectIndexFile, $MyFileName;
fwrite($HTAccess, preg_replace('/^\s+/m', '', //Strip whitespace - This file makes authentication required to enter the directory, and makes the .htaccess and password (if it is in the current directory) files unviewable
($OnlyProtectIndexFile ? "" : '').'
AuthType Basic
AuthName "Access Required"
AuthUserFile "'.($PassFileName[0]=='/' ? $PassFileName : getcwd()."/$PassFileName").'"
require valid-user
'.($OnlyProtectIndexFile ? '' : '').'
order deny,allow
deny from all
'
));
fclose($HTAccess);
}
}
//Human readable sizes
function HumanReadableSize($Size)
{
$MetricSizes=Array('Bytes', 'KB', 'MB', 'GB', 'TB');
for($SizeOn=0;$Size>=1024 && $SizeOn'The uploaded file exceeds the upload_max_filesize ('.ini_get('upload_max_filesize').').', UPLOAD_ERR_FORM_SIZE=>'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.', UPLOAD_ERR_PARTIAL=>'The uploaded file was only partially uploaded.', UPLOAD_ERR_NO_FILE=>'No file was uploaded.', UPLOAD_ERR_NO_TMP_DIR=>'Missing a temporary folder.', UPLOAD_ERR_CANT_WRITE=>'Failed to write file to disk.', UPLOAD_ERR_EXTENSION=>'File upload stopped by extension.');
if(isset($UploadErrors[$_FILES['UploadFile']['error']]))
ReturnMessage($UploadErrors[$_FILES['UploadFile']['error']]);
else
ReturnMessage('Unknown file upload error.');
}
else if($_FILES['UploadFile']['size']<0) //Check for negative file size
ReturnMessage('Unknown file upload error.');
else if(!IsFileNameOK($_FILES['UploadFile']['name'], false)) //Confirm valid file name
ReturnMessage('Cannot create', '!'.$_FILES['UploadFile']['name'], '; invalid file name.');
else if(move_uploaded_file($_FILES['UploadFile']['tmp_name'], $_FILES['UploadFile']['name'])===FALSE) //Move uploaded file into local folder
ReturnMessage('Attempt to move uploaded file into current folder failed.');
else //Successfull renamed
ReturnMessage('File', "!".$_FILES['UploadFile']['name'], 'successfully uploaded.');
break;
case 'EditUser':
if(!$AllowUserEdit) //Confirm permission
ReturnMessage('Not allowed to edit other user information.');
else if(!isset($_REQUEST['UserName']) || !isset($_REQUEST['UserPassword'])) //Check for passed information
ReturnMessage('User update information not supplied.');
else //Attempt update
UpdatePassFile($_REQUEST['UserName'], $_REQUEST['UserPassword']);
break;
case 'EditPassword':
if(!$AllowPasswordEdit) //Confirm permission
ReturnMessage('Not allowed to edit password.');
else if(!isset($_SERVER['PHP_AUTH_USER'])) //Check for passed apache username
ReturnMessage('Username could not be retreived.');
else if(!isset($_REQUEST['UserPassword'])) //Check for passed information
ReturnMessage('User update information not supplied.');
else if($_REQUEST['UserPassword']=='') //Check for passed information
ReturnMessage('Cannot set a blank password.');
else //Attempt update
{
$_REQUEST['UserName']=$_SERVER['PHP_AUTH_USER'];
UpdatePassFile($_REQUEST['UserName'], $_REQUEST['UserPassword']);
}
break;
default: //An unknown action was passed
ReturnMessage('Invalid action', 'MyAction', '.');
}
}
//Output logged in information
if(isset($_SERVER['PHP_AUTH_USER']))
print "Logged in as: $_SERVER[PHP_AUTH_USER] [Log out] ";
//Output folder information
print 'Index for: '.htmlentities($MyDir).'
';
//Loop through all files in directory
if($AllowFileList)
{
//Gather file list
$DirHan=opendir('./');
$MyFiles=Array();
while(($FileName=readdir($DirHan))!==FALSE)
if(!in_array($FileName, $DoNotShowList) && is_file($FileName)) //Bypass files in our do not show list
$MyFiles[]=Array('Name'=>$FileName, 'Size'=>filesize($FileName), 'ModTime'=>filemtime($FileName));
closedir($DirHan);
//Sort files
function MySortFunc($a, $b) { global $SortBy, $SortDesc; return ($a[$SortBy] >= $b[$SortBy]) ^ $SortDesc; }
usort($MyFiles, 'MySortFunc');
//Output contents in a table
if(count($MyFiles)) //If files are found
{
//Table head
print '