diff --git a/lib/DirScanner.php b/lib/DirScanner.php index 916162d..d2b3d21 100644 --- a/lib/DirScanner.php +++ b/lib/DirScanner.php @@ -1,6 +1,7 @@ '关键词', 'snapshot' => '快照图片', ]; + private $rootDir; //当前扫描的根目录 + private $scanningDirLevel = 0; //当前扫描的目录深度 private $scanResults = []; //目录扫描结果 @@ -69,11 +72,7 @@ Class DirScanner { //解析描述文件内容 - private function parseDescriptionFiles($realpath, $extension) { - if (!in_array($extension, $this->allowReadContentFileExtensions)) { - return false; - } - + private function parseDescriptionFiles($realpath) { $field = preg_replace('/^.+_([a-z0-9]+)\.txt$/i', "$1", $realpath); if ($field == $realpath) {return false;} $content = file_get_contents($realpath); @@ -84,7 +83,19 @@ Class DirScanner { } //解析快捷方式文件内容 - private function parseShortCuts($realpath) { + private function parseShortCuts($realpath, $filename) { + $content = file_get_contents($realpath); + if (empty($content) || !preg_match('/\[InternetShortcut\]/i', $content)) {return false;} + + preg_match('/URL=(\S+)/i', $content, $matches); + if (empty($matches) || empty($matches[1])) { + return false; + } + + return [ + 'name' => $filename, + 'url' => $matches[1], + ]; } //根据文件路径生成唯一编号 @@ -112,6 +123,66 @@ Class DirScanner { return $valid; } + //根据路径生成目录数组 + private function getDirData($realpath, $files) { + $id = $this->getId($realpath); + return [ + 'id' => $id, + 'directory' => basename($realpath), + 'realpath' => $realpath, + 'path' => $this->getDirPath($realpath), + 'files' => $files, + ]; + } + + //根据路径生成文件数组,兼容URL文件 + private function getFileData($realpath, $dirLevel) { + $id = $this->getId($realpath); + $fp = fopen($realpath, 'r'); + $fstat = fstat($fp); + fclose($fp); + $pathinfo = pathinfo($realpath); + $extension = strtolower($pathinfo['extension']); + return [ + 'id' => $id, + 'filename' => $pathinfo['filename'], + 'extension' => $extension, + 'fstat' => [ + 'size' => $fstat['size'], + 'atime' => $fstat['atime'], + 'mtime' => $fstat['mtime'], + 'ctime' => $fstat['ctime'], + ], + 'realpath' => $realpath, + 'path' => $this->getFilePath( $this->getDirectoryName($pathinfo['dirname'], $dirLevel), $pathinfo['filename'], $extension ), + ]; + } + + //根据路径和根目录获取当前扫描的目录深度 + private function getScanningLevel($rootDir, $dirname) { + $level = 0; + + if ($dirname == $rootDir) { + $level = 1; + }else { + $dirname = preg_replace('/\/$/', '', $dirname); + $dirs = explode('/', str_replace($rootDir, '', $dirname)); + $level = count($dirs); + } + + return $level; + } + + //根据路径和当前扫描深度获取目录名 + private function getDirectoryName($dirname, $dirLevel) { + if ($dirLevel <= 0) {return basename($dirname);} + $dirname = preg_replace('/\/$/', '', $dirname); + $dirname = preg_replace('/^\//', '', $dirname); + $names = explode('/', $dirname); + if ($dirLevel >= count($names)) {return $dirname;} + return implode('/', array_splice($names, -$dirLevel)); + } + //根据文件生成防盗链网址 //参考:https://nginx.org/en/docs/http/ngx_http_secure_link_module.html#secure_link @@ -139,6 +210,16 @@ Class DirScanner { //根据文件生成相对路径 protected function getFilePath($directory, $filename, $extension) { + if (empty($directory)) { + $directory = '/'; + } + if (!preg_match('/\/$/', $directory)) { + $directory .= '/'; + } + if (!preg_match('/^\//', $directory)) { + $directory = "/{$directory}"; + } + $extensionPathMap = [ //默认每种文件读取内容最大大小 'txt' => '', 'md' => '/view/', @@ -168,6 +249,11 @@ Class DirScanner { return $path; } + //根据目录生成相对路径 + protected function getDirPath($realpath) { + return '/list/?dir=' . urlencode(basename($realpath)); + } + //设置Nginx防盗链开启或关闭,以及密钥、加密方式、超时时长 public function setNginxSecure($secureOn, $secret = '', $userIp = '', $pattern = '', $timeout = 0) { @@ -269,6 +355,37 @@ Class DirScanner { //扫描目录获取目录和文件列表,支持指定目录扫描深度(目录级数) public function scan($dir, $levels = 3) { + $tree = array(); + + $ignore_files = array('.', '..'); + if (is_dir($dir)) { + if (!preg_match('/\/$/', $dir)) {$dir .= '/';} + if (empty($this->rootDir)) { + $this->rootDir = $dir; + } + $this->scanningDirLevel = $this->getScanningLevel($this->rootDir, $dir); + $nextLevels = $levels - $this->scanningDirLevel; + + $files = scandir($dir); + foreach($files as $file) { + if (in_array($file, $ignore_files)) {continue;} + + $realpath = realpath("{$dir}{$file}"); + if (is_dir($realpath)) { + $files = []; + if ($nextLevels > 0) { + $files = $this->scan($realpath, $nextLevels); + } + + $tree[] = $this->getDirData($realpath, $files); + }else { + $tree[] = $this->getFileData($realpath, $this->scanningDirLevel); + } + } + } + + + return $tree; } } diff --git a/test/DirScannerTest.php b/test/DirScannerTest.php index aa34f8b..706be53 100644 --- a/test/DirScannerTest.php +++ b/test/DirScannerTest.php @@ -63,3 +63,9 @@ $scanner = new DirScannerTest(); //$scanner->getFilePathTest('/content/视频/游戏/', 'demo', 'm3u8'); //$scanner->getFilePathTest('/content/视频/游戏/', '推荐', 'url'); //$scanner->getFilePathTest('/content/视频/游戏/', '测试', 'mp4'); + +//$dirTree = $scanner->scan('./'); +//$dirTree = $scanner->scan(__DIR__); +$dirTree = $scanner->scan(__DIR__ . '/', 3); +print_r($dirTree); +echo "\n";