<?php
/**
 * Class DirScanner
 */

Class DirScanner {
    private $nginxSecureOn = false;                     //Nginx防盗链开启状态
    private $nginxSecret = 'foo=bar';                   //Nginx防盗链密钥
    private $userIp = '127.0.0.1';                      //用户IP地址
    private $nginxSecureTimeout = 1800;                 //Nginx防盗链有效期,单位:秒
    private $nginxSecureLinkMd5Pattern = '{secure_link_expires}{uri}{remote_addr} {secret}';         //Nginx防盗链MD5加密方式
    private $allowReadContentFileExtensions = [     //允许读取文件内容的文件类型
        'txt',
        'md',
        'url',
    ];
    private $fields = [                             //私有属性字段名和说明
        'directory' => '目录名',
        'filename' => '文件名',
        'realpath' => '完整路径',
        'path' => '相对网址',
        'extension' => '文件后缀',
        'fstat' => '资源状态',                      //同php方法fstat: https://www.php.net/manual/en/function.fstat.php
        'content' => 'MD文件内容',
        'shortcut' => 'URL快捷方式',

        'description' => '描述',
        'keywords' => '关键词',
        'snapshot' => '快照图片',
    ];
    private $scanResults = [];                      //目录扫描结果


    protected $supportFileExtensions = [            //支持的文件类型
        'txt',     //纯文本
        'md',      //纯文本
        'url',     //快捷方式
        'jpg',     //图片
        'png',     //图片
        'gif',     //图片
        'ico',     //图标
        'mp4',     //视频
        'ts',      //视频
        'm3u8',    //视频
    ];
    protected $maxReadFilesize = [                  //默认每种文件读取内容最大大小
        'txt' => 100*1024,          //纯文本
        'md' => 5*1024*1024,        //纯文本
        'url' => 20*1024,           //快捷方式
        'jpg' => 500*1024,          //图片
        'png' => 500*1024,          //图片
        'gif' => 500*1024,          //图片
        'ico' => 50*1024,           //图标
        'mp4' => 100*1024*1024,     //视频
        'ts' => 10*1024*1024,       //视频
        'm3u8' => 10*1024*1024,     //视频
    ];
    protected $securedFileExtensions = [            //开启Nginx防盗链的文件类型
        'jpg',     //图片
        'png',     //图片
        'gif',     //图片
        'ico',     //图标
        'mp4',     //视频
        'ts',      //视频
        'm3u8',    //视频
    ];

    public $scanTimeCost = 0;                       //上一次目录扫描耗时,单位:微秒


    //解析描述文件内容
    private function parseDescriptionFiles($realpath) {
    }

    //解析快捷方式文件内容
    private function parseShortCuts($realpath) {
    }

    //根据文件路径生成唯一编号
    private function getId($realpath) {
        return !empty($realpath) ? md5($realpath) : '';
    }


    //根据文件生成防盗链网址
    //参考:https://nginx.org/en/docs/http/ngx_http_secure_link_module.html#secure_link
    //防盗链参数名:md5, expires
    protected function getSecureLink($path) {
        $expires = time() + $this->nginxSecureTimeout;
        $originStr = str_replace([
                '{secure_link_expires}',
                '{uri}',
                '{remote_addr}',
                '{secret}',
            ], [
                $expires,
                $path,
                $this->userIp,
                $this->nginxSecret,
            ], $this->nginxSecureLinkMd5Pattern);

        $md5 = base64_encode( md5($originStr, true) );
        $md5 = strtr($md5, '+/', '-_');
        $md5 = str_replace('=', '', $md5);

        return "{$path}?md5={$md5}&expires={$expires}";
    }

    //根据文件生成相对路径
    protected function getFilePath($directory, $filename, $extension) {
        $extensionPathMap = [                  //默认每种文件读取内容最大大小
            'txt' => '',
            'md' => '/view/',
            'url' => '/link/',
            'm3u8' => '/m3u8/',
            'jpg' => "{$directory}{$filename}.{$extension}",
            'png' => "{$directory}{$filename}.{$extension}",
            'gif' => "{$directory}{$filename}.{$extension}",
            'ico' => "{$directory}{$filename}.{$extension}",
            'mp4' => "{$directory}{$filename}.{$extension}",
            'ts' => "{$directory}{$filename}.{$extension}",
        ];

        $path = isset($extensionPathMap[$extension]) ? $extensionPathMap[$extension] : '';

        if (!empty($path) && in_array($extension, ['md', 'url', 'm3u8'])) {
            if ($this->nginxSecureOn && $extension == 'm3u8') {
                $path = $this->getSecureLink($path);
                $path = "{$path}&file=" . urlencode($filename);
            }else {
                $path = "{$path}?file=" . urlencode($filename);
            }
        }else if (!empty($path) && $this->nginxSecureOn) {
            $path = $this->getSecureLink($path);
        }

        return $path;
    }


    //设置Nginx防盗链开启或关闭,以及密钥、加密方式、超时时长
    public function setNginxSecure($secureOn, $secret = '', $userIp = '', $pattern = '', $timeout = 0) {
        $status = false;
        if (is_string($secureOn) && strtolower($secureOn) == 'on') {
            $status = true;
        }else if (is_string($secureOn) && strtolower($secureOn) == 'off') {
            $status = false;
        }else if ((bool)$secureOn == true) {
            $status = true;
        }
        $this->nginxSecureOn = $status;

        if (!empty($secret) && is_string($secret)) {
            $this->nginxSecret = $secret;
        }

        if (!empty($userIp) && is_string($userIp)) {
            $this->userIp = $userIp;
        }

        if (!empty($pattern) && is_string($pattern)) {
            $this->nginxSecureLinkMd5Pattern = $pattern;
        }

        if ((int)$timeout > 0) {
            $this->nginxSecureTimeout = (int)$timeout;
        }
    }

    //设置Nginx防盗链密钥
    public function setNginxSecret($secret) {
        if (!empty($secret) && is_string($secret)) {
            $this->nginxSecret = $secret;
        }
    }

    //获取Nginx防盗链密钥
    public function getNginxSecret() {
        return $this->nginxSecret;
    }

    //设置Nginx防盗链密钥
    public function setUserIp($userIp) {
        if (!empty($userIp) && is_string($userIp)) {
            $this->userIp = $userIp;
        }
    }

    //获取Nginx防盗链密钥
    public function getUserIp() {
        return $this->userIp;
    }

    //设置Nginx防盗链MD5加密方式
    /**
     * Nginx防盗链MD5加密方式参考下面网址中的示例,
     * 将Nginx的变量替换$符号为英文大括号;
     * 
     * 示例:
     * ```
     * {secure_link_expires}{uri}{remote_addr} {secret}
     * ```
     * Nginx文档参考:http://nginx.org/en/docs/http/ngx_http_secure_link_module.html#secure_link_md5
     */
    public function setNginxSecureLinkMd5Pattern($pattern) {
        if (!empty($pattern) && is_string($pattern)) {
            $this->nginxSecureLinkMd5Pattern = $pattern;
        }
    }

    //获取Nginx防盗链MD5加密方式
    public function getNginxSecureLinkMd5Pattern() {
        return $this->nginxSecureLinkMd5Pattern;
    }

    //设置Nginx防盗链超时时长,单位:秒
    public function setNginxSecureTimeout($timeout) {
        if ((int)$timeout > 0) {
            $this->nginxSecureTimeout = (int)$timeout;
        }
    }

    //获取Nginx防盗链超时时长,单位:秒
    public function getNginxSecureTimeout() {
        return $this->nginxSecureTimeout;
    }

    //获取是否开启防盗链
    public function isSecureOn() {
        return $this->nginxSecureOn;
    }

    //扫描目录获取目录和文件列表,支持指定目录扫描深度(目录级数)
    public function scan($dir, $levels = 3) {
    }

}