diff --git a/controller/ApiController.php b/controller/ApiController.php index 5a0c2b0..71d866c 100644 --- a/controller/ApiController.php +++ b/controller/ApiController.php @@ -38,6 +38,21 @@ Class ApiController extends Controller { return $this->renderJson($params); } + //判断父目录是否合法 + protected function isParentDirectoryValid($parentDir) { + if (empty($parentDir) || strpos($parentDir, '../') !== false) { + return false; + } + + $valid = true; + $target = __DIR__ . '/../www/' . FSC::$app['config']['content_directory'] . "/{$parentDir}"; + if (!is_dir($target)) { + $valid = false; + } + + return $valid; + } + //目录、文件列表 public function actionLs() { $code = 0; @@ -51,6 +66,7 @@ Class ApiController extends Controller { $scanner = new DirScanner(); $scanner->setWebRoot(FSC::$app['config']['content_directory']); + $scanner->isApi = true; //realpath返回相对路径 $target = __DIR__ . '/../www/' . FSC::$app['config']['content_directory']; $maxLevels = FSC::$app['config']['maxScanDirLevels']; $dirTree = $scanner->scan($target, $maxLevels); @@ -81,6 +97,12 @@ Class ApiController extends Controller { $cateId = $this->get('id', $menus[0]['id']); $data['menus'] = $menus; + + //替换realpath,改为相对路径返回 + $basePath = realpath($target); + if (!preg_match('/\/$/', $basePath)) { + $basePath .= '/'; + } $data['dirTree'] = $scanResults[$cateId]; $code = 1; @@ -117,10 +139,12 @@ Class ApiController extends Controller { $target = __DIR__ . '/../www/' . FSC::$app['config']['content_directory']; if (!empty($parentDir)) { $target = "{$target}/{$parentDir}"; - } - if (!is_dir($target)) { - $err = "父目录{$parentDir}不存在"; - return $this->renderJson(compact('code', 'msg', 'err', 'data')); + + //父目录合法性检查 + if ($this->isParentDirectoryValid($parentDir) == false) { + $err = "父目录{$parentDir}不存在"; + return $this->renderJson(compact('code', 'msg', 'err', 'data'), $this->httpStatus['notAllowed']); + } } try { @@ -164,10 +188,12 @@ Class ApiController extends Controller { $target = __DIR__ . '/../www/' . FSC::$app['config']['content_directory']; if (!empty($parentDir)) { $target = "{$target}/{$parentDir}"; - } - if (!is_dir($target)) { - $err = "父目录{$parentDir}不存在"; - return $this->renderJson(compact('code', 'msg', 'err', 'data')); + + //父目录合法性检查 + if ($this->isParentDirectoryValid($parentDir) == false) { + $err = "父目录{$parentDir}不存在"; + return $this->renderJson(compact('code', 'msg', 'err', 'data'), $this->httpStatus['notAllowed']); + } } try { @@ -196,25 +222,21 @@ Class ApiController extends Controller { return $this->renderJson(compact('code', 'msg', 'err', 'data'), $this->httpStatus['notLogined']); } - - $parentDir = $this->post('parent', ''); $fromDir = $this->post('from', ''); $toDir = $this->post('to', ''); $maxDirLen = 50; if (empty($fromDir) || mb_strlen($fromDir, 'utf-8') > $maxDirLen || empty($toDir) || mb_strlen($toDir, 'utf-8') > $maxDirLen) { $err = "目录名不能为空且最长 {$maxDirLen} 个字符"; return $this->renderJson(compact('code', 'msg', 'err', 'data')); + }else if ($this->isParentDirectoryValid($fromDir) == false) { //目录合法性检查 + $err = "目录{$fromDir}不存在"; + return $this->renderJson(compact('code', 'msg', 'err', 'data'), $this->httpStatus['notAllowed']); + }else if ($this->isParentDirectoryValid($toDir) == false) { //目录合法性检查 + $err = "目录{$toDir}不存在"; + return $this->renderJson(compact('code', 'msg', 'err', 'data'), $this->httpStatus['notAllowed']); } $target = __DIR__ . '/../www/' . FSC::$app['config']['content_directory']; - if (!empty($parentDir)) { - $target = "{$target}/{$parentDir}"; - } - if (!is_dir($target)) { - $err = "父目录{$parentDir}不存在"; - return $this->renderJson(compact('code', 'msg', 'err', 'data')); - } - try { $res = rename("{$target}/{$fromDir}", "{$target}/{$toDir}"); if ($res) { @@ -257,10 +279,12 @@ Class ApiController extends Controller { $target = __DIR__ . '/../www/' . FSC::$app['config']['content_directory']; if (!empty($parentDir)) { $target = "{$target}/{$parentDir}"; - } - if (!is_dir($target)) { - $err = "父目录{$parentDir}不存在"; - return $this->renderJson(compact('code', 'msg', 'err', 'data')); + + //父目录合法性检查 + if ($this->isParentDirectoryValid($parentDir) == false) { + $err = "父目录{$parentDir}不存在"; + return $this->renderJson(compact('code', 'msg', 'err', 'data'), $this->httpStatus['notAllowed']); + } } try { @@ -304,10 +328,12 @@ Class ApiController extends Controller { $target = __DIR__ . '/../www/' . FSC::$app['config']['content_directory']; if (!empty($parentDir)) { $target = "{$target}/{$parentDir}"; - } - if (!is_dir($target)) { - $err = "父目录{$parentDir}不存在"; - return $this->renderJson(compact('code', 'msg', 'err', 'data')); + + //父目录合法性检查 + if ($this->isParentDirectoryValid($parentDir) == false) { + $err = "父目录{$parentDir}不存在"; + return $this->renderJson(compact('code', 'msg', 'err', 'data'), $this->httpStatus['notAllowed']); + } } try { @@ -521,6 +547,9 @@ Class ApiController extends Controller { }else if (!preg_match('/^data:[a-z0-9]+\/[a-z0-9]+;base64,/i', $upfile)) { $err = '图片数据必需为base64格式!'; return $this->renderJson(compact('code', 'msg', 'err', 'data'), $this->httpStatus['notLogined']); + }else if (!empty($parentDir) && $this->isParentDirectoryValid($parentDir) == false) { //父目录合法性检查 + $err = "父目录{$parentDir}不存在"; + return $this->renderJson(compact('code', 'msg', 'err', 'data'), $this->httpStatus['notAllowed']); } //base64格式数据支持 diff --git a/lib/DirScanner.php b/lib/DirScanner.php index 13f55a7..82115c0 100644 --- a/lib/DirScanner.php +++ b/lib/DirScanner.php @@ -75,6 +75,7 @@ Class DirScanner { ); public $scanTimeCost = 0; //上一次目录扫描耗时,单位:毫秒 + public $isApi = false; //如果为API获取数据,则realpath只返回相对路径 //判断目录名或文件名是否合法 @@ -173,7 +174,7 @@ Class DirScanner { $data = array( 'id' => $id, 'directory' => $this->basename($realpath), - 'realpath' => $realpath, + 'realpath' => $this->isApi ? $this->getRelativeDirname($realpath) : $realpath, 'path' => $this->getDirPath($id), ); @@ -223,7 +224,7 @@ Class DirScanner { 'mtime' => $fstat['mtime'], 'ctime' => $fstat['ctime'], ), - 'realpath' => $realpath, + 'realpath' => $this->isApi ? $this->getRelativeDirname($realpath) : $realpath, 'path' => $this->getFilePath( $id, $this->getRelativeDirname($pathinfo['dirname']), $pathinfo['filename'], $extension, $fstat['mtime'] ), );