/*
WebFM - Web File Manager 0.2
Copyright (C) 2005-2006, Chris Chabot
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*//*
made with tab-size: 4
To configure this file manager for all virtual hosts
and hide the script from the virual host's document root
place fm.php in a dir outside of the document root
For example /var/www/fm.php, and the images in /var/www/fmicons
then configure Apache aliases to access them as such:
Alias /filemanager "/var/www/fm.php"
Alias /fmicons/ "/var/www/fmicons/"
then you can use the file manager on any virtual host thru
http://localhost/filemanager
*/
$conf_images = '/fmicons'; // Directory that contains the FileManager images
$conf_showdirs = TRUE; // Show directories in the file list?
$conf_chroot = $_SERVER['DOCUMENT_ROOT']; // Set this manualy to '' or any other given path to alow browsing outside of the webroot
$conf_sort_dirs = TRUE; // Sort the directories by name (otherwise displayed in order of file system)
$conf_resolveid = TRUE; // Resolve UID / GID names?
$conf_passwddir = ''; // Overrule passwd file location
// ini settings to allow long execution time, larger memory usage and large file uploads
ini_set("max_execution_time",60);
ini_set("upload_max_filesize","32M");
ini_set("memory_limit","16M");
ini_set("output_buffering",1);
ini_set("magic_quotes_gpc",0);
// Force no cache for this script so directories are reloaded correctly
header("Pragma: no-cache");
header("Cache-Control: no-store");
function change_passwd()
{
global $conf_images, $passwd_key, $passwd, $passwd_file;
if (isset($_POST['newpass'])) {
$passwd[$passwd_key] = crypt($_POST['newpass'],'$fm');
$output = "\n\$passwd = array(\n";
reset($passwd);
$cnt = 1;
while (list($key,$val) = each($passwd)) {
$output .= "'$key' => '$val'";
if ($cnt < count($passwd)) {
$output .= ",";
}
$output .= "\n";
$cnt++;
}
$output .= ");\n?>";
$fp = fopen($passwd_file,'w+');
fwrite($fp,$output);
fclose($fp);
echo "";
return;
} else {
echo "
\n".
"";
}
}
function authenticate_header()
{
Header("WWW-authenticate: basic realm=\"{$_SERVER['SERVER_NAME']} (Please use FM as username)\"");
Header("HTTP/1.0 401 Unauthorized");
die("
Login required
All unauthorised access is denied.
");
}
function authenticate_get_passwd()
{
global $passwd_file, $passwd_key, $conf_passwddir;
// find passwd file location. Prefered is outside of the document root
// so the encrypted passwords cant be downloaded by the file manager
// and brute-force cracked. This only works if fm.php is located outside of
// the document-root and uses an Apache Alias to call it. Also the web
// process owner should have write permission to the directory, or create
// the file and make the web-user the owner of it
// (ie: touch fm_passwd.php && chown apache.apache fm_passwd.php)
// Fallbacks are document_root, and current directory
$passwd_file = FALSE;
if ($conf_passwddir && $conf_passwddir != '') {
$passwd_file = $conf_passwddir."/fm_passwd.php";
if (!authenticate_check_file($passwd_file)) $passwd_file = false;
}
if (!$passwd_file && isset($_SERVER['PATH_TRANSLATED'])) {
$passwd_file = dirname($_SERVER['PATH_TRANSLATED'])."/fm_passwd.php";
if (!authenticate_check_file($passwd_file)) $passwd_file = false;
}
if (!$passwd_file && isset($_SERVER['DOCUMENT_ROOT'])) {
$passwd_file = $_SERVER['DOCUMENT_ROOT']."/fm_passwd.php";
if (!authenticate_check_file($passwd_file)) $passwd_file = false;
}
if (!$passwd_file) {
$passwd_file = "fm_passwd.php";
if (!authenticate_check_file($passwd_file)) {
die("Could not create passwd file(s), aborting");
}
}
$passwd_key = $_SERVER['SERVER_NAME'];
}
function authenticate_check_file($file)
{
if (!file_exists($file)) {
if (!@touch($file)) {
return false;
}
}
return true;
}
function authenticate()
{
global $passwd_file, $passwd_key, $passwd;
authenticate_get_passwd();
include_once($passwd_file);
if (isset($_SERVER['PHP_AUTH_PW'])) {
if (isset($passwd[$passwd_key])) {
if ($passwd[$passwd_key] == crypt($_SERVER['PHP_AUTH_PW'],'$fm')) {
return true;
}
} else {
// allow user in, but trigger missing password alert
return false;
}
}
authenticate_header();
}
function download_file()
{
global $conf_chroot;
if (!isset($_GET['file']) || $_GET['file'] == '') {
return;
}
$filename = basename($_GET['file']);
$file = $conf_chroot.format_path(dirname($_GET['file'])).$filename;
if (!file_exists($file)) {
die("No such file or directory");
}
$size = filesize($file);
header("Content-Type: application/save");
header("Content-Length: $size");
header("Content-Disposition: attachment; filename=\"$filename\"");
header("Content-Transfer-Encoding: binary");
if ($fp = fopen("$file", "rb")) {
fpassthru($fp);
}
fclose($fp);
}
function recurse_paste_or_delete($file,$dest_dir,$action)
{
global $conf_chroot;
$dest = $conf_chroot.$dest_dir.basename($file);
if (is_dir($file)) {
$dir = substr($file,strrpos($file,'/')+1);
if ($action == 'cut' || $action == 'copy') {
if (($mod = fileperms($file)) === FALSE) {
// if we cant read old dir mod, assume a safe default
$mod = '0755';
}
mkdir($conf_chroot.$dest_dir.$dir,$mod);
}
$dh = @opendir($file);
while (($name = readdir($dh)) !== FALSE) {
if ($name != '.' && $name != '..') {
recurse_paste_or_delete($file.'/'.$name,$dest_dir.$dir.'/',$action);
}
}
@closedir($dh);
if ($action == 'delete' || $action == 'cut') {
rmdir($file);
}
} else switch ($action) {
case 'cut':
// Prior to PHP 4.3.3, rename() could not rename files across
// partitions on *nix based systems
$mod = fileperms($file);
if (version_compare(phpversion(),'4.3.3') == -1) {
if (copy($file,$dest)) {
unlink($file);
}
} else {
rename($file,$dest);
}
// Set dest file mods same as original
if ($mod) {
chmod($dest,$mod);
}
break;
case 'copy':
$mod = fileperms($file);
copy($file,$dest);
// Set dest file mods same as original
if ($mod) {
chmod($dest,$mod);
}
break;
case 'delete':
unlink($file);
break;
}
}
function paste_or_delete($action)
{
global $current_path, $conf_chroot;
reset($_SESSION['selected']);
while (list(,$file) = each($_SESSION['selected'])) {
$real_file = $conf_chroot.$file;
if (file_exists($real_file)) {
recurse_paste_or_delete($real_file,$current_path,$action);
}
}
// w/o clearing stat cache, php would show deleted/moved files in readdir()
clearstatcache();
}
function make_directory()
{
global $conf_chroot, $conf_images, $current_path;
if (!is_dir($conf_chroot.$current_path)) {
// Quick check to see if path is a valid location.
// Path it self is already filtered in main with format_path()
die("Invalid path specified");
}
if (isset($_POST['dir']) && $_POST['dir'] != '') {
$dir = format_path($conf_chroot.$current_path.$_POST['dir']);
if (!mkdir($dir,0755)) {
echo "\n";
}
echo "";
} else {
echo "\n".
"";
}
}
function upload_file()
{
global $conf_images, $conf_chroot, $current_path;
if (!is_dir($conf_chroot.$current_path)) {
// Quick check to see if path is a valid location.
// Path it self is already filtered in main with format_path()
die("Invalid path specified");
}
if (count($_FILES) == 0) {
echo "\n".
"";
} else {
if ($_FILES['userfile']['error'] !== 0) {
switch ($_FILES['userfile']['error']) {
case UPLOAD_ERR_INI_SIZE:
case UPLOAD_ERR_FORM_SIZE:
$reason = "File size exceeds max allowed";
break;
case UPLOAD_ERR_PARTIAL:
$reason = "File only partialy uploaded";
break;
case UPLOAD_ERR_NO_FILE:
$reason = "No file specified";
break;
default:
$reason = "Unhandled error";
break;
}
echo "
Error uploading file: $reason
";
}
$dest = $conf_chroot.$current_path.basename($_FILES['userfile']['name']);
// move_uploaded_file prevents upload file injection attacks, etc so
// doesn't need to be re-checked in userspace
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $dest)) {
echo "";
} else {
echo "
Error uploading file: Possible file upload attack!