修复已知安全问题,新增文件删除功能
This commit is contained in:
parent
78c9fe01dd
commit
b4b45b3c6b
@ -4,7 +4,6 @@ namespace app\controllers;
|
|||||||
|
|
||||||
use app\models\RenameForm;
|
use app\models\RenameForm;
|
||||||
use app\utils\FileTypeDetector;
|
use app\utils\FileTypeDetector;
|
||||||
use InvalidArgumentException;
|
|
||||||
use Yii;
|
use Yii;
|
||||||
use yii\filters\VerbFilter;
|
use yii\filters\VerbFilter;
|
||||||
use yii\helpers\ArrayHelper;
|
use yii\helpers\ArrayHelper;
|
||||||
@ -48,8 +47,11 @@ class HomeController extends Controller
|
|||||||
$rootDataDirectory = Yii::getAlias(Yii::$app->params['dataDirectory']);
|
$rootDataDirectory = Yii::getAlias(Yii::$app->params['dataDirectory']);
|
||||||
$userId = Yii::$app->user->id;
|
$userId = Yii::$app->user->id;
|
||||||
|
|
||||||
if ($directory == null | $directory == '.') {
|
if ($directory === '.' ||$directory == null) {
|
||||||
|
$directory = null;
|
||||||
$parentDirectory = null;
|
$parentDirectory = null;
|
||||||
|
} elseif ($directory === '..' || str_contains($directory, '../')) {
|
||||||
|
throw new NotFoundHttpException('Invalid directory.');
|
||||||
} else {
|
} else {
|
||||||
$parentDirectory = dirname($directory);
|
$parentDirectory = dirname($directory);
|
||||||
}
|
}
|
||||||
@ -83,7 +85,20 @@ class HomeController extends Controller
|
|||||||
// 获取路径下的所有文件和文件夹
|
// 获取路径下的所有文件和文件夹
|
||||||
$directoryContents = scandir($path);
|
$directoryContents = scandir($path);
|
||||||
|
|
||||||
return array_diff($directoryContents, ['.', '..']);
|
// 移除 '.' 和 '..'
|
||||||
|
$directoryContents = array_diff($directoryContents, ['.', '..']);
|
||||||
|
|
||||||
|
// 使用 usort 对目录内容进行排序,使文件夹始终在文件之前
|
||||||
|
usort($directoryContents, function ($a, $b) use ($path) {
|
||||||
|
$aIsDir = is_dir($path . '/' . $a);
|
||||||
|
$bIsDir = is_dir($path . '/' . $b);
|
||||||
|
if ($aIsDir === $bIsDir) {
|
||||||
|
return strnatcasecmp($a, $b); // 如果两者都是文件夹或都是文件,按名称排序
|
||||||
|
}
|
||||||
|
return $aIsDir ? -1 : 1; // 文件夹始终在文件之前
|
||||||
|
});
|
||||||
|
|
||||||
|
return $directoryContents;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -99,7 +114,7 @@ class HomeController extends Controller
|
|||||||
$relativePath = rawurldecode($relativePath);
|
$relativePath = rawurldecode($relativePath);
|
||||||
|
|
||||||
// 检查相对路径是否只包含允许的字符
|
// 检查相对路径是否只包含允许的字符
|
||||||
if (!preg_match('/^[\w\-.\/]+$/u', $relativePath)) {
|
if (!preg_match('/^[\w\-.\/\s]+$/u', $relativePath)) {
|
||||||
throw new NotFoundHttpException('Invalid file path.');
|
throw new NotFoundHttpException('Invalid file path.');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,7 +151,7 @@ class HomeController extends Controller
|
|||||||
$relativePath = rawurldecode($relativePath);
|
$relativePath = rawurldecode($relativePath);
|
||||||
|
|
||||||
// 检查相对路径是否只包含允许的字符
|
// 检查相对路径是否只包含允许的字符
|
||||||
if (!preg_match('/^[\w\-.\/]+$/u', $relativePath)) {
|
if (!preg_match('/^[\w\-.\/\s]+$/u', $relativePath)) {
|
||||||
throw new NotFoundHttpException('Invalid file path.');
|
throw new NotFoundHttpException('Invalid file path.');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,56 +193,63 @@ class HomeController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function actionDelete()
|
public function actionDelete()
|
||||||
{
|
{
|
||||||
// 从 POST 请求中获取 relativePath 参数
|
|
||||||
$relativePath = Yii::$app->request->post('relativePath');
|
$relativePath = Yii::$app->request->post('relativePath');
|
||||||
|
|
||||||
// 对相对路径进行解码
|
|
||||||
$relativePath = rawurldecode($relativePath);
|
$relativePath = rawurldecode($relativePath);
|
||||||
|
if (!preg_match('/^[\w\-.\/\s]+$/u', $relativePath)) {
|
||||||
// 检查相对路径是否只包含允许的字符
|
|
||||||
if (!preg_match('/^[\w\-.\/]+$/u', $relativePath)) {
|
|
||||||
throw new NotFoundHttpException('Invalid file path.');
|
throw new NotFoundHttpException('Invalid file path.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// 确定文件的绝对路径
|
|
||||||
$absolutePath = Yii::getAlias(Yii::$app->params['dataDirectory']) . '/' . Yii::$app->user->id . '/' . $relativePath;
|
$absolutePath = Yii::getAlias(Yii::$app->params['dataDirectory']) . '/' . Yii::$app->user->id . '/' . $relativePath;
|
||||||
|
|
||||||
// 检查文件或文件夹是否存在
|
|
||||||
if (!file_exists($absolutePath)) {
|
if (!file_exists($absolutePath)) {
|
||||||
throw new NotFoundHttpException('File or directory not found.');
|
throw new NotFoundHttpException('File or directory not found.');
|
||||||
|
} else {
|
||||||
|
$realPath = realpath($absolutePath);
|
||||||
|
$expectedPathPrefix = realpath(Yii::getAlias(Yii::$app->params['dataDirectory']) . '/' . Yii::$app->user->id);
|
||||||
|
if (!str_starts_with($realPath, $expectedPathPrefix)) {
|
||||||
|
throw new NotFoundHttpException('File or directory not found.');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除文件或文件夹
|
|
||||||
if (is_dir($absolutePath)) {
|
if (is_dir($absolutePath)) {
|
||||||
// 如果是文件夹,递归删除文件夹及其内容
|
if (!$this->deleteDirectory($absolutePath)) {
|
||||||
$this->deleteDirectory($absolutePath);
|
Yii::$app->session->setFlash('error', 'Failed to delete directory.');
|
||||||
|
} else {
|
||||||
|
Yii::$app->session->setFlash('success', 'Directory deleted successfully.');
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// 如果是文件,直接删除文件
|
if (!unlink($absolutePath)) {
|
||||||
$fileinfo = $absolutePath; //要删了,准备一下
|
Yii::$app->session->setFlash('error', 'Failed to delete file.');
|
||||||
$fileinfo2 = $fileinfo;
|
} else {
|
||||||
//unlink($absolutePath);
|
Yii::$app->session->setFlash('success', 'File deleted successfully.');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return $this->redirect(['index', 'directory' => dirname($relativePath)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 递归删除目录及其内容
|
* 递归删除目录及其内容
|
||||||
* @param string $dir 目录路径
|
* @param string $dir 目录路径
|
||||||
*/
|
*/
|
||||||
protected function deleteDirectory($dir)
|
protected function deleteDirectory($dir): bool
|
||||||
{
|
{
|
||||||
if (!is_dir($dir)) {
|
if (!is_dir($dir)) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$files = array_diff(scandir($dir), ['.', '..']);
|
$files = array_diff(scandir($dir), ['.', '..']);
|
||||||
foreach ($files as $file) {
|
foreach ($files as $file) {
|
||||||
$dir1 = $dir;
|
if (is_dir("$dir/$file")) {
|
||||||
$file1 = $file;
|
if (!$this->deleteDirectory("$dir/$file")) {
|
||||||
$file2 = $file1;
|
return false;
|
||||||
is_dir("$dir/$file") ? $this->deleteDirectory("$dir/$file") : ''; //unlink("$dir/$file");
|
}
|
||||||
|
} else {
|
||||||
|
if (!unlink("$dir/$file")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$dir1 = $dir;
|
if (!rmdir($dir)) {
|
||||||
$dir2 = $dir1;
|
return false;
|
||||||
rmdir($dir);
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user