PHPFM:一个单文件、响应式文件管理器






4.88/5 (9投票s)
为您的 PHP 网站提供的非常快速的文件管理器
GitLab URL: https://gitlab.com/windowssnt/PHPFileManager。 欢迎贡献!
引言
我尝试过几个文件管理器,但它们似乎都非常复杂。 为什么不自己做一个呢?
- 单个文件。 只需将 phpfm.php 复制到您的根目录,就完成了。
- Bootstrap, jQuery, BootBox, Font Awesome, Chosen, Data Tables
- 如果通过 HTTP 访问,则使用 HTTP digest 登录,如果通过 HTTPS 访问,则使用表单登录。
- 支持多个用户,具有特定的根文件夹和每个文件夹的读/写访问权限选项。
- 将用户保存到自身或 SQLite 数据库。
- 创建文件夹。
- 上传文件。
- 以 zip 格式上传多个文件。
- 下载文件。
- 以 zip 格式下载多个文件。
- 删除文件/文件。
登录
如果您处于 HTTPS 连接中,登录是一个简单的 Bootstrap 表单
对于第一次登录,请以 root 用户名,不使用密码登录。
密码以 sha-1
哈希形式保存,并提供注销选项(终止会话)。
如果您处于 HTTP 连接中,密码将以明文形式保存,但身份验证方法是 HTTP digest,以避免传输原始密码。
$users 数组
$users = array('root' => array('admin' => '1','password' => '',
'root' => '.','access' => array('.' => 2)))
“access
”数组本身是一个数组,其中包含目录和访问级别对(1 读,2 写)。
为了安全起见,PHPFM 从不允许访问包含“..
”或以“/
”开头的任何文件。
如果将用户保存到自身,则使用一个简单的函数来序列化 users
数组
function LoadUsers()
{
global $users;
if (count($users) == 1 && $users['root']['password'] == "")
return "\$users = array();\r\n";
$u = "\$users = array(\r\n";
$i = 0;
foreach($users as $username => $user)
{
if ($i > 0)
$u .= ",\r\n";
$acc = "array(";// array("." => 2)
$ii = 0;
foreach($user['access'] as $acxd => $acx)
{
if ($ii > 0)
$acc .= ",";
$acc .= sprintf("'%s' => %s",$acxd,$acx);
$ii++;
}
$acc .= ")";
$u .= sprintf("'%s' => array('admin' => '%s','password' =>
'%s','root' => '%s','access' => %s)",
$username,$user['admin'],$user['password'],$user['root'],$acc);
$i++;
}
$u .= "\r\n);";
return $u;
}
如果保存到数据库,则使用 SQLite。 创建用户(或更改根密码)后,您将无法再在两种方法之间切换。
接口
文件或 Zip 上传
使用一个简单的 PHP $_FILE
表单
if (array_key_exists("zip",$_POST) && $_POST['zip'] == 1)
{
$zip = new ZipArchive;
$zip->open($tempfile);
$nf = $zip->numFiles;
for($i = 0; $i < $nf ; $i++)
{
$fn2 = $zip->getNameIndex($i);
if (strstr($fn2,"..") !== false || strstr($fn2,"/") === $fn2)
{
unlink($tempfile);
$_SESSION['error'] = "File contains files with .. or /, not allowed.";
die;
}
}
$zip->extractTo($cr);
}
else
{
$dbdata = file_get_contents($tempfile);
$full = $_SESSION['current'].'/'.$fn;
file_put_contents($full,$dbdata);
}
unlink($tempfile);
文件或 Zip 下载
对于单个文件,使用直接的 application/octet-stream
header('Content-Description: Download');
header('Content-Type: application/octet-stream');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header(sprintf("Content-disposition: attachment;filename=%s",basename($u)));
header('Content-Length: ' . filesize($u));
readfile($u);
或者 ZIP 下载,同时检查权限
$what = $_POST['massdownload'];
$fuf = "";
$dp = strrpos($_POST['massdownload'],"/");
if ($dp === false)
$fuf = $_SESSION['current'].'/';
else
$fuf = substr($_GET['down'],0,$dp);
if (AccessType($fuf) === 0)
{
$_SESSION['error'] = "Read access denied to folder <b>$root</b>.";
}
else
{
$arr = array();
$items = explode(',',$what);
foreach($items as $item)
{
if (strstr($item,"/") == $item)
die;
if (strstr($item,"..") !== false)
die;
$full = $_SESSION['current'].'/'.$item;
enumDir($full,$arr);
}
$tz = tempnam(".","zip");
if (file_exists($tz))
unlink($tz);
$tz .= ".zip";
if (file_exists($tz))
unlink($tz);
$zip = new ZipArchive;
$zipo = $zip->open($tz,ZipArchive::CREATE | ZipArchive::OVERWRITE);
foreach($arr as $a)
{
if (is_dir($a))
continue;
$rs = $zip->addFile($a,substr($a,2));
if (!$rs)
die;
}
$zip->close();
Down($tz,1);
unlink($tz);
die;
}
玩得开心!
历史
- 2017年1月23日:首次发布