[
  {
    "path": ".gitignore",
    "content": "**/.DS_Store\n"
  },
  {
    "path": "README.md",
    "content": "## 简介\n\n本项目是基于：\n\n- Oneindex\n\n- OneindexN项目地址：https://github.com/xieqifei/OneindexN\n\n详细安装教程：\n- [基于Onedrive和Server搭建下载站/网盘](https://www.mintimate.cn/2020/09/22/oneindex)\n\n教程视频：\n- [8分钟利用OneDrive搭建不限速的OneIndex分享网盘](https://www.bilibili.com/video/BV1ph41197aa)\n\n\n打赏\n- 爱发电：[Mintimate的电圈](https://www.afdian.net/@mintimate/plan)\n\n![](https://cdn.jsdelivr.net/gh/Mintimate/OneindexM/demo/demo.png)\n\n### 特别注意\nOneindexM的默认密码为：**MintimateBlog**\n\n## 修改功能：\n\n### 后台：\n\n- 选择安装世纪互联/国际版（如需修改版本，需要删除config文件夹里的文件后重新进入安装程序）\n- 指定文件夹/全部文件夹，关闭Readme.md、index.html、head.md渲染（如果开启游客离线上传，可以关闭此路径的渲染，避免游客上传会被渲染的文件。）\n\n### 前台\n\n以下功能仅支持nexmoe主题\n- 搜索功能：全局搜索/当前页过滤\n- 文件操作：删除/新建/重命名/剪切/复制/分享等。仅管理员可用\n- 文件上传：4M以下的文件在线上传。url远程上传，仅onedrive个人版支持。aria2离线上传，需自行安装在vps上安装aria2并完成相关配置。\n- 外部视频播放器播放接口。需要安装对应播放器。\n- 管理员登陆后，查看加密文件夹无需密码。\n\n## 更新日志\n- 2021.12.03：修复PHP7.x查询函数警告问题；修复文件过滤、查询出错问题；修复排序不可用问题；移除Jq、Bootstrap；调整部分UI\n- 2021.08.03：修复Cookies循环问题、修复世纪互联版本部分情况不可用问题。\n- 2021.07.01：修复因为Onedrive接口更换，而导致的无法部署。\n- 2021.06.25：更换重写URL服务器。\n\n## 部署网站\n\n网站环境尽量使用Nginx或Apache，配合PHP5.7+版本。\n\n建议参考文章：\n![基于Onedrive和Server搭建下载站/网盘](https://www.mintimate.cn/2020/09/22/oneindex)\n\n<hr/>\n\n**以下是上游Readme.md内容**\n\n## 功能\n\n不占用服务器空间，不走服务器流量，  \n\n直接列出 OneDrive 目录，文件直链下载。  \n\n## 使用及免责协议\n\n[使用及免责协议](./使用及免责协议.md)\n\n## 安装运行\n\n### 需求：\n\n1、PHP空间，PHP 5.6+ 需打开curl支持  \n2、OneDrive 账号 (个人、企业版或教育版/工作或学校帐户)  \n3、OneIndex 程序   \n\n### 计划任务  \n\n[可选]**推荐配置**，非必需。后台定时刷新缓存，可增加前台访问的速度。  \n\n```\n# 每小时刷新一次token\n0 * * * * /具体路径/php /程序具体路径/one.php token:refresh\n\n# 每十分钟后台刷新一遍缓存\n*/10 * * * * /具体路径/php /程序具体路径/one.php cache:refresh\n```\n\n### Docker 安装运行\n\n- 请参考[TimeBye/oneindex](https://github.com/TimeBye/oneindex)\n\n## 特殊文件实现功能  \n\n` README.md `、`HEAD.md` 、 `.password`特殊文件使用  \n\n可以参考[https://github.com/donwa/oneindex/tree/files](https://github.com/donwa/oneindex/tree/files)  \n\n**在文件夹底部添加说明:**  \n\n>在 OneDrive 的文件夹中添加` README.md `文件，使用 Markdown 语法。  \n\n**在文件夹头部添加说明:**  \n\n>在 OneDrive 的文件夹中添加`HEAD.md` 文件，使用 Markdown 语法。  \n\n**加密文件夹:**  \n\n>在 OneDrive 的文件夹中添加`.password`文件，填入密码，密码不能为空。  \n\n**直接输出网页:**  \n\n>在 OneDrive 的文件夹中添加`index.html` 文件，程序会直接输出网页而不列目录。  \n>配合 文件展示设置-直接输出 效果更佳。  \n\n## 命令行功能  \n\n仅能在PHP CLI模式下运行  \n\n**清除缓存:**  \n\n```\nphp one.php cache:clear\n```\n\n**刷新缓存:**  \n\n```\nphp one.php cache:refresh\n```\n\n**刷新令牌:**  \n\n```\nphp one.php token:refresh\n```\n\n**上传文件:**  \n\n```\nphp one.php upload:file 本地文件 [OneDrive文件]\n```\n\n**上传文件夹:**  \n\n```\nphp one.php upload:folder 本地文件夹 [OneDrive文件夹]\n```\n\n例如：  \n\n```\n//上传demo.zip 到OneDrive 根目录  \nphp one.php upload:file demo.zip  \n\n//上传demo.zip 到OneDrive /test/目录  \nphp one.php upload:file demo.zip /test/  \n\n//上传demo.zip 到OneDrive /test/目录并将其命名为 d.zip  \nphp one.php upload:file demo.zip /test/d.zip  \n\n//上传up/ 到OneDrive /test/ 目录  \nphp one.php upload:file up/ /test/\n```\n\n## 使用Aria2\n\nNginx添加反向代理\n\n```\nlocation /jsonrpc {\n        proxy_pass http://localhost:6800/jsonrpc;\n        proxy_redirect off;\n        proxy_set_header        X-Real-IP       $remote_addr;\n        proxy_set_header        X-Forwarded-For\n        $proxy_add_x_forwarded_for;\n        proxy_set_header Host $host;\n\t}\n```\n\nnginx会监听发送给`http://yoursite/jsonrpc`的消息，然后将他转发给`http:localhost:6800/jsonrpc`，相当于你在yaaw中设置rpc时，只需要将其设置为`http://yoursite/jsonrpc`或者`https://yoursite/jsonrpc`,省略的端口信息为http对应80,https对应443，这些端口浏览器会自动转发，不用在设置中指定。如果你设置了反向代理，那么使用前台yaaw时，就不用在做rpc设置了。否则你需要去重新设置。\n\n![](https://i.loli.net/2020/06/25/9cY2PiBr6usqXen.png)\n\n**关闭aria2远程RPC**\n\n仅vps本地也就是nginx转发的请求能到达6800。其他主机不能访问6800端口。\n\n```shell\nvim /root/.aria2c/aria2.conf\n```\n\n修改aria2配置内容\n\n```\n# 启用RPC, 默认:false\nenable-rpc=true\n# 接受所有远程请求, 默认:false\nrpc-allow-origin-all=false\n# 允许外部访问, 默认:false\nrpc-listen-all=false\n# RPC监听端口, 端口被占用时可以修改, 默认:6800\nrpc-listen-port=6800\n```\n\n> 请注意，关闭远程请求并不能阻止其他主机向aria2发送请求，在不设置token时，任何人都可以通过直接向`http://yoursite/jsonrpc`这个地址发送请求连接aria2。如果你开启游客离线下载可以这么设置。如果你不希望有人通过其他aria2前端连接你的aria2，请你务必设置token，但是这样做，你也必须在使用的时候修改rpc设置，好在，第一次修改设置后，之后浏览器都会记住这个设置。\n\n> 博客：https://sci.ci\n>\n> 如果应用有bug，或者你有好的修改建议，可以通过邮箱联系我：im@xieqifei.com\n\n## 参考资料\n\n《[github YAAW项目](https://github.com/binux/yaaw)》\n\n《[Issue：一旦使用HTTPS协议就无法连接](https://github.com/mayswind/AriaNg/issues/62)》\n\n《[Nginx 反向代理 Aria2 JSONRPC](https://kenvix.com/post/nginx-proxy-aria2/)》\n"
  },
  {
    "path": "cache/abc",
    "content": "\n"
  },
  {
    "path": "config/README.md",
    "content": "# oneindex\nOneDrive Directory Index\n"
  },
  {
    "path": "controller/AdminController.php",
    "content": "<?php\ndefine('VIEW_PATH', ROOT.'view/admin/');\nclass AdminController{\n    static $default_config = array(\n      'site_name' =>'OneIndex',\n      'site_name_small' =>'',\n      'password' => 'MintimateBlog',\n      'style'=>'nexmoe',\n      'onedrive_root' =>'',\n      'except_path' =>'',\n      'cache_type'=>'secache',\n      'cache_expire_time' => 10,\n      'cache_refresh_time' => 600,\n      'root_path' => '?',\n      'show'=> array (\n          'stream'=>['txt'],\n        'image' => ['bmp','jpg','jpeg','png','gif'],\n        'video5'=>['mp4','webm','mkv'],\n        'video'=>[],\n        'video2'=>['avi','mpg', 'mpeg', 'rm', 'rmvb', 'mov', 'wmv', 'asf', 'ts', 'flv'],\n        'audio'=>['ogg','mp3','wav'],\n        'code'=>['html','htm','php', 'css', 'go','java','js','json','txt','sh','md'],\n        'doc'=>['csv','doc','docx','odp','ods','odt','pot','potm','potx','pps','ppsx','ppsxm','ppt','pptm','pptx','rtf','xls','xlsx']\n      ),\n      'images'=>['home'=>false,'public'=>false, 'exts'=>['jpg','png','gif','bmp']],\n      'offline'=>array(\n          'offline'=>false,\n          'online'=>false,\n          'upload_path'=>'/upload/'\n        )\n    );\n    \n    function __construct(){\n    }\n\n    function login(){\n        if(!empty($_POST['password']) && $_POST['password'] == config('password')){\n            setcookie('admin', md5(config('password').config('refresh_token')) );\n            return view::direct(get_absolute_path(dirname($_SERVER['SCRIPT_NAME'])).'?/admin/');\n        }\n        return view::load('login')->with('title', '系统管理');\n    }\n\n    function logout(){\n        setcookie('admin', '' );\n        return view::direct(get_absolute_path(dirname($_SERVER['SCRIPT_NAME'])).'?/login');\n    }\n\n    function settings(){\n        $message = false;\n\n        if($_POST){\n            \n            if ($this->cache_exists($_POST['cache_type'])) {\n                $message = '保存成功';\n                config('cache_type', $_POST['cache_type']);\n            } else {\n                $message = '缓存类型不可用，请确认已经安装了该拓展。';\n                config('cache_type', 'secache');\n            }\n            //判断不渲染目录是否为全部不渲染\n            if($_POST['except_path']){\n                $except_path=(strcmp($_POST['except_path'],'all')==0?'all':get_absolute_path($_POST['except_path']));\n            }else{\n                $except_path='';\n            }\n            config('site_name', $_POST['site_name']);\n            config('style', $_POST['style']);\n            config('onedrive_root', get_absolute_path($_POST['onedrive_root']));\n            config('except_path',$except_path);\n            config('onedrive_hide', $_POST['onedrive_hide']);\n            config('onedrive_hotlink', $_POST['onedrive_hotlink']);\n            config('cache_expire_time', intval($_POST['cache_expire_time']));\n            $_POST['root_path'] = empty($_POST['root_path'])?'?':'';\n            config('root_path', $_POST['root_path']);\n        }\n\n        $config = config('@base');\n\n        return view::load('settings')->with('config', $config)->with('message', $message);\n    }\n    \n    function offline(){\n        if($_POST){\n            $config['offline'] = empty($_POST['offline'])?false:true;\n            $config['online'] = empty($_POST['online'])?false:true;\n            $config['upload_path'] = empty($_POST['upload_path']) ? '/' : get_absolute_path($_POST['upload_path']);\n            config('offline@base',$config);\n        }\n        $config = config('offline@base');\n        return view::load('offline')->with('config',$config);\n    }\n    \n    /**\n     * 判断缓存类型\n     *\n     * @param string $cache_type 缓存类型\n     * @return void\n     */\n    function cache_exists($cache_type){\n        // 需要判断环境的缓存类型\n        $_cache_type = [\n            'redis',\n            'memcache',\n        ];\n\n        if (in_array($cache_type, $_cache_type)) {\n            return class_exists(ucfirst($cache_type));\n        }\n\n        return true;\n    }\n\n    function cache(){\n        if(!is_null($_POST['clear'])){\n            cache::clear();\n            $message = \"清除缓存成功\";\n        }elseif ( !is_null($_POST['refresh']) ){\n            oneindex::refresh_cache(get_absolute_path(config('onedrive_root')));\n            $message = \"重建缓存成功\";\n        }\n        return view::load('cache')->with('message', $message);\n    }\n\n    function images(){\n        if($_POST){\n            $config['home'] = empty($_POST['home'])?false:true;\n            $config['public'] = empty($_POST['public'])?false:true;\n            $config['exts'] = explode(\" \", $_POST['exts']);\n            config('images@base',$config);\n        }\n        $config = config('images@base');\n        return view::load('images')->with('config', $config);;\n    }\n\n\n    function show(){\n        if(!empty($_POST) ){\n            foreach($_POST as $n=>$ext){\n                $show[$n] = explode(' ', $ext);\n            }\n            config('show', $show);\n        }\n        $names = [\n            'stream'=>'直接输出(<5M)，走本服务器流量(stream)',\n            'image' =>'图片(image)',\n            'video'=>'Dplayer 视频(video)',\n            'video2'=>'Dplayer DASH 视频(video2)/个人版账户不支持',\n            'video5'=>'html5视频(video5)',\n            'audio'=>'音频播放(audio)',\n            'code'=>'文本/代码(code)',\n            'doc'=>'文档(doc)'\n        ];\n        $show = config('show');\n        return view::load('show')->with('names', $names)->with('show', $show);\n    }\n\n    function setpass(){\n        if($_SERVER['REQUEST_METHOD'] == 'POST'){\n            if($_POST['old_pass'] == config('password')){\n                if($_POST['password'] == $_POST['password2']){\n                    config('password', $_POST['password']);\n                    $message = \"修改成功\";\n                }else{\n                    $message = \"两次密码不一致，修改失败\";\n                }\n            }else{\n                $message = \"原密码错误，修改失败\";\n            }\n        }\n        return view::load('setpass')->with('message', $message);\n    }\n    \n    function install(){\n        if(!empty($_GET['code'])){\n            return $this->install_3();\n        }\n        switch ( intval($_GET['step']) ){\n            case 1:\n                return $this->install_1();\n            case 2:\n                return $this->install_2();\n            default:\n                return $this->install_0();\n        }\n    }\n\n    function install_0(){\n        $check['php'] = version_compare(PHP_VERSION,'5.5.0','ge');\n        $check['curl'] = function_exists('curl_init');\n        $check['config'] = is_writable(ROOT.'config/');\n        $check['cache'] = is_writable(ROOT.'cache/');\n\n        return view::load('install/install_0')->with('title','系统安装')\n                        ->with('check', $check);\n    }\n\n    function install_1(){\n        if(!empty($_POST['client_secret']) && !empty($_POST['client_id']) && !empty($_POST['redirect_uri']) && !empty($_POST['area'])){\n            config('@base', self::$default_config);\n            config('client_secret',$_POST['client_secret']);\n            config('client_id',$_POST['client_id']);\n            config('redirect_uri',$_POST['redirect_uri']);\n            config('area',$_POST['area']);\n            return view::direct('?step=2');\n        }\n        if($_SERVER['HTTP_HOST'] == 'localhost'){\n            $redirect_uri = 'http://'.$_SERVER['HTTP_HOST'].get_absolute_path(dirname($_SERVER['PHP_SELF']));\n        }else{\n            // 非https,调用ju.tn中转\n            $redirect_uri = 'https://tool.mintimate.cn/oneindexM/';\n        }\n        \n        $ru = \"https://developer.microsoft.com/en-us/graph/quick-start?appID=_appId_&appName=_appName_&redirectUrl={$redirect_uri}&platform=option-php\";\n        $deepLink = \"/quickstart/graphIO?publicClientSupport=false&appName=oneindex&redirectUrl={$redirect_uri}&allowImplicitFlow=false&ru=\".urlencode($ru);\n        $app_url = \"https://apps.dev.microsoft.com/?deepLink=\".urlencode($deepLink);\n        return view::load('install/install_1')->with('title','系统安装')\n                        ->with('redirect_uri', $redirect_uri)\n                        ->with('app_url', $app_url);\n    }\n\n    function install_2(){\n        return view::load('install/install_2')->with('title','系统安装');\n    }\n\n    function install_3(){\n        $data = onedrive::authorize($_GET['code']);\n        if(!empty($data['refresh_token'])){\n            config('refresh_token',$data['refresh_token']);\n            config('@token', $data);\n        }\n        return view::load('install/install_3')->with('refresh_token',$data['refresh_token']);\n        \n    }\n}\n"
  },
  {
    "path": "controller/CommonController.php",
    "content": "<?php \ndefine('VIEW_PATH', ROOT.'view/');\nclass CommonController{\n\t\n\tfunction __construct(){\n\t}\n\t//aria2\n\tfunction offline(){\n\t\tif(config('offline')['offline']||is_login()){\n\t\t\treturn view::load('common/offline');\n\t\t}\n\t\telse{\n\t\t\treturn view::load('common/tips')->with('tip','管理员未授权使用');\n\t\t}\n\t}\n\n\t//搜索\n\tfunction search(){\n\t\tif(is_login()){\n\t\t\tif($_POST['keyword']){\n\t\t\t\t$keyword=$_POST['keyword'];\n\t\t\t\t$items = onedrive::search($keyword);\n\t\t\t\tif(!$items){\n\t\t\t\t\treturn view::load('common/tips')->with('tip','没有找到与“'.$_POST['keyword'].'”有关的内容');\n\t\t\t\t}\n\t\t\t\t$searchinfo['keyword']=$keyword;\n\t\t\t\t$searchinfo['count']=count($items);\n\t\t\t\treturn view::load('common/search')->with('items',$items)->with('searchinfo',$searchinfo);\n\t\t\t}else{\n\t\t\t\treturn '参数错误';\n\t\t\t}\n\t\t}\n\t\telse{\n\t\t\treturn '请登陆后尝试';\n\t\t}\n\t}\n\t//新建文件夹\n\t//post参数：uploadurl，当前url的路径\n\tfunction create_folder(){\n\t\tif(is_login()){\n\t\t\t$urlinfo=parse_url($_POST['uploadurl']);\n\t\t\tif(stristr($_POST['uploadurl'],'?')){\n\t\t\t\t$paths = explode('/', rawurldecode($urlinfo['query']));\n\t\t\t}else{\n\t\t\t\t$paths = explode('/', rawurldecode($urlinfo['path']));\n\t\t\t}\n\t\t\t$paths=array_values($paths);\n\t\t\t$remotepath = get_absolute_path(join('/', $paths));\n\t\t\t$data = onedrive::create_folder(str_replace('//','/',config('onedrive_root').$remotepath),$_POST['foldername']);\n\t\t\toneindex::refresh_cache(get_absolute_path(config('onedrive_root')));\n\t\t\treturn $data;\n\t\t}\n\t\telse{\n\t\t\treturn '未登录无法新建文件夹';\n\t\t}\n\t}\n\t//重命名\n\t//post参数：name：新名称；itemid：itemid\n\tfunction rename(){\n\t\tif(is_login()){\n\t\t\t$newname=$_POST['name'];\n\t\t\t$itemid=$_POST['itemid'];\n\t\t\t$resp=onedrive::rename($itemid,$newname);\n\t\t\toneindex::refresh_cache(get_absolute_path(config('onedrive_root')));\n\t\t\treturn $resp;\n\t\t}\n\t\telse{\n\t\t\treturn '未登录无法重命名';\n\t\t}\n\t}\n\t//删除\n\t//传入一个stringfy后的itemid的数组\n\tfunction deleteitems(){\n\t\tif(is_login()){\n\t\t\t$data = file_get_contents( \"php://input\" );\n\t\t\t$items = json_decode( $data );\n\t\t\t$resp=onedrive::delete($items);\n\t\t\toneindex::refresh_cache(get_absolute_path(config('onedrive_root')));\n\t\t\treturn $resp;\n\t\t}\n\t\telse{\n\t\t\treturn '未登录无法删除';\n\t\t}\n\t}\n\t//url上传\n\tfunction upload_url(){\n\t\tif(is_login()){\n\t\t\tif($_POST['file_url']&&$_POST['path_url']){\n\t\t\t\t$file_url=$_POST['file_url'];\n\t\t\t\t$path_url=$_POST['path_url'];\n\t\t\t\tif($_POST['file_name']){\n\t\t\t\t\t$file_name = $_POST['file_name'];\n\t\t\t\t}\n\t\t\t\telse{\n\t\t\t\t\t$file_name = pathinfo(parse_url($file_url,PHP_URL_PATH),PATHINFO_BASENAME);\n\t\t\t\t}\n\t\t\t\t$path = str_replace('//','/',$this->url2path($path_url).'/'.$file_name);\n\t\t\t\t$process_url = onedrive::upload_url($path , $file_url);\n\t\t\t\tif($process_url){\n\t\t\t\t\treturn $process_url;\n\t\t\t\t}\n\t\t\t\telse{\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\t\t\t}else{\n\t\t\t\treturn '参数错误';\n\t\t\t}\n\t\t}else{\n\t\t\treturn '未登录';\n\t\t}\n\t}\n\n\t//在线上传，大小限制在4M\n\t//post参数：onlinefile：一个文件；uploadurl：当前url路径\n\tfunction onlinefileupload()\n\t{\n\t\t\n\t\tif($this->uploadcondition($_FILES[\"onlinefile\"]) ){\n\t\t\t$filename = $_FILES[\"onlinefile\"]['name'];\n\t\t\t$content = file_get_contents( $_FILES[\"onlinefile\"]['tmp_name']);\n\t\t\t//管理员不受上传目录限制\n\t\t\tif(is_login()){\n\t\t\t\t//获取路径\n\t\t\t\t$paths = explode('/', rawurldecode($_POST['uploadurl']));\n\t\t\t\tif(strcmp($paths[1],'?')==0){\n\t\t\t\t\tarray_shift($paths);\n\t\t\t\t\tarray_shift($paths);\n\t\t\t\t}\n\t\t\t\t//$paths=array_shift($paths);\n\t\t\t\t$remotepath = get_absolute_path(join('/', $paths));\n\t\t\t}\n\t\t\t//游客只能上传到指定目录\n\t\t\telse{\n\t\t\t\t$remotepath =  config('offline')['upload_path'];\n\t\t\t}\n\t\t\t$remotefile = $remotepath.$filename;\n\t\t\t$result = onedrive::upload(str_replace('//','/',config('onedrive_root').$remotefile), $content);\n\t\t\t\n\t\t\tif($result){\n\t\t\t\t$root = get_absolute_path(dirname($_SERVER['SCRIPT_NAME'])).config('root_path');\n\t\t\t\t$http_type = ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')) ? 'https://' : 'http://';\n\t\t\t\t$url = $_SERVER['HTTP_HOST'].$root.'/'.$remotepath.rawurldecode($filename).((config('root_path') == '?')?'&s':'?s');\n\t\t\t\t$url = $http_type.str_replace('//','/', $url);\n\t\t\t\t$result['path']=$url;\n\t\t\t\t// view::direct($url);\n\t\t\t\treturn json_encode($result);\n\t\t\t}\n\t\t}else{\n\t\t\treturn '未登录或文件过大';\n\t\t}\n\t\t\n\t}\n\t//上传文件的条件判断\n\tfunction uploadcondition($file){\n\t\t\n\t\tif($file['size'] > 4485760 || $file['size'] == 0){\n\t\t\treturn false;\n\t\t}\n\t\tif(config('offline')['online']==false&&!is_login()){\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n\t//粘贴\n\tfunction paste(){\n\t\tif(is_login()){\n\t\t\t$data = file_get_contents( \"php://input\" );\n\t\t\t$jsondata = json_decode($data);//字符串转对象。\n\t\t\tif($jsondata->cutitems){\n\t\t\t\t$cutitems=$jsondata->cutitems;\n\t\t\t\t$url=$jsondata->url;\n\t\t\t\treturn $this->cut($cutitems,$url);\n\t\t\t}\n\t\t\tif($jsondata->copyitems){\n\t\t\t\t$copyitems=$jsondata->copyitems;\n\t\t\t\t$url=$jsondata->url;\n\t\t\t\treturn $this->copy($copyitems,$url);\n\t\t\t}\n\t\t\treturn '操作失误，请重新尝试！';\n\t\t}\n\t\telse{\n\t\t\treturn '未登录无法重命名';\n\t\t}\n\t}\n\t//移动或剪切\n\tfunction cut($cutitems,$url){\n\t\t$itemid=$this->url2id($url);\n\t\t$resp=onedrive::move($cutitems,$itemid);\n\t\toneindex::refresh_cache(get_absolute_path(config('onedrive_root')));\n\t\treturn json_encode(json_decode(json_encode($resp)));//decode去掉字符串中的转义字符再\n\t}\n\t//复制\n\tfunction copy($copyitems,$url){\n\t\t$itemid=$this->url2id($url);\n\t\t$resp=onedrive::copy($copyitems,$itemid);\n\t\toneindex::refresh_cache(get_absolute_path(config('onedrive_root')));\n\t\treturn $resp;\n\t}\n\t//url转路径\n\tfunction url2path($url){\n\t\t$paths=array();\n\t\t$urlinfo=parse_url($url);\n\t\tif(stristr($url,'?')){\n\t\t\t$paths = explode('/', rawurldecode($urlinfo['query']));\n\t\t}else{\n\t\t\t$paths = explode('/', rawurldecode($urlinfo['path']));\n\t\t}\n\t\tif(strcmp($paths[1],'?')==0){\n\t\t\tarray_shift($paths);\n\t\t\tarray_shift($paths);\n\t\t}\n\t\t$remotepath = get_absolute_path(join('/', $paths));\n\t\t$path = str_replace('//','/',config('onedrive_root').$remotepath);\n\t\treturn $path;\n\t}\n\n\t//url转id\n\tfunction url2id($url){\n\t\t$urlinfo=parse_url($url);\n\t\tif(stristr($url,'?')){\n\t\t\t$paths = explode('/', rawurldecode($urlinfo['query']));\n\t\t}else{\n\t\t\t$paths = explode('/', rawurldecode($urlinfo['path']));\n\t\t}\n\t\t$paths=array_values($paths);\n\t\t$totalpath = str_replace('//','/',config('onedrive_root').get_absolute_path(join('/', $paths)));\n\t\t$itemid=onedrive::path2id($totalpath);\n\t\treturn $itemid;\n\t}\n\t\n}\n"
  },
  {
    "path": "controller/ImagesController.php",
    "content": "<?php \n\nclass ImagesController{\n\tfunction generateRandomString($length) {\n            $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';\n            $randomString = '';\n            for ($i = 0; $i < $length; $i++) {\n                $randomString .= $characters[rand(0, strlen($characters) - 1)];\n            }\n            return $randomString;\n        }\n\t\n\tfunction index(){\n\t\tif($this->is_image($_FILES[\"file\"]) ){\n\t\t    $filename = $_FILES[\"file\"]['name'];\n\t\t\t$content = file_get_contents( $_FILES[\"file\"]['tmp_name']);\n\t\t\t$remotepath =  'images/'.date('Y/m/d/').$this->generateRandomString(10).'/';\n\t\t\t$remotefile = $remotepath.$filename;\n\t\t\t$result = onedrive::upload(config('onedrive_root').$remotefile, $content);\n\t\t\t\n\t\t\tif($result){\n\t\t\t\t$root = get_absolute_path(dirname($_SERVER['SCRIPT_NAME'])).config('root_path');\n\t\t\t\t$http_type = ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')) ? 'https://' : 'http://';\n\t\t\t\t$url = $_SERVER['HTTP_HOST'].$root.'/'.$remotepath.rawurldecode($filename).((config('root_path') == '?')?'&s':'?s');\n\t\t\t\t$url = $http_type.str_replace('//','/', $url);\n\t\t\t\tview::direct($url);\n\t\t\t}\n\t\t}\n\t\treturn view::load('images/index');\n\t}\n\n\tfunction is_image($file){\n\t\t$config = config('images@base');\n\t\t$ext = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));\n\t\tif(!in_array($ext,$config['exts'])){\n\t\t\treturn false;\n\t\t}\n\t\tif($file['size'] > 10485760 || $file['size'] == 0){\n\t\t\treturn false;\n\t\t}\n\n\t\treturn true;\n\t}\n}\n"
  },
  {
    "path": "controller/IndexController.php",
    "content": "<?php \nclass IndexController{\n\tprivate $url_path;\n\tprivate $name;\n\tprivate $path;\n\tprivate $items;\n\tprivate $time;\n\n\tfunction __construct(){\n\t\t//获取路径和文件名\n\t\t$paths = explode('/', rawurldecode($_GET['path']));\n\t\tif(substr($_SERVER['REQUEST_URI'], -1) != '/'){\n\t\t\t$this->name = array_pop($paths);\n\t\t}\n\t\t$this->url_path = get_absolute_path(join('/', $paths));\n\t\t$this->path = get_absolute_path(config('onedrive_root').$this->url_path);\n\t\t//获取文件夹下所有元素\n\t\t$this->items = $this->items($this->path);\n\t}\n\n\t\n\tfunction index(){\n\t\t//是否404\n\t\t$this->is404();\n\n\t\t$this->is_password();\n\n\t\theader(\"Expires:-1\");\n\t\theader(\"Cache-Control:no_cache\");\n\t\theader(\"Pragma:no-cache\");\n\n\t\tif(!empty($this->name)){//file\n\t\t\treturn $this->file();\n\t\t}else{//dir\n\t\t\treturn $this->dir();\n\t\t}\n\t}\n\n\t//判断是否加密\n\tfunction is_password(){\n\t\tif(empty($this->items['.password'])){\n\t\t\treturn false;\n\t\t}else{\n\t\t\t$this->items['.password']['path'] = get_absolute_path($this->path).'.password';\n \t\t}\n\t\t\n\t\t$password = $this->get_content($this->items['.password']);\n\t\tlist($password) = explode(\"\\n\",$password);\n\t\t$password = trim($password);\n\t\tunset($this->items['.password']);\n\t\tif(!empty($password) && strcmp($password, $_COOKIE[md5($this->path)]) === 0||$_COOKIE['admin'] == md5(config('password').config('refresh_token'))){\n\t\t\treturn true;\n\t\t}\n\n\t\t$this->password($password);\n\t\t\n\t}\n\n\tfunction password($password){\n\t\tif(!empty($_POST['password']) && strcmp($password, $_POST['password']) === 0){\n\t\t\tsetcookie(md5($this->path), $_POST['password']);\n\t\t\treturn true;\n\t\t}\n\t\t$navs = $this->navs();\n\t\techo view::load('password')->with('navs',$navs);\n\t\texit();\n\t}\n\n\t//文件\n\tfunction file(){\n\t\t$item = $this->items[$this->name];\n\t\tif ($item['folder']) {//是文件夹\n\t\t\t$url = $_SERVER['REQUEST_URI'].'/';\n\t\t}elseif(!is_null($_GET['t']) ){//缩略图\n\t\t\t$url = $this->thumbnail($item);\n\t\t}elseif($_SERVER['REQUEST_METHOD'] == 'POST' || !is_null($_GET['s']) ){\n\t\t\treturn $this->show($item);\n\t\t}else{//返回下载链接\n\t\t\t$url = $item['downloadUrl'];\n\t\t}\n\t\theader('Location: '.$url);\n\t}\n\n\n\t\n\t//文件夹\n\tfunction dir(){\n\t\t$root = get_absolute_path(dirname($_SERVER['SCRIPT_NAME'])).config('root_path');\n\t\t$navs = $this->navs();\n\t\t//以'/'拆分路径，并重新连接\n\t\t$except_paths_buffer = explode('/', config('except_path'));\n\t\t$except_path_buffer = get_absolute_path(join('/', $except_paths_buffer));\n\t\t$upload_paths_buffer = explode('/', config('offline')['upload_path']);\n\t\t$upload_path_buffer = get_absolute_path(join('/', $upload_paths_buffer));\n\t\t$online = config('offline')['online'];\n\t\t//定义变脸，表示是否渲染此目录下的文件\n\t\t$iscolorbar = true;\n\t\t//不渲染设置为all，或者当前路径与指定不渲染路径相同，则不渲染。如果设置为空，则渲染\n\t\tif(strcmp(config('except_path'),'all')==0||strcmp(get_absolute_path($this->path), get_absolute_path(config('onedrive_root').$except_path_buffer))==0){\n\t\t\t$iscolorbar = false;\n\t\t}else if(empty(config('except_path'))){\n\t\t\t$iscolorbar = true;\n\t\t}\n\t\t//指定的游客在线上传路径是否和当前路径一致，相同则不渲染。\n\t\tif(strcmp(get_absolute_path($this->path),get_absolute_path(config('onedrive_root').$upload_path_buffer))==0){\n\t\t\t$iscolorbar = false;\n\t\t}\n\t\t\n\t\tif($iscolorbar)\n\t\t{\n\t\t\tif($this->items['index.html']){\n\t\t\t\t$this->items['index.html']['path'] = get_absolute_path($this->path).'index.html';\n\t\t\t\t$index = $this->get_content($this->items['index.html']);\n\t\t\t\theader('Content-type: text/html');\n\t\t\t\techo $index;\n\t\t\t\texit();\n\t\t\t}\n\t\n\t\t\tif($this->items['README.md']){\n\t\t\t\t$this->items['README.md']['path'] = get_absolute_path($this->path).'README.md';\n\t\t\t\t$readme = $this->get_content($this->items['README.md']);\n\t\t\t\t$Parsedown = new Parsedown();\n\t\t\t\t$readme = $Parsedown->text($readme);\n\t\t\t\t//不在列表中展示\n\t\t\t\tunset($this->items['README.md']);\n\t\t\t}\n\t\n\t\t\tif($this->items['HEAD.md']){\n\t\t\t\t$this->items['HEAD.md']['path'] = get_absolute_path($this->path).'HEAD.md';\n\t\t\t\t$head = $this->get_content($this->items['HEAD.md']);\n\t\t\t\t$Parsedown = new Parsedown();\n\t\t\t\t$head = $Parsedown->text($head);\n\t\t\t\t//不在列表中展示\n\t\t\t\tunset($this->items['HEAD.md']);\n\t\t\t}\n\t\t}\n\t\t\n\t\t//在线上传条件，后台开启或者登陆为管理员\n\t\tif(config('offline')['online']||is_login()){\n\t\t\t$manager['online']=true;\n\t\t}\n\t\telse{\n\t\t\t$manager['online']=false;\n\t\t}\n\n\t\tif(config('offline')['offline']||is_login()){\n\t\t\t$manager['offline']=true;\n\t\t}else{\n\t\t\t$manager['offline']=false;\n\t\t}\n\n\t\tif(is_login()){\n\t\t\t$manager['create_folder']=true;\n\t\t}else{\n\t\t\t$manager['create_folder']=false;\n\t\t}\n\t\treturn view::load('list')->with('title', empty(str_replace(\"/\",\"\",urldecode($this->url_path)))?\"根目录\":str_replace(\"/\",\"\",urldecode($this->url_path)))\n\t\t\t\t\t->with('navs', $navs)\n\t\t\t\t\t->with('path',join(\"/\", array_map(\"rawurlencode\", explode(\"/\", $this->url_path)))  )\n\t\t\t\t\t->with('root', $root)\n\t\t\t\t\t->with('items', $this->items)\n\t\t\t\t\t->with('head',$head)\n\t\t\t\t\t->with('readme',$readme)\n\t\t\t\t\t->with('manager',$manager);\n\t}\n\n\tfunction show($item){\n\t\t$root = get_absolute_path(dirname($_SERVER['SCRIPT_NAME'])).(config('root_path')?'?/':'');\n\t\t$ext = strtolower(pathinfo($item['name'], PATHINFO_EXTENSION));\n\t\t$data['title'] = $item['name'];\n\t\t$data['navs'] = $this->navs();\n\t\t$data['item'] = $item;\n\t\t$data['ext'] = $ext;\n\t\t$data['item']['path'] = get_absolute_path($this->path).$this->name;\n\t\t$http_type = ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')) ? 'https://' : 'http://';\n\t\t$uri = onedrive::urlencode(get_absolute_path($this->url_path.'/'.$this->name));\n\t\t$data['url'] = $http_type.$_SERVER['HTTP_HOST'].$root.$uri;\n\t\t\n\n\t\t$show = config('show');\n\t\tforeach($show as $n=>$exts){\n\t\t\tif(in_array($ext,$exts)){\n\t\t\t\treturn view::load('show/'.$n)->with($data);\n\t\t\t}\n\t\t}\n\n\t\theader('Location: '.$item['downloadUrl']);\n\t}\n\t//缩略图\n\tfunction thumbnail($item){\n\t\tif(!empty($_GET['t'])){\n\t\t\tlist($width, $height) = explode('|', $_GET['t']);\n\t\t}else{\n\t\t\t//800 176 96\n\t\t\t$width = $height = 800;\n\t\t}\n\t\t$item['thumb'] = onedrive::thumbnail($this->path.$this->name);\n\t\tlist($item['thumb'],$tmp) = explode('&width=', $item['thumb']);\n\t\t$item['thumb'] .= strpos($item['thumb'], '?')?'&':'?';\n\t\treturn $item['thumb'].\"width={$width}&height={$height}\";\n\t}\n\n\t//文件夹下元素\n\tfunction items($path, $fetch=false){\n\t\t$items = cache::get('dir_'.$this->path, function(){\n\t\t\treturn onedrive::dir($this->path);\n\t\t}, config('cache_expire_time'));\n\t\treturn $items;\n\t}\n\n\tfunction navs(){\n\t\t$root = get_absolute_path(dirname($_SERVER['SCRIPT_NAME'])).config('root_path');\n\t\t$navs['/'] = get_absolute_path($root.'/');\n\t\tforeach(explode('/',$this->url_path) as $v){\n\t\t\tif(empty($v)){\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t$navs[rawurldecode($v)] = end($navs).$v.'/';\n\t\t}\n\t\tif(!empty($this->name)){\n\t\t\t$navs[$this->name] = end($navs).urlencode($this->name);\n\t\t}\n\t\t\n\t\treturn $navs;\n\t}\n\n\tstatic function get_content($item){\n\t\t$content = cache::get('content_'.$item['path'], function() use ($item){\n\t\t\t$resp = fetch::get($item['downloadUrl']);\n\t\t\tif($resp->http_code == 200){\n\t\t\t\treturn $resp->content;\n\t\t\t}\n\t\t}, config('cache_expire_time') );\n\t\treturn $content;\n\t}\n\n\n\n\t//时候404\n\tfunction is404(){\n\t\tif(!empty($this->items[$this->name]) || (empty($this->name) && is_array($this->items)) ){\n\t\t\treturn false;\n\t\t}\n\n\t\thttp_response_code(404);\n\t\tview::load('404')->show();\n\t\tdie();\n\t}\n\n\tfunction __destruct(){\n\t\tif (!function_exists(\"fastcgi_finish_request\")) {\n\t\t\treturn;\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "controller/UploadController.php",
    "content": "<?php \ndefine('VIEW_PATH', ROOT.'view/admin/');\nclass UploadController{\n\n\t//从网站服务器目录上传文件\n\tfunction index(){\n\t\tif($_POST['upload'] == 1){\n\t\t\t$local = realpath($_POST['local']);\n\t\t\t$remotepath = get_absolute_path($_POST['remote']);\n\t\t\tif(is_file($local)){\n\t\t\t\t$this->add_task($local, $remotepath);\n\t\t\t\t$message = \"文件<kbd>\".$local.\"</kbd>已添加到队列\";\n\t\t\t}elseif(is_dir($local)){\n\t\t\t\t$this->scan_dir($local, $remotepath);\n\t\t\t\t$message = \"文件夹<kbd>\".$local.\"</kbd>已添加到队列\";\n\t\t\t}elseif($local == realpath('.')){\n\t\t\t\t$message = \"因为安全原因，程序文件夹根目录不能上传\";\n\t\t\t}else{\n\t\t\t\t$message = \"文件不存在\";\n\t\t\t}\n\t\t\t$request = $this->task_request();\n\t\t\t$request['url'] = substr($request['url'],0,-4).'run';\n\t\t\tfetch::post($request);\n\t\t}elseif(!empty($_POST['begin_task'])){\n\t\t\t$this->task($_POST['begin_task']);\n\t\t}elseif(!empty($_POST['delete_task'])){\n\t\t\tunset($_POST['delete_task']);\n\t\t\tconfig('@upload', (array)$uploads);\n\t\t}elseif(!empty($_POST['empty_uploaded'])){\n\t\t\tconfig('@uploaded', array());\n\t\t}\n\t\t$uploading = config('@upload');\n\t\t$uploaded = array_reverse((array)config('@uploaded'));\n\t\treturn view::load('upload')->with('uploading', $uploading)->with('uploaded', $uploaded)->with('message', $message);\n\t}\n\n\t//扫描文件夹，添加到任务队列\n\tprivate function scan_dir($localpath, $remotepath){\n\t\t$files = scandir($localpath);\n\t\tforeach ($files as $file) {\n\t\t\tif ($file == '.' || $file == '..') {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (is_dir($localpath . '/' . $file)) {\n\t\t        $this->scan_dir($localpath . '/' . $file, $remotepath.$file.'/');\n\t\t    }else{\n\t\t\t    $localfile = realpath($localpath . '/' . $file);\n\t\t\t    $remotefile = $remotepath.$file;\n\t\t\t    $this->add_task($localfile, $remotefile);\n\t\t    }\n\t\t}\n\t}\n\n\tprivate function add_task($localfile, $remotefile){\n\t    $task = array(\n\t\t\t'localfile'=>$localfile,\n\t\t\t'remotepath' => $remotefile,\n\t\t\t'filesize'=>onedrive::_filesize($localfile),\n\t\t\t'upload_type'=>'web',\n\t\t\t'update_time'=>0,\n\t    );\n\n\t    $uploads = (array)config('@upload');\n\t    if(empty($uploads[$remotefile])){\n\t\t    $uploads[$remotefile] = $task;\n\t\t    config('@upload', $uploads);\n\t    }\n\t}\n\n\t//运行队列中的任务\n\tfunction run(){\n\t\t$uploads = (array)config('@upload');\n\t\t$time = time();\n\t\t$runing = 0;\n\t\tforeach($uploads as $task){\n\t\t\tif($time < ($task['update_time']+60) AND $task['type']=='web' ){\n\t\t\t\t$runing = $runing +1;\n\t\t\t}\n\t\t\tif($runing > 5)break;\n\t\t}\n\t\t\n\t\tforeach($uploads as $remotepath=>$task){\n\t\t\tif($time < ($task['update_time']+60) OR !is_array($task) ){\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t$runing = $runing +1;\n\t\t\tprint $remotepath.PHP_EOL;\n\t\t\tfetch::post($this->task_request($remotepath));\n\t\t\tif($runing > 5)break;\n\t\t}\n\n\t\tif(count($uploads) > 5){\n\t\t\tset_time_limit(100);\n\t\t\tsleep(60);\n\t\t\t$request = $this->task_request();\n\t\t\t$request['url'] = substr($request['url'],0,-4).'run';\n\t\t\tfetch::get($request);\n\t\t}\n\t}\n\n\tprivate function task_request($remotepath=''){\n\t\t$request['headers'] = \"Cookie: admin=\".md5(config('password').config('refresh_token')).PHP_EOL;\n\t\t$request['headers'] .= \"Host: \".$_SERVER['HTTP_HOST'];\n\t\t$request['curl_opt']=[CURLOPT_CONNECTTIMEOUT => 1,CURLOPT_TIMEOUT=>1,CURLOPT_FOLLOWLOCATION=>true];\n\t\t$http_type = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 'https://' : 'http://';\n\t\t$request['url'] = $http_type.'127.0.0.1'.get_absolute_path(dirname($_SERVER['PHP_SELF'])).'?/admin/upload/task';\n\t\t$request['post_data'] = 'remotepath='.urlencode($remotepath);\n\t\treturn $request;\n\t}\n\t\n\t//执行任务\n\tfunction task($remotepath=null){\n\t\t$remotepath = is_null($remotepath)?$_POST['remotepath']:$remotepath;\n\t\t//file_put_contents('log.txt',$remotepath.PHP_EOL, FILE_APPEND);\n\t\t$uploads = config('@upload');\n\t\t$task = $uploads[$remotepath];\n\n\t\tif(empty($task)){\n\t\t\treturn;\n\t\t}\n\t\tif($task['filesize'] < 10485760){\n\t\t\t@onedrive::upload($task['remotepath'], file_get_contents($task['localfile']));\n\t\t\tunset($uploads[$remotepath]);\n\t\t\t\t\n\t\t\tconfig('@upload', (array)$uploads);\n\t\t\tconfig($remotepath.'@uploaded','success');\n\t\t}else{\n\t\t\t$uploads[$remotepath]['update_time'] = time();\n\t\t\tconfig('@upload', (array)$uploads);\n\t\t\t$this->upload_large_file($task);\n\t\t}\n\t}\n\n\tfunction upload_large_file($task){\t\t\n\t\t//创建上传会话\n\t\tif(empty($task['url'])){\n\t\t\t$data = onedrive::create_upload_session($task['remotepath']);\n\t\t\tif(!empty($data['uploadUrl'])){\n\t\t\t\t$task['url'] = $data['uploadUrl'];\n\t\t\t\t$task['offset'] = 0;\n\t\t\t\t$task['length'] = 327680;\n\t\t\t\t$task['update_time'] = time();\n\t\t\t\tconfig($task['remotepath'].'@upload',$task);\n\t\t\t}elseif ( $data === false ){\n\t\t\t\t$uploads = config('@upload');\n\t\t\t\tunset($uploads[$task['remotepath']]);\n\t\t\t\tconfig('@upload', $uploads);\n\t\t\t\tconfig($task['remotepath'].'@uploaded','exists');\n\t\t\t}\n\t\t}else{\n\t\t\t$begin_time = microtime(true);\n\t\t\tset_time_limit(0);\n\t\t\t$data = onedrive::upload_session($task['url'], $task['localfile'], $task['offset'], $task['length']);\n\t\t\tif(!empty($data['nextExpectedRanges'])){ \n\t\t\t//继续上传\n\t\t\t\t$upload_time = microtime(true) - $begin_time;\n\t\t\t\t$task['speed'] = $task['length']/$upload_time;\n\t\t\t\t$task['length'] = intval($task['length']/$upload_time/32768*2)*327680;\n\t\t\t\t$task['length'] = ($task['length']>104857600)?104857600:$task['length'];\n\t\t\t\tlist($offset, $filesize) = explode('-',$data['nextExpectedRanges'][0]);\n\t\t\t\t$task['offset'] = intval($offset);\n\t\t\t\t$info['update_time'] = time();\n\t\t\t\tconfig($task['remotepath'].'@upload',$task);\n\t\t\t}elseif(!empty($data['@content.downloadUrl']) || !empty($data['id'])){ \n\t\t\t//上传完成\n\t\t\t\tunset($uploads[$task['remotepath']]);\n\t\t\t\tconfig('@upload', $uploads);\n\t\t\t\tconfig($task['remotepath'].'@uploaded','success');\n\t\t\t\treturn;\n\t\t\t}else{\n\t\t\t//失败，重新获取信息\n\t\t\t\techo \"re get url\";\n\t\t\t\t$data = onedrive::upload_session_status($task['url']);\n\t\t\t\tif(empty($data)|| $info['length']<100){\n\t\t\t\t\tonedrive::delete_upload_session($task['url']);\n\t\t\t\t\tunset($task['url']);\n\t\t\t\t\tconfig($task['remotepath'].'@upload', $task);\n\t\t\t\t}elseif(!empty($data['nextExpectedRanges'])){\n\t\t\t\t\tlist($offset, $filesize) = explode('-',$data['nextExpectedRanges'][0]);\n\t\t\t\t\t$task['offset'] = intval($offset);\n\t\t\t\t\t$task['length'] = $task['length']/1.5;\n\t\t\t\t\tconfig($task['remotepath'].'@upload', $task);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t$request= $this->task_request($task['remotepath']);\n\t\t$resp = fetch::post($request);\n\t\t//var_dump($resp);\n\t}\n\t\n}\n"
  },
  {
    "path": "index.php",
    "content": "<?php\n\nrequire  __DIR__.'/init.php';\n/**\n *    程序安装\n */\n//选择OD国际版?世纪互联版。\nif (config('area')!==\"cn\"){\n\tonedrive::$api_url = 'https://graph.microsoft.com/v1.0';\n\tonedrive::$oauth_url = 'https://login.microsoftonline.com/common/oauth2/v2.0';\n}else{\n\tonedrive::$api_url = \"https://microsoftgraph.chinacloudapi.cn/v1.0\";\n    onedrive::$oauth_url = \"https://login.partner.microsoftonline.cn/common/oauth2/v2.0\";\n}\n\nif( empty( config('refresh_token') ) ){\n\troute::any('/','AdminController@install');\n}\n\n/**\n *    系统后台\n */\nroute::group(function(){\n\treturn ($_COOKIE['admin'] == md5(config('password').config('refresh_token')) );\n},function(){\n\troute::get('/logout','AdminController@logout');\n\troute::any('/admin/','AdminController@settings');\n\troute::any('/admin/cache','AdminController@cache');\n\troute::any('/admin/show','AdminController@show');\n\troute::any('/admin/setpass','AdminController@setpass');\n\troute::any('/admin/images','AdminController@images');\n    route::any('/admin/offline','AdminController@offline');\n\troute::any('/admin/upload','UploadController@index');\n\t//守护进程\n\troute::any('/admin/upload/run','UploadController@run');\n\t//上传进程\n\troute::post('/admin/upload/task','UploadController@task');\n});\n//登陆\nroute::any('/login','AdminController@login');\n\n//onedrive操作\nroute::any('/offline','CommonController@offline');\nroute::any('/onlinefileupload','CommonController@onlinefileupload');\nroute::any('/create_folder','CommonController@create_folder');\nroute::any('/rename','CommonController@rename');\nroute::any('/deleteitems','CommonController@deleteitems');\nroute::any('/search','CommonController@search');\nroute::any('/paste','CommonController@paste');\nroute::any('/upload_url','CommonController@upload_url');\n//跳转到登陆\nroute::any('/admin/',function(){\n\treturn view::direct(get_absolute_path(dirname($_SERVER['SCRIPT_NAME'])).'?/login');\n});\n\ndefine('VIEW_PATH', ROOT.'view/themes/'.(config('style')?config('style'):'material').'/');\n/**\n *    OneImg\n */\n$images = config('images@base');\nif( ($_COOKIE['admin'] == md5(config('password').config('refresh_token')) || $images['public']) ){\n\troute::any('/images','ImagesController@index');\n\tif($images['home']){\n\t\troute::any('/','ImagesController@index');\n\t}\n}\n\n\n/**\n *    列目录\n */\nroute::group(function () {\n\t$hotlink = config('onedrive_hotlink');\n\n\t// 未启用防盗链\n\tif (!$hotlink) {\n\t\treturn true;\n\t}\n\t// referer 不存在\n\tif (!isset($_SERVER['HTTP_REFERER'])) {\n\t\treturn true;\n\t}\n\n\t$referer_domain = get_domain($_SERVER['HTTP_REFERER']);\n\t// 当前域本身\n\tif (str_is(get_domain(), $referer_domain)) {\n\t\treturn true;\n\t}\n\n\t// 白名单\n\t$hotlinks = explode(';', $hotlink);\n\t$referer = false;\n\t\n\tforeach ($hotlinks as $_hotlink) {\n\t\tif (str_is(trim($_hotlink), $referer_domain)) {\n\t\t\t$referer = true;\n\t\t}\n\t}\n\tif (!$referer) {\n\t\theader('HTTP/1.1 403 Forbidden');\n\t}\n\n\treturn $referer;\n}, function() {\n    route::any('{path:#all}','IndexController@index');\n});\n"
  },
  {
    "path": "init.php",
    "content": "<?php\nerror_reporting(E_ALL & ~E_NOTICE);\ndate_default_timezone_set('PRC');\ndefine('TIME', time());\n!defined('ROOT') && define('ROOT', str_replace(\"\\\\\", \"/\", dirname(__FILE__)) . '/');\n\n//__autoload方法\nfunction i_autoload($className) {\n\tif (is_int(strripos($className, '..'))) {\n\t\treturn;\n\t}\n\t$file = ROOT . 'lib/' . $className . '.php';\n\tif (file_exists($file)) {\n\t\tinclude $file;\n\t}\n}\nspl_autoload_register('i_autoload');\n\n!defined('FILE_FLAGS') && define('FILE_FLAGS', LOCK_EX);\n/**\n * config('name');\n * config('name@file');\n * config('@file');\n */\nif (!function_exists('config')) {\n\t!defined('CONFIG_PATH') && define('CONFIG_PATH', ROOT . 'config/');\n\tfunction config($key) {\n\t\tstatic $configs = array();\n\t\tlist($key, $file) = explode('@', $key, 2);\n\t\t$file = empty($file) ? 'base' : $file;\n\n\t\t$file_name = CONFIG_PATH . $file . '.php';\n\t\t//读取配置\n\t\tif (empty($configs[$file]) AND file_exists($file_name)) {\n\t\t\t$configs[$file] = @include $file_name;\n\t\t}\n\t\tif (func_num_args() === 2) {\n\t\t\t$value = func_get_arg(1);\n\t\t\t//写入配置\n\t\t\tif (!empty($key)) {\n\t\t\t\t$configs[$file] = (array) $configs[$file];\n\t\t\t\tif (is_null($value)) {\n\t\t\t\t\tunset($configs[$file][$key]);\n\t\t\t\t} else {\n\t\t\t\t\t$configs[$file][$key] = $value;\n\t\t\t\t}\n\t\t\t\t//cache::clear();\n\t\t\t} else {\n\t\t\t\tif (is_null($value)) {\n\t\t\t\t\treturn unlink($file_name);\n\t\t\t\t} else {\n\t\t\t\t\t$configs[$file] = $value;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfile_put_contents($file_name, \"<?php return \" . var_export($configs[$file], true) . \";\", FILE_FLAGS);\n\t\t} else {\n\t\t\t//返回结果\n\t\t\tif (!empty($key)) {\n\t\t\t\treturn $configs[$file][$key];\n\t\t\t}\n\n\t\t\treturn $configs[$file];\n\t\t}\n\n\t}\n}\n\n// cache\ndefine('CACHE_PATH', ROOT.'cache/');\ncache::$type = empty( config('cache_type') )?'secache':config('cache_type');\n\n\nif (!function_exists('db')) {\n\tfunction db($table) {\n\t\treturn db::table($table);\n\t}\n}\n\nif (!function_exists('view')) {\n\tfunction view($file, $set = null) {\n\t\treturn view::load($file, $set = null);\n\t}\n}\n\nif (!function_exists('_')) {\n\tfunction _($str) {\n\t\treturn htmlspecialchars($str);\n\t}\n}\n\nif (!function_exists('e')) {\n\tfunction e($str) {\n\t\techo $str;\n\t}\n}\n\nif (!function_exists('str_is')) {\n\tfunction str_is($pattern, $value)\n\t{\n\t\tif (is_null($pattern)) {\n\t\t\t$patterns = [];\n\t\t}\n\t\t$patterns = ! is_array($pattern) ? [$pattern] : $pattern;\n\t\tif (empty($patterns)) {\n\t\t\treturn false;\n\t\t}\n\t\tforeach ($patterns as $pattern) {\n\t\t\tif ($pattern == $value) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\t$pattern = preg_quote($pattern, '#');\n\t\t\t$pattern = str_replace('\\*', '.*', $pattern);\n\t\t\tif (preg_match('#^'.$pattern.'\\z#u', $value) === 1) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n}\n\nif (!function_exists('get_domain')) {\n\tfunction get_domain($url=null)\n\t{\n\t\tif (is_null($url)) {\n\t\t\treturn $_SERVER['HTTP_HOST'];\n\t\t}\n\t\treturn strstr(ltrim(strstr($url, '://'), '://'), '/', true);\n\t}\n}\n\nfunction get_absolute_path($path) {\n    $path = str_replace(array('/', '\\\\', '//'), '/', $path);\n    $parts = array_filter(explode('/', $path), 'strlen');\n    $absolutes = array();\n    foreach ($parts as $part) {\n        if ('.' == $part) continue;\n        if ('..' == $part) {\n            array_pop($absolutes);\n        } else {\n            $absolutes[] = $part;\n        }\n    }\n    return str_replace('//','/','/'.implode('/', $absolutes).'/');\n}\n\nfunction is_login(){\n\tif($_COOKIE['admin'] == md5(config('password').config('refresh_token'))){\n\t\treturn true;\n\t}else{\n\t\treturn false;\n\t}\n}\n\n!defined('CONTROLLER_PATH') && define('CONTROLLER_PATH', ROOT.'controller/');\nonedrive::$client_id = config('client_id');\nonedrive::$client_secret = config('client_secret');\nonedrive::$redirect_uri = config('redirect_uri');"
  },
  {
    "path": "lib/Parsedown.php",
    "content": "<?php\n\n#\n#\n# Parsedown\n# http://parsedown.org\n#\n# (c) Emanuil Rusev\n# http://erusev.com\n#\n# For the full license information, view the LICENSE file that was distributed\n# with this source code.\n#\n#\n\nclass Parsedown\n{\n    # ~\n\n    const version = '1.7.1';\n\n    # ~\n\n    function text($text)\n    {\n        # make sure no definitions are set\n        $this->DefinitionData = array();\n\n        # standardize line breaks\n        $text = str_replace(array(\"\\r\\n\", \"\\r\"), \"\\n\", $text);\n\n        # remove surrounding line breaks\n        $text = trim($text, \"\\n\");\n\n        # split text into lines\n        $lines = explode(\"\\n\", $text);\n\n        # iterate through lines to identify blocks\n        $markup = $this->lines($lines);\n\n        # trim line breaks\n        $markup = trim($markup, \"\\n\");\n\n        return $markup;\n    }\n\n    #\n    # Setters\n    #\n\n    function setBreaksEnabled($breaksEnabled)\n    {\n        $this->breaksEnabled = $breaksEnabled;\n\n        return $this;\n    }\n\n    protected $breaksEnabled;\n\n    function setMarkupEscaped($markupEscaped)\n    {\n        $this->markupEscaped = $markupEscaped;\n\n        return $this;\n    }\n\n    protected $markupEscaped;\n\n    function setUrlsLinked($urlsLinked)\n    {\n        $this->urlsLinked = $urlsLinked;\n\n        return $this;\n    }\n\n    protected $urlsLinked = true;\n\n    function setSafeMode($safeMode)\n    {\n        $this->safeMode = (bool) $safeMode;\n\n        return $this;\n    }\n\n    protected $safeMode;\n\n    protected $safeLinksWhitelist = array(\n        'http://',\n        'https://',\n        'ftp://',\n        'ftps://',\n        'mailto:',\n        'data:image/png;base64,',\n        'data:image/gif;base64,',\n        'data:image/jpeg;base64,',\n        'irc:',\n        'ircs:',\n        'git:',\n        'ssh:',\n        'news:',\n        'steam:',\n    );\n\n    #\n    # Lines\n    #\n\n    protected $BlockTypes = array(\n        '#' => array('Header'),\n        '*' => array('Rule', 'List'),\n        '+' => array('List'),\n        '-' => array('SetextHeader', 'Table', 'Rule', 'List'),\n        '0' => array('List'),\n        '1' => array('List'),\n        '2' => array('List'),\n        '3' => array('List'),\n        '4' => array('List'),\n        '5' => array('List'),\n        '6' => array('List'),\n        '7' => array('List'),\n        '8' => array('List'),\n        '9' => array('List'),\n        ':' => array('Table'),\n        '<' => array('Comment', 'Markup'),\n        '=' => array('SetextHeader'),\n        '>' => array('Quote'),\n        '[' => array('Reference'),\n        '_' => array('Rule'),\n        '`' => array('FencedCode'),\n        '|' => array('Table'),\n        '~' => array('FencedCode'),\n    );\n\n    # ~\n\n    protected $unmarkedBlockTypes = array(\n        'Code',\n    );\n\n    #\n    # Blocks\n    #\n\n    protected function lines(array $lines)\n    {\n        $CurrentBlock = null;\n\n        foreach ($lines as $line)\n        {\n            if (chop($line) === '')\n            {\n                if (isset($CurrentBlock))\n                {\n                    $CurrentBlock['interrupted'] = true;\n                }\n\n                continue;\n            }\n\n            if (strpos($line, \"\\t\") !== false)\n            {\n                $parts = explode(\"\\t\", $line);\n\n                $line = $parts[0];\n\n                unset($parts[0]);\n\n                foreach ($parts as $part)\n                {\n                    $shortage = 4 - mb_strlen($line, 'utf-8') % 4;\n\n                    $line .= str_repeat(' ', $shortage);\n                    $line .= $part;\n                }\n            }\n\n            $indent = 0;\n\n            while (isset($line[$indent]) and $line[$indent] === ' ')\n            {\n                $indent ++;\n            }\n\n            $text = $indent > 0 ? substr($line, $indent) : $line;\n\n            # ~\n\n            $Line = array('body' => $line, 'indent' => $indent, 'text' => $text);\n\n            # ~\n\n            if (isset($CurrentBlock['continuable']))\n            {\n                $Block = $this->{'block'.$CurrentBlock['type'].'Continue'}($Line, $CurrentBlock);\n\n                if (isset($Block))\n                {\n                    $CurrentBlock = $Block;\n\n                    continue;\n                }\n                else\n                {\n                    if ($this->isBlockCompletable($CurrentBlock['type']))\n                    {\n                        $CurrentBlock = $this->{'block'.$CurrentBlock['type'].'Complete'}($CurrentBlock);\n                    }\n                }\n            }\n\n            # ~\n\n            $marker = $text[0];\n\n            # ~\n\n            $blockTypes = $this->unmarkedBlockTypes;\n\n            if (isset($this->BlockTypes[$marker]))\n            {\n                foreach ($this->BlockTypes[$marker] as $blockType)\n                {\n                    $blockTypes []= $blockType;\n                }\n            }\n\n            #\n            # ~\n\n            foreach ($blockTypes as $blockType)\n            {\n                $Block = $this->{'block'.$blockType}($Line, $CurrentBlock);\n\n                if (isset($Block))\n                {\n                    $Block['type'] = $blockType;\n\n                    if ( ! isset($Block['identified']))\n                    {\n                        $Blocks []= $CurrentBlock;\n\n                        $Block['identified'] = true;\n                    }\n\n                    if ($this->isBlockContinuable($blockType))\n                    {\n                        $Block['continuable'] = true;\n                    }\n\n                    $CurrentBlock = $Block;\n\n                    continue 2;\n                }\n            }\n\n            # ~\n\n            if (isset($CurrentBlock) and ! isset($CurrentBlock['type']) and ! isset($CurrentBlock['interrupted']))\n            {\n                $CurrentBlock['element']['text'] .= \"\\n\".$text;\n            }\n            else\n            {\n                $Blocks []= $CurrentBlock;\n\n                $CurrentBlock = $this->paragraph($Line);\n\n                $CurrentBlock['identified'] = true;\n            }\n        }\n\n        # ~\n\n        if (isset($CurrentBlock['continuable']) and $this->isBlockCompletable($CurrentBlock['type']))\n        {\n            $CurrentBlock = $this->{'block'.$CurrentBlock['type'].'Complete'}($CurrentBlock);\n        }\n\n        # ~\n\n        $Blocks []= $CurrentBlock;\n\n        unset($Blocks[0]);\n\n        # ~\n\n        $markup = '';\n\n        foreach ($Blocks as $Block)\n        {\n            if (isset($Block['hidden']))\n            {\n                continue;\n            }\n\n            $markup .= \"\\n\";\n            $markup .= isset($Block['markup']) ? $Block['markup'] : $this->element($Block['element']);\n        }\n\n        $markup .= \"\\n\";\n\n        # ~\n\n        return $markup;\n    }\n\n    protected function isBlockContinuable($Type)\n    {\n        return method_exists($this, 'block'.$Type.'Continue');\n    }\n\n    protected function isBlockCompletable($Type)\n    {\n        return method_exists($this, 'block'.$Type.'Complete');\n    }\n\n    #\n    # Code\n\n    protected function blockCode($Line, $Block = null)\n    {\n        if (isset($Block) and ! isset($Block['type']) and ! isset($Block['interrupted']))\n        {\n            return;\n        }\n\n        if ($Line['indent'] >= 4)\n        {\n            $text = substr($Line['body'], 4);\n\n            $Block = array(\n                'element' => array(\n                    'name' => 'pre',\n                    'handler' => 'element',\n                    'text' => array(\n                        'name' => 'code',\n                        'text' => $text,\n                    ),\n                ),\n            );\n\n            return $Block;\n        }\n    }\n\n    protected function blockCodeContinue($Line, $Block)\n    {\n        if ($Line['indent'] >= 4)\n        {\n            if (isset($Block['interrupted']))\n            {\n                $Block['element']['text']['text'] .= \"\\n\";\n\n                unset($Block['interrupted']);\n            }\n\n            $Block['element']['text']['text'] .= \"\\n\";\n\n            $text = substr($Line['body'], 4);\n\n            $Block['element']['text']['text'] .= $text;\n\n            return $Block;\n        }\n    }\n\n    protected function blockCodeComplete($Block)\n    {\n        $text = $Block['element']['text']['text'];\n\n        $Block['element']['text']['text'] = $text;\n\n        return $Block;\n    }\n\n    #\n    # Comment\n\n    protected function blockComment($Line)\n    {\n        if ($this->markupEscaped or $this->safeMode)\n        {\n            return;\n        }\n\n        if (isset($Line['text'][3]) and $Line['text'][3] === '-' and $Line['text'][2] === '-' and $Line['text'][1] === '!')\n        {\n            $Block = array(\n                'markup' => $Line['body'],\n            );\n\n            if (preg_match('/-->$/', $Line['text']))\n            {\n                $Block['closed'] = true;\n            }\n\n            return $Block;\n        }\n    }\n\n    protected function blockCommentContinue($Line, array $Block)\n    {\n        if (isset($Block['closed']))\n        {\n            return;\n        }\n\n        $Block['markup'] .= \"\\n\" . $Line['body'];\n\n        if (preg_match('/-->$/', $Line['text']))\n        {\n            $Block['closed'] = true;\n        }\n\n        return $Block;\n    }\n\n    #\n    # Fenced Code\n\n    protected function blockFencedCode($Line)\n    {\n        if (preg_match('/^['.$Line['text'][0].']{3,}[ ]*([^`]+)?[ ]*$/', $Line['text'], $matches))\n        {\n            $Element = array(\n                'name' => 'code',\n                'text' => '',\n            );\n\n            if (isset($matches[1]))\n            {\n                $class = 'language-'.$matches[1];\n\n                $Element['attributes'] = array(\n                    'class' => $class,\n                );\n            }\n\n            $Block = array(\n                'char' => $Line['text'][0],\n                'element' => array(\n                    'name' => 'pre',\n                    'handler' => 'element',\n                    'text' => $Element,\n                ),\n            );\n\n            return $Block;\n        }\n    }\n\n    protected function blockFencedCodeContinue($Line, $Block)\n    {\n        if (isset($Block['complete']))\n        {\n            return;\n        }\n\n        if (isset($Block['interrupted']))\n        {\n            $Block['element']['text']['text'] .= \"\\n\";\n\n            unset($Block['interrupted']);\n        }\n\n        if (preg_match('/^'.$Block['char'].'{3,}[ ]*$/', $Line['text']))\n        {\n            $Block['element']['text']['text'] = substr($Block['element']['text']['text'], 1);\n\n            $Block['complete'] = true;\n\n            return $Block;\n        }\n\n        $Block['element']['text']['text'] .= \"\\n\".$Line['body'];\n\n        return $Block;\n    }\n\n    protected function blockFencedCodeComplete($Block)\n    {\n        $text = $Block['element']['text']['text'];\n\n        $Block['element']['text']['text'] = $text;\n\n        return $Block;\n    }\n\n    #\n    # Header\n\n    protected function blockHeader($Line)\n    {\n        if (isset($Line['text'][1]))\n        {\n            $level = 1;\n\n            while (isset($Line['text'][$level]) and $Line['text'][$level] === '#')\n            {\n                $level ++;\n            }\n\n            if ($level > 6)\n            {\n                return;\n            }\n\n            $text = trim($Line['text'], '# ');\n\n            $Block = array(\n                'element' => array(\n                    'name' => 'h' . min(6, $level),\n                    'text' => $text,\n                    'handler' => 'line',\n                ),\n            );\n\n            return $Block;\n        }\n    }\n\n    #\n    # List\n\n    protected function blockList($Line)\n    {\n        list($name, $pattern) = $Line['text'][0] <= '-' ? array('ul', '[*+-]') : array('ol', '[0-9]+[.]');\n\n        if (preg_match('/^('.$pattern.'[ ]+)(.*)/', $Line['text'], $matches))\n        {\n            $Block = array(\n                'indent' => $Line['indent'],\n                'pattern' => $pattern,\n                'element' => array(\n                    'name' => $name,\n                    'handler' => 'elements',\n                ),\n            );\n\n            if($name === 'ol')\n            {\n                $listStart = stristr($matches[0], '.', true);\n\n                if($listStart !== '1')\n                {\n                    $Block['element']['attributes'] = array('start' => $listStart);\n                }\n            }\n\n            $Block['li'] = array(\n                'name' => 'li',\n                'handler' => 'li',\n                'text' => array(\n                    $matches[2],\n                ),\n            );\n\n            $Block['element']['text'] []= & $Block['li'];\n\n            return $Block;\n        }\n    }\n\n    protected function blockListContinue($Line, array $Block)\n    {\n        if ($Block['indent'] === $Line['indent'] and preg_match('/^'.$Block['pattern'].'(?:[ ]+(.*)|$)/', $Line['text'], $matches))\n        {\n            if (isset($Block['interrupted']))\n            {\n                $Block['li']['text'] []= '';\n\n                $Block['loose'] = true;\n\n                unset($Block['interrupted']);\n            }\n\n            unset($Block['li']);\n\n            $text = isset($matches[1]) ? $matches[1] : '';\n\n            $Block['li'] = array(\n                'name' => 'li',\n                'handler' => 'li',\n                'text' => array(\n                    $text,\n                ),\n            );\n\n            $Block['element']['text'] []= & $Block['li'];\n\n            return $Block;\n        }\n\n        if ($Line['text'][0] === '[' and $this->blockReference($Line))\n        {\n            return $Block;\n        }\n\n        if ( ! isset($Block['interrupted']))\n        {\n            $text = preg_replace('/^[ ]{0,4}/', '', $Line['body']);\n\n            $Block['li']['text'] []= $text;\n\n            return $Block;\n        }\n\n        if ($Line['indent'] > 0)\n        {\n            $Block['li']['text'] []= '';\n\n            $text = preg_replace('/^[ ]{0,4}/', '', $Line['body']);\n\n            $Block['li']['text'] []= $text;\n\n            unset($Block['interrupted']);\n\n            return $Block;\n        }\n    }\n\n    protected function blockListComplete(array $Block)\n    {\n        if (isset($Block['loose']))\n        {\n            foreach ($Block['element']['text'] as &$li)\n            {\n                if (end($li['text']) !== '')\n                {\n                    $li['text'] []= '';\n                }\n            }\n        }\n\n        return $Block;\n    }\n\n    #\n    # Quote\n\n    protected function blockQuote($Line)\n    {\n        if (preg_match('/^>[ ]?(.*)/', $Line['text'], $matches))\n        {\n            $Block = array(\n                'element' => array(\n                    'name' => 'blockquote',\n                    'handler' => 'lines',\n                    'text' => (array) $matches[1],\n                ),\n            );\n\n            return $Block;\n        }\n    }\n\n    protected function blockQuoteContinue($Line, array $Block)\n    {\n        if ($Line['text'][0] === '>' and preg_match('/^>[ ]?(.*)/', $Line['text'], $matches))\n        {\n            if (isset($Block['interrupted']))\n            {\n                $Block['element']['text'] []= '';\n\n                unset($Block['interrupted']);\n            }\n\n            $Block['element']['text'] []= $matches[1];\n\n            return $Block;\n        }\n\n        if ( ! isset($Block['interrupted']))\n        {\n            $Block['element']['text'] []= $Line['text'];\n\n            return $Block;\n        }\n    }\n\n    #\n    # Rule\n\n    protected function blockRule($Line)\n    {\n        if (preg_match('/^(['.$Line['text'][0].'])([ ]*\\1){2,}[ ]*$/', $Line['text']))\n        {\n            $Block = array(\n                'element' => array(\n                    'name' => 'hr'\n                ),\n            );\n\n            return $Block;\n        }\n    }\n\n    #\n    # Setext\n\n    protected function blockSetextHeader($Line, array $Block = null)\n    {\n        if ( ! isset($Block) or isset($Block['type']) or isset($Block['interrupted']))\n        {\n            return;\n        }\n\n        if (chop($Line['text'], $Line['text'][0]) === '')\n        {\n            $Block['element']['name'] = $Line['text'][0] === '=' ? 'h1' : 'h2';\n\n            return $Block;\n        }\n    }\n\n    #\n    # Markup\n\n    protected function blockMarkup($Line)\n    {\n        if ($this->markupEscaped or $this->safeMode)\n        {\n            return;\n        }\n\n        if (preg_match('/^<(\\w[\\w-]*)(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*(\\/)?>/', $Line['text'], $matches))\n        {\n            $element = strtolower($matches[1]);\n\n            if (in_array($element, $this->textLevelElements))\n            {\n                return;\n            }\n\n            $Block = array(\n                'name' => $matches[1],\n                'depth' => 0,\n                'markup' => $Line['text'],\n            );\n\n            $length = strlen($matches[0]);\n\n            $remainder = substr($Line['text'], $length);\n\n            if (trim($remainder) === '')\n            {\n                if (isset($matches[2]) or in_array($matches[1], $this->voidElements))\n                {\n                    $Block['closed'] = true;\n\n                    $Block['void'] = true;\n                }\n            }\n            else\n            {\n                if (isset($matches[2]) or in_array($matches[1], $this->voidElements))\n                {\n                    return;\n                }\n\n                if (preg_match('/<\\/'.$matches[1].'>[ ]*$/i', $remainder))\n                {\n                    $Block['closed'] = true;\n                }\n            }\n\n            return $Block;\n        }\n    }\n\n    protected function blockMarkupContinue($Line, array $Block)\n    {\n        if (isset($Block['closed']))\n        {\n            return;\n        }\n\n        if (preg_match('/^<'.$Block['name'].'(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*>/i', $Line['text'])) # open\n        {\n            $Block['depth'] ++;\n        }\n\n        if (preg_match('/(.*?)<\\/'.$Block['name'].'>[ ]*$/i', $Line['text'], $matches)) # close\n        {\n            if ($Block['depth'] > 0)\n            {\n                $Block['depth'] --;\n            }\n            else\n            {\n                $Block['closed'] = true;\n            }\n        }\n\n        if (isset($Block['interrupted']))\n        {\n            $Block['markup'] .= \"\\n\";\n\n            unset($Block['interrupted']);\n        }\n\n        $Block['markup'] .= \"\\n\".$Line['body'];\n\n        return $Block;\n    }\n\n    #\n    # Reference\n\n    protected function blockReference($Line)\n    {\n        if (preg_match('/^\\[(.+?)\\]:[ ]*<?(\\S+?)>?(?:[ ]+[\"\\'(](.+)[\"\\')])?[ ]*$/', $Line['text'], $matches))\n        {\n            $id = strtolower($matches[1]);\n\n            $Data = array(\n                'url' => $matches[2],\n                'title' => null,\n            );\n\n            if (isset($matches[3]))\n            {\n                $Data['title'] = $matches[3];\n            }\n\n            $this->DefinitionData['Reference'][$id] = $Data;\n\n            $Block = array(\n                'hidden' => true,\n            );\n\n            return $Block;\n        }\n    }\n\n    #\n    # Table\n\n    protected function blockTable($Line, array $Block = null)\n    {\n        if ( ! isset($Block) or isset($Block['type']) or isset($Block['interrupted']))\n        {\n            return;\n        }\n\n        if (strpos($Block['element']['text'], '|') !== false and chop($Line['text'], ' -:|') === '')\n        {\n            $alignments = array();\n\n            $divider = $Line['text'];\n\n            $divider = trim($divider);\n            $divider = trim($divider, '|');\n\n            $dividerCells = explode('|', $divider);\n\n            foreach ($dividerCells as $dividerCell)\n            {\n                $dividerCell = trim($dividerCell);\n\n                if ($dividerCell === '')\n                {\n                    continue;\n                }\n\n                $alignment = null;\n\n                if ($dividerCell[0] === ':')\n                {\n                    $alignment = 'left';\n                }\n\n                if (substr($dividerCell, - 1) === ':')\n                {\n                    $alignment = $alignment === 'left' ? 'center' : 'right';\n                }\n\n                $alignments []= $alignment;\n            }\n\n            # ~\n\n            $HeaderElements = array();\n\n            $header = $Block['element']['text'];\n\n            $header = trim($header);\n            $header = trim($header, '|');\n\n            $headerCells = explode('|', $header);\n\n            foreach ($headerCells as $index => $headerCell)\n            {\n                $headerCell = trim($headerCell);\n\n                $HeaderElement = array(\n                    'name' => 'th',\n                    'text' => $headerCell,\n                    'handler' => 'line',\n                );\n\n                if (isset($alignments[$index]))\n                {\n                    $alignment = $alignments[$index];\n\n                    $HeaderElement['attributes'] = array(\n                        'style' => 'text-align: '.$alignment.';',\n                    );\n                }\n\n                $HeaderElements []= $HeaderElement;\n            }\n\n            # ~\n\n            $Block = array(\n                'alignments' => $alignments,\n                'identified' => true,\n                'element' => array(\n                    'name' => 'table',\n                    'handler' => 'elements',\n                ),\n            );\n\n            $Block['element']['text'] []= array(\n                'name' => 'thead',\n                'handler' => 'elements',\n            );\n\n            $Block['element']['text'] []= array(\n                'name' => 'tbody',\n                'handler' => 'elements',\n                'text' => array(),\n            );\n\n            $Block['element']['text'][0]['text'] []= array(\n                'name' => 'tr',\n                'handler' => 'elements',\n                'text' => $HeaderElements,\n            );\n\n            return $Block;\n        }\n    }\n\n    protected function blockTableContinue($Line, array $Block)\n    {\n        if (isset($Block['interrupted']))\n        {\n            return;\n        }\n\n        if ($Line['text'][0] === '|' or strpos($Line['text'], '|'))\n        {\n            $Elements = array();\n\n            $row = $Line['text'];\n\n            $row = trim($row);\n            $row = trim($row, '|');\n\n            preg_match_all('/(?:(\\\\\\\\[|])|[^|`]|`[^`]+`|`)+/', $row, $matches);\n\n            foreach ($matches[0] as $index => $cell)\n            {\n                $cell = trim($cell);\n\n                $Element = array(\n                    'name' => 'td',\n                    'handler' => 'line',\n                    'text' => $cell,\n                );\n\n                if (isset($Block['alignments'][$index]))\n                {\n                    $Element['attributes'] = array(\n                        'style' => 'text-align: '.$Block['alignments'][$index].';',\n                    );\n                }\n\n                $Elements []= $Element;\n            }\n\n            $Element = array(\n                'name' => 'tr',\n                'handler' => 'elements',\n                'text' => $Elements,\n            );\n\n            $Block['element']['text'][1]['text'] []= $Element;\n\n            return $Block;\n        }\n    }\n\n    #\n    # ~\n    #\n\n    protected function paragraph($Line)\n    {\n        $Block = array(\n            'element' => array(\n                'name' => 'p',\n                'text' => $Line['text'],\n                'handler' => 'line',\n            ),\n        );\n\n        return $Block;\n    }\n\n    #\n    # Inline Elements\n    #\n\n    protected $InlineTypes = array(\n        '\"' => array('SpecialCharacter'),\n        '!' => array('Image'),\n        '&' => array('SpecialCharacter'),\n        '*' => array('Emphasis'),\n        ':' => array('Url'),\n        '<' => array('UrlTag', 'EmailTag', 'Markup', 'SpecialCharacter'),\n        '>' => array('SpecialCharacter'),\n        '[' => array('Link'),\n        '_' => array('Emphasis'),\n        '`' => array('Code'),\n        '~' => array('Strikethrough'),\n        '\\\\' => array('EscapeSequence'),\n    );\n\n    # ~\n\n    protected $inlineMarkerList = '!\"*_&[:<>`~\\\\';\n\n    #\n    # ~\n    #\n\n    public function line($text, $nonNestables=array())\n    {\n        $markup = '';\n\n        # $excerpt is based on the first occurrence of a marker\n\n        while ($excerpt = strpbrk($text, $this->inlineMarkerList))\n        {\n            $marker = $excerpt[0];\n\n            $markerPosition = strpos($text, $marker);\n\n            $Excerpt = array('text' => $excerpt, 'context' => $text);\n\n            foreach ($this->InlineTypes[$marker] as $inlineType)\n            {\n                # check to see if the current inline type is nestable in the current context\n\n                if ( ! empty($nonNestables) and in_array($inlineType, $nonNestables))\n                {\n                    continue;\n                }\n\n                $Inline = $this->{'inline'.$inlineType}($Excerpt);\n\n                if ( ! isset($Inline))\n                {\n                    continue;\n                }\n\n                # makes sure that the inline belongs to \"our\" marker\n\n                if (isset($Inline['position']) and $Inline['position'] > $markerPosition)\n                {\n                    continue;\n                }\n\n                # sets a default inline position\n\n                if ( ! isset($Inline['position']))\n                {\n                    $Inline['position'] = $markerPosition;\n                }\n\n                # cause the new element to 'inherit' our non nestables\n\n                foreach ($nonNestables as $non_nestable)\n                {\n                    $Inline['element']['nonNestables'][] = $non_nestable;\n                }\n\n                # the text that comes before the inline\n                $unmarkedText = substr($text, 0, $Inline['position']);\n\n                # compile the unmarked text\n                $markup .= $this->unmarkedText($unmarkedText);\n\n                # compile the inline\n                $markup .= isset($Inline['markup']) ? $Inline['markup'] : $this->element($Inline['element']);\n\n                # remove the examined text\n                $text = substr($text, $Inline['position'] + $Inline['extent']);\n\n                continue 2;\n            }\n\n            # the marker does not belong to an inline\n\n            $unmarkedText = substr($text, 0, $markerPosition + 1);\n\n            $markup .= $this->unmarkedText($unmarkedText);\n\n            $text = substr($text, $markerPosition + 1);\n        }\n\n        $markup .= $this->unmarkedText($text);\n\n        return $markup;\n    }\n\n    #\n    # ~\n    #\n\n    protected function inlineCode($Excerpt)\n    {\n        $marker = $Excerpt['text'][0];\n\n        if (preg_match('/^('.$marker.'+)[ ]*(.+?)[ ]*(?<!'.$marker.')\\1(?!'.$marker.')/s', $Excerpt['text'], $matches))\n        {\n            $text = $matches[2];\n            $text = preg_replace(\"/[ ]*\\n/\", ' ', $text);\n\n            return array(\n                'extent' => strlen($matches[0]),\n                'element' => array(\n                    'name' => 'code',\n                    'text' => $text,\n                ),\n            );\n        }\n    }\n\n    protected function inlineEmailTag($Excerpt)\n    {\n        if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<((mailto:)?\\S+?@\\S+?)>/i', $Excerpt['text'], $matches))\n        {\n            $url = $matches[1];\n\n            if ( ! isset($matches[2]))\n            {\n                $url = 'mailto:' . $url;\n            }\n\n            return array(\n                'extent' => strlen($matches[0]),\n                'element' => array(\n                    'name' => 'a',\n                    'text' => $matches[1],\n                    'attributes' => array(\n                        'href' => $url,\n                    ),\n                ),\n            );\n        }\n    }\n\n    protected function inlineEmphasis($Excerpt)\n    {\n        if ( ! isset($Excerpt['text'][1]))\n        {\n            return;\n        }\n\n        $marker = $Excerpt['text'][0];\n\n        if ($Excerpt['text'][1] === $marker and preg_match($this->StrongRegex[$marker], $Excerpt['text'], $matches))\n        {\n            $emphasis = 'strong';\n        }\n        elseif (preg_match($this->EmRegex[$marker], $Excerpt['text'], $matches))\n        {\n            $emphasis = 'em';\n        }\n        else\n        {\n            return;\n        }\n\n        return array(\n            'extent' => strlen($matches[0]),\n            'element' => array(\n                'name' => $emphasis,\n                'handler' => 'line',\n                'text' => $matches[1],\n            ),\n        );\n    }\n\n    protected function inlineEscapeSequence($Excerpt)\n    {\n        if (isset($Excerpt['text'][1]) and in_array($Excerpt['text'][1], $this->specialCharacters))\n        {\n            return array(\n                'markup' => $Excerpt['text'][1],\n                'extent' => 2,\n            );\n        }\n    }\n\n    protected function inlineImage($Excerpt)\n    {\n        if ( ! isset($Excerpt['text'][1]) or $Excerpt['text'][1] !== '[')\n        {\n            return;\n        }\n\n        $Excerpt['text']= substr($Excerpt['text'], 1);\n\n        $Link = $this->inlineLink($Excerpt);\n\n        if ($Link === null)\n        {\n            return;\n        }\n\n        $Inline = array(\n            'extent' => $Link['extent'] + 1,\n            'element' => array(\n                'name' => 'img',\n                'attributes' => array(\n                    'src' => $Link['element']['attributes']['href'],\n                    'alt' => $Link['element']['text'],\n                ),\n            ),\n        );\n\n        $Inline['element']['attributes'] += $Link['element']['attributes'];\n\n        unset($Inline['element']['attributes']['href']);\n\n        return $Inline;\n    }\n\n    protected function inlineLink($Excerpt)\n    {\n        $Element = array(\n            'name' => 'a',\n            'handler' => 'line',\n            'nonNestables' => array('Url', 'Link'),\n            'text' => null,\n            'attributes' => array(\n                'href' => null,\n                'title' => null,\n            ),\n        );\n\n        $extent = 0;\n\n        $remainder = $Excerpt['text'];\n\n        if (preg_match('/\\[((?:[^][]++|(?R))*+)\\]/', $remainder, $matches))\n        {\n            $Element['text'] = $matches[1];\n\n            $extent += strlen($matches[0]);\n\n            $remainder = substr($remainder, $extent);\n        }\n        else\n        {\n            return;\n        }\n\n        if (preg_match('/^[(]\\s*+((?:[^ ()]++|[(][^ )]+[)])++)(?:[ ]+(\"[^\"]*\"|\\'[^\\']*\\'))?\\s*[)]/', $remainder, $matches))\n        {\n            $Element['attributes']['href'] = $matches[1];\n\n            if (isset($matches[2]))\n            {\n                $Element['attributes']['title'] = substr($matches[2], 1, - 1);\n            }\n\n            $extent += strlen($matches[0]);\n        }\n        else\n        {\n            if (preg_match('/^\\s*\\[(.*?)\\]/', $remainder, $matches))\n            {\n                $definition = strlen($matches[1]) ? $matches[1] : $Element['text'];\n                $definition = strtolower($definition);\n\n                $extent += strlen($matches[0]);\n            }\n            else\n            {\n                $definition = strtolower($Element['text']);\n            }\n\n            if ( ! isset($this->DefinitionData['Reference'][$definition]))\n            {\n                return;\n            }\n\n            $Definition = $this->DefinitionData['Reference'][$definition];\n\n            $Element['attributes']['href'] = $Definition['url'];\n            $Element['attributes']['title'] = $Definition['title'];\n        }\n\n        return array(\n            'extent' => $extent,\n            'element' => $Element,\n        );\n    }\n\n    protected function inlineMarkup($Excerpt)\n    {\n        if ($this->markupEscaped or $this->safeMode or strpos($Excerpt['text'], '>') === false)\n        {\n            return;\n        }\n\n        if ($Excerpt['text'][1] === '/' and preg_match('/^<\\/\\w[\\w-]*[ ]*>/s', $Excerpt['text'], $matches))\n        {\n            return array(\n                'markup' => $matches[0],\n                'extent' => strlen($matches[0]),\n            );\n        }\n\n        if ($Excerpt['text'][1] === '!' and preg_match('/^<!---?[^>-](?:-?[^-])*-->/s', $Excerpt['text'], $matches))\n        {\n            return array(\n                'markup' => $matches[0],\n                'extent' => strlen($matches[0]),\n            );\n        }\n\n        if ($Excerpt['text'][1] !== ' ' and preg_match('/^<\\w[\\w-]*(?:[ ]*'.$this->regexHtmlAttribute.')*[ ]*\\/?>/s', $Excerpt['text'], $matches))\n        {\n            return array(\n                'markup' => $matches[0],\n                'extent' => strlen($matches[0]),\n            );\n        }\n    }\n\n    protected function inlineSpecialCharacter($Excerpt)\n    {\n        if ($Excerpt['text'][0] === '&' and ! preg_match('/^&#?\\w+;/', $Excerpt['text']))\n        {\n            return array(\n                'markup' => '&amp;',\n                'extent' => 1,\n            );\n        }\n\n        $SpecialCharacter = array('>' => 'gt', '<' => 'lt', '\"' => 'quot');\n\n        if (isset($SpecialCharacter[$Excerpt['text'][0]]))\n        {\n            return array(\n                'markup' => '&'.$SpecialCharacter[$Excerpt['text'][0]].';',\n                'extent' => 1,\n            );\n        }\n    }\n\n    protected function inlineStrikethrough($Excerpt)\n    {\n        if ( ! isset($Excerpt['text'][1]))\n        {\n            return;\n        }\n\n        if ($Excerpt['text'][1] === '~' and preg_match('/^~~(?=\\S)(.+?)(?<=\\S)~~/', $Excerpt['text'], $matches))\n        {\n            return array(\n                'extent' => strlen($matches[0]),\n                'element' => array(\n                    'name' => 'del',\n                    'text' => $matches[1],\n                    'handler' => 'line',\n                ),\n            );\n        }\n    }\n\n    protected function inlineUrl($Excerpt)\n    {\n        if ($this->urlsLinked !== true or ! isset($Excerpt['text'][2]) or $Excerpt['text'][2] !== '/')\n        {\n            return;\n        }\n\n        if (preg_match('/\\bhttps?:[\\/]{2}[^\\s<]+\\b\\/*/ui', $Excerpt['context'], $matches, PREG_OFFSET_CAPTURE))\n        {\n            $url = $matches[0][0];\n\n            $Inline = array(\n                'extent' => strlen($matches[0][0]),\n                'position' => $matches[0][1],\n                'element' => array(\n                    'name' => 'a',\n                    'text' => $url,\n                    'attributes' => array(\n                        'href' => $url,\n                    ),\n                ),\n            );\n\n            return $Inline;\n        }\n    }\n\n    protected function inlineUrlTag($Excerpt)\n    {\n        if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<(\\w+:\\/{2}[^ >]+)>/i', $Excerpt['text'], $matches))\n        {\n            $url = $matches[1];\n\n            return array(\n                'extent' => strlen($matches[0]),\n                'element' => array(\n                    'name' => 'a',\n                    'text' => $url,\n                    'attributes' => array(\n                        'href' => $url,\n                    ),\n                ),\n            );\n        }\n    }\n\n    # ~\n\n    protected function unmarkedText($text)\n    {\n        if ($this->breaksEnabled)\n        {\n            $text = preg_replace('/[ ]*\\n/', \"<br />\\n\", $text);\n        }\n        else\n        {\n            $text = preg_replace('/(?:[ ][ ]+|[ ]*\\\\\\\\)\\n/', \"<br />\\n\", $text);\n            $text = str_replace(\" \\n\", \"\\n\", $text);\n        }\n\n        return $text;\n    }\n\n    #\n    # Handlers\n    #\n\n    protected function element(array $Element)\n    {\n        if ($this->safeMode)\n        {\n            $Element = $this->sanitiseElement($Element);\n        }\n\n        $markup = '<'.$Element['name'];\n\n        if (isset($Element['attributes']))\n        {\n            foreach ($Element['attributes'] as $name => $value)\n            {\n                if ($value === null)\n                {\n                    continue;\n                }\n\n                $markup .= ' '.$name.'=\"'.self::escape($value).'\"';\n            }\n        }\n\n        if (isset($Element['text']))\n        {\n            $markup .= '>';\n\n            if (!isset($Element['nonNestables'])) \n            {\n                $Element['nonNestables'] = array();\n            }\n\n            if (isset($Element['handler']))\n            {\n                $markup .= $this->{$Element['handler']}($Element['text'], $Element['nonNestables']);\n            }\n            else\n            {\n                $markup .= self::escape($Element['text'], true);\n            }\n\n            $markup .= '</'.$Element['name'].'>';\n        }\n        else\n        {\n            $markup .= ' />';\n        }\n\n        return $markup;\n    }\n\n    protected function elements(array $Elements)\n    {\n        $markup = '';\n\n        foreach ($Elements as $Element)\n        {\n            $markup .= \"\\n\" . $this->element($Element);\n        }\n\n        $markup .= \"\\n\";\n\n        return $markup;\n    }\n\n    # ~\n\n    protected function li($lines)\n    {\n        $markup = $this->lines($lines);\n\n        $trimmedMarkup = trim($markup);\n\n        if ( ! in_array('', $lines) and substr($trimmedMarkup, 0, 3) === '<p>')\n        {\n            $markup = $trimmedMarkup;\n            $markup = substr($markup, 3);\n\n            $position = strpos($markup, \"</p>\");\n\n            $markup = substr_replace($markup, '', $position, 4);\n        }\n\n        return $markup;\n    }\n\n    #\n    # Deprecated Methods\n    #\n\n    function parse($text)\n    {\n        $markup = $this->text($text);\n\n        return $markup;\n    }\n\n    protected function sanitiseElement(array $Element)\n    {\n        static $goodAttribute = '/^[a-zA-Z0-9][a-zA-Z0-9-_]*+$/';\n        static $safeUrlNameToAtt  = array(\n            'a'   => 'href',\n            'img' => 'src',\n        );\n\n        if (isset($safeUrlNameToAtt[$Element['name']]))\n        {\n            $Element = $this->filterUnsafeUrlInAttribute($Element, $safeUrlNameToAtt[$Element['name']]);\n        }\n\n        if ( ! empty($Element['attributes']))\n        {\n            foreach ($Element['attributes'] as $att => $val)\n            {\n                # filter out badly parsed attribute\n                if ( ! preg_match($goodAttribute, $att))\n                {\n                    unset($Element['attributes'][$att]);\n                }\n                # dump onevent attribute\n                elseif (self::striAtStart($att, 'on'))\n                {\n                    unset($Element['attributes'][$att]);\n                }\n            }\n        }\n\n        return $Element;\n    }\n\n    protected function filterUnsafeUrlInAttribute(array $Element, $attribute)\n    {\n        foreach ($this->safeLinksWhitelist as $scheme)\n        {\n            if (self::striAtStart($Element['attributes'][$attribute], $scheme))\n            {\n                return $Element;\n            }\n        }\n\n        $Element['attributes'][$attribute] = str_replace(':', '%3A', $Element['attributes'][$attribute]);\n\n        return $Element;\n    }\n\n    #\n    # Static Methods\n    #\n\n    protected static function escape($text, $allowQuotes = false)\n    {\n        return htmlspecialchars($text, $allowQuotes ? ENT_NOQUOTES : ENT_QUOTES, 'UTF-8');\n    }\n\n    protected static function striAtStart($string, $needle)\n    {\n        $len = strlen($needle);\n\n        if ($len > strlen($string))\n        {\n            return false;\n        }\n        else\n        {\n            return strtolower(substr($string, 0, $len)) === strtolower($needle);\n        }\n    }\n\n    static function instance($name = 'default')\n    {\n        if (isset(self::$instances[$name]))\n        {\n            return self::$instances[$name];\n        }\n\n        $instance = new static();\n\n        self::$instances[$name] = $instance;\n\n        return $instance;\n    }\n\n    private static $instances = array();\n\n    #\n    # Fields\n    #\n\n    protected $DefinitionData;\n\n    #\n    # Read-Only\n\n    protected $specialCharacters = array(\n        '\\\\', '`', '*', '_', '{', '}', '[', ']', '(', ')', '>', '#', '+', '-', '.', '!', '|',\n    );\n\n    protected $StrongRegex = array(\n        '*' => '/^[*]{2}((?:\\\\\\\\\\*|[^*]|[*][^*]*[*])+?)[*]{2}(?![*])/s',\n        '_' => '/^__((?:\\\\\\\\_|[^_]|_[^_]*_)+?)__(?!_)/us',\n    );\n\n    protected $EmRegex = array(\n        '*' => '/^[*]((?:\\\\\\\\\\*|[^*]|[*][*][^*]+?[*][*])+?)[*](?![*])/s',\n        '_' => '/^_((?:\\\\\\\\_|[^_]|__[^_]*__)+?)_(?!_)\\b/us',\n    );\n\n    protected $regexHtmlAttribute = '[a-zA-Z_:][\\w:.-]*(?:\\s*=\\s*(?:[^\"\\'=<>`\\s]+|\"[^\"]*\"|\\'[^\\']*\\'))?';\n\n    protected $voidElements = array(\n        'area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source',\n    );\n\n    protected $textLevelElements = array(\n        'a', 'br', 'bdo', 'abbr', 'blink', 'nextid', 'acronym', 'basefont',\n        'b', 'em', 'big', 'cite', 'small', 'spacer', 'listing',\n        'i', 'rp', 'del', 'code',          'strike', 'marquee',\n        'q', 'rt', 'ins', 'font',          'strong',\n        's', 'tt', 'kbd', 'mark',\n        'u', 'xm', 'sub', 'nobr',\n                   'sup', 'ruby',\n                   'var', 'span',\n                   'wbr', 'time',\n    );\n}\n"
  },
  {
    "path": "lib/cache/filecache_.php",
    "content": "<?php \nclass filecache_{\n\tprivate $cache_path;\n\t\n\tfunction __construct($cache_path= null){\n\t\tif(empty($cache_path)){\n\t\t\t$cache_path = CACHE_PATH;\n\t\t}\n\t\t$this->cache_path = $cache_path;\n\t}\n\n\tfunction get($key){\n\t\t$file = $this->cache_path . md5($key) . '.php';\n\t\t$data = @include $file;\n\t\tif( is_array($data) && $data['expire'] > time() && !is_null($data['data']) ){\n\t\t\treturn $data['data'];\n\t\t}else{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tfunction set($key, $value=null, $expire=99999999){\n\t\t$file = $this->cache_path . md5($key) . '.php';\n\t\t$data['expire'] = time() + $expire;\n\t\t$data['data'] = $value;\n\t\treturn @file_put_contents($file, \"<?php return \" . var_export($data, true) . \";\", FILE_FLAGS);\n\t}\n\n\tfunction clear(){\n\t\tarray_map('unlink', glob($this->cache_path.'*.php'));\n\t}\n}"
  },
  {
    "path": "lib/cache/memcache_.php",
    "content": "<?php \nclass memcache_{\n\tprivate $m;\n\t\n\tfunction __construct($config = null){\n\t\t$this->m = new Memcache();\n\t\tif(empty($config)){\n\t\t\t$config = 'localhost:11211';\n\t\t}\n\t\tlist($host, $port) = explode(':', $config, 2);\n\t\t$this->m->addServer($host, $port);\n\t}\n\n\tfunction get($key){\n\t\t$data = $this->m->get($key);\n\t\tif( is_array($data) && $data['expire'] > time() && !is_null($data['data']) ){\n\t\t\treturn $data['data'];\n\t\t}else{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tfunction set($key, $value=null, $expire=99999999){\n\t\t$data['expire'] = time() + $expire;\n\t\t$data['data'] = $value;\n\t\treturn $this->m->set($key, $data);\n\t}\n\n\tfunction clear(){\n\t\t$this->m->flush(10);\n\t}\n}\n"
  },
  {
    "path": "lib/cache/redis_.php",
    "content": "<?php\nclass redis_{\n        private $redis;\n\n        function __construct($config = null){\n                $this->redis = new Redis();\n                if(empty($config)){\n                        $config = 'localhost:6379';\n                }\n                list($host, $port) = explode(':', $config, 2);\n                $this->redis->pconnect($host, $port);\n        }\n\n        function get($key){\n                $gRefreshTime = $this->redis->get(\"OneIndex_gRefreshTime\");\n                $key = \"OneIndex_$gRefreshTime\\_\" . $key;\n                $data = $this->redis->get($key);\n                return unserialize($data) ?: null;\n        }\n\n        function set($key, $value=null, $expire=600){\n                $gRefreshTime = $this->redis->get(\"OneIndex_gRefreshTime\");\n                if (empty($gRefreshTime)) {\n                        $gRefreshTime = time();\n                        $this->redis->set(\"OneIndex_gRefreshTime\", $gRefreshTime);\n                }\n                $key = \"OneIndex_$gRefreshTime\\_\" . $key;\n                return $this->redis->set($key, serialize($value), $expire);\n        }\n\n        function clear(){\n                $this->redis->set(\"OneIndex_gRefreshTime\", $gRefreshTime);\n        }\n}\n"
  },
  {
    "path": "lib/cache/secache_.php",
    "content": "<?php \nclass secache_{\n\tprivate $cachefile;\n\tprivate $c;\n\t\n\tfunction __construct($config=null){\n\t\t\n\t\tlist($cachefile, $size) = explode(':', $config, 2);\n\t\t\n\t\tif(empty($cachefile)){\n\t\t\t$cachefile = CACHE_PATH.'cachedata';\n\t\t}\n\n\t\tif(empty($size)){\n\t\t\t$size = '100M';\n\t\t}\n\n\t\tdefine('SECACHE_SIZE',$size);\n\t\t$this->cachefile = $cachefile;\n\t\t$this->c = new secache();\n\t\t$this->c->workat($this->cachefile);\n\t}\n\n\tfunction get($key){\n\t\t$this->c->fetch(md5($key),$data);\n\t\tif( is_array($data) && $data['expire'] > time() && !is_null($data['data']) ){\n\t\t\treturn $data['data'];\n\t\t}else{\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tfunction set($key, $value=null, $expire=99999999){\n\t\t$data['expire'] = time() + $expire;\n\t\t$data['data'] = $value;\n\t\treturn $this->c->store(md5($key),$data);\n\t\t\n\t}\n\n\tfunction clear(){\n\t\treturn $this->c->clear();\n\t}\n}\n\nclass secache{\n    var $idx_node_size = 40;\n\tvar $idx_node_base = 0;\n    var $data_base_pos = 262588; //40+20+24*16+16*16*16*16*4;\n    var $schema_item_size = 24;\n    var $header_padding = 20; //保留空间 放置php标记防止下载\n    var $info_size = 20; //保留空间 4+16 maxsize|ver\n    //40起 添加20字节保留区域\n    var $idx_seq_pos = 40; //id 计数器节点地址\n    var $dfile_cur_pos = 44; //id 计数器节点地址\n    var $idx_free_pos = 48; //id 空闲链表入口地址\n    var $idx_base_pos = 444; //40+20+24*16\n    var $min_size = 10240; //10M最小值\n    var $schema_struct = array('size','free','lru_head','lru_tail','hits','miss');\n    var $ver = '$Rev$';\n    var $name = '系统默认缓存(文件型)';\n    function workat($file){\n        $this->_file = $file.'.php';\n        $this->_bsize_list = array(\n            512=>10,\n            3<<10=>10,\n            8<<10=>10,\n            20<<10=>4,\n            30<<10=>2,\n            50<<10=>2,\n            80<<10=>2,\n            96<<10=>2,\n            128<<10=>2,\n            224<<10=>2,\n            256<<10=>2,\n            512<<10=>1,\n            1024<<10=>1,\n        );\n        $this->_node_struct = array(\n            'next'=>array(0,'V'),\n            'prev'=>array(4,'V'),\n            'data'=>array(8,'V'),\n            'size'=>array(12,'V'),\n            'lru_right'=>array(16,'V'),\n            'lru_left'=>array(20,'V'),\n            'key'=>array(24,'H*'),\n        );\n        if(!file_exists($this->_file)){\n            $this->create();\n        }else{\n            $this->_rs = fopen($this->_file,'rb+') or $this->trigger_error('Can\\'t open the cachefile: '.realpath($this->_file),E_USER_ERROR);\n            $this->_seek($this->header_padding);\n            $info = unpack('V1max_size/a*ver',fread($this->_rs,$this->info_size));\n\t\t\t$info['ver'] = trim($info['ver']);\n            if($info['ver']!=$this->ver){\n                $this->_format(true);\n            }else{\n                $this->max_size = $info['max_size'];\n            }\n        }\n        $this->idx_node_base = $this->data_base_pos+$this->max_size;\n        $this->_block_size_list = array_keys($this->_bsize_list);\n        sort($this->_block_size_list);\n        return true;\n    }\n    function create(){\n        $this->_rs = fopen($this->_file,'wb+') or $this->trigger_error('Can\\'t open the cachefile: '.realpath($this->_file),E_USER_ERROR);;\n        fseek($this->_rs,0);\n        fputs($this->_rs,'<'.'?php exit()?'.'>');\n        return $this->_format();\n    }\n    function _puts($offset,$data){\n        if($offset < $this->max_size*1.5){\n            $this->_seek($offset);\n            return fputs($this->_rs,$data);\n        }else{\n            $this->trigger_error('Offset over quota:'.$offset,E_USER_ERROR);\n        }\n    }\n    function _seek($offset){\n        return fseek($this->_rs,$offset);\n    }\n    function clear(){\n        return $this->_format(true);\n    }\n    function fetch($key,&$return){\n        if($this->lock(false)){\n            $locked = true;\n        }\n        if($this->search($key,$offset)){\n            $info = $this->_get_node($offset);\n            $schema_id = $this->_get_size_schema_id($info['size']);\n            if($schema_id===false){\n                if($locked) $this->unlock();\n                return false;\n            }\n            $this->_seek($info['data']);\n            $data = fread($this->_rs,$info['size']);\n            $return = unserialize($data);\n            if($return===false){\n                if($locked) $this->unlock();\n                return false;\n            }\n            if($locked){\n                $this->_lru_push($schema_id,$info['offset']);\n                $this->_set_schema($schema_id,'hits',$this->_get_schema($schema_id,'hits')+1);\n                return $this->unlock();\n            }else{\n                return true;\n            }\n        }else{\n            if($locked) $this->unlock();\n            return false;\n        }\n    }\n    /**\n     * lock\n     * 如果flock不管用，请继承本类，并重载此方法\n     *\n     * @param mixed $is_block 是否阻塞\n     * @access public\n     * @return void\n     */\n    function lock($is_block,$whatever=false){\n        ignore_user_abort(1);\n        return flock($this->_rs, $is_block?LOCK_EX:LOCK_EX+LOCK_NB);\n    }\n    /**\n     * unlock\n     * 如果flock不管用，请继承本类，并重载此方法\n     *\n     * @access public\n     * @return void\n     */\n    function unlock(){\n        ignore_user_abort(0);\n        return flock($this->_rs, LOCK_UN);\n    }\n    function delete($key,$pos=false){\n        if($pos || $this->search($key,$pos)){\n            if($info = $this->_get_node($pos)){\n                //删除data区域\n                if($info['prev']){\n                    $this->_set_node($info['prev'],'next',$info['next']);\n                    $this->_set_node($info['next'],'prev',$info['prev']);\n                }else{ //改入口位置\n                    $this->_set_node($info['next'],'prev',0);\n                    $this->_set_node_root($key,$info['next']);\n                }\n                $this->_free_dspace($info['size'],$info['data']);\n                $this->_lru_delete($info);\n                $this->_free_node($pos);\n                return $info['prev'];\n            }\n        }\n        return false;\n    }\n    function store($key,$value){\n        if($this->lock(true)){\n            //save data\n            $data = serialize($value);\n            $size = strlen($data);\n            //get list_idx\n            $has_key = $this->search($key,$list_idx_offset);\n            $schema_id = $this->_get_size_schema_id($size);\n            if($schema_id===false){\n                $this->unlock();\n                return false;\n            }\n            if($has_key){\n                $hdseq = $list_idx_offset;\n                $info = $this->_get_node($hdseq);\n                if($schema_id == $this->_get_size_schema_id($info['size'])){\n                    $dataoffset = $info['data'];\n                }else{\n                    //破掉原有lru\n                    $this->_lru_delete($info);\n                    if(!($dataoffset = $this->_dalloc($schema_id))){\n                        $this->unlock();\n                        return false;\n                    }\n                    $this->_free_dspace($info['size'],$info['data']);\n                    $this->_set_node($hdseq,'lru_left',0);\n                    $this->_set_node($hdseq,'lru_right',0);\n                }\n                $this->_set_node($hdseq,'size',$size);\n                $this->_set_node($hdseq,'data',$dataoffset);\n            }else{\n                if(!($dataoffset = $this->_dalloc($schema_id))){\n                    $this->unlock();\n                    return false;\n                }\n                $hdseq = $this->_alloc_idx(array(\n                    'next'=>0,\n                    'prev'=>$list_idx_offset,\n                    'data'=>$dataoffset,\n                    'size'=>$size,\n                    'lru_right'=>0,\n                    'lru_left'=>0,\n                    'key'=>$key,\n                ));\n                if($list_idx_offset>0){\n                    $this->_set_node($list_idx_offset,'next',$hdseq);\n                }else{\n                    $this->_set_node_root($key,$hdseq);\n                }\n            }\n            if($dataoffset>$this->max_size){\n                $this->trigger_error('alloc datasize:'.$dataoffset,E_USER_WARNING);\n                return false;\n            }\n            $this->_puts($dataoffset,$data);\n            $this->_set_schema($schema_id,'miss',$this->_get_schema($schema_id,'miss')+1);\n            $this->_lru_push($schema_id,$hdseq);\n            $this->unlock();\n            return true;\n        }else{\n            $this->trigger_error(\"Couldn't lock the file !\",E_USER_WARNING);\n            return false;\n        }\n    }\n    /**\n     * search\n     * 查找指定的key\n     * 如果找到节点则$pos=节点本身 返回true\n     * 否则 $pos=树的末端 返回false\n     *\n     * @param mixed $key\n     * @access public\n     * @return void\n     */\n    function search($key,&$pos){\n        return $this->_get_pos_by_key($this->_get_node_root($key),$key,$pos);\n    }\n    function _get_size_schema_id($size){\n        foreach($this->_block_size_list as $k=>$block_size){\n            if($size <= $block_size){\n                return $k;\n            }\n        }\n        return false;\n    }\n    function _parse_str_size($str_size,$default){\n        if(preg_match('/^([0-9]+)\\s*([gmk]|)$/i',$str_size,$match)){\n            switch(strtolower($match[2])){\n            case 'g':\n                if($match[1]>1){\n                    $this->trigger_error('Max cache size 1G',E_USER_ERROR);\n                }\n                $size = $match[1]<<30;\n                break;\n            case 'm':\n                $size = $match[1]<<20;\n                break;\n            case 'k':\n                $size = $match[1]<<10;\n                break;\n            default:\n                $size = $match[1];\n            }\n            if($size<=0){\n                $this->trigger_error('Error cache size '.$this->max_size,E_USER_ERROR);\n                return false;\n            }elseif($size<10485760){\n                return 10485760;\n            }else{\n                return $size;\n            }\n        }else{\n            return $default;\n        }\n    }\n    function _format($truncate=false){\n        if($this->lock(true,true)){\n            if($truncate){\n                $this->_seek(0);\n                ftruncate($this->_rs,$this->idx_node_base);\n            }\n            $this->max_size = $this->_parse_str_size(SECACHE_SIZE,15728640); //default:15m\n            $this->_puts($this->header_padding,pack('V1a*',$this->max_size,$this->ver));\n            ksort($this->_bsize_list);\n            $ds_offset = $this->data_base_pos;\n            $i=0;\n            foreach($this->_bsize_list as $size=>$count){\n                //将预分配的空间注册到free链表里\n                $count *= min(3,floor($this->max_size/10485760));\n                $next_free_node = 0;\n                for($j=0;$j<$count;$j++){\n                    $this->_puts($ds_offset,pack('V',$next_free_node));\n                    $next_free_node = $ds_offset;\n                    $ds_offset+=intval($size);\n                }\n                $code = pack(str_repeat('V1',count($this->schema_struct)),$size,$next_free_node,0,0,0,0);\n                $this->_puts(60+$i*$this->schema_item_size,$code);\n                $i++;\n            }\n            $this->_set_dcur_pos($ds_offset);\n            $this->_puts($this->idx_base_pos,str_repeat(\"\\0\",262144));\n            $this->_puts($this->idx_seq_pos,pack('V',1));\n            $this->unlock();\n            return true;\n        }else{\n            $this->trigger_error(\"Couldn't lock the file !\",E_USER_ERROR);\n            return false;\n        }\n    }\n    function _get_node_root($key){\n        $this->_seek(hexdec(substr($key,0,4))*4+$this->idx_base_pos);\n        $a= fread($this->_rs,4);\n        list(,$offset) = unpack('V',$a);\n        return $offset;\n    }\n    function _set_node_root($key,$value){\n        return $this->_puts(hexdec(substr($key,0,4))*4+$this->idx_base_pos,pack('V',$value));\n    }\n    function _set_node($pos,$key,$value){\n        if(!$pos){\n            return false;\n        }\n        if(isset($this->_node_struct[$key])){\n            return $this->_puts($pos*$this->idx_node_size+$this->idx_node_base+$this->_node_struct[$key][0],pack($this->_node_struct[$key][1],$value));\n        }else{\n            return false;\n        }\n    }\n    function _get_pos_by_key($offset,$key,&$pos){\n        if(!$offset){\n            $pos = 0;\n            return false;\n        }\n        $info = $this->_get_node($offset);\n        if($info['key']==$key){\n            $pos = $info['offset'];\n            return true;\n        }elseif($info['next'] && $info['next']!=$offset){\n            return $this->_get_pos_by_key($info['next'],$key,$pos);\n        }else{\n            $pos = $offset;\n            return false;\n        }\n    }\n    function _lru_delete($info){\n        if($info['lru_right']){\n            $this->_set_node($info['lru_right'],'lru_left',$info['lru_left']);\n        }else{\n            $this->_set_schema($this->_get_size_schema_id($info['size']),'lru_tail',$info['lru_left']);\n        }\n        if($info['lru_left']){\n            $this->_set_node($info['lru_left'],'lru_right',$info['lru_right']);\n        }else{\n            $this->_set_schema($this->_get_size_schema_id($info['size']),'lru_head',$info['lru_right']);\n        }\n        return true;\n    }\n    function _lru_push($schema_id,$offset){\n        $lru_head = $this->_get_schema($schema_id,'lru_head');\n        $lru_tail = $this->_get_schema($schema_id,'lru_tail');\n        if((!$offset) || ($lru_head==$offset))return;\n        $info = $this->_get_node($offset);\n        $this->_set_node($info['lru_right'],'lru_left',$info['lru_left']);\n        $this->_set_node($info['lru_left'],'lru_right',$info['lru_right']);\n        $this->_set_node($offset,'lru_right',$lru_head);\n        $this->_set_node($offset,'lru_left',0);\n        $this->_set_node($lru_head,'lru_left',$offset);\n        $this->_set_schema($schema_id,'lru_head',$offset);\n        if($lru_tail==0){\n            $this->_set_schema($schema_id,'lru_tail',$offset);\n        }elseif($lru_tail==$offset && $info['lru_left']){\n            $this->_set_schema($schema_id,'lru_tail',$info['lru_left']);\n        }\n        return true;\n    }\n    function _get_node($offset){\n        $this->_seek($offset*$this->idx_node_size + $this->idx_node_base);\n        $info = unpack('V1next/V1prev/V1data/V1size/V1lru_right/V1lru_left/H*key',fread($this->_rs,$this->idx_node_size));\n        $info['offset'] = $offset;\n        return $info;\n    }\n    function _lru_pop($schema_id){\n        if($node = $this->_get_schema($schema_id,'lru_tail')){\n            $info = $this->_get_node($node);\n            if(!$info['data']){\n                return false;\n            }\n            $this->delete($info['key'],$info['offset']);\n            if(!$this->_get_schema($schema_id,'free')){\n                $this->trigger_error('pop lru,But nothing free...',E_USER_ERROR);\n            }\n            return $info;\n        }else{\n            return false;\n        }\n    }\n    function _dalloc($schema_id,$lru_freed=false){\n        if($free = $this->_get_schema($schema_id,'free')){ //如果lru里有链表\n            $this->_seek($free);\n            list(,$next) = unpack('V',fread($this->_rs,4));\n            $this->_set_schema($schema_id,'free',$next);\n            return $free;\n        }elseif($lru_freed){\n            $this->trigger_error('Bat lru poped freesize',E_USER_ERROR);\n            return false;\n        }else{\n            $ds_offset = $this->_get_dcur_pos();\n            $size = $this->_get_schema($schema_id,'size');\n            if($size+$ds_offset > $this->max_size){\n                if($info = $this->_lru_pop($schema_id)){\n                    return $this->_dalloc($schema_id,$info);\n                }else{\n                    $this->trigger_error('Can\\'t alloc dataspace',E_USER_ERROR);\n                    return false;\n                }\n            }else{\n                $this->_set_dcur_pos($ds_offset+$size);\n                return $ds_offset;\n            }\n        }\n    }\n    function _get_dcur_pos(){\n        $this->_seek($this->dfile_cur_pos);\n        list(,$ds_offset) = unpack('V',fread($this->_rs,4));\n        return $ds_offset;\n    }\n    function _set_dcur_pos($pos){\n        return $this->_puts($this->dfile_cur_pos,pack('V',$pos));\n    }\n    function _free_dspace($size,$pos){\n        if($pos>$this->max_size){\n            $this->trigger_error('free dspace over quota:'.$pos,E_USER_ERROR);\n            return false;\n        }\n        $schema_id = $this->_get_size_schema_id($size);\n        if($free = $this->_get_schema($schema_id,'free')){\n            $this->_puts($free,pack('V1',$pos));\n        }else{\n            $this->_set_schema($schema_id,'free',$pos);\n        }\n        $this->_puts($pos,pack('V1',0));\n    }\n    function _dfollow($pos,&$c){\n        $c++;\n        $this->_seek($pos);\n        list(,$next) = unpack('V1',fread($this->_rs,4));\n        if($next){\n            return $this->_dfollow($next,$c);\n        }else{\n            return $pos;\n        }\n    }\n    function _free_node($pos){\n        $this->_seek($this->idx_free_pos);\n        list(,$prev_free_node) = unpack('V',fread($this->_rs,4));\n        $this->_puts($pos*$this->idx_node_size+$this->idx_node_base,pack('V',$prev_free_node).str_repeat(\"\\0\",$this->idx_node_size-4));\n        return $this->_puts($this->idx_free_pos,pack('V',$pos));\n    }\n    function _alloc_idx($data){\n        $this->_seek($this->idx_free_pos);\n        list(,$list_pos) = unpack('V',fread($this->_rs,4));\n        if($list_pos){\n            $this->_seek($list_pos*$this->idx_node_size+$this->idx_node_base);\n            list(,$prev_free_node) = unpack('V',fread($this->_rs,4));\n            $this->_puts($this->idx_free_pos,pack('V',$prev_free_node));\n        }else{\n            $this->_seek($this->idx_seq_pos);\n            list(,$list_pos) = unpack('V',fread($this->_rs,4));\n            $this->_puts($this->idx_seq_pos,pack('V',$list_pos+1));\n        }\n        return $this->_create_node($list_pos,$data);\n    }\n    function _create_node($pos,$data){\n        $this->_puts($pos*$this->idx_node_size + $this->idx_node_base\n            ,pack('V1V1V1V1V1V1H*',$data['next'],$data['prev'],$data['data'],$data['size'],$data['lru_right'],$data['lru_left'],$data['key']));\n        return $pos;\n    }\n    function _set_schema($schema_id,$key,$value){\n        $info = array_flip($this->schema_struct);\n        return $this->_puts(60+$schema_id*$this->schema_item_size + $info[$key]*4,pack('V',$value));\n    }\n    function _get_schema($id,$key){\n        $info = array_flip($this->schema_struct);\n        $this->_seek(60+$id*$this->schema_item_size);\n        unpack('V1'.implode('/V1',$this->schema_struct),fread($this->_rs,$this->schema_item_size));\n        $this->_seek(60+$id*$this->schema_item_size + $info[$key]*4);\n        list(,$value) =unpack('V',fread($this->_rs,4));\n        return $value;\n    }\n    function _all_schemas(){\n        $schema = array();\n        for($i=0;$i<16;$i++){\n            $this->_seek(60+$i*$this->schema_item_size);\n            $info = unpack('V1'.implode('/V1',$this->schema_struct),fread($this->_rs,$this->schema_item_size));\n            if($info['size']){\n                $info['id'] = $i;\n                $schema[$i] = $info;\n            }else{\n                return $schema;\n            }\n        }\n    }\n    function schemaStatus(){\n        $return = array();\n        foreach($this->_all_schemas() as $k=>$schemaItem){\n            if($schemaItem['free']){\n                $this->_dfollow($schemaItem['free'],$schemaItem['freecount']);\n            }\n            $return[] = $schemaItem;\n        }\n        return $return;\n    }\n    function status(&$curBytes,&$totalBytes){\n        $totalBytes = $curBytes = 0;\n        $hits = $miss = 0;\n        $schemaStatus = $this->schemaStatus();\n        $totalBytes = $this->max_size;\n        $freeBytes = $this->max_size - $this->_get_dcur_pos();\n        foreach($schemaStatus as $schema){\n            $freeBytes+=$schema['freecount']*$schema['size'];\n            $miss += $schema['miss'];\n            $hits += $schema['hits'];\n        }\n        $curBytes = $totalBytes-$freeBytes;\n        $return[] = array('name'=>'缓存命中','value'=>$hits);\n        $return[] = array('name'=>'缓存未命中','value'=>$miss);\n        return $return;\n    }\n    function trigger_error($errstr,$errno){\n        trigger_error($errstr,$errno);\n    }\n}\n?>\n"
  },
  {
    "path": "lib/cache.php",
    "content": "<?php\n\n\t!defined('CACHE_PATH') && define('CACHE_PATH', sys_get_temp_dir().'/');\n\tclass cache{\n\t\t// 驱动方式（支持filecache/memcache/secache）\n\t\tstatic $type = 'secache';\n\n\t\t// 返回缓存实例\n    \tprotected static function c(){\n\t    \tstatic $instance = null;\n\t    \tif(!is_null($instance)){\n\t\t    \treturn $instance;\n\t    \t}\n\t    \t\n\t\t\tlist($type, $config) = explode(':', self::$type, 2);\n\n\t\t\t$type .= '_';\n\t    \tif( in_array($type, array('filecache_', 'memcache_', 'secache_', 'redis_')) ){\n\t\t    \t$file = str_replace(\"\\\\\", \"/\", dirname(__FILE__)) . '/cache/'.$type.'.php';\n\t\t\t    include_once( $file );\n\t\t    \t$instance = new $type($config);\n\t\t    \treturn $instance;\n\t    \t}\n    \t}\n\n\t\t// 获取缓存\n\t\tstatic function get($key, $default=null, $expire=99999999){\n\t\t\t$value = self::c()->get($key);\n\t\t\tif(!is_null($value)){\n\t\t\t\treturn $value;\n\t\t\t}elseif(is_callable($default)){\n\t\t\t\t$value = $default();\n\t\t\t\tself::set($key, $value, $expire);\n\t\t\t\treturn $value;\n\t\t\t}elseif(!is_null($default)){\n\t\t\t\tself::set($key, $default, $expire);\n\t\t\t\treturn $default;\n\t\t\t}\n\t\t}\n\n\t\t// 设置缓存\n\t\tstatic function set($key, $value, $expire=99999999){\n\t\t\treturn self::c()->set($key, $value, $expire);\n\t\t}\n\n\t\t// 清空缓存\n\t\tstatic function clear(){\n\t\t\treturn self::c()->clear();\n\t\t}\n\n\t\t// 删除缓存\n\t\tstatic function del($key){\n\t\t\treturn self::set($key, null);\n\t\t}\n\n\t\t// 判断缓存是否设置\n\t\tstatic function has($key){\n\t\t\tif(is_null(self::get($key))){\n\t\t\t\treturn false;\n\t\t\t}else{\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\t// 读取并删除缓存\n\t\tstatic function pull($key){\n\t\t\t$value = self::get($key);\n\t\t\tself::del($key);\n\t\t\treturn $value;\n\t\t}\n\t}\n"
  },
  {
    "path": "lib/fetch.php",
    "content": "<?php\nclass fetch {\n\tpublic static $headers = \"User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36\";\n\tpublic static $cookies;\n\tpublic static $curl_opt;\n\tpublic static $proxy;\n\n\tpublic static $max_connect = 10;\n\n\tpublic static function init($opt = array()) {\n\t\tself::$curl_opt = array(\n\t\t\tCURLOPT_RETURNTRANSFER => 1, //true, $head 有请求的返回值\n\t\t\tCURLOPT_BINARYTRANSFER => true, //返回原生的Raw输出\n\t\t\tCURLOPT_HEADER => true, //启用时会将头文件的信息作为数据流输出。\n\t\t\tCURLOPT_FAILONERROR => true, //显示HTTP状态码，默认行为是忽略编号小于等于400的HTTP信息。\n\t\t\tCURLOPT_AUTOREFERER => true, //当根据Location:重定向时，自动设置header中的Referer:信息。\n\t\t\tCURLOPT_FOLLOWLOCATION => false, //跳转\n\t\t\tCURLOPT_CONNECTTIMEOUT => 3, //在发起连接前等待的时间，如果设置为0，则无限等待。\n\t\t\tCURLOPT_TIMEOUT => 5, //设置cURL允许执行的最长秒数。\n\t\t\tCURLOPT_ENCODING => 'gzip,deflate',\n\t\t\tCURLOPT_SSL_VERIFYHOST => false,\n\t\t\tCURLOPT_SSL_VERIFYPEER => false,\n\t\t);\n\t\tforeach ($opt as $k => $v) {\n\t\t\tself::$curl_opt[$k] = $v;\n\t\t}\n\t}\n\n\t/**\n\t * fetch::get('http://www.google.com/');\n\t * fetch::post('http://www.google.com/', array('name'=>'foo'));\n\t */\n\tpublic static function __callstatic($method, $args) {\n\t\tif (is_null(self::$curl_opt)) {\n\t\t\tself::init();\n\t\t}\n\t\t@list($request, $post_data, $callback) = $args;\n\t\tif (is_callable($post_data)) {\n\t\t\t$callback = $post_data;\n\t\t\t$post_data = null;\n\t\t}\n\n\t\t//single_curl\n\t\tif (is_string($request) || !empty($request['url'])) {\n\t\t\t$request = self::bulid_request($request, $method, $post_data, $callback);\n\t\t\treturn self::single_curl($request);\n\t\t} elseif (is_array($request)) {\n\t\t\t//rolling_curl\n\t\t\tforeach ($request as $k => $r) {\n\t\t\t\t$requests[$k] = self::bulid_request($r, $method, $post_data, $callback);\n\t\t\t}\n\t\t\treturn self::rolling_curl($requests);\n\t\t}\n\t}\n\n\tprivate static function bulid_request($request, $method = 'GET', $post_data = null, $callback = null) {\n\t\t//url\n\t\tif (is_string($request)) {\n\t\t\t$request = array('url' => $request);\n\t\t}\n\t\tempty($request['method']) && $request['method'] = $method;\n\t\tempty($request['post_data']) && $request['post_data'] = $post_data;\n\t\tempty($request['callback']) && $request['callback'] = $callback;\n\t\treturn $request;\n\t}\n\n\tprivate static function bulid_ch(&$request) {\n\t\t// url\n\t\t$ch = curl_init($request['url']);\n\t\t// curl_opt\n\t\t$curl_opt = empty($request['curl_opt']) ? array() : $request['curl_opt'];\n\t\t$curl_opt = $curl_opt + (array) self::$curl_opt;\n\t\t// method\n\t\t$curl_opt[CURLOPT_CUSTOMREQUEST] = strtoupper($request['method']);\n\t\t// post_data\n\t\tif (!empty($request['post_data'])) {\n\t\t\t$curl_opt[CURLOPT_POST] = true;\n\t\t\t$curl_opt[CURLOPT_POSTFIELDS] = $request['post_data'];\n\t\t}\n\t\t// header\n\t\t$headers = @self::bulid_request_header($request['headers'], $cookies);\n\t\t$curl_opt[CURLOPT_HTTPHEADER] = $headers;\n\n\t\t// cookies\n\t\t$request['cookies'] = empty($request['cookies']) ? fetch::$cookies : $request['cookies'];\n\t\t$cookies = empty($request['cookies']) ? $cookies : self::cookies_arr2str($request['cookies']);\n\t\tif (!empty($cookies)) {\n\t\t\t$curl_opt[CURLOPT_COOKIE] = $cookies;\n\t\t}\n\n\t\t//proxy\n\t\t$proxy = empty($request['proxy']) ? self::$proxy : $request['proxy'];\n\t\tif (!empty($proxy)) {\n\t\t\t$curl_opt[CURLOPT_PROXY] = $proxy;\n\t\t}\n\n\t\t//setopt\n\t\tcurl_setopt_array($ch, $curl_opt);\n\n\t\t$request['curl_opt'] = $curl_opt;\n\t\t$request['ch'] = $ch;\n\n\t\treturn $ch;\n\t}\n\n\tprivate static function response($raw, $ch) {\n\t\t$response = (object) curl_getinfo($ch);\n\t\t$response->raw = $raw;\n\t\t//$raw = fetch::iconv($raw, $response->content_type);\n\t\t$response->headers = substr($raw, 0, $response->header_size);\n\t\t$response->cookies = fetch::get_respone_cookies($response->headers);\n\t\tfetch::$cookies = array_merge((array) fetch::$cookies, $response->cookies);\n\t\t$response->content = substr($raw, $response->header_size);\n\t\treturn $response;\n\t}\n\n\tprivate static function single_curl($request) {\n\t\t$ch = self::bulid_ch($request);\n\t\t$raw = curl_exec($ch);\n\t\t$response = self::response($raw, $ch);\n\t\tcurl_close($ch);\n\t\tif (is_callable($request['callback'])) {\n\t\t\tcall_user_func($request['callback'], $response, $request);\n\t\t}\n\t\treturn $response;\n\t}\n\n\tprivate static function rolling_curl($requests) {\n\t\t$master = curl_multi_init();\n\t\t$map = array();\n\t\t// start the first batch of requests\n\t\tdo {\n\t\t\t$k = key($requests);\n\t\t\t$request = current($requests);\n\t\t\tnext($requests);\n\t\t\t$ch = self::bulid_ch($request);\n\t\t\tcurl_multi_add_handle($master, $ch);\n\t\t\t$key = (string) $ch;\n\t\t\t$map[$key] = array($k, $request['callback']);\n\t\t} while (count($map) < self::$max_connect && count($map) < count($requests));\n\n\t\tdo {\n\t\t\twhile (($execrun = curl_multi_exec($master, $running)) == CURLM_CALL_MULTI_PERFORM);\n\t\t\tif ($execrun != CURLM_OK) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\t// a request was just completed -- find out which one\n\t\t\twhile ($done = curl_multi_info_read($master)) {\n\t\t\t\t$key = (string) $done['handle'];\n\n\t\t\t\tlist($k, $callback) = $map[$key];\n\n\t\t\t\t// get the info and content returned on the request\n\t\t\t\t$raw = curl_multi_getcontent($done['handle']);\n\t\t\t\t$response = self::response($raw, $done['handle']);\n\t\t\t\t$responses[$k] = $response;\n\n\t\t\t\t// send the return values to the callback function.\n\t\t\t\tif (is_callable($callback)) {\n\t\t\t\t\t$key = (string) $done['handle'];\n\t\t\t\t\tunset($map[$key]);\n\t\t\t\t\tcall_user_func($callback, $response, $requests[$k], $k);\n\t\t\t\t}\n\n\t\t\t\t// start a new request (it's important to do this before removing the old one)\n\t\t\t\t$k = key($requests);\n\t\t\t\tif (!empty($k)) {\n\t\t\t\t\t$k = key($requests);\n\t\t\t\t\t$request = current($requests);\n\t\t\t\t\tnext($requests);\n\t\t\t\t\t$ch = self::bulid_ch($request);\n\t\t\t\t\tcurl_multi_add_handle($master, $ch);\n\t\t\t\t\t$key = (string) $ch;\n\t\t\t\t\t$map[$key] = array($k, $request['callback']);\n\t\t\t\t\tcurl_multi_exec($master, $running);\n\t\t\t\t}\n\n\t\t\t\t// remove the curl handle that just completed\n\t\t\t\tcurl_multi_remove_handle($master, $done['handle']);\n\t\t\t}\n\n\t\t\t// Block for data in / output; error handling is done by curl_multi_exec\n\t\t\tif ($running) {\n\t\t\t\tcurl_multi_select($master, 10);\n\t\t\t}\n\n\t\t} while ($running);\n\n\t\treturn $responses;\n\t}\n\n\tprivate static function bulid_request_header($headers, &$cookies) {\n\t\tif (is_array($headers)) {\n\t\t\t$headers = join(PHP_EOL, $headers);\n\t\t}\n\t\tif (is_array(self::$headers)) {\n\t\t\tself::$headers = join(PHP_EOL, self::$headers);\n\t\t}\n\t\t$headers = self::$headers.PHP_EOL .$headers;\n\n\t\tforeach (explode(PHP_EOL, $headers) as $k => $v) {\n\t\t\t@list($k, $v) = explode(':', $v, 2);\n\t\t\tif (empty($k) || empty($v)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t$k = implode('-', array_map('ucfirst', explode('-', $k)));\n\t\t\t$tmp[$k] = $v;\n\t\t}\n\n\t\tforeach ((array) $tmp as $k => $v) {\n\t\t\tif ($k == 'Cookie') {\n\t\t\t\t$cookies = $v;\n\t\t\t} else {\n\t\t\t\t$return[] = $k . ':' . $v;\n\t\t\t}\n\t\t}\n\t\treturn (array) $return;\n\t}\n\n\tpublic static function iconv(&$raw, $content_type) {\n\t\t@list($tmp, $charset) = explode('CHARSET=', strtoupper($content_type));\n\n\t\tif (empty($charset) && stripos($content_type, 'html') > 0) {\n\t\t\tpreg_match('@\\<meta.+?charset=([\\w]+)[\\'|\\\"]@i', $raw, $matches);\n\t\t\t$charset = empty($matches[1]) ? null : $matches[1];\n\t\t}\n\n\t\treturn empty($charset) ? $raw : iconv($charset, \"UTF-8//IGNORE\", $raw);\n\t}\n\n\tpublic static function get_respone_cookies($raw) {\n\t\t$cookies = array();\n\t\tif(strpos($raw, PHP_EOL) != false){\n\t\t    $lines = explode(PHP_EOL, $raw);\n\t\t}elseif(strpos($raw, \"\\r\\n\") != false){\n\t\t    $lines = explode(\"\\r\\n\", $raw);\n\t\t}elseif(strpos($raw, '\\r\\n') != false){\n\t\t    $lines = explode('\\r\\n', $raw);\n\t\t}\n\t\t\n\t\tforeach ((array)$lines as $line) {\n\t\t\tif (substr($line, 0, 11) == 'Set-Cookie:') {\n\t\t\t\tlist($k, $v) = explode('=', substr($line, 11), 2);\n\t\t\t\tlist($v, $tmp) = explode(';', $v);\n\t\t\t\t$cookies[trim($k)] = trim($v);\n\t\t\t}\n\t\t}\n\t\treturn $cookies;\n\t}\n\n\tpublic static function cookies_arr2str($arr) {\n\t\t$str = \"\";\n\t\tforeach ((array) $arr as $k => $v) {\n\t\t\t$str .= $k . \"=\" . $v . \"; \";\n\t\t}\n\t\treturn $str;\n\t}\n}"
  },
  {
    "path": "lib/onedrive.php",
    "content": "<?php\n\tclass onedrive{\n\t\tstatic $client_id;\n\t\tstatic $client_secret;\n\t\tstatic $redirect_uri;\n\t\t//国际版\n\t\tstatic $api_url = 'https://graph.microsoft.com/v1.0';\n\t\tstatic $oauth_url = 'https://login.microsoftonline.com/common/oauth2/v2.0';\n\t\t//世纪互联版\n\t\t// static $api_url = \"https://microsoftgraph.chinacloudapi.cn/v1.0\";\n\t\t// static $oauth_url = \"https://login.partner.microsoftonline.cn/common/oauth2/v2.0\";\n\n\t\t//验证URL，浏览器访问、授权\n\t\tstatic function authorize_url(){\n\t\t\t$client_id = self::$client_id;\n\t\t\t$scope = urlencode(\"offline_access files.readwrite.all\");\n\t\t\t$redirect_uri = self::$redirect_uri;\n\t\t\t$url = self::$oauth_url.\"/authorize?client_id={$client_id}&scope={$scope}&response_type=code&redirect_uri={$redirect_uri}\";\n\t\t\t\n\t\t\tif($_SERVER['HTTP_HOST'] != 'localhost'){\n\t\t\t\t$url .= '&state='.urlencode('http://'.$_SERVER['HTTP_HOST'].get_absolute_path(dirname($_SERVER['PHP_SELF'])));\n\t\t\t}\n\t\t\t\n\t\t\treturn $url;\n\t\t}\n\n\t\t//使用 $code, 获取 $refresh_token\n\t\tstatic function authorize($code = \"\"){\n\t\t\t$client_id = self::$client_id;\n\t\t\t$client_secret = self::$client_secret;\n\t\t\t$redirect_uri = self::$redirect_uri;\n\n\t\t\t$url = self::$oauth_url.\"/token\";\n\t\t\t$post_data = \"client_id={$client_id}&redirect_uri={$redirect_uri}&client_secret={$client_secret}&code={$code}&grant_type=authorization_code\";\n\t\t\tfetch::$headers = \"Content-Type: application/x-www-form-urlencoded\";\n\t\t\t$resp = fetch::post($url, $post_data);\n\t\t\t$data = json_decode($resp->content, true);\n\t\t\treturn $data;\n\t\t}\n\n\t\t//使用 $refresh_token，获取 $access_token\n\t\tstatic function get_token($refresh_token){\n\t\t\t$client_id = self::$client_id;\n\t\t\t$client_secret = self::$client_secret;\n\t\t\t$redirect_uri = self::$redirect_uri;\n\n\t\t\t$request['url'] = self::$oauth_url.\"/token\";\n\t\t\t$request['post_data']  = \"client_id={$client_id}&redirect_uri={$redirect_uri}&client_secret={$client_secret}&refresh_token={$refresh_token}&grant_type=refresh_token\";\n\t\t\t$request['headers']= \"Content-Type: application/x-www-form-urlencoded\";\n\t\t\t$resp = fetch::post($request);\n\t\t\t$data = json_decode($resp->content, true);\n\t\t\treturn $data;\n\t\t}\n\n\t\t//获取 $access_token, 带缓存\n\t\tstatic function access_token(){\n\t\t\t$token = config('@token');\n\t\t\tif($token['expires_on'] > time()+600){\n\t\t\t\treturn $token['access_token'];\n\t\t\t}else{\n            \t\t\tif (empty($token) || empty($token['refresh_token'])) {\n                \t\t\t$refresh_token = config('refresh_token');\n            \t\t\t} else {\n                \t\t\t$refresh_token = $token['refresh_token'];\n            \t\t\t}\n\t\t\t\t$token = self::get_token($refresh_token);\n\t\t\t\tif(!empty($token['refresh_token'])){\n\t\t\t\t\t$token['expires_on'] = time()+ $token['expires_in'];\n\t\t\t\t\tconfig('@token', $token);\n\t\t\t\t\treturn $token['access_token'];\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn \"\";\n\t\t}\n\n\n\t\t// 生成一个request，带token\n\t\tstatic function request($path=\"/\", $query=\"\"){\n\t\t\t$path = self::urlencode($path);\n\t\t\t$path = empty($path)?'/':\":/{$path}:/\";\n\t\t\t$token = self::access_token();\n\t\t\t$request['headers'] = \"Authorization: bearer {$token}\".PHP_EOL.\"Content-Type: application/json\".PHP_EOL;\n\t\t\t$request['url'] = self::$api_url.\"/me/drive/root\".$path.$query;\n\t\t\treturn $request;\n\t\t}\n\n\t\t\n\t\t//返回目录信息\n\t\tstatic function dir($path=\"/\"){\n\t\t\t$request = self::request($path, 'children?select=name,size,folder,lastModifiedDateTime,id,@microsoft.graph.downloadUrl');\n\t\t\t$items = array();\n\t\t\tself::dir_next_page($request, $items);\n\t\t\t//不在列表显示的文件夹\n\t\t\t$hide_list = explode(PHP_EOL,config('onedrive_hide'));\n\t\t\tif(is_array($hide_list) && count($hide_list)>0){\n\t\t\t\tforeach($hide_list as $hide_dir){\n\t\t\t\t\tforeach($items as $key=>$_array){\n\t\t\t\t\t\t$buf = trim($hide_dir);\n\t\t\t\t\t\tif($buf && stristr($key, $buf))unset($items[$key]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn $items;\n\t\t}\n\n\t\t//通过分页获取页面所有item\n\t\tstatic function dir_next_page($request, &$items, $retry=0){\n\t\t\t$resp = fetch::get($request);\n\t\t\t\n\t\t\t$data = json_decode($resp->content, true);\n\t\t\tif(empty($data) && $retry < 3){\n\t\t\t\t$retry += 1;\n\t\t\t\treturn self::dir_next_page($request, $items, $retry);\n\t\t\t}\n\t\t\t\n\t\t\tforeach((array)$data['value'] as $item){\n\t\t\t\t//var_dump($item);\n\t\t\t\t$items[$item['name']] = array(\n\t\t\t\t\t'name'=>$item['name'],\n\t\t\t\t\t'id' => $item['id'],\n\t\t\t\t\t'size'=>$item['size'],\n\t\t\t\t\t'lastModifiedDateTime'=>strtotime($item['lastModifiedDateTime']),\n\t\t\t\t\t'downloadUrl'=>$item['@microsoft.graph.downloadUrl'],\n\t\t\t\t\t'folder'=>empty($item['folder'])?false:true\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif(!empty($data['@odata.nextLink'])){\n\t\t\t\t$request = self::request();\n\t\t\t\t$request['url'] = $data['@odata.nextLink'];\n\t\t\t\treturn self::dir_next_page($request, $items);\n\t\t\t}\n\t\t}\n\t\n\t\t//关键字搜索\n\t\tstatic function search($keyword){\n\t\t\t$token = self::access_token();\n\t\t\t$keyword=self::urlencode($keyword);\n\t\t\t$request['headers'] = \"Authorization: bearer {$token}\".PHP_EOL.\"Content-Type: application/json\".PHP_EOL;\n\t\t\t$request['url'] = self::$api_url.\"/me/drive/root/search(q='\".$keyword.\"')\";\n\t\t\t$resp=fetch::get($request);\n\t\t\t$data = json_decode($resp->content, true);\n\n\t\t\tforeach((array)$data['value'] as $item){\n\t\t\t\t//var_dump($item);\n\t\t\t\t$path = self::id2path($item['id']);\n\t\t\t\t$items[$item['name']] = array(\n\t\t\t\t\t'name'=>$item['name'],\n\t\t\t\t\t'id' => $item['id'],\n\t\t\t\t\t'size'=>$item['size'],\n\t\t\t\t\t'lastModifiedDateTime'=>strtotime($item['lastModifiedDateTime']),\n\t\t\t\t\t'folder'=>empty($item['folder'])?false:true,\n\t\t\t\t\t'path'=>$path\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn $items;\n\t\t}\n\n\t\t//文件缩略图链接\n\t\tstatic function thumbnail($path,$size='large'){\n\t\t\t$request = self::request($path,\"thumbnails/0?select={$size}\");\n\t\t\t$resp = fetch::get($request);\n\t\t\t$data = json_decode($resp->content, true);\n\t\t\t$request = self::request($path,\"thumbnails/0?select={$size}\");\n\t\t\treturn @$data[$size]['url'];\n\t\t}\n\n\t\tstatic function share($path){\n\t\t\t$request = self::request($path,\"createLink\");\n\t\t\t$post_data['type'] = 'view';\n\t\t\t$post_data['scope'] = 'anonymous';\n\t\t\t$resp = fetch::post($request, json_encode($post_data));\n\t\t\t$data = json_decode($resp->content, true);\n\t\t\treturn $data;\n\t\t}\n\n\t\t//文件上传函数\n\t\tstatic function upload($path,$content){\n\t\t\t$request = self::request($path,\"content\");\n\t\t\t$request['post_data'] = $content;\n\t\t\t$resp = fetch::put($request);\n\t\t\t$data = @json_decode($resp->content, true);\n\t\t\treturn $data;\n\t\t}\n\t\t//url上传\n\t\tstatic function upload_url($path, $url){\n\t\t\t$request = self::request(get_absolute_path(dirname($path)),\"children\");\n\t\t\t$request['headers'] .= \"Prefer: respond-async\".PHP_EOL;\n\t\t\t$post_data['@microsoft.graph.sourceUrl'] = $url;\n\t\t\t$post_data['name'] = pathinfo($path, PATHINFO_BASENAME );\n\t\t\t$post_data['file'] = json_decode(\"{}\");\n\t\t\t$request['post_data'] = json_encode($post_data);\n\t\t\t$resp = fetch::post($request);\n\t\t\tlist($tmp, $location) = explode('Location:', $resp->headers);\n\t\t\tlist($location, $tmp) = explode(PHP_EOL, $location);\n\t\t\t// return $resp;\n\t\t\treturn trim($location);\n\t\t}\n\t\t\n\t\tstatic function create_upload_session($path){\n\t\t\t$request = self::request($path, 'createUploadSession');\n\t\t\t$request['post_data'] = '{\"item\": {\"@microsoft.graph.conflictBehavior\": \"fail\"}}';\n\t\t\t$token = self::access_token();\n\t\t\t$resp = fetch::post($request);\n\t\t\t$data = json_decode($resp->content, true);\n\t\t\tif($resp->http_code == 409){\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\treturn $data;\n\t\t}\n\n\t\tstatic function upload_session($url, $file, $offset, $length=10240){\n\t\t\t$token = self::access_token();\n\t\t\t$file_size = self::_filesize($file);\n\t\t\t$content_length = (($offset+$length)>$file_size)?($file_size-$offset):$length;\n\t\t\t$end = $offset+$content_length-1;\n\t\t\t$post_data = self::file_content($file, $offset, $length);\n\n\t\t\t$request['url'] = $url;\n\t\t\t$request['curl_opt']=[CURLOPT_TIMEOUT=>360];\n\t\t\t$request['headers'] = \"Authorization: bearer {$token}\".PHP_EOL;\n\t\t\t$request['headers'] .= \"Content-Length: {$content_length}\".PHP_EOL;\n\t\t\t$request['headers'] .= \"Content-Range: bytes {$offset}-{$end}/{$file_size}\";\n\t\t\t$request['post_data'] = $post_data;\n\t\t\t$resp = fetch::put($request);\n\t\t\t$data = json_decode($resp->content, true);\n\t\t\treturn $data;\n\t\t}\n\n\t\tstatic function upload_session_status($url){\n\t\t\t$token = self::access_token();\n\t\t\tfetch::$headers = \"Authorization: bearer {$token}\".PHP_EOL.\"Content-Type: application/json\".PHP_EOL;\n\t\t\t$resp = fetch::get($url);\n\t\t\t$data = json_decode($resp->content, true);\n\t\t\treturn $data;\n\t\t}\n\n\t\tstatic function delete_upload_session($url){\n\t\t\t$token = self::access_token();\n\t\t\tfetch::$headers = \"Authorization: bearer {$token}\".PHP_EOL.\"Content-Type: application/json\".PHP_EOL;\n\t\t\t$resp = fetch::delete($url);\n\t\t\t$data = json_decode($resp->content, true);\n\t\t\treturn $data;\n\t\t}\n\n\t\tstatic function file_content($file, $offset, $length){\n\t\t\t$handler = fopen($file, \"rb\") OR die('获取文件内容失败');\n\t\t\tfseek($handler, $offset);\n\t\t\t\n\t\t\treturn fread($handler, $length);\n\t\t}\n\n\t\tstatic function human_filesize($size, $precision = 1) {\n\t\t\tfor($i = 0; ($size / 1024) > 1; $i++, $size /= 1024) {}\n\t\t\treturn round($size, $precision).(['B','KB','MB','GB','TB','PB','EB','ZB','YB'][$i]);\n\t\t}\n\n\t\tstatic function urlencode($path){\n\t\t\tforeach(explode('/', $path) as $k=>$v){\n\t\t\t\tif(empty(!$v)){\n\t\t\t\t\t$paths[] = rawurlencode($v);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn @join('/',$paths);\n\t\t}\n\t\t\t\n\t\tstatic function _filesize($path){\n\t\t    if (!file_exists($path))\n\t\t        return false;\n\t\t    $size = filesize($path);\n\t\t    \n\t\t    if (!($file = fopen($path, 'rb')))\n\t\t        return false;\n\t\t    \n\t\t    if ($size >= 0){//Check if it really is a small file (< 2 GB)\n\t\t        if (fseek($file, 0, SEEK_END) === 0){//It really is a small file\n\t\t            fclose($file);\n\t\t            return $size;\n\t\t        }\n\t\t    }\n\t\t    \n\t\t    //Quickly jump the first 2 GB with fseek. After that fseek is not working on 32 bit php (it uses int internally)\n\t\t    $size = PHP_INT_MAX - 1;\n\t\t    if (fseek($file, PHP_INT_MAX - 1) !== 0){\n\t\t        fclose($file);\n\t\t        return false;\n\t\t    }\n\t\t    \n\t\t    $length = 1024 * 1024;\n\t\t    while (!feof($file)){//Read the file until end\n\t\t        $read = fread($file, $length);\n\t\t        $size = bcadd($size, $length);\n\t\t    }\n\t\t    $size = bcsub($size, $length);\n\t\t    $size = bcadd($size, strlen($read));\n\t\t    \n\t\t    fclose($file);\n\t\t    return $size;\n\t\t}\n\n\t\t//新建文件夹\n\t\tpublic static function create_folder($path = '/', $name = '新建文件夹')\n\t\t{\n\t\t\t$path = self::urlencode($path);\n\t\t\t$path = empty($path) ? '/' : \":/{$path}:/\";\n\t\t\t$api = self::$api_url.\"/me/drive/root\".$path.'/children';\n\t\t\t$token = self::access_token();\n\t\t\t$curl = curl_init();\n\t\t\tcurl_setopt_array($curl, array(\n\t\t\t\tCURLOPT_URL => $api,\n\t\t\t\tCURLOPT_RETURNTRANSFER => true,\n\t\t\t\tCURLOPT_ENCODING => '',\n\t\t\t\tCURLOPT_MAXREDIRS => 10,\n\t\t\t\tCURLOPT_TIMEOUT => 0,\n\t\t\t\tCURLOPT_FOLLOWLOCATION => true,\n\t\t\t\tCURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,\n\t\t\t\tCURLOPT_CUSTOMREQUEST => 'POST',\n\t\t\t\tCURLOPT_POSTFIELDS => \"{\\n  \\\"name\\\": \\\"\".$name.\"\\\",\\n  \\\"folder\\\": { },\\n  \\\"@microsoft.graph.conflictBehavior\\\": \\\"rename\\\"\\n}\",\n\t\t\t\tCURLOPT_HTTPHEADER => array(\n\t\t\t\t\t'Authorization: Bearer '.$token.'',\n\t\t\t\t\t'Content-Type: application/json',\n\t\t\t\t),\n\t\t\t));\n\t\n\t\t\t$response = curl_exec($curl);\n\t\n\t\t\tcurl_close($curl);\n\t\t\treturn $response;\n\t\t}\n\n\t\t//文件重命名\n\t\tpublic static function rename($itemid, $name)\n\t\t{\n\t\t\t$token = self::access_token();\n\t\t\t$api = str_replace('root', 'items/'.$itemid, self::$api_url.\"/me/drive/root\");\n\t\t\t$curl = curl_init();\n\t\t\tcurl_setopt_array($curl, array(\n\t\t\t\tCURLOPT_URL => $api,\n\t\t\t\tCURLOPT_RETURNTRANSFER => true,\n\t\t\t\tCURLOPT_ENCODING => '',\n\t\t\t\tCURLOPT_MAXREDIRS => 10,\n\t\t\t\tCURLOPT_TIMEOUT => 0,\n\t\t\t\tCURLOPT_FOLLOWLOCATION => true,\n\t\t\t\tCURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,\n\t\t\t\tCURLOPT_CUSTOMREQUEST => 'PATCH',\n\t\t\t\tCURLOPT_POSTFIELDS => \"{\\n  \\\"name\\\": \\\"\".$name.\"\\\"\\n}\",\n\t\t\t\tCURLOPT_HTTPHEADER => array(\n\t\t\t\t\t'Authorization: Bearer '.$token,\n\t\t\t\t\t'Content-Type: application/json',\n\t\t\t\t),\n\t\t\t));\n\t\t\t$response = curl_exec($curl);\n\t\t\tcurl_close($curl);\n\t\t\treturn $response;\n\t\t}\n\t\t\n\t\t  //文件删除\n\t\t  public static function delete($itemid = array())\n\t\t  {\n\t\t\t  $access_token = self::access_token();\n\t\t\t  $apie = str_replace('root', 'items/', self::$api_url.\"/me/drive/root\");\n\t\t\t  $apis = array();\n\t\t\t  for ($i = 0; $i < count($itemid); ++$i) {\n\t\t\t\t  $apis[$i] = $apie.$itemid[$i];\n\t\t\t  }\n\t\t\t  $result = $res = $ch = array();\n\t\t\t  $nch = 0;\n\t\t\t  $mh = curl_multi_init();\n\t\t\t  foreach ($apis as $nk => $url) {\n\t\t\t\t  $timeout = 20;\n\t\t\t\t  $ch[$nch] = curl_init();\n\t\t\t\t  curl_setopt_array($ch[$nch], array(\n\t\t\t\t\t  CURLOPT_URL => $url,\n\t\t\t\t\t  CURLOPT_TIMEOUT => $timeout,\n\t\t\t\t\t  CURLOPT_RETURNTRANSFER => true,\n\t\t\t\t\t  CURLOPT_MAXREDIRS => 10,\n\t\t\t\t\t  CURLOPT_FOLLOWLOCATION => true,\n\t\t\t\t\t  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,\n\t\t\t\t\t  CURLOPT_CUSTOMREQUEST => 'DELETE',\n\t\t\t\t\t  CURLOPT_HTTPHEADER => array(\n\t\t\t\t\t\t  'Authorization: Bearer '.$access_token,\n\t\t\t\t\t\t  'Content-Type: application/json',\n\t\t\t\t\t  ),\n\t\t\t\t  ));\n\t  \n\t\t\t\t  curl_multi_add_handle($mh, $ch[$nch]);\n\t\t\t\t  ++$nch;\n\t\t\t  }\n\t  \n\t\t\t  /* wait for performing request */\n\t  \n\t\t\t  do {\n\t\t\t\t  $mrc = curl_multi_exec($mh, $running);\n\t\t\t  } while (CURLM_CALL_MULTI_PERFORM == $mrc);\n\t  \n\t\t\t  while ($running && $mrc == CURLM_OK) {\n\t\t\t\t  // wait for network\n\t\t\t\t  if (curl_multi_select($mh, 0.5) > -1) {\n\t\t\t\t\t  // pull in new data;\n\t\t\t\t\t  do {\n\t\t\t\t\t\t  $mrc = curl_multi_exec($mh, $running);\n\t\t\t\t\t  } while (CURLM_CALL_MULTI_PERFORM == $mrc);\n\t\t\t\t  }\n\t\t\t  }\n\t  \n\t\t\t  if ($mrc != CURLM_OK) {\n\t\t\t\t  error_log('CURL Data Error');\n\t\t\t  }\n\t\t\t  /* get data */\n\t\t\t  $nch = 0;\n\t\t\t  foreach ($apis as $moudle => $node) {\n\t\t\t\t  if (($err = curl_error($ch[$nch])) == '') {\n\t\t\t\t\t  $res[$nch] = curl_multi_getcontent($ch[$nch]);\n\t\t\t\t\t  $result[$moudle] = $res[$nch];\n\t\t\t\t  } else {\n\t\t\t\t\t  error_log('curl error');\n\t\t\t\t  }\n\t\t\t\t  curl_multi_remove_handle($mh, $ch[$nch]);\n\t\t\t\t  curl_close($ch[$nch]);\n\t\t\t\t  ++$nch;\n\t\t\t  }\n\t\t\t  curl_multi_close($mh);\n\t\t\t  return $result;\n\t\t  }\n\t\t  \n\t\t//文件批量移动\n\t\tpublic static function move($itemid = array(), $newitemid)\n\t\t{\t\t\n\t\t\t// var_dump($itemid);\n\t\t\t$apis = array();\n\t\t\t$api = str_replace('root', 'items/', self::$api_url.\"/me/drive/root\");\n\t\t\tfor ($i = 0; $i < count($itemid); ++$i) {\n\t\t\t\t$apis[$i] = $api.$itemid[$i];\n\t\t\t}\n\n\t\t\n\t\t\t// $result = $res = $ch = array();\n\t\t\t$nch = 0;\n\t\t\t$mh = curl_multi_init();\n\t\t\tforeach ($apis as $nk => $url) {\n\t\t\t\t$timeout = 20;\n\t\t\t\t$ch[$nch] = curl_init();\n\t\t\t\tcurl_setopt_array($ch[$nch], array(\n\t\t\t\t\tCURLOPT_URL => $url,\n\t\t\t\t\tCURLOPT_TIMEOUT => $timeout,\n\t\t\t\t\tCURLOPT_RETURNTRANSFER => true,\n\t\t\t\t\tCURLOPT_MAXREDIRS => 10,\n\t\t\t\t\tCURLOPT_FOLLOWLOCATION => true,\n\t\t\t\t\tCURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,\n\t\t\t\t\tCURLOPT_CUSTOMREQUEST => 'PATCH',\n\t\t\t\t\tCURLOPT_POSTFIELDS => \"{\\n  \\\"parentReference\\\": {\\n    \\\"id\\\": \\\"\".$newitemid.\"\\\"\\n  }\\n  \\n}\",\n\t\t\t\t\tCURLOPT_HTTPHEADER => array(\n\t\t\t\t\t\t'Authorization: Bearer '.self::access_token(),\n\t\t\t\t\t\t'Content-Type: application/json',\n\t\t\t\t\t),\n\t\t\t\t));\n\n\t\t\t\tcurl_multi_add_handle($mh, $ch[$nch]);\n\t\t\t\t++$nch;\n\t\t\t}\n\n\t\t\t/* wait for performing request */\n\n\t\t\tdo {\n\t\t\t\t$mrc = curl_multi_exec($mh, $running);\n\t\t\t} while (CURLM_CALL_MULTI_PERFORM == $mrc);\n\n\t\t\twhile ($running && $mrc == CURLM_OK) {\n\t\t\t\t// wait for network\n\t\t\t\tif (curl_multi_select($mh, 0.5) > -1) {\n\t\t\t\t\t// pull in new data;\n\t\t\t\t\tdo {\n\t\t\t\t\t\t$mrc = curl_multi_exec($mh, $running);\n\t\t\t\t\t} while (CURLM_CALL_MULTI_PERFORM == $mrc);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ($mrc != CURLM_OK) {\n\t\t\t\terror_log('CURL Data Error');\n\t\t\t}\n\n\t\t\t/* get data */\n\n\t\t\t$nch = 0;\n\n\t\t\tforeach ($apis as $moudle => $node) {\n\t\t\t\tif (($err = curl_error($ch[$nch])) == '') {\n\t\t\t\t\t$res[$nch] = curl_multi_getcontent($ch[$nch]);\n\t\t\t\t\t$result[$moudle] = $res[$nch];\n\t\t\t\t} else {\n\t\t\t\t\terror_log('curl error');\n\t\t\t\t}\n\n\t\t\t\tcurl_multi_remove_handle($mh, $ch[$nch]);\n\t\t\t\tcurl_close($ch[$nch]);\n\t\t\t\t++$nch;\n\t\t\t}\n\n\t\t\tcurl_multi_close($mh);\n\t\t\treturn $result;\n\t\t}\n\n\t\t //文件批量复制\n\t\t public static function copy($itemids=array(), $destitemid){\n\t\t\t\n\t\t\t$detail = self::detail($destitemid);\n\t\t\t$dvid = $detail['parentReference']['driveId'];//其driveid与其父项dvid相同\n\t\t\t$token = self::access_token();\n\t\t\t$request['headers'] = \"Authorization: bearer {$token}\".PHP_EOL.\"Content-Type: application/json\".PHP_EOL;\n\t\t\tforeach($itemids as $index => $itemid){\n\t\t\t\t$itemdetail=self::detail($itemid);\n\t\t\t\t$request['url'] = self::$api_url.\"/me/drive/items/\".$itemid.'/copy';\n\t\t\t\t$request['post_data'] = '{\"parentReference\": {\"driveId\": \"'.$dvid.'\",\"id\": \"'.$destitemid.'\"},\"name\": \"'.$itemdetail['name'].'\"}';\n\t\t\t\t$resp[$index]=fetch::post($request);\n\t\t\t}\n\t\t\treturn $resp;\n\t\t }\n\n\t\t //文件路径转itemid\n\t\t public static function path2id($path)\n\t\t {\n\t\t\t $request = self::request(urldecode($path));\n\t\t\t $access_token = self::access_token();\n\t\t\t $request['headers'] = \"Authorization: bearer {$access_token}\".PHP_EOL.'Content-Type: application/json'.PHP_EOL;\n\t\t\t $resp = fetch::get($request);\n\t\t\t $data = json_decode($resp->content, true);\n\t\t\t return $data['id'];\n\t\t }\n\n\t\t //itemid转文件路径，原理：移动项目到其本身所在文件夹，可以返回其路径信息\n\t\t //itemid：待转item的id\n\t\t //parentid：待转item父项id。\n\t\t public static function id2path($itemid)\n\t\t {\n\t\t\t$resp_json = self::detail($itemid);\n\t\t\t$totalpath=$resp_json['parentReference']['path'];\n\t\t\t$count=strpos($totalpath,\"/drive/root:\");\n\t\t\t$pathwithroot=substr_replace($totalpath,\"\",$count,strlen('/drive/root:'));\n\t\t\t$count2 = strpos($pathwithroot,chr(config('onedrive_path')));\n\t\t\t$path = config('root_path').'/'.substr_replace($pathwithroot,\"\",$count2,strlen(config('onedrive_root'))).'/';\n\t\t\t$path = str_replace(\"//\",'/',$path).$resp_json['name'];\n\t\t\treturn $path;\n\t\t }\n\n\t\t //itemid获取详细信息\n\t\t public static function detail($itemid){\n\t\t\t$token = self::access_token();\n\t\t\t$request['headers'] = \"Authorization: bearer {$token}\".PHP_EOL.\"Content-Type: application/json\".PHP_EOL;\n\t\t\t$request['url'] = self::$api_url.\"/me/drive/items/\".$itemid;\n\t\t\t$resp = fetch::get($request);\n\t\t\t$data = json_decode($resp->content, true);\n\t\t\treturn $data;\n\t\t }\n\n\t\t\n\t}\n"
  },
  {
    "path": "lib/oneindex.php",
    "content": "<?php\n\tclass oneindex{\n\t\tstatic $dir = array();\n\t\tstatic $file = array();\n\t\tstatic $thumb = array();\n\n\t\t//使用 $refresh_token，获取 $access_token\n\t\tstatic function get_token($refresh_token){\n\t\t\t\n\t\t}\n\n\t\t// 刷新缓存\n\t\tstatic function refresh_cache($path){\n\t\t\tset_time_limit(0);\n\t\t\tif( php_sapi_name() == \"cli\" ){\n\t\t\t   echo $path.PHP_EOL;\n\t\t\t}\n\t\t\t$items = onedrive::dir($path);\n\t\t\tif(is_array($items)){\n\t\t\t\tcache::set('dir_'.$path, $items, config('cache_expire_time') );\n\t\t\t}\n\t\t\tforeach((array)$items as $item){\n\t\t\t    if($item['folder']){\n\t\t\t        self::refresh_cache($path.$item['name'].'/');\n\t\t\t    }\n\t\t\t}\n\t\t}\n\n\t\t// 列目录\n\t\tstatic function dir($path = '/'){\n\t\t\t$path = self::get_absolute_path($path);\n\n\t\t\tif(!empty(self::$dir[$path])){\n\t\t\t\treturn self::$dir[$path];\n\t\t\t} \n\t\t\t\n\t\t\tself::$dir[$path] = cache::get('dir_'.$path, function() use ($path){\n\t\t\t\treturn onedrive::dir($path);\n\t\t\t}, config('cache_expire_time'));\n\t\t\treturn self::$dir[$path];\n\t\t}\n\n\t\t// 获取文件信息\n\t\tstatic function file($path){\n\t\t\t$path = self::get_absolute_path($path);\n\t\t\t$path_parts = pathinfo($path);\n\t\t\t$items = self::dir($path_parts['dirname']);\n\t\t\tif(!empty($items) && !empty($items[$path_parts['basename']])){\n\t\t\t\treturn $items[$path_parts['basename']];\n\t\t\t}\n\t\t}\n\n\t\t\n\t\t// 文件是否存在\n\t\tstatic function file_exists($path){\n\t\t\tif(!empty(self::file($path))){\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\n\t\t//获取文件内容\n\t\tstatic function get_content($path){\n\t\t\t$item = self::file($path);\n\t\t\t// 仅小于10M 获取内容\n\t\t\tif(empty($item) OR $item['size'] > 10485760){\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\treturn cache::get('content_'.$item['path'], function() use ($item){\n\t\t\t\t$resp = fetch::get($item['downloadUrl']);\n\t\t\t\tif($resp->http_code == 200){\n\t\t\t\t\treturn $resp->content;\n\t\t\t\t}\n\t\t\t}, config('cache_expire_time') );\n\t\t}\n\n\n\n\t\t//缩略图\n\t\tstatic function thumb($path,$width=800,$height=800){\n\t\t\t$path = self::get_absolute_path($path);\n\t\t\tif(empty(self::$thumb[$path])){\n\t\t\t\tself::$thumb[$path] = cache::get('thumb_'.$path, function() use ($path){\n\t\t\t\t\t$url = onedrive::thumbnail($path);\n\t\t\t\t\tlist($url,$tmp) = explode('&width=', $url);\n\t\t\t\t\treturn $url;\n\t\t\t\t}, config('cache_expire_time'));\n\t\t\t}\n\t\t\t\n\t\t\tself::$thumb[$path] .= strpos(self::$thumb[$path], '?')?'&':'?';\n\t\t\treturn self::$thumb[$path].\"width={$width}&height={$height}\";\n\t\t}\n\n\t\t//获取下载链接\n\t\tstatic function download_url($path){\n\t\t\t$item = self::file($path);\n\t\t\tif(!empty($item['downloadUrl'])){\n\t\t\t\treturn $item['downloadUrl'];\n\t\t\t}\n\t\t\treturn false;\n\t\t}\n\n\t\tstatic function web_url($path){\n\t\t\t$path = self::get_absolute_path($path);\n\t\t\t$path = rtrim($path, '/');\n\n\t\t\tif(!empty(config($path.'@weburl'))){\n\t\t\t\treturn config($path.'@weburl');\n\t\t\t}else{\n\t\t\t\t$share = onedrive::share($path);\n\t\t\t\tif(!empty($share['link']['webUrl'])){\n\t\t\t\t\tconfig($path.'@weburl', $share['link']['webUrl']);\n\t\t\t\t\treturn $share['link']['webUrl'];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tstatic function direct_link($path){\n\t\t\t$web_url = self::web_url($path);\n\t\t\tif(!empty($web_url)){\n\t\t\t\t$arr = explode('/', $web_url);\n\t\t\t\tif( strpos($arr[2],'sharepoint.com') >0 ){\n\t\t\t\t\t$k = array_pop($arr);\n\t\t\t\t\tunset($arr[3]);\n\t\t\t\t\tunset($arr[4]);\n\t\t\t\t\treturn join('/', $arr).'/_layouts/15/download.aspx?share='.$k;\n\t\t\t\t}elseif ( strpos($arr[2],'1drv.ms') >0 ){\n\t\t\t\t\t# code...\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\n\t\t//工具函数获取绝对路径\n\t\tstatic function get_absolute_path($path) {\n\t\t    $path = str_replace(array('/', '\\\\', '//'), '/', $path);\n\t\t    $parts = array_filter(explode('/', $path), 'strlen');\n\t\t    $absolutes = array();\n\t\t    foreach ($parts as $part) {\n\t\t        if ('.' == $part) continue;\n\t\t        if ('..' == $part) {\n\t\t            array_pop($absolutes);\n\t\t        } else {\n\t\t            $absolutes[] = $part;\n\t\t        }\n\t\t    }\n\t\t    return str_replace('//','/','/'.implode('/', $absolutes).'/');\n\t\t}\n\t}\n"
  },
  {
    "path": "lib/route.php",
    "content": "<?php\nclass route {\n\tpublic static $uri;\n\tprivate static $method;\n\tprivate static $root = '/';\n\tstatic $runed = false;\n\n\tpublic static $patterns = array(\n\t\t'#any' => '[^/]+',\n\t\t'#num' => '[0-9]+',\n\t\t'#all' => '.*',\n\t);\n\n\tpublic static function __callstatic($method, $args) {\n\t\tif (self::$runed) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (empty(self::$method)) {\n\t\t\tself::init();\n\t\t}\n\n\t\t$method = strtoupper($method);\n\t\tif ($method != self::$method && !in_array($method, ['ANY', 'ERROR', 'ON'])) {\n\t\t\treturn;\n\t\t}\n\t\t$pattern = trim(array_shift($args), '\\/');\n\t\t$pattern = self::$root . $pattern;\n\n\t\tif (self::uri_match($pattern, self::$uri)) {\n\t\t\tif (is_string($args[0]) && strpos($args[0], '@') > 0) {\n\t\t\t\tlist($class, $action) = explode('@', $args[0]);\n\t\t\t\t$object = new $class();\n\t\t\t\t$args[0] = array($object, $action);\n\t\t\t}\n\n\t\t\t$return = call_user_func($args[0]);\n\t\t\tif (is_array($return)) {\n\t\t\t\tprint json_encode($return);\n\t\t\t} else {\n\t\t\t\tprint (string) $return;\n\t\t\t}\n\t\t\tself::$runed = true;\n\t\t}\n\t}\n\n\tpublic static function init() {\n\t\tif (!empty(self::$method)) {return;}\n\t\tself::$uri = self::get_uri();\n\t\tself::$method = empty($_POST['_METHOD']) ? $_SERVER['REQUEST_METHOD'] : $_POST['_METHOD'];\n\t\tif (defined('CONTROLLER_PATH')) {\n\t\t\tspl_autoload_register(function ($class) {\n\t\t\t\t$file = CONTROLLER_PATH . $class . '.php';\n\t\t\t\tif (file_exists($file)) {\n\t\t\t\t\tinclude $file;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tpublic static function auto($controller_path) {\n\t\tself::init();\n\t\t$uri = self::get_uri();\n\t\tlist($tmp, $controller, $action) = explode('/', $uri);\n\t\t$controller = empty($controller) ? 'IndexController' : ucfirst($controller) . 'Controller';\n\t\t$action = empty($action) ? 'index' : $action;\n\t\t$file = $controller_path . $controller . '.php';\n\t\tif (file_exists($file)) {\n\t\t\tinclude $file;\n\t\t\tif (is_callable(array($controller, $action))) {\n\t\t\t\t$obj = new $controller();\n\t\t\t\tprint (string) $obj->$action();\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t}\n\n\tpublic static function group($middleware, $callback){\n\t\tself::init();\n\t\tif (is_string($middleware) && strpos($middleware, '@') > 0) {\n\t\t\tlist($class, $action) = explode('@', $middleware);\n\t\t\t$object = new $class();\n\t\t\t$result = $object->$action();\n\t\t}elseif(is_callable($middleware)){\n\t\t\t$result = $middleware();\n\t\t}\n\n\t\tif($result == true && is_callable($callback)){\n\t\t\treturn $callback();\n\t\t}\n\t}\n\n\tpublic static function resource($name, $controller) {\n\t\tself::get('/' . $name, $controller . '@index');\n\t\tself::get('/' . $name . '/add', $controller . '@add');\n\t\tself::post('/' . $name, $controller . '@store');\n\t\tself::get('/' . $name . '/{id:#num}', $controller . '@show');\n\t\tself::get('/' . $name . '/{id:#num}/edit', $controller . '@edit');\n\t\tself::post('/' . $name . '/{id:#num}', $controller . '@update');\n\t\tself::get('/' . $name . '/{id:#num}/delete', $controller . '@delete');\n\t}\n\n\tpublic static function uri_match($pattern, $uri) {\n\t\t$pattern = ($pattern == '/') ? '/' : rtrim($pattern, '\\/');\n\n\t\t$ps = explode('/', $pattern);\n\n\t\t$searches = array_keys(static::$patterns);\n\t\t$replaces = array_values(static::$patterns);\n\n\t\tforeach($ps as &$p){\n\t\t\t\t$p = str_replace($searches, $replaces, $p);\n\t\t\t\t$p = preg_replace(\"`\\{(\\w+)\\:([^\\)]+)\\}`\", '(?P<$1>$2)', $p);\t\n\t\t}\n\n\t\t$pattern = join('/',$ps);\n\n\t\tif (preg_match(\"`^{$pattern}$`\", $uri)) {\n\t\t\tpreg_match_all(\"`^{$pattern}$`\", $uri, $matches, PREG_PATTERN_ORDER);\n\t\t\tforeach ($matches as $key => $value) {\n\t\t\t\tif (!is_int($key)) {\n\t\t\t\t\t$_GET[$key] = $matches[$key][0];\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\t}\n\n\tpublic static function get_uri() {\n\t\t$file = basename($_SERVER['PHP_SELF']);\n\t\t$path = dirname($_SERVER['PHP_SELF']);\n\t\t$req_uri = $_SERVER['REQUEST_URI'];\n\n\t\tif ($path != '/' && strpos($req_uri, $path) === 0) {\n\t\t\t$req_uri = substr($req_uri, strlen($path));\n\t\t}\n\n\t\tif (strpos($req_uri, '/?/') === 0) {\n\t\t\t$req_uri = parse_url($req_uri, PHP_URL_QUERY);\n\t\t\tlist($req_uri) = explode('&', $req_uri);\n\t\t\tunset($_GET[$req_uri]);\n\t\t}\n\t\t$uri = parse_url($req_uri, PHP_URL_PATH);\n\t\treturn '/' . trim($uri, '\\/');\n\t}\n}"
  },
  {
    "path": "lib/sqlite.php",
    "content": "<?php\n\nclass sqlite implements \\Countable\n{\n    /**\n     * @var PDO\n     */\n    private $db = null;\n\n    /**\n     * @var string\n     */\n    private $name = null;\n\n    public function __construct($name, $filename = \"data.sqlite3\")\n    {\n        $this->db = new PDO('sqlite:' . $filename);\n        $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);\n        $this->name = $name;\n        $this->createTable();\n    }\n\n    /**\n     * @param string $key key\n     *\n     * @throws InvalidArgumentException\n     * @return string|null\n     */\n    public function get($key)\n    {\n        if (!is_string($key)) {\n            throw new InvalidArgumentException('Expected string as key');\n        }\n\n        $stmt = $this->db->prepare(\n            'SELECT value FROM ' . $this->name . ' WHERE key = :key;'\n        );\n        $stmt->bindParam(':key', $key, PDO::PARAM_STR);\n        $stmt->execute();\n\n        if ($row = $stmt->fetch(PDO::FETCH_OBJ)) {\n            return $row->value;\n        }\n\n        return null;\n    }\n\n    /**\n     * @param string $key key\n     * @param string $value value\n     *\n     * @throws InvalidArgumentException\n     */\n    public function set($key, $value)\n    {\n        if (!is_string($key)) {\n            throw new InvalidArgumentException('Expected string as key');\n        }\n\n        $queryString = 'REPLACE INTO ' . $this->name . ' VALUES (:key, :value);';\n        $stmt = $this->db->prepare($queryString);\n        $stmt->bindParam(':key', $key, \\PDO::PARAM_STR);\n        $stmt->bindParam(':value', $value, \\PDO::PARAM_STR);\n        $stmt->execute();\n    }\n\n    /**\n     * @param string $key key\n     *\n     * @return null\n     */\n    public function delete($key)\n    {\n        $stmt = $this->db->prepare(\n            'DELETE FROM ' . $this->name . ' WHERE key = :key;'\n        );\n        $stmt->bindParam(':key', $key, \\PDO::PARAM_STR);\n        $stmt->execute();\n    }\n\n    /**\n     * Delete all values from store\n     *\n     * @return null\n     */\n    public function deleteAll()\n    {\n        $stmt = $this->db->prepare('DELETE FROM ' . $this->name);\n        $stmt->execute();\n        $this->data = array();\n    }\n\n    /**\n     * @return int\n     */\n    public function count()\n    {\n        return (int) $this->db->query('SELECT COUNT(*) FROM ' . $this->name)->fetchColumn();\n    }\n\n    /**\n     * Create storage table in database if not exists\n     *\n     * @return null\n     */\n    private function createTable()\n    {\n        $stmt = 'CREATE TABLE IF NOT EXISTS \"' . $this->name . '\"';\n        $stmt.= '(key TEXT PRIMARY KEY, value TEXT);';\n        $this->db->exec($stmt);\n    }\n}\n"
  },
  {
    "path": "lib/view.php",
    "content": "<?php\n!defined('VIEW_PATH') && define('VIEW_PATH', 'view/');\nclass view {\n\tprivate $_view = array('file' => '', 'data' => array());\n\tstatic $_pos = null;\n    static $_section = null;\n\n\tstatic function load($file, $set = null) {\n\t\tif (is_int(strripos($file, '..'))) {\n\t\t\tdie(\"error view file name:$file\");\n\t\t}\n\t\t$file = str_replace('.', '/', $file);\n\n\t\treturn new view($file, $set);\n\t}\n\n\tpublic function __construct($file, $set = null) {\n\t\tif (isset(self::$_pos)) {\n\t\t\t$this->_view['parent'] = self::$_pos;\n\t\t\t$this->with($this->_view['parent']->_view['data']);\n\t\t}\n\t\t$this->_view['file'] = $file;\n\t\t$this->with($set);\n\t}\n\n\tpublic function with($name, $value = NULL) {\n\t\tif (is_array($name)) {\n\t\t\t$this->_view['data'] = array_merge($this->_view['data'], $name);\n\t\t} elseif (is_string($name)) {\n\t\t\t$this->_view['data'][$name] = $value;\n\t\t}\n\t\treturn $this;\n\t}\n\n\tpublic function __toString() {\n\t\tself::$_pos = $this;\n\n\t\t$this->_view['file'] = VIEW_PATH . $this->_view['file'] . '.php';\n\t\tif(!file_exists($this->_view['file'])){\n\t\t\tself::to404('404');\n\t\t}\n\n\t\textract($this->_view['data']);\n\n\t\tob_start();\n\t\tinclude $this->_view['file'];\n\n\t\tif (isset($this->_view['layout'])) {\n\t\t\techo $this->_view['layout'] . ob_get_clean();\n\t\t}\n\n\n\t\tself::$_pos = isset($this->_view['parent']) ? $this->_view['parent'] : NULL;\n\n\t\t$return_str = ob_get_clean();\n\n\t\treturn $return_str;\n\t}\n\n\tpublic function show() {\n\t\techo $this;\n\t}\n\n    \n\tstatic function layout($file) {\n\t\tob_start();\n\t\t$view_layout = self::load($file);\n\t\tself::$_pos->_view['layout'] = $view_layout;\n\t}\n\n\tstatic function section($name) {\n\t\tif (isset(self::$_pos->_view['section'][$name])) {\n\t\t\techo self::$_pos->_view['section'][$name];\n\t\t} elseif (isset(self::$_pos->_view['parent']->_view['section'][$name])) {\n\t\t\techo self::$_pos->_view['parent']->_view['section'][$name];\n\t\t}\n\t}\n\n\tstatic function begin($name) {\n        self::$_section = $name;\n\t\tob_start();\n\t}\n\n\tstatic function end() {\n\t\tself::$_pos->_view['section'][self::$_section] = ob_get_clean();\n        self::$_section = null;\n\t}\n\n\tstatic function direct($loction) {\n\t\theader(\"Location:$loction\");\n\t\texit();\n\t}\n\n\tstatic function abort() {\n\t\theader(\"HTTP/1.1 502 Bad Gateway\");\n\t\texit();\n\t}\n\n\tstatic function to404(){\n\t\theader(\"HTTP/1.1 404 Not Found\");\n\t\texit();\n\t}\n}\n"
  },
  {
    "path": "one.php",
    "content": "<?php \nif( php_sapi_name() !== \"cli\" ){\n   die( \"NoAccess\" );\n}\nrequire 'init.php';\nini_set('memory_limit', '128M');\n\nclass one{\n\tstatic function cache_clear(){\n\t\tcache::clear();\n\t}\n\n\tstatic function cache_refresh(){\n\t\toneindex::refresh_cache(get_absolute_path(config('onedrive_root')));\n\t}\n\n\tstatic function token_refresh(){\n\t\t$refresh_token = config('refresh_token');\n\t\t$token = onedrive::get_token($refresh_token);\n\t\tif(!empty($token['refresh_token'])){\n\t\t\tconfig('@token', $token);\n\t\t}\n\t}\n\n\tstatic function upload_file($localfile, $remotefile=null){\n\t\t$localfile = realpath($localfile);\n\t\tif(!file_exists($localfile)){\n\t\t\texit('file not exists');\n\t\t}\n\t\tprint ' 本地文件：'.$localfile.PHP_EOL;\n\n\t\tif(empty($remotefile)){\n\t\t\t$remotepath = pathinfo($localfile, PATHINFO_BASENAME);\n\t\t}elseif(substr($remotefile, -1) == '/'){\n\t\t\t$remotepath = get_absolute_path($remotefile);\n\t\t\t$remotepath = substr($remotepath,1).pathinfo($localfile, PATHINFO_BASENAME);\n\t\t}else{\n\t\t\t$remotepath = ltrim($remotefile, '/');\n\t\t}\n\t\tprint ' 远程文件：'.$remotepath.PHP_EOL;\n\t\t\n\t\t$filesize = onedrive::_filesize($localfile) OR die('无法获取文件大小');\n\t\tif($filesize < 10485760){\n\t\t\tprint ' 上传方式：直接上传'.PHP_EOL;\n\t\t\t$begin_time = microtime(true);\n\t\t\t$result = onedrive::upload($remotepath, file_get_contents($localfile));\n\t\t\tif(!empty($result)){\n\t\t\t\t$upload_time = microtime(true) - $begin_time;\n\t\t\t\tprint ' 上传成功:'.onedrive::human_filesize($filesize/$upload_time).'/s'.PHP_EOL;\n\t\t\t}else{\n\t\t\t\tprint ' 上传失败!'.PHP_EOL;\n\t\t\t}\n\t\t}else{\n\t\t\tprint ' 上传方式：分块上传'.PHP_EOL;\n\t\t\treturn self::upload_large_file($localfile, $remotepath);\n\t\t}\n\t\treturn;\n\t}\n\t\n\tstatic function upload_folder($localfolder, $remotefolder='/'){\n\t\t$localfolder = realpath($localfolder);\n\t\t$remotefolder = get_absolute_path($remotefolder);\n\t\tprint ' 开始上传文件夹'.PHP_EOL;\n\t\tself::folder2upload($localfolder,$remotefolder);\n\t}\n\n\tstatic function folder2upload($localfolder, $remotefolder){\n\t\t$files = scandir($localfolder);\n\t\tforeach ($files as $file) {\n\t\t\tif ($file == '.' || $file == '..') {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (is_dir($localfolder . '/' . $file)) {\n\t\t        self::folder2upload($localfolder . '/' . $file, $remotefolder.$file.'/');\n\t\t    }else{\n\t\t\t    $localfile = realpath($localfolder . '/' . $file);\n\t\t\t    $remotefile = $remotefolder.$file;\n\t\t\t    self::upload_file($localfile, $remotefile);\n\t\t    }\n\t\t}\n\t}\n\n\t//static function add2uploading($path,$remotefolder) {\n\t//  $files = scandir($path);\n\t//  foreach ($files as $file) {\n\t//    if ($file != '.' && $file != '..') {\n\t//      if (is_dir($path . '/' . $file)) {\n\t//        self::add2uploading($path . '/' . $file, $remotefolder.$file.'/');\n\t//      } else {\n\t//\t    $localfile = realpath($path . '/' . $file);\n\t//\t    echo $localfile.PHP_EOL;\n\t//\t    $remotepath = $remotefolder.$file;\n\t//        $task = array(\n\t//\t\t\t'localfile'=>$localfile,\n\t//\t\t\t'remotepath' => $remotepath,\n\t//\t\t\t'filesize'=>onedrive::_filesize($localfile),\n\t//\t\t\t'update_time'=>0\n\t//        );\n\t//        $uploads = config('@upload');\n\t//        if(empty($uploads[$remotepath])){\n\t//\t        $uploads[$remotepath] = $task;\n\t//\t        config('@upload', $uploads);\n\t//        }\n\t//      }\n\t//    }\n\t//  }\n\t//}\n\n\n\tstatic function upload_large_file($localfile, $remotepath){\n\t\tfetch::init([CURLOPT_TIMEOUT=>200]);\n\t\t$upload = config('@upload');\n\t\t$info = $upload[$remotepath];\n\t\tif(empty($info['url'])){\n\t\t\tprint ' 创建上传会话'.PHP_EOL;\n\t\t\t$data = onedrive::create_upload_session($remotepath);\n\t\t\tif(!empty($data['uploadUrl'])){\n\t\t\t\t$info['url'] = $data['uploadUrl'];\n\t\t\t\t$info['localfile'] = $localfile;\n\t\t\t\t$info['remotepath'] = $remotepath;\n\t\t\t\t$info['filesize'] = onedrive::_filesize($localfile);\n\t\t\t\t$info['offset'] = 0;\n\t\t\t\t$info['length'] = 327680;\n\t\t\t\t$info['update_time'] = time();\n\t\t\t\t$upload[$remotepath] = $info;\n\t\t\t\tconfig('@upload', $upload);\n\t\t\t}elseif ( $data === false ){\n\t\t\t\tprint ' 文件已存在!'.PHP_EOL;\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\t\n\t\tif(empty($info['url'])){\n\t\t\tprint ' 获取会话失败！'.PHP_EOL;\n\t\t\tsleep(3);\n\t\t\treturn self::upload_large_file($localfile, $remotepath);\n\t\t}\n\t\t\n\t\tprint ' 上传分块'.onedrive::human_filesize($info['length']).'\t';\n\t\t$begin_time = microtime(true);\n\t\t$data = onedrive::upload_session($info['url'], $info['localfile'], $info['offset'], $info['length']);\n\n\t\tif(!empty($data['nextExpectedRanges'])){\n\t\t\t$upload_time = microtime(true) - $begin_time;\n\t\t\t$info['speed'] = $info['length']/$upload_time;\n\t\t\t\n\t\t\tprint onedrive::human_filesize($info['speed']).'/s'.'\t'.round(($info['offset']/$info['filesize'])*100).'%\t'.PHP_EOL;\n\t\t\t$info['length'] = intval($info['length']/$upload_time/32768*2)*327680;\n\t\t\t$info['length'] = ($info['length']>104857600)?104857600:$info['length'];\n\t\t\t\n\t\t\tlist($offset, $filesize) = explode('-',$data['nextExpectedRanges'][0]);\n\t\t\t$info['offset'] = $offset;\n\t\t\t$info['update_time'] = time();\n\t\t\t$upload[$remotepath] = $info;\n\t\t\tconfig('@upload', $upload);\n\t\t}elseif(!empty($data['@content.downloadUrl']) || !empty($data['id'])){\n\t\t\tunset($upload[$remotepath]);\n\t\t\tconfig('@upload', $upload);\n\t\t\tprint ' 上传完成！'.PHP_EOL;\n\t\t\treturn;\n\t\t}else{\n\t\t\tprint ' 失败!'.PHP_EOL;\n\t\t\t$data = onedrive::upload_session_status($info['url']);\n\t\t\tif(empty($data)|| $info['length']<100){\n\t\t\t\tonedrive::delete_upload_session($info['url']);\n\t\t\t\tunset($upload[$remotepath]);\n\t\t\t\tconfig('@upload', $upload);\n\t\t\t}elseif(!empty($data['nextExpectedRanges'])){\n\t\t\t\tlist($offset, $filesize) = explode('-',$data['nextExpectedRanges'][0]);\n\t\t\t\t$info['offset'] = $offset;\n\t\t\t\t$info['length'] = $info['length']/1.5;\n\t\t\t\t$upload[$remotepath] = $info;\n\t\t\t\tconfig('@upload', $upload);\n\t\t\t}\n\t\t}\n\n\t\treturn self::upload_large_file($localfile, $remotepath);\n\t\t\n\t}\n\n\t\n}\n\n\narray_shift($argv);\n$action = str_replace(':', '_',array_shift($argv));\n\nif(is_callable(['one',$action])){\n\t@call_user_func_array(['one',$action], $argv);\n\texit();\n}\n?>\noneindex commands :\n cache\n  cache:clear    \tclear cache\n  cache:refresh  \trefresh cache\n token\n  token:refresh  \trefresh token\n upload\n  upload:file  \t\tupload a file to onedrive\n  upload:folder  \tupload a folder to onedrive\n"
  },
  {
    "path": "statics/common/offline/css/main.css",
    "content": "/* \n * Copyright (C) 2015 Binux <roy@binux.me>\n *\n * This file is part of YAAW (https://github.com/binux/yaaw).\n *\n * YAAW is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Lesser General Public License as\n * published by the Free Software Foundation, either version 3 of\n * the License, or (at your option) any later version.\n *\n * YAAW is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Lesser General Public License for more details.\n *\n * You may get a copy of the GNU Lesser General Public License\n * from http://www.gnu.org/licenses/lgpl.txt\n *\n */\n\n.select-box {\n    cursor: pointer;\n    user-select: none;\n    -moz-user-select: none;\n}\n.btn-inline {\n    /* fix for MAC/chrome */\n    display: inline !important;\n}\n.btn-inline:before, .btn-inline:after {\n    /* fix for IE8 */\n    content: none !important;\n    display: none !important;\n}\n\n/* header */\n.main-head {\n    position: relative;\n}\n.main-head h1 {\n    display: inline-block;\n}\n\n#main-alert {\n    position: absolute;\n    left: 0;\n    width: 100%;\n    text-align: center;\n}\n#main-alert-inline {\n    display: inline-block;\n    text-align: left;\n    position: relative;\n    top: -10px;\n    z-index: 99;\n}\n\n#global-info {\n    position: absolute;\n    bottom: 0;\n    right: 0;\n}\n#global-version {\n    text-align: right;\n}\n\n/* main-control */\n#main-control {\n    margin-top: 10px;\n}\n\n#select-btn {\n    margin-right: 30px;\n}\n.select-box {\n    display: inline-block;\n    vertical-align: text-top;\n    border: 1px solid #C6C6C6;\n    border: 1px solid rgba(155, 155, 155, .57);\n    width: 14px;\n    height: 14px;\n    line-height: 14px;\n}\n\n#do-all-btn {\n    position: relative;\n    margin-left: 10px;\n}\n\n#info-btn {\n    margin-left: 10px;\n}\n\n#other-grp {\n}\n\n/* active-tasks */\n#active-tasks {\n    margin-top: 40px;\n}\n.empty-tasks {\n    text-align: center;\n    padding: 8px;\n}\n.section-header {\n    font-size: 16px;\n}\n.section-header i {\n    margin-right: 5px;\n    vertical-align: baseline;\n}\n\n/* other-tasks */\n#other-tasks {\n    margin-top: 40px;\n}\n#waiting-tasks-table {\n    margin-bottom: 0;\n}\n#stopped-tasks-table {\n    border-top: 0;\n    margin-top: 0;\n}\n\n/* tasks */\n.tasks-table {\n    margin: 0;\n    margin-top: 10px;\n}\n\n.task.selected {\n    background-color: #F9F9F9;\n}\n.tasks-table > li {\n    display: block;\n    position: relative;\n    margin-top: -1px;\n    border-top: 1px solid #DDD;\n    border-bottom: 1px solid #DDD;\n    line-height: 18px;\n    text-align: left;\n    vertical-align: top;\n}\n.tasks-table > li:hover {\n    background-color: #f5f5f5;\n}\n\n.left-area {\n    position: relative;\n    padding: 8px;\n}\n.right-area {\n    position: absolute;\n    top: 0;\n    right: 0;\n    padding: 8px;\n}\n\n.task .task-name {\n    cursor: pointer;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    white-space: nowrap;\n}\n.task .task-name span {\n    word-break: break-all;\n    margin-left: 3px;\n    font-size: 18px;\n    font-weight: bold;\n}\n\n.task .task-name .select-box {\n    vertical-align: -15%;\n}\n.task:hover .select-box {\n    border-color: #666;\n}\n\n.task .task-info span {\n    margin-right: 8px;\n}\n\n.task .task-info,\n.task .progress-info {\n    margin-top: 4px;\n}\n.task .progress {\n    margin: 1px 0;\n}\n\n.task .download-speed,\n.task .upload-speed,\n.task .seeders {\n    margin-right: 8px;\n}\n\n#other-tasks .task-info {\n    margin: 0;\n    overflow: hidden;\n    white-space: nowrap;\n}\n\n@media (max-height: 600px) {\n    .modal.fade.in {\n        position: absolute;\n        top: 260px;\n    }\n}\n\n@media (max-width: 550px) {\n    .modal.fade.in {\n        top: 60px;\n    }\n    .modal-body {\n        max-height: none;\n    }\n\n    #main-alert {\n        top: 25px;\n    }\n\n    #offline-cached {\n        display: none;\n    }\n\n    #select-btn {\n        margin-right: 10px;\n    }\n    #not-selected-grp {\n        float: right;\n    }\n    #selected-grp {\n        float: right;\n    }\n    #other-grp {\n        clear: both;\n        margin-top: 5px;\n    }\n\n    #active-tasks {\n        margin-top: 20px;\n    }\n    #active-tasks .left-area {\n        padding-bottom: 0;\n        margin-right: 0;\n    }\n    .task .task-name {\n        margin-right: 0;\n        overflow: visible;\n        white-space: normal;\n    }\n    #active-tasks .right-area {\n        padding-top: 0;\n        position: relative;\n        width: auto;\n    }\n\n    #other-tasks .left-area {\n        margin-right: 0;\n    }\n    #other-tasks .right-area {\n        position: relative;\n        padding-top: 0;\n    }\n    #other-tasks .right-area .task-info {\n        position: absolute;\n        top: 0;\n        left: 0;\n    }\n    #other-tasks .right-area .pull-right {\n        width: 100%;\n    }\n    #other-tasks .right-area .pull-right .progress {\n        margin-left: 110px;\n    }\n}\n@media (min-width: 551px) and (max-width: 980px) {\n    #active-tasks .left-area {\n        margin-right: 186px;\n    }\n    #active-tasks .right-area {\n        width: 170px;\n    }\n\n    #other-tasks .left-area {\n        margin-right: 246px;\n    }\n    #other-tasks .right-area {\n        width: 230px;\n    }\n    #other-tasks .task-info {\n        width: 120px;\n    }\n    #other-tasks .progress {\n        width: 100px;\n    }\n}\n@media (min-width: 980px) {\n    #active-tasks .left-area {\n        margin-right: 286px;\n    }\n    #active-tasks .right-area {\n        width: 270px;\n    }\n\n    #other-tasks .left-area {\n        margin-right: 416px;\n    }\n    #other-tasks .right-area {\n        width: 400px;\n    }\n    #other-tasks .task-info {\n        width: 190px;\n    }\n    #other-tasks .progress {\n        width: 200px;\n    }\n}\n\n/* task infobox */\n.info-open {\n    background-color: #F9F9F9;\n}\n.info-box {\n}\n.info-box .tab-content {\n    height: 300px;\n    overflow-y: auto;\n}\n.info-box .nav {\n    margin-top: -1px;\n    margin-bottom: 0;\n    height: 300px;\n}\n#ib-status,\n#ib-options,\n#ib-peers {\n    position: relative;\n    margin: 18px 0;\n}\n#ib-files .file-list {\n    margin-left: -25px;\n}\n#ib-files ul,\n#ib-options ul {\n    margin-top: 5px;\n}\n#ib-files li {\n    display: block;\n    cursor: pointer;\n    line-height: 14px;\n    padding-bottom: 6px;\n    vertical-align: top;\n    border-bottom: 1px solid #FFF;\n}\n#ib-files .ib-file-title:hover {\n    border-bottom: 1px solid #666;\n}\n#ib-file-btn,\n#ib-options-btn {\n    float: right !important;\n    margin: 0 0 5px 5px;\n}\n@media (max-width: 980px) {\n    #ib-file-btn, #ib-options-btn {\n        float: none !important;\n        margin-bottom: 5px;\n    }\n}\n.ib-file-title {\n    margin-left: 5px;\n}\n.ib-file-size {\n    margin-left: 20px;\n}\n#ib-options li {\n    display: block;\n    float: left;\n    padding-bottom: 6px;\n    margin-right: 100px;\n}\n#ib-options li span {\n    display: block;\n    text-align: right;\n    padding-right: 1em;\n    width: 140px;\n    line-height: 24px;\n}\n#ib-options li > * {\n    float: left;\n}\n#ib-peers .ip_port {\n    display: inline-block;\n    width: 250px;\n}\n\n/* task-contextmenu */\n\n#task-contextmenu {\n    position: fixed;\n    z-index: 99;\n}\n\n/* add task modal */\n#add-task-modal {\n    overflow-x: hidden;\n}\n#add-task-modal .modal-body.hover {\n    padding: 13px;\n    border: 2px solid #666;\n}\n\n#add-task-uri {\n    text-align: center;\n    white-space: nowrap;\n    padding: 10px 19px;\n    margin: 0;\n    overflow: hidden;\n}\n#add-task-uri div {\n    padding-right: 118px;\n}\n#uri-input {\n    width: 100%; \n}\n#uri-textarea {\n    box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    width: 100%;\n    margin: 0;\n}\n\n#uri-more {\n    font-size: 7px;\n    text-align: center;\n    height: 10px;\n    margin: 0 20px 20px;\n    line-height: 10px;\n    color: #DDD;\n    background-color: whiteSmoke;\n    cursor: pointer;\n}\n#uri-more:hover {\n    background-color: #DDD;\n    color: #999;\n}\n\n#torrent-up-input {\n    position: absolute;\n    top: 0;\n    left: 0;\n    text-align: right;\n    height: 100%;\n    width: 100%;\n    -moz-opacity: 0;\n    filter: alpha(opacity: 0);\n    opacity: 0;\n    z-index: 2;\n    cursor: pointer;\n}\n#torrent-up-btn {\n    position: relative;\n}\n\n#add-task-alert {\n    position: relative;\n    top: 5px;\n}\n\n#add-task-option {\n    padding: 0 50px 0 20px;\n}\n@media (max-width: 480px) {\n    #add-task-option {\n        padding: 0 10px 0 20px;\n    }\n}\n#add-task-option .controls {\n    padding-right: 10px;\n}\n#add-task-option .input-xlarge {\n    width: 100%;\n}\n#add-task-option .half {\n    float: left;\n    width: 220px;\n}\n#add-task-option .control-label {\n    width: 70px;\n}\n#add-task-option .controls {\n    margin-left: 85px;\n}\n\n/* aria2 global setting */\n#copyright {\n    margin-top: 10px;\n    float: left;\n}\n#setting-form .rpc-path-group .controls {\n    padding-right: 70px;\n}\n@media (max-width: 480px) {\n    #setting-form .rpc-path-group .controls {\n        padding-right: 35px;\n    }\n}\n#setting-form .rpc-path-wrap {\n    padding-right: 34px;\n    width: 100%;\n}\n#setting-form .rpc-path-wrap .add-on {\n    position: absolute;\n    right: 1px;\n}\n#rpc-path {\n  width: 100%;\n  height: 28px;\n  box-sizing: border-box;\n  -moz-box-sizing: border-box;\n}\n#aria2-gs-form {\n    margin-right: 30px;\n}\n@media (max-width: 480px) {\n    #aria2-gs-form {\n        margin-right: 0;\n    }\n}\n#aria2-gs-form .controls {\n    padding-right: 10px;\n}\n#aria2-gs-form .input-xlarge {\n    width: 100%;\n}\n#aria2-gs-form .half {\n    float: left;\n    width: 240px;\n    margin-left: 10px;\n}\n#aria2-gs-form .half .control-label {\n    width: 110px;\n}\n#aria2-gs-form .half .controls {\n    margin-left: 130px;\n    padding-right: 0;\n}\n\n/* vim: set et sw=4 ts=4 sts=4 fdm=marker ff=unix fenc=utf8: */ \n"
  },
  {
    "path": "statics/common/offline/js/aria2.js",
    "content": "/* \n * Copyright (C) 2015 Binux <roy@binux.me>\n *\n * This file is part of YAAW (https://github.com/binux/yaaw).\n *\n * YAAW is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Lesser General Public License as\n * published by the Free Software Foundation, either version 3 of\n * the License, or (at your option) any later version.\n *\n * YAAW is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Lesser General Public License for more details.\n *\n * You may get a copy of the GNU Lesser General Public License\n * from http://www.gnu.org/licenses/lgpl.txt\n *\n */\n\nif (typeof ARIA2==\"undefined\"||!ARIA2) var ARIA2=(function(){\n  var jsonrpc_interface, jsonrpc_protocol, jsonrpc_ws, interval_id, rpc_secret = null,\n      unique_id = 0, ws_callback = {};\n  var active_tasks_snapshot=\"\", finished_tasks_list=undefined, tasks_cnt_snapshot=\"\", select_lock=false, need_refresh=false;\n  var auto_refresh=false;\n\n  function get_error(result) {\n    if (typeof result == \"string\")\n      return result;\n    else if (typeof result.error == \"string\")\n      return result.error;\n    else if (result.error && result.error.message)\n      return result.error.message;\n  }\n\n  function default_error(result) {\n    //console.debug(result);\n\n    var error_msg = get_error(result);\n\n    $(\"#main-alert .alert\").attr(\"class\", \"alert alert-error\");\n    $(\"#main-alert .alert-msg\").html(\"<strong>Error: </strong>\"+error_msg);\n    $(\"#main-alert\").show();\n  }\n\n  function main_alert(_class, msg, timeout) {\n    var msg_id = (new Date()).getTime();\n    $(\"#main-alert .alert\").attr(\"class\", \"alert \"+_class);\n    $(\"#main-alert .alert-msg\").html(msg);\n    $(\"#main-alert\").data(\"msg_id\", msg_id).show();\n    if (timeout) {\n      window.setTimeout(function() { \n        if($(\"#main-alert\").data(\"msg_id\") == msg_id) {\n          $(\"#main-alert\").fadeOut();\n        }\n      }, timeout);\n    }\n    return msg_id;\n  }\n\n  function bind_event(dom) {\n    dom.find(\"[rel=tooltip]\").tooltip({\"placement\": \"bottom\", trigger : 'hover'});\n  }\n\n  function get_title(result) {\n    var dir = result.dir;\n    var title = \"Unknown\";\n    if (result.bittorrent && result.bittorrent.info && result.bittorrent.info.name)\n      title = result.bittorrent.info.name;\n    else if (result.files[0].path && result.files[0].path.replace(\n      new RegExp(\"^\"+dir.replace(/\\\\/g, \"/\").replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&')+\"/?\"), \"\").split(\"/\").length) {\n      title = result.files[0].path.replace(new RegExp(\"^\"+dir.replace(/\\\\/g, \"/\").replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g, '\\\\$&')+\"/?\"), \"\").split(\"/\");\n      if (result.bittorrent)\n        title = title[0];\n      else\n        title = title[title.length-1];\n    } else if (result.files.length && result.files[0].uris.length && result.files[0].uris[0].uri)\n      title = result.files[0].uris[0].uri;\n\n    if (result.files.length > 1) {\n      var cnt = 0;\n      for (var i=0; i<result.files.length; i++) {\n        if (result.files[i].selected == \"true\")\n          cnt += 1;\n      }\n      if (cnt > 1)\n        title += \" (\"+cnt+ \" files..)\"\n    }\n    return title;\n  }\n\n  function request_auth(url) {\n    return url.match(/^(?:(?![^:@]+:[^:@\\/]*@)[^:\\/?#.]+:)?(?:\\/\\/)?(?:([^:@]*(?::[^:@]*)?)?@)?/)[1];\n  }\n  function remove_auth(url) {\n    return url.replace(/^((?![^:@]+:[^:@\\/]*@)[^:\\/?#.]+:)?(\\/\\/)?(?:(?:[^:@]*(?::[^:@]*)?)?@)?(.*)/, '$1$2$3');\n  }\n\n  return {\n    init: function(path, onready) {\n      var connect_msg_id = main_alert(\"alert-info\", \"connecting...\");\n      $(\"#add-task-option-wrap\").empty().append(YAAW.tpl.add_task_option({}));\n      $(\"#aria2-gsetting\").empty().append(YAAW.tpl.aria2_global_setting({}));\n\n      jsonrpc_interface = path || location.protocol+\"//\"+(location.host.split(\":\")[0]||\"localhost\")+\":6800\"+\"/jsonrpc\";\n      var auth_str = request_auth(jsonrpc_interface);\n      if (auth_str && auth_str.indexOf('token:') == 0) {\n        rpc_secret = auth_str;\n        jsonrpc_interface = remove_auth(jsonrpc_interface);\n      }\n\n      if (jsonrpc_interface.indexOf(\"http\") == 0) {\n        jsonrpc_protocol = \"http\";\n        $.jsonRPC.setup({endPoint: jsonrpc_interface, namespace: 'aria2'});\n        ARIA2.request = ARIA2.request_http;\n        ARIA2.batch_request = ARIA2.batch_request_http;\n        if (onready) onready();\n        if ($(\"#main-alert\").data(\"msg_id\") == connect_msg_id) {\n          $(\"#main-alert\").fadeOut();\n        }\n      } else if (jsonrpc_interface.indexOf(\"ws\") == 0 && WebSocket) {\n        jsonrpc_protocol = \"ws\"\n        jsonrpc_ws = new WebSocket(jsonrpc_interface);\n        jsonrpc_ws.onmessage = function(event) {\n          var data = JSON.parse(event.data);\n          //console.debug(data);\n          if ($.isArray(data) && data.length) {\n            var id = data[0].id;\n            if (ws_callback[id]) {\n              ws_callback[id].success(data);\n              delete ws_callback[id];\n            }\n          } else {\n            if (ws_callback[data.id]) {\n              if (data.error)\n                ws_callback[data.id].error(data);\n              else\n                ws_callback[data.id].success(data);\n              delete ws_callback[data.id];\n            };\n          };\n        };\n        jsonrpc_ws.onerror = function(event) {\n          console.warn(\"error\", event);\n          main_alert(\"alert-error\", \"websocket error. you may need reflush this page to restart.\");\n          ws_callback = {};\n        };\n        jsonrpc_ws.onopen = function() {\n          ARIA2.request = ARIA2.request_ws;\n          ARIA2.batch_request = ARIA2.batch_request_ws;\n          if (onready) onready();\n          if ($(\"#main-alert\").data(\"msg_id\") == connect_msg_id) {\n            $(\"#main-alert\").fadeOut();\n          }\n        };\n      } else {\n        main_alert(\"alert-error\", \"Unknown protocol\");\n      };\n    },\n\n    request: function(){},\n    batch_request: function(){},\n\n    request_http: function(method, params, success, error) {\n      if (error == undefined)\n        error = default_error;\n      if (rpc_secret) {\n        params = params || [];\n        if (!$.isArray(params)) params = [params];\n        params.unshift(rpc_secret);\n      }\n      $.jsonRPC.request(method, {params:params, success:success, error:error});\n    },\n\n    batch_request_http: function(method, params, success, error) {\n      if (error == undefined)\n        error = default_error;\n      var commands = new Array();\n      $.each(params, function(i, n) {\n        n = n || [];\n        if (!$.isArray(n)) n = [n];\n        if (rpc_secret) {\n          n.unshift(rpc_secret);\n        }\n        commands.push({method: method, params: n});\n      });\n      $.jsonRPC.batchRequest(commands, {success:success, error:error});\n    },\n\n    _request_data: function(method, params, id) {\n      var dataObj = {\n        jsonrpc: '2.0',\n        method: 'aria2.'+method,\n        id: id\n      }\n      if(typeof(params) !== 'undefined') {\n        dataObj.params = params;\n      }\n      return dataObj;\n    },\n\n    _get_unique_id: function() {\n      ++unique_id;\n      return unique_id;\n    },\n\n    request_ws: function(method, params, success, error) {\n      var id = ARIA2._get_unique_id();\n      ws_callback[id] = {\n        'success': success || function(){},\n        'error': error || default_error,\n      };\n      if (rpc_secret) {\n        params = params || [];\n        if (!$.isArray(params)) params = [params];\n        params.unshift(rpc_secret);\n      }\n      jsonrpc_ws.send(JSON.stringify(ARIA2._request_data(method, params, id)));\n    },\n\n    batch_request_ws: function(method, params, success, error) {\n      var data = [];\n      var id = ARIA2._get_unique_id();\n      ws_callback[id] = {\n        'success': success || function(){},\n        'error': error || default_error,\n      };\n      for (var i=0,l=params.length; i<l; i++) {\n        var n = params[i];\n        n = n || [];\n        if (!$.isArray(n)) n = [n];\n        if (rpc_secret) {\n          n.unshift(rpc_secret);\n        }\n        data.push(ARIA2._request_data(method, n, id))\n      };\n      jsonrpc_ws.send(JSON.stringify(data));\n    },\n\n    main_alert: main_alert,\n\n    add_task: function(uri, options) {\n      if (!uri) return false;\n      if (!$.isArray(uri)) uri = [uri];\n      if (!options) options = {};\n      ARIA2.request(\"addUri\", [uri, options],\n        function(result) {\n          //console.debug(result);\n          ARIA2.refresh();\n          $(\"#add-task-modal\").modal('hide');\n          YAAW.add_task.clean();\n        }, \n        function(result) {\n          //console.debug(result);\n\n          var error_msg = get_error(result);\n\n          $(\"#add-task-alert .alert-msg\").text(error_msg);\n          $(\"#add-task-alert\").show();\n          console.warn(\"add task error: \"+error_msg);\n        });\n    },\n\n    madd_task: function(uris, options) {\n      if (!$.isArray(uris)) uris = [uris];\n      var params = [];\n      for (var i=0; i<uris.length; i++) {\n        var uri = uris[i].trim();\n        if (uri) params.push([[uri], options]);\n      };\n      ARIA2.batch_request(\"addUri\", params,\n        function(result) {\n          //console.debug(result);\n\n          var error = new Array();\n          $.each(result, function(i, n) {\n            var error_msg = get_error(n);\n            if (error_msg) error.push(error_msg);\n          });\n\n          if (error.length == 0) {\n            ARIA2.refresh();\n            $(\"#add-task-modal\").modal('hide');\n            YAAW.add_task.clean();\n          } else {\n            var error_msg = error.join(\"<br />\");\n            $(\"#add-task-alert .alert-msg\").html(error_msg);\n            $(\"#add-task-alert\").show();\n            console.warn(\"add task error: \"+error_msg);\n          }\n        }\n      );\n    },\n\n    add_torrent: function(torrent, options) {\n      if (!torrent) return false;\n      if (!options) options = {};\n      ARIA2.request(\"addTorrent\", [torrent, [], options],\n        function(result) {\n          //console.debug(result);\n          ARIA2.refresh();\n          $(\"#add-task-modal\").modal('hide');\n          YAAW.add_task.clean();\n        }, \n        function(result) {\n          //console.debug(result);\n\n          var error_msg = get_error(result);\n\n          $(\"#add-task-alert .alert-msg\").text(error_msg);\n          $(\"#add-task-alert\").show();\n          console.warn(\"add task error: \"+error_msg);\n        });\n    },\n\n    add_metalink: function(metalink, options) {\n      if (!metalink) return false;\n      if (!options) options = {};\n      ARIA2.request(\"addMetalink\", [metalink, [], options],\n        function(result) {\n          //console.debug(result);\n          ARIA2.refresh();\n          $(\"#add-task-modal\").modal('hide');\n          YAAW.add_task.clean();\n        }, \n        function(result) {\n          //console.debug(result);\n\n          var error_msg = get_error(result);\n\n          $(\"#add-task-alert .alert-msg\").text(error_msg);\n          $(\"#add-task-alert\").show();\n          console.warn(\"add task error: \"+error_msg);\n        });\n    },\n\n    restart_task: function(gids) {\n      if (!$.isArray(gids)) gids = [gids];\n      $.each(gids, function(n, gid) {\n        var result = $(\"#task-gid-\"+gid).data(\"raw\");\n        var uris = [];\n        $.each(result.files, function(n, e) {\n          if (e.uris.length)\n            uris.push(e.uris[0].uri);\n        });\n        if (result.bittorrent) {\n          var magnet_link = \"magnet:?xt=urn:btih:\"+result.infoHash;\n          if (result.bittorrent.info.name)\n            magnet_link += \"&dn=\"+result.bittorrent.info.name;\n          if (result.bittorrent.announceList.length)\n            magnet_link += \"&tr=\"+result.bittorrent.announceList.join(\"&tr=\");\n          uris.push(magnet_link);\n        }\n        if (uris.length > 0) {\n          ARIA2.request(\"getOption\", [gid], function(result) {\n            var options = result.result;\n            ARIA2.madd_task(uris, options);\n          });\n        }\n      });\n    },\n\n    tell_active: function(keys) {\n      if (select_lock) return;\n      ARIA2.request(\"tellActive\", keys,\n        function(result) {\n          //console.debug(result);\n\n          if (select_lock) return;\n          if (!result.result) {\n            main_alert(\"alert-error\", \"<strong>Error: </strong>rpc result error.\", 5000);\n          }\n\n          var snapshot = new Array();\n          $.each(result.result, function(i, e) {\n            snapshot.push(e.gid);\n          });\n          if (snapshot.sort().join(\",\") != active_tasks_snapshot) {\n            active_tasks_snapshot = snapshot.sort().join(\",\");\n            need_refresh = true;\n            if (auto_refresh && !select_lock)\n              ARIA2.refresh();\n          }\n        \n          result = ARIA2.status_fix(result.result);\n          $(\"#active-tasks-table\").empty().append(YAAW.tpl.active_task({\"tasks\": result}));\n          $.each(result, function(n, e) {\n            $(\"#task-gid-\"+e.gid).data(\"raw\", e);\n          });\n          bind_event($(\"#active-tasks-table\"))\n        }\n      );\n    },\n\n    check_active_list: function() {\n      ARIA2.request(\"tellActive\", [[\"gid\"]],\n        function(result) {\n          //console.debug(result);\n\n          if (!result.result) {\n            main_alert(\"alert-error\", \"<strong>Error: </strong>rpc result error.\", 5000);\n          }\n\n          var snapshot = new Array();\n          $.each(result.result, function(i, e) {\n            snapshot.push(e.gid);\n          });\n          if (snapshot.sort().join(\",\") != active_tasks_snapshot) {\n            active_tasks_snapshot = snapshot.sort().join(\",\");\n            need_refresh = true;\n            if (auto_refresh && !select_lock)\n              ARIA2.refresh();\n          }\n        }\n      );\n    },\n\n    tell_waiting: function(keys) {\n      if (select_lock) return;\n      var params = [0, 1000];\n      if (keys) params.push(keys);\n      ARIA2.request(\"tellWaiting\", params,\n        function(result) {\n          if (select_lock) return;\n          if (!result.result) {\n            main_alert(\"alert-error\", \"<strong>Error: </strong>rpc result error.\", 5000);\n          }\n\n          result = ARIA2.status_fix(result.result);\n          $(\"#waiting-tasks-table\").empty().append(YAAW.tpl.other_task({\"tasks\": result}));\n          $.each(result, function(n, e) {\n            $(\"#task-gid-\"+e.gid).data(\"raw\", e);\n          });\n          bind_event($(\"#waiting-tasks-table\"))\n\n          if ($(\"#other-tasks .task\").length == 0)\n            $(\"#waiting-tasks-table\").append($(\"#other-task-empty\").text())\n        }\n      );\n    },\n\n    tell_stopped: function(keys) {\n      if (select_lock) return;\n      var params = [0, 1000];\n      if (keys) params.push(keys);\n      ARIA2.request(\"tellStopped\", params,\n        function(result) {\n          //console.debug(result);\n          if (select_lock) return;\n\n          if (!result.result) {\n            main_alert(\"alert-error\", \"<strong>Error: </strong>rpc result error.\", 5000);\n          }\n\n          result = ARIA2.status_fix(result.result);\n\n          if (finished_tasks_list === undefined) {\n            finished_tasks_list = new Array();\n            $.each(result, function(i, e) {\n              if (e.status != \"complete\")\n                return;\n              finished_tasks_list.push(e.gid);\n            });\n          } else {\n            $.each(result, function(i, e) {\n              if (e.status != \"complete\")\n                return;\n              if (finished_tasks_list.indexOf(e.gid) != -1)\n                return;\n              if (ARIA2.finish_notification) {\n                YAAW.notification(\"Aria2 Task Finished\", e.title);\n              }\n              finished_tasks_list.push(e.gid);\n            });\n          }\n\n          $(\"#stopped-tasks-table\").empty().append(YAAW.tpl.other_task({\"tasks\": result.reverse()}));\n          $.each(result, function(n, e) {\n            $(\"#task-gid-\"+e.gid).data(\"raw\", e);\n          });\n          bind_event($(\"#stopped-tasks-table\"))\n\n          if ($(\"#waiting-tasks-table .empty-tasks\").length > 0 &&\n            $(\"#stopped-tasks-table .task\").length > 0) {\n              $(\"#waiting-tasks-table\").empty();\n            }\n\n        }\n      );\n    },\n\n    status_fix: function(results) {\n      for (var i=0; i<results.length; i++) {\n        var result = results[i];\n\n        result.title = get_title(result);\n        if (result.totalLength == 0)\n          result.progress = 0;\n        else\n          result.progress = (result.completedLength * 1.0 / result.totalLength * 100).toFixed(2);\n        result.eta = (result.totalLength - result.completedLength)/result.downloadSpeed;\n\n        result.progressStatus = {\n          \"active\"  : \"progress-striped\",\n          \"complete\": \"progress-success\",\n          \"removed\" : \"progress-warning\",\n          \"error\"   : \"progress-danger\"\n        }[result.status];\n\n        result.downloadSpeed = parseInt(result.downloadSpeed);\n        result.uploadSpeed = parseInt(result.uploadSpeed);\n        result.uploadLength = parseInt(result.uploadLength);\n        result.completedLength = parseInt(result.completedLength);\n        result.numSeeders = parseInt(result.numSeeders);\n        result.connections = parseInt(result.connections);\n      }\n      return results;\n    },\n\n    change_pos: function(gid, pos, how) {\n      ARIA2.request(\"changePosition\", [gid, pos, how],\n        function(result) {\n          //console.debug(result);\n\n          main_alert(\"alert-info\", \"Moved\", 1000);\n          ARIA2.refresh();\n        }\n      );\n    },\n\n    change_selected_pos: function(gids, pos, how) {\n      var params = [];\n      $.each(gids, function(i, n) {\n        params.push([n, pos, how]);\n      });\n      ARIA2.batch_request(\"changePosition\", params,\n        function(result) {\n          //console.debug(result);\n\n          main_alert(\"alert-info\", \"Moved\", 1000);\n          ARIA2.refresh();\n        }\n      );\n    },\n\n    pause: function(gids) {\n      if (!$.isArray(gids)) gids = [gids];\n      ARIA2.batch_request(\"pause\", gids,\n        function(result) {\n          //console.debug(result);\n\n          var error = new Array();\n          $.each(result, function(i, n) {\n            var error_msg = get_error(n);\n            if (error_msg) error.push(error_msg);\n          });\n\n          if (error.length == 0) {\n            main_alert(\"alert-info\", \"Paused\", 1000);\n            ARIA2.refresh();\n          } else {\n            main_alert(\"alert-error\", error.join(\"<br />\"), 3000);\n          }\n        }\n      );\n    },\n\n    unpause: function(gids) {\n      if (!$.isArray(gids)) gids = [gids];\n      ARIA2.batch_request(\"unpause\", gids,\n        function(result) {\n          //console.debug(result);\n\n          var error = new Array();\n          $.each(result, function(i, n) {\n            var error_msg = get_error(n);\n            if (error_msg) error.push(error_msg);\n          });\n\n          if (error.length == 0) {\n            main_alert(\"alert-info\", \"Started\", 1000);\n            ARIA2.refresh();\n          } else {\n            main_alert(\"alert-error\", error.join(\"<br />\"), 3000);\n          }\n        }\n      );\n    },\n\n    remove: function(gids) {\n      if (!$.isArray(gids)) gids = [gids];\n      ARIA2.batch_request(\"remove\", gids,\n        function(result) {\n          //console.debug(result);\n\n          var error = new Array();\n          $.each(result, function(i, n) {\n            var error_msg = get_error(n);\n            if (error_msg) error.push(error_msg);\n          });\n\n          if (error.length == 0) {\n            main_alert(\"alert-info\", \"Removed\", 1000);\n            ARIA2.refresh();\n          } else {\n            main_alert(\"alert-error\", error.join(\"<br />\"), 3000);\n          }\n        }\n      );\n    },\n\n    remove_result: function(gids) {\n      if (!$.isArray(gids)) gids = [gids];\n      ARIA2.batch_request(\"removeDownloadResult\", gids,\n        function(result) {\n          //console.debug(result);\n\n          var error = new Array();\n          $.each(result, function(i, n) {\n            var error_msg = get_error(n);\n            if (error_msg) error.push(error_msg);\n          });\n\n          if (error.length == 0) {\n            main_alert(\"alert-info\", \"Removed\", 1000);\n            ARIA2.tell_stopped();\n          } else {\n            main_alert(\"alert-error\", error.join(\"<br />\"), 3000);\n          }\n        }\n      );\n    },\n\n    get_options: function(gid) {\n      ARIA2.request(\"getOption\", [gid],\n        function(result) {\n          //console.debug(result);\n\n          $(\"#ib-options\").empty().append(YAAW.tpl.ib_options(result.result));\n          if ($(\"#task-gid-\"+gid).attr(\"data-status\") == \"active\")\n            $(\"#ib-options-form *[name]:not(.active-allowed)\").attr(\"disabled\", true);\n        }\n      );\n    },\n\n    change_options: function(gid, options) {\n      ARIA2.request(\"changeOption\", [gid, options],\n        function(result) {\n          //console.debug(result);\n\n          main_alert(\"alert-info\", \"option updated\", 1000);\n        }\n      );\n    },\n\n    get_peers: function(gid) {\n      ARIA2.request(\"getPeers\", [gid],\n        function(result) {\n          console.debug(result);\n\n          $(\"#ib-peers\").empty().append(YAAW.tpl.ib_peers(result.result));\n        }\n      );\n    },\n\n    pause_all: function() {\n      ARIA2.request(\"pauseAll\", [],\n        function(result) {\n          //console.debug(result);\n\n          ARIA2.refresh();\n          main_alert(\"alert-info\", \"Paused all tasks. Please wait for action such as contacting BitTorrent tracker.\", 2000);\n        }\n      );\n    },\n\n    unpause_all: function() {\n      ARIA2.request(\"unpauseAll\", [],\n        function(result) {\n          //console.debug(result);\n\n          ARIA2.refresh();\n          main_alert(\"alert-info\", \"Unpaused all tasks.\", 2000);\n        }\n      );\n    },\n\n    purge_download_result: function() {\n      ARIA2.request(\"purgeDownloadResult\", [],\n        function(result) {\n          //console.debug(result);\n\n          ARIA2.refresh();\n          main_alert(\"alert-info\", \"Removed all completed/error/removed downloads tasks.\", 2000);\n        }\n      );\n    },\n\n    get_global_option: function() {\n      ARIA2.request(\"getGlobalOption\", [],\n        function(result) {\n          if (!result.result)\n            main_alert(\"alert-error\", \"<strong>Error: </strong>rpc result error.\", 5000);\n\n          result = result.result;\n          $(\"#aria2-gsetting\").empty().append(YAAW.tpl.aria2_global_setting(result));\n        }\n      );\n    },\n\n    init_add_task_option: function() {\n      ARIA2.request(\"getGlobalOption\", [],\n        function(result) {\n          if (!result.result)\n            main_alert(\"alert-error\", \"<strong>Error: </strong>rpc result error.\", 5000);\n\n          result = result.result;\n          result[\"parameterized-uri\"] = (result[\"parameterized-uri\"] == \"true\" ? true : false)\n          $(\"#add-task-option-wrap\").empty().append(YAAW.tpl.add_task_option(result));\n        }\n      );\n    },\n\n    change_global_option: function(options) {\n      ARIA2.request(\"changeGlobalOption\", [options],\n        function(result) {\n          if (!result.result)\n            main_alert(\"alert-error\", \"<strong>Error: </strong>rpc result error.\", 5000);\n          else\n            main_alert(\"alert-success\", \"Saved\", 2000);\n        }\n      );\n    },\n\n    global_stat: function() {\n      ARIA2.request(\"getGlobalStat\", [],\n        function(result) {\n          if (!result.result) {\n            main_alert(\"alert-error\", \"<strong>Error: </strong>rpc result error.\", 5000);\n          }\n\n          result = result.result;\n          var _tasks_cnt_snapshot = \"\"+result.numActive+\",\"+result.numWaiting+\",\"+result.numStopped;\n\n          if (_tasks_cnt_snapshot != tasks_cnt_snapshot) {\n            tasks_cnt_snapshot = _tasks_cnt_snapshot;\n            need_refresh = true;\n            if (auto_refresh && !select_lock)\n              ARIA2.refresh();\n          }\n\n          $(\"#global-speed\").empty().append(YAAW.tpl.global_speed(result));\n          var title = \"↓\"+YAAW.tpl.view.format_size_0()(result.downloadSpeed);\n          if (result.uploadSpeed > 0)\n            title += \" ↑\"+YAAW.tpl.view.format_size_0()(result.uploadSpeed);\n          title += \" - Yet Another Aria2 Web Frontend\";\n          document.title = title;\n        }\n      );\n    },\n\n    get_version: function() {\n      ARIA2.request(\"getVersion\", [],\n        function(result) {\n          if (!result.result) {\n            main_alert(\"alert-error\", \"<strong>Error: </strong>rpc result error.\", 5000);\n          }\n\n          $(\"#global-version\").text(\"Aria2 \"+result.result.version || \"\");\n        }\n      );\n    },\n\n    get_status: function(gid) {\n      ARIA2.request(\"tellStatus\", [gid],\n        function(result) {\n          if (!result.result) {\n            main_alert(\"alert-error\", \"<strong>Error: </strong>rpc result error.\", 5000);\n          }\n\n          result = result.result;\n          result.uris = [];\n          for (var i=0; i<result.files.length; i++) {\n            var file = result.files[i];\n            file.title = file.path.replace(new RegExp(\"^\"+result.dir.replace(/\\\\/g, \"[\\\\/]\")+\"/?\"), \"\");\n            file.selected = file.selected == \"true\" ? true : false;\n            if (file.uris && file.uris.length) {\n              for (var j=0; j<file.uris.length; j++) {\n                var uri = file.uris[j].uri;\n                if (result.uris.indexOf(uri) == -1) {\n                  result.uris.push(uri);\n                }\n              }\n            }\n          };\n          console.log(result.uris);\n          $(\"#ib-status\").empty().append(YAAW.tpl.ib_status(result));\n          $(\"#ib-files .file-list\").empty().append(YAAW.tpl.files_tree(result.files));\n          if ($(\"#task-gid-\"+gid).attr(\"data-status\") == \"active\")\n            $(\"#ib-file-save\").hide();\n          if (result.bittorrent) {\n            $(\"#ib-peers-a\").show();\n          }\n        }\n      );\n    },\n\n    change_option: function(gid, options) {\n      ARIA2.request(\"changeOption\", [gid, options],\n        function(result) {\n          if (!result.result) {\n            main_alert(\"alert-error\", \"<strong>Error: </strong>rpc result error.\", 5000);\n          } else {\n            main_alert(\"alert-success\", \"Change Options OK!\", 2000);\n          }\n        }\n      );\n    },\n\n    /********************************************************/\n\n    refresh: function() {\n      if (!select_lock) {\n        need_refresh = false;\n        ARIA2.tell_active();\n        ARIA2.tell_waiting();\n        ARIA2.tell_stopped();\n      }\n    },\n\n    select_lock: function (bool) {\n      select_lock = bool;\n    },\n\n    auto_refresh: function(interval) {\n      if (interval_id)\n        window.clearInterval(interval_id);\n      if (!(interval > 0)) {\n        auto_refresh = false;\n        return ;\n      }\n      interval_id = window.setInterval(function() {\n        ARIA2.global_stat();\n        if (select_lock) {\n          if (need_refresh) {\n            main_alert(\"\", \"Task list have changed since last update. Click 'Refresh' button to update task list.\");\n          }\n        } else {\n          if (need_refresh) {\n            ARIA2.refresh();\n          } else {\n            ARIA2.tell_active();\n          }\n        }\n      }, interval);\n      auto_refresh = true;\n    },\n\n    finish_notification: 1,\n  }\n})();\n"
  },
  {
    "path": "statics/common/offline/js/jquery.Storage.js",
    "content": "/**\n * Storage plugin\n * Provides a simple interface for storing data such as user preferences.\n * Storage is useful for saving and retreiving data from the user's browser.\n * For newer browsers, localStorage is used.\n * If localStorage isn't supported, then cookies are used instead.\n * Retrievable data is limited to the same domain as this file.\n *\n * Usage:\n * This plugin extends jQuery by adding itself as a static method.\n * $.Storage - is the class name, which represents the user's data store, whether it's cookies or local storage.\n *             <code>if ($.Storage)</code> will tell you if the plugin is loaded.\n * $.Storage.set(\"name\", \"value\") - Stores a named value in the data store.\n * $.Storage.set({\"name1\":\"value1\", \"name2\":\"value2\", etc}) - Stores multiple name/value pairs in the data store.\n * $.Storage.get(\"name\") - Retrieves the value of the given name from the data store.\n * $.Storage.remove(\"name\") - Permanently deletes the name/value pair from the data store.\n *\n * @author Dave Schindler\n *\n * Distributed under the MIT License\n *\n * Copyright (c) 2010 Dave Schindler\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n */\n(function($) {\n\t// Private data\n\tvar isLS=typeof window.localStorage!=='undefined';\n\t// Private functions\n\tfunction wls(n,v){var c;if(typeof n===\"string\"&&typeof v===\"string\"){localStorage[n]=v;return true;}else if(typeof n===\"object\"&&typeof v===\"undefined\"){for(c in n){if(n.hasOwnProperty(c)){localStorage[c]=n[c];}}return true;}return false;}\n\tfunction wc(n,v){var dt,e,c;dt=new Date();dt.setTime(dt.getTime()+31536000000);e=\"; expires=\"+dt.toGMTString();if(typeof n===\"string\"&&typeof v===\"string\"){document.cookie=n+\"=\"+v+e+\"; path=/\";return true;}else if(typeof n===\"object\"&&typeof v===\"undefined\"){for(c in n) {if(n.hasOwnProperty(c)){document.cookie=c+\"=\"+n[c]+e+\"; path=/\";}}return true;}return false;}\n\tfunction rls(n){return localStorage[n];}\n\tfunction rc(n){var nn, ca, i, c;nn=n+\"=\";ca=document.cookie.split(';');for(i=0;i<ca.length;i++){c=ca[i];while(c.charAt(0)===' '){c=c.substring(1,c.length);}if(c.indexOf(nn)===0){return c.substring(nn.length,c.length);}}return null;}\n\tfunction dls(n){return delete localStorage[n];}\n\tfunction dc(n){return wc(n,\"\",-1);}\n\n\t/**\n\t* Public API\n\t* $.Storage - Represents the user's data store, whether it's cookies or local storage.\n\t* $.Storage.set(\"name\", \"value\") - Stores a named value in the data store.\n\t* $.Storage.set({\"name1\":\"value1\", \"name2\":\"value2\", etc}) - Stores multiple name/value pairs in the data store.\n\t* $.Storage.get(\"name\") - Retrieves the value of the given name from the data store.\n\t* $.Storage.remove(\"name\") - Permanently deletes the name/value pair from the data store.\n\t*/\n\t$.extend({\n\t\tStorage: {\n\t\t\tset: isLS ? wls : wc,\n\t\t\tget: isLS ? rls : rc,\n\t\t\tremove: isLS ? dls :dc\n\t\t}\n\t});\n})(jQuery);"
  },
  {
    "path": "statics/common/offline/js/jquery.jsonrpc.js",
    "content": "(function($) {\n  $.extend({\n    jsonRPC: {\n      // RPC Version Number\n      version: '2.0',\n\n      // End point URL, sets default in requests if not\n      // specified with the request call\n      endPoint: null,\n\n      // Default namespace for methods\n      namespace: null,\n\n      /*\n       * Provides the RPC client with an optional default endpoint and namespace\n       *\n       * @param {object} The params object which can contains\n       *   {string} endPoint The default endpoint for RPC requests\n       *   {string} namespace The default namespace for RPC requests\n       */\n      setup: function(params) {\n        this._validateConfigParams(params);\n        this.endPoint = params.endPoint;\n        this.namespace = params.namespace;\n        this.auth = this.endPoint.match(/^(?:(?![^:@]+:[^:@\\/]*@)[^:\\/?#.]+:)?(?:\\/\\/)?(?:([^:@]*(?::[^:@]*)?)?@)?/)[1];\n        return this;\n      },\n\n      /*\n       * Convenience wrapper method to allow you to temporarily set a config parameter\n       * (endPoint or namespace) and ensure it gets set back to what it was before\n       *\n       * @param {object} The params object which can contains\n       *   {string} endPoint The default endpoint for RPC requests\n       *   {string} namespace The default namespace for RPC requests\n       * @param {function} callback The function to call with the new params in place\n       */\n      withOptions: function(params, callback) {\n        this._validateConfigParams(params);\n        // No point in running if there isn't a callback received to run\n        if(typeof(callback) === 'undefined') throw(\"No callback specified\");\n\n        origParams = {endPoint: this.endPoint, namespace: this.namespace};\n        this.setup(params);\n        callback.call(this);\n        this.setup(origParams);\n      },\n\n      /*\n       * Performas a single RPC request\n       *\n       * @param {string} method The name of the rpc method to be called\n       * @param {object} options A collection of object which can contains\n       *  params {array} the params array to send along with the request\n       *  success {function} a function that will be executed if the request succeeds\n       *  error {function} a function that will be executed if the request fails\n       *  url {string} the url to send the request to\n       *  id {string} the provenance id for this request (defaults to 1)\n       * @return {undefined}\n       */\n      request: function(method, options) {\n        if(typeof(options) === 'undefined') {\n          options = { id: 1 };\n        }\n        if (typeof(options.id) === 'undefined') {\n          options.id = 1;\n        }\n\n        // Validate method arguments\n        this._validateRequestMethod(method);\n        this._validateRequestParams(options.params);\n        this._validateRequestCallbacks(options.success, options.error);\n\n        // Perform the actual request\n        this._doRequest(JSON.stringify(this._requestDataObj(method, options.params, options.id)), options);\n\n        return true;\n      },\n\n      /*\n       * Submits multiple requests\n       * Takes an array of objects that contain a method and params\n       *\n       * @params {array} requests an array of request object which can contain\n       *  method {string} the name of the method\n       *  param {object} the params object to be sent with the request\n       *  id {string} the provenance id for the request (defaults to an incrementer starting at 1)\n       * @param {object} options A collection of object which can contains\n       *  success {function} a function that will be executed if the request succeeds\n       *  error {function} a function that will be executed if the request fails\n       *  url {string} the url to send the request to\n       * @return {undefined}\n       */\n      batchRequest: function(requests, options) {\n        if(typeof(options) === 'undefined') {\n          options = {};\n        }\n\n        // Ensure our requests come in as an array\n        if(!$.isArray(requests) || requests.length === 0) throw(\"Invalid requests supplied for jsonRPC batchRequest. Must be an array object that contain at least a method attribute\");\n\n        // Make sure each of our request objects are valid\n        var _that = this;\n        $.each(requests, function(i, req) {\n          _that._validateRequestMethod(req.method);\n          _that._validateRequestParams(req.params);\n          if (typeof(req.id) === 'undefined') {\n            req.id = i + 1;\n          }\n        });\n        this._validateRequestCallbacks(options.success, options.error);\n\n        var data = [],\n            request;\n\n        // Prepare our request object\n        for(var i = 0; i<requests.length; i++) {\n          request = requests[i];\n          data.push(this._requestDataObj(request.method, request.params, request.id));\n        }\n\n        this._doRequest(JSON.stringify(data), options);\n      },\n\n      // Validate a params hash\n      _validateConfigParams: function(params) {\n        if(typeof(params) === 'undefined') {\n          throw(\"No params specified\");\n        }\n        else {\n          if(params.endPoint && typeof(params.endPoint) !== 'string'){\n            throw(\"endPoint must be a string\");\n          }\n          if(params.namespace && typeof(params.namespace) !== 'string'){\n            throw(\"namespace must be a string\");\n          }\n        }\n      },\n\n      // Request method must be a string\n      _validateRequestMethod: function(method) {\n        if(typeof(method) !== 'string') throw(\"Invalid method supplied for jsonRPC request\")\n        return true;\n      },\n\n      // Validate request params.  Must be a) empty, b) an object (e.g. {}), or c) an array\n      _validateRequestParams: function(params) {\n        if(!(params === null ||\n             typeof(params) === 'undefined' ||\n             typeof(params) === 'object' ||\n             $.isArray(params))) {\n          throw(\"Invalid params supplied for jsonRPC request. It must be empty, an object or an array.\");\n        }\n        return true;\n      },\n\n      _validateRequestCallbacks: function(success, error) {\n        // Make sure callbacks are either empty or a function\n        if(typeof(success) !== 'undefined' &&\n           typeof(success) !== 'function') throw(\"Invalid success callback supplied for jsonRPC request\");\n        if(typeof(error) !== 'undefined' &&\n         typeof(error) !== 'function') throw(\"Invalid error callback supplied for jsonRPC request\");\n        return true;\n      },\n\n      // Internal method used for generic ajax requests\n      _doRequest: function(data, options) {\n        var _that = this;\n        $.ajax({\n          type: 'POST',\n          async: false !== options.async,\n          dataType: 'json',\n          //contentType: 'application/json',\n          url: this._requestUrl(options.url),\n          data: data,\n          cache: false,\n          processData: false,\n          beforeSend: function (xhr) {\n              var authority = _that._requestAuth(options.url);\n              if (authority) { \n                  xhr.setRequestHeader(\"Authorization\", \"Basic \"+$.base64.encode(authority));\n              }\n          },\n          error: function(json) {\n            _that._requestError.call(_that, json, options.error);\n          },\n          success: function(json) {\n            _that._requestSuccess.call(_that, json, options.success, options.error);\n          }\n        })\n      },\n\n      // Determines the appropriate request URL to call for a request\n      _requestUrl: function(url) {\n        url = url || this.endPoint;\n        url = url.replace(/^((?![^:@]+:[^:@\\/]*@)[^:\\/?#.]+:)?(\\/\\/)?(?:(?:[^:@]*(?::[^:@]*)?)?@)?(.*)/, '$1$2$3'); // auth string not allowed in url for firefox\n        return url + '?tm=' + new Date().getTime()\n      },\n\n      _requestAuth: function(url) {\n        return url ? url.match(/^(?:(?![^:@]+:[^:@\\/]*@)[^:\\/?#.]+:)?(?:\\/\\/)?(?:([^:@]*(?::[^:@]*)?)?@)?/)[1] : this.auth;\n      },\n\n      // Creates an RPC suitable request object\n      _requestDataObj: function(method, params, id) {\n        var dataObj = {\n          jsonrpc: this.version,\n          method: this.namespace ? this.namespace +'.'+ method : method,\n          id: id\n        }\n        if(typeof(params) !== 'undefined') {\n          dataObj.params = params;\n        }\n        return dataObj;\n      },\n\n      // Handles calling of error callback function\n      _requestError: function(json, error) {\n        if (typeof(error) !== 'undefined' && typeof(error) === 'function') {\n            error(this._response(json.responseText));\n        }\n      },\n\n      // Handles calling of RPC success, calls error callback\n      // if the response contains an error\n      // TODO: Handle error checking for batch requests\n      _requestSuccess: function(json, success, error) {\n        var response = this._response(json);\n\n        // If we've encountered an error in the response, trigger the error callback if it exists\n        if(response.error && typeof(error) === 'function') {\n          error(response);\n          return;\n        }\n\n        // Otherwise, successful request, run the success request if it exists\n        if(typeof(success) === 'function') {\n          success(response);\n        }\n      },\n\n      // Returns a generic RPC 2.0 compatible response object\n      _response: function(json) {\n        if (typeof(json) === 'undefined' || json === \"\") {\n          return {\n            error: 'Internal server error',\n            version: '2.0'\n          };\n        }\n        else {\n          try {\n            if(typeof(json) === 'string') {\n              json = eval ( '(' + json + ')' );\n            }\n\n            if (($.isArray(json) && json.length > 0 && json[0].jsonrpc !== '2.0') ||\n                (!$.isArray(json) && json.jsonrpc !== '2.0')) {\n              throw 'Version error';\n            }\n\n            return json;\n          }\n          catch (e) {\n            return {\n              error: 'Internal server error: ' + e,\n              version: '2.0'\n            }\n          }\n        }\n      }\n\n    }\n  });\n})(jQuery);\n"
  },
  {
    "path": "statics/common/offline/js/mustache.js",
    "content": "/*!\n * mustache.js - Logic-less {{mustache}} templates with JavaScript\n * http://github.com/janl/mustache.js\n */\nvar Mustache = (typeof module !== \"undefined\" && module.exports) || {};\n\n(function (exports) {\n\n  exports.name = \"mustache.js\";\n  exports.version = \"0.5.0-dev\";\n  exports.tags = [\"{{\", \"}}\"];\n  exports.parse = parse;\n  exports.compile = compile;\n  exports.render = render;\n  exports.clearCache = clearCache;\n\n  // This is here for backwards compatibility with 0.4.x.\n  exports.to_html = function (template, view, partials, send) {\n    var result = render(template, view, partials);\n\n    if (typeof send === \"function\") {\n      send(result);\n    } else {\n      return result;\n    }\n  };\n\n  var _toString = Object.prototype.toString;\n  var _isArray = Array.isArray;\n  var _forEach = Array.prototype.forEach;\n  var _trim = String.prototype.trim;\n\n  var isArray;\n  if (_isArray) {\n    isArray = _isArray;\n  } else {\n    isArray = function (obj) {\n      return _toString.call(obj) === \"[object Array]\";\n    };\n  }\n\n  var forEach;\n  if (_forEach) {\n    forEach = function (obj, callback, scope) {\n      return _forEach.call(obj, callback, scope);\n    };\n  } else {\n    forEach = function (obj, callback, scope) {\n      for (var i = 0, len = obj.length; i < len; ++i) {\n        callback.call(scope, obj[i], i, obj);\n      }\n    };\n  }\n\n  var spaceRe = /^\\s*$/;\n\n  function isWhitespace(string) {\n    return spaceRe.test(string);\n  }\n\n  var trim;\n  if (_trim) {\n    trim = function (string) {\n      return string == null ? \"\" : _trim.call(string);\n    };\n  } else {\n    var trimLeft, trimRight;\n\n    if (isWhitespace(\"\\xA0\")) {\n      trimLeft = /^\\s+/;\n      trimRight = /\\s+$/;\n    } else {\n      // IE doesn't match non-breaking spaces with \\s, thanks jQuery.\n      trimLeft = /^[\\s\\xA0]+/;\n      trimRight = /[\\s\\xA0]+$/;\n    }\n\n    trim = function (string) {\n      return string == null ? \"\" :\n        String(string).replace(trimLeft, \"\").replace(trimRight, \"\");\n    };\n  }\n\n  var escapeMap = {\n    \"&\": \"&amp;\",\n    \"<\": \"&lt;\",\n    \">\": \"&gt;\",\n    '\"': '&quot;',\n    \"'\": '&#39;'\n  };\n\n  function escapeHTML(string) {\n    return String(string).replace(/&(?!\\w+;)|[<>\"']/g, function (s) {\n      return escapeMap[s] || s;\n    });\n  }\n\n  /**\n   * Adds the `template`, `line`, and `file` properties to the given error\n   * object and alters the message to provide more useful debugging information.\n   */\n  function debug(e, template, line, file) {\n    file = file || \"<template>\";\n\n    var lines = template.split(\"\\n\"),\n        start = Math.max(line - 3, 0),\n        end = Math.min(lines.length, line + 3),\n        context = lines.slice(start, end);\n\n    var c;\n    for (var i = 0, len = context.length; i < len; ++i) {\n      c = i + start + 1;\n      context[i] = (c === line ? \" >> \" : \"    \") + context[i];\n    }\n\n    e.template = template;\n    e.line = line;\n    e.file = file;\n    e.message = [file + \":\" + line, context.join(\"\\n\"), \"\", e.message].join(\"\\n\");\n\n    return e;\n  }\n\n  /**\n   * Looks up the value of the given `name` in the given context `stack`.\n   */\n  function lookup(name, stack, defaultValue) {\n    if (name === \".\") {\n      return stack[stack.length - 1];\n    }\n\n    var names = name.split(\".\");\n    var lastIndex = names.length - 1;\n    var target = names[lastIndex];\n\n    var value, context, i = stack.length, j, localStack;\n    while (i) {\n      localStack = stack.slice(0);\n      context = stack[--i];\n\n      j = 0;\n      while (j < lastIndex) {\n        context = context[names[j++]];\n\n        if (context == null) {\n          break;\n        }\n\n        localStack.push(context);\n      }\n\n      if (context && typeof context === \"object\" && target in context) {\n        value = context[target];\n        break;\n      }\n    }\n\n    // If the value is a function, call it in the current context.\n    if (typeof value === \"function\") {\n      value = value.call(localStack[localStack.length - 1]);\n    }\n\n    if (value == null)  {\n      return defaultValue;\n    }\n\n    return value;\n  }\n\n  function renderSection(name, stack, callback, inverted) {\n    var buffer = \"\";\n    var value =  lookup(name, stack);\n\n    if (inverted) {\n      // From the spec: inverted sections may render text once based on the\n      // inverse value of the key. That is, they will be rendered if the key\n      // doesn't exist, is false, or is an empty list.\n      if (value == null || value === false || (isArray(value) && value.length === 0)) {\n        buffer += callback();\n      }\n    } else if (isArray(value)) {\n      forEach(value, function (value) {\n        stack.push(value);\n        buffer += callback();\n        stack.pop();\n      });\n    } else if (typeof value === \"object\") {\n      stack.push(value);\n      buffer += callback();\n      stack.pop();\n    } else if (typeof value === \"function\") {\n      var scope = stack[stack.length - 1];\n      var scopedRender = function (template) {\n        return render(template, scope);\n      };\n      buffer += value.call(scope, callback(), scopedRender) || \"\";\n    } else if (value) {\n      buffer += callback();\n    }\n\n    return buffer;\n  }\n\n  /**\n   * Parses the given `template` and returns the source of a function that,\n   * with the proper arguments, will render the template. Recognized options\n   * include the following:\n   *\n   *   - file     The name of the file the template comes from (displayed in\n   *              error messages)\n   *   - tags     An array of open and close tags the `template` uses. Defaults\n   *              to the value of Mustache.tags\n   *   - debug    Set `true` to log the body of the generated function to the\n   *              console\n   *   - space    Set `true` to preserve whitespace from lines that otherwise\n   *              contain only a {{tag}}. Defaults to `false`\n   */\n  function parse(template, options) {\n    options = options || {};\n\n    var tags = options.tags || exports.tags,\n        openTag = tags[0],\n        closeTag = tags[tags.length - 1];\n\n    var code = [\n      'var buffer = \"\";', // output buffer\n      \"\\nvar line = 1;\", // keep track of source line number\n      \"\\ntry {\",\n      '\\nbuffer += \"'\n    ];\n\n    var spaces = [],      // indices of whitespace in code on the current line\n        hasTag = false,   // is there a {{tag}} on the current line?\n        nonSpace = false; // is there a non-space char on the current line?\n\n    // Strips all space characters from the code array for the current line\n    // if there was a {{tag}} on it and otherwise only spaces.\n    var stripSpace = function () {\n      if (hasTag && !nonSpace && !options.space) {\n        while (spaces.length) {\n          code.splice(spaces.pop(), 1);\n        }\n      } else {\n        spaces = [];\n      }\n\n      hasTag = false;\n      nonSpace = false;\n    };\n\n    var sectionStack = [], updateLine, nextOpenTag, nextCloseTag;\n\n    var setTags = function (source) {\n      tags = trim(source).split(/\\s+/);\n      nextOpenTag = tags[0];\n      nextCloseTag = tags[tags.length - 1];\n    };\n\n    var includePartial = function (source) {\n      code.push(\n        '\";',\n        updateLine,\n        '\\nvar partial = partials[\"' + trim(source) + '\"];',\n        '\\nif (partial) {',\n        '\\n  buffer += render(partial,stack[stack.length - 1],partials);',\n        '\\n}',\n        '\\nbuffer += \"'\n      );\n    };\n\n    var openSection = function (source, inverted) {\n      var name = trim(source);\n\n      if (name === \"\") {\n        throw debug(new Error(\"Section name may not be empty\"), template, line, options.file);\n      }\n\n      sectionStack.push({name: name, inverted: inverted});\n\n      code.push(\n        '\";',\n        updateLine,\n        '\\nvar name = \"' + name + '\";',\n        '\\nvar callback = (function () {',\n        '\\n  return function () {',\n        '\\n    var buffer = \"\";',\n        '\\nbuffer += \"'\n      );\n    };\n\n    var openInvertedSection = function (source) {\n      openSection(source, true);\n    };\n\n    var closeSection = function (source) {\n      var name = trim(source);\n      var openName = sectionStack.length != 0 && sectionStack[sectionStack.length - 1].name;\n\n      if (!openName || name != openName) {\n        throw debug(new Error('Section named \"' + name + '\" was never opened'), template, line, options.file);\n      }\n\n      var section = sectionStack.pop();\n\n      code.push(\n        '\";',\n        '\\n    return buffer;',\n        '\\n  };',\n        '\\n})();'\n      );\n\n      if (section.inverted) {\n        code.push(\"\\nbuffer += renderSection(name,stack,callback,true);\");\n      } else {\n        code.push(\"\\nbuffer += renderSection(name,stack,callback);\");\n      }\n\n      code.push('\\nbuffer += \"');\n    };\n\n    var sendPlain = function (source) {\n      code.push(\n        '\";',\n        updateLine,\n        '\\nbuffer += lookup(\"' + trim(source) + '\",stack,\"\");',\n        '\\nbuffer += \"'\n      );\n    };\n\n    var sendEscaped = function (source) {\n      code.push(\n        '\";',\n        updateLine,\n        '\\nbuffer += escapeHTML(lookup(\"' + trim(source) + '\",stack,\"\"));',\n        '\\nbuffer += \"'\n      );\n    };\n\n    var line = 1, c, callback;\n    for (var i = 0, len = template.length; i < len; ++i) {\n      if (template.slice(i, i + openTag.length) === openTag) {\n        i += openTag.length;\n        c = template.substr(i, 1);\n        updateLine = '\\nline = ' + line + ';';\n        nextOpenTag = openTag;\n        nextCloseTag = closeTag;\n        hasTag = true;\n\n        switch (c) {\n        case \"!\": // comment\n          i++;\n          callback = null;\n          break;\n        case \"=\": // change open/close tags, e.g. {{=<% %>=}}\n          i++;\n          closeTag = \"=\" + closeTag;\n          callback = setTags;\n          break;\n        case \">\": // include partial\n          i++;\n          callback = includePartial;\n          break;\n        case \"#\": // start section\n          i++;\n          callback = openSection;\n          break;\n        case \"^\": // start inverted section\n          i++;\n          callback = openInvertedSection;\n          break;\n        case \"/\": // end section\n          i++;\n          callback = closeSection;\n          break;\n        case \"{\": // plain variable\n          closeTag = \"}\" + closeTag;\n          // fall through\n        case \"&\": // plain variable\n          i++;\n          nonSpace = true;\n          callback = sendPlain;\n          break;\n        default: // escaped variable\n          nonSpace = true;\n          callback = sendEscaped;\n        }\n\n        var end = template.indexOf(closeTag, i);\n\n        if (end === -1) {\n          throw debug(new Error('Tag \"' + openTag + '\" was not closed properly'), template, line, options.file);\n        }\n\n        var source = template.substring(i, end);\n\n        if (callback) {\n          callback(source);\n        }\n\n        // Maintain line count for \\n in source.\n        var n = 0;\n        while (~(n = source.indexOf(\"\\n\", n))) {\n          line++;\n          n++;\n        }\n\n        i = end + closeTag.length - 1;\n        openTag = nextOpenTag;\n        closeTag = nextCloseTag;\n      } else {\n        c = template.substr(i, 1);\n\n        switch (c) {\n        case '\"':\n        case \"\\\\\":\n          nonSpace = true;\n          code.push(\"\\\\\" + c);\n          break;\n        case \"\\r\":\n          // Ignore carriage returns.\n          break;\n        case \"\\n\":\n          spaces.push(code.length);\n          code.push(\"\\\\n\");\n          stripSpace(); // Check for whitespace on the current line.\n          line++;\n          break;\n        default:\n          if (isWhitespace(c)) {\n            spaces.push(code.length);\n          } else {\n            nonSpace = true;\n          }\n\n          code.push(c);\n        }\n      }\n    }\n\n    if (sectionStack.length != 0) {\n      throw debug(new Error('Section \"' + sectionStack[sectionStack.length - 1].name + '\" was not closed properly'), template, line, options.file);\n    }\n\n    // Clean up any whitespace from a closing {{tag}} that was at the end\n    // of the template without a trailing \\n.\n    stripSpace();\n\n    code.push(\n      '\";',\n      \"\\nreturn buffer;\",\n      \"\\n} catch (e) { throw {error: e, line: line}; }\"\n    );\n\n    // Ignore `buffer += \"\";` statements.\n    var body = code.join(\"\").replace(/buffer \\+= \"\";\\n/g, \"\");\n\n    if (options.debug) {\n      if (typeof console != \"undefined\" && console.log) {\n        console.log(body);\n      } else if (typeof print === \"function\") {\n        print(body);\n      }\n    }\n\n    return body;\n  }\n\n  /**\n   * Used by `compile` to generate a reusable function for the given `template`.\n   */\n  function _compile(template, options) {\n    var args = \"view,partials,stack,lookup,escapeHTML,renderSection,render\";\n    var body = parse(template, options);\n    var fn = new Function(args, body);\n\n    // This anonymous function wraps the generated function so we can do\n    // argument coercion, setup some variables, and handle any errors\n    // encountered while executing it.\n    return function (view, partials) {\n      partials = partials || {};\n\n      var stack = [view]; // context stack\n\n      try {\n        return fn(view, partials, stack, lookup, escapeHTML, renderSection, render);\n      } catch (e) {\n        throw debug(e.error, template, e.line, options.file);\n      }\n    };\n  }\n\n  // Cache of pre-compiled templates.\n  var _cache = {};\n\n  /**\n   * Clear the cache of compiled templates.\n   */\n  function clearCache() {\n    _cache = {};\n  }\n\n  /**\n   * Compiles the given `template` into a reusable function using the given\n   * `options`. In addition to the options accepted by Mustache.parse,\n   * recognized options include the following:\n   *\n   *   - cache    Set `false` to bypass any pre-compiled version of the given\n   *              template. Otherwise, a given `template` string will be cached\n   *              the first time it is parsed\n   */\n  function compile(template, options) {\n    options = options || {};\n\n    // Use a pre-compiled version from the cache if we have one.\n    if (options.cache !== false) {\n      if (!_cache[template]) {\n        _cache[template] = _compile(template, options);\n      }\n\n      return _cache[template];\n    }\n\n    return _compile(template, options);\n  }\n\n  /**\n   * High-level function that renders the given `template` using the given\n   * `view` and `partials`. If you need to use any of the template options (see\n   * `compile` above), you must compile in a separate step, and then call that\n   * compiled function.\n   */\n  function render(template, view, partials) {\n    return compile(template)(view, partials);\n  }\n\n})(Mustache);\n"
  },
  {
    "path": "statics/common/offline/js/peerid.js",
    "content": "(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require==\"function\"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error(\"Cannot find module '\"+o+\"'\")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){\n(function (Buffer){\n\nvar utils = require('./lib/utils')\n\n/**\n * Parses and returns the client type and version of a bittorrent peer id.\n * Throws an exception if the peer id is invalid.\n *\n * @param {Buffer|string} peerId (as Buffer or hex/utf8 string)\n */\nmodule.exports = function (peerId) {\n  var buffer\n\n  if (Buffer.isBuffer(peerId)) {\n    buffer = peerId\n    peerId = peerId.toString('utf8')\n  } else if (typeof peerId === 'string') {\n    buffer = new Buffer(peerId, 'utf8')\n\n    // assume utf8 peerId, but if that's invalid, then try hex encoding\n    if (buffer.length !== 20)\n      buffer = new Buffer(peerId, 'hex')\n  } else {\n    throw new Error('Invalid peerId must be Buffer or hex string: ' + peerId)\n  }\n\n  if (buffer.length !== 20) {\n    throw new Error('Invalid peerId length (hex buffer must be 20 bytes): ' + peerId)\n  }\n\n  // overwrite original peerId string with guaranteed utf8 version\n  peerId = buffer.toString('utf8')\n\n  var UNKNOWN = 'unknown'\n  var FAKE = 'fake'\n  var client = null\n  var version\n  var data\n\n  // If the client reuses parts of the peer ID of other peers, then try to determine this\n  // first (before we misidentify the client).\n  if (utils.isPossibleSpoofClient(peerId)) {\n    if ((client = utils.decodeBitSpiritClient(peerId, buffer))) return client\n    if ((client = utils.decodeBitCometClient(peerId, buffer))) return client\n    return { client: \"BitSpirit?\" }\n  }\n\n  // See if the client uses Az style identification\n  if (utils.isAzStyle(peerId)) {\n    if ((client = getAzStyleClientName(peerId))) {\n      version = getAzStyleClientVersion(client, peerId)\n\n      // Hack for fake ZipTorrent clients - there seems to be some clients\n      // which use the same identifier, but they aren't valid ZipTorrent clients\n      if (client.startsWith(\"ZipTorrent\") && peerId.startsWith(\"bLAde\", 8)) {\n        return {\n          client: UNKNOWN + \" [\" + FAKE  + \": \" + name + \"]\",\n          version: version\n        }\n      }\n\n      // BitTorrent 6.0 Beta currently misidentifies itself\n      if (\"\\u00B5Torrent\" === client && \"6.0 Beta\" === version) {\n        return {\n          client: \"Mainline\",\n          version: \"6.0 Beta\"\n        }\n      }\n\n      // If it's the rakshasa libtorrent, then it's probably rTorrent\n      if (client.startsWith(\"libTorrent (Rakshasa)\")) {\n        return {\n          client: client + \" / rTorrent*\",\n          version: version\n        }\n      }\n\n      return {\n        client: client,\n        version: version\n      }\n    }\n  }\n\n  // See if the client uses Shadow style identification\n  if (utils.isShadowStyle(peerId)) {\n    if ((client = getShadowStyleClientName(peerId))) {\n      // TODO: handle shadow style client version numbers\n      return { client: client }\n    }\n  }\n\n  // See if the client uses Mainline style identification\n  if (utils.isMainlineStyle(peerId)) {\n    if ((client = getMainlineStyleClientName(peerId))) {\n      // TODO: handle mainline style client version numbers\n      return { client: client }\n    }\n  }\n\n  // Check for BitSpirit / BitComet disregarding from spoof mode\n  if ((client = utils.decodeBitSpiritClient(peerId, buffer))) return client\n  if ((client = utils.decodeBitCometClient(peerId, buffer))) return client\n\n  // See if the client identifies itself using a particular substring\n  if ((data = getSimpleClient(peerId))) {\n    client = data.client\n\n    // TODO: handle simple client version numbers\n    return {\n      client: client,\n      version: data.version\n    }\n  }\n\n  // See if client is a known to be awkward\n  if ((client = utils.identifyAwkwardClient(peerId, buffer))) {\n    return client\n  }\n\n  // TODO: handle unknown az-formatted and shadow-formatted clients\n  return { client: \"unknown\" }\n}\n\n// Az style two byte code identifiers to real client name\nvar azStyleClients = {}\nvar azStyleClientVersions = {}\n\n// Shadow's style one byte code identifiers to real client name\nvar shadowStyleClients = {}\nvar shadowStyleClientVersions = {}\n\n// Mainline's new style uses one byte code identifiers too\nvar mainlineStyleClients = {}\n\n// Clients with completely custom naming schemes\nvar customStyleClients = []\n\nvar VER_AZ_THREE_DIGITS = \"1.2.3\"\nvar VER_AZ_THREE_DIGITS_PLUS_MNEMONIC = \"1.2.3 [4]\"\nvar VER_AZ_FOUR_DIGITS = \"1.2.3.4\"\nvar VER_AZ_TWO_MAJ_TWO_MIN = \"12.34\"\nvar VER_AZ_SKIP_FIRST_ONE_MAJ_TWO_MIN = \"2.34\"\nvar VER_AZ_KTORRENT_STYLE = \"1.2.3=[RD].4\"\nvar VER_AZ_TRANSMISSION_STYLE = \"transmission\"\nvar VER_AZ_THREE_ALPHANUMERIC_DIGITS = \"2.33.4\"\nvar NO_VERSION = \"NO_VERSION\"\n\nfunction addAzStyle (id, client, version) {\n  version = version || VER_AZ_FOUR_DIGITS\n  azStyleClients[id] = client\n  azStyleClientVersions[client] = version\n}\n\nfunction addShadowStyle (id, client, version) {\n  version = version || VER_AZ_THREE_DIGITS\n  shadowStyleClients[id] = client\n  shadowStyleClientVersions[client] = version\n}\n\nfunction addMainlineStyle (id, client) {\n  mainlineStyleClients[id] = client\n}\n\nfunction addSimpleClient (client, version, id, position) {\n  if (typeof id === 'number' || typeof id === 'undefined') {\n    position = id\n    id = version\n    version = undefined\n  }\n\n  customStyleClients.push({\n    id: id,\n    client: client,\n    version: version,\n    position: position || 0\n  })\n}\n\nfunction getAzStyleClientName (peerId) {\n  return azStyleClients[peerId.substring(1, 3)]\n}\n\nfunction getShadowStyleClientName (peerId) {\n  return shadowStyleClients[peerId.substring(0, 1)]\n}\n\nfunction getMainlineStyleClientName (peerId) {\n  return mainlineStyleClients[peerId.substring(0, 1)]\n}\n\nfunction getSimpleClient (peerId) {\n  for (var i = 0; i < customStyleClients.length; ++i) {\n    var client = customStyleClients[i]\n\n    if (peerId.startsWith(client.id, client.position)) {\n      return client\n    }\n  }\n\n  return null\n}\n\nfunction getAzStyleClientVersion (client, peerId) {\n  var version = azStyleClientVersions[client]\n  if (!version) return null\n\n  return utils.getAzStyleVersionNumber(peerId.substring(3, 7), version)\n}\n\n(function () {\n  // add known clients alphabetically\n  addAzStyle(\"A~\", \"Ares\", VER_AZ_THREE_DIGITS)\n  addAzStyle(\"AG\", \"Ares\", VER_AZ_THREE_DIGITS)\n  addAzStyle(\"AN\", \"Ares\", VER_AZ_FOUR_DIGITS)\n  addAzStyle(\"AR\", \"Ares\") // Ares is more likely than ArcticTorrent\n  addAzStyle(\"AV\", \"Avicora\")\n  addAzStyle(\"AX\", \"BitPump\", VER_AZ_TWO_MAJ_TWO_MIN)\n  addAzStyle(\"AT\", \"Artemis\")\n  addAzStyle(\"AZ\", \"Vuze\", VER_AZ_FOUR_DIGITS)\n  addAzStyle(\"BB\", \"BitBuddy\", \"1.234\")\n  addAzStyle(\"BC\", \"BitComet\", VER_AZ_SKIP_FIRST_ONE_MAJ_TWO_MIN)\n  addAzStyle(\"BE\", \"BitTorrent SDK\")\n  addAzStyle(\"BF\", \"BitFlu\", NO_VERSION)\n  addAzStyle(\"BG\", \"BTG\", VER_AZ_FOUR_DIGITS)\n  addAzStyle(\"bk\", \"BitKitten (libtorrent)\")\n  addAzStyle(\"BR\", \"BitRocket\", \"1.2(34)\")\n  addAzStyle(\"BS\", \"BTSlave\")\n  addAzStyle(\"BW\", \"BitWombat\")\n  addAzStyle(\"BX\", \"BittorrentX\")\n  addAzStyle(\"CB\", \"Shareaza Plus\")\n  addAzStyle(\"CD\", \"Enhanced CTorrent\", VER_AZ_TWO_MAJ_TWO_MIN)\n  addAzStyle(\"CT\", \"CTorrent\", \"1.2.34\")\n  addAzStyle(\"DP\", \"Propogate Data Client\")\n  addAzStyle(\"DE\", \"Deluge\", VER_AZ_FOUR_DIGITS)\n  addAzStyle(\"EB\", \"EBit\")\n  addAzStyle(\"ES\", \"Electric Sheep\", VER_AZ_THREE_DIGITS)\n  addAzStyle(\"FC\", \"FileCroc\")\n  addAzStyle(\"FG\", \"FlashGet\", VER_AZ_SKIP_FIRST_ONE_MAJ_TWO_MIN)\n  addAzStyle(\"FT\", \"FoxTorrent/RedSwoosh\")\n  addAzStyle(\"GR\", \"GetRight\", \"1.2\")\n  addAzStyle(\"GS\", \"GSTorrent\") // TODO: Format is v\"abcd\"\n  addAzStyle(\"HL\", \"Halite\", VER_AZ_THREE_DIGITS)\n  addAzStyle(\"HN\", \"Hydranode\")\n  addAzStyle(\"KG\", \"KGet\")\n  addAzStyle(\"KT\", \"KTorrent\", VER_AZ_KTORRENT_STYLE)\n  addAzStyle(\"LC\", \"LeechCraft\")\n  addAzStyle(\"LH\", \"LH-ABC\")\n  addAzStyle(\"LK\", \"linkage\", VER_AZ_THREE_DIGITS)\n  addAzStyle(\"LP\", \"Lphant\", VER_AZ_TWO_MAJ_TWO_MIN)\n  addAzStyle(\"LT\", \"libtorrent (Rasterbar)\", VER_AZ_THREE_ALPHANUMERIC_DIGITS)\n  addAzStyle(\"lt\", \"libTorrent (Rakshasa)\", VER_AZ_THREE_ALPHANUMERIC_DIGITS)\n  addAzStyle(\"LW\", \"LimeWire\", NO_VERSION) // The \"0001\" bytes found after the LW commonly refers to the version of the BT protocol implemented. Documented here: http://www.limewire.org/wiki/index.php?title=BitTorrentRevision\n  addAzStyle(\"MO\", \"MonoTorrent\")\n  addAzStyle(\"MP\", \"MooPolice\", VER_AZ_THREE_DIGITS)\n  addAzStyle(\"MR\", \"Miro\")\n  addAzStyle(\"MT\", \"MoonlightTorrent\")\n  addAzStyle(\"NE\", \"BT Next Evolution\", VER_AZ_THREE_DIGITS)\n  addAzStyle(\"NX\", \"Net Transport\")\n  addAzStyle(\"OS\", \"OneSwarm\", VER_AZ_FOUR_DIGITS)\n  addAzStyle(\"OT\", \"OmegaTorrent\")\n  addAzStyle(\"PC\", \"CacheLogic\", \"12.3-4\" )\n  addAzStyle(\"PD\", \"Pando\")\n  addAzStyle(\"PE\", \"PeerProject\")\n  addAzStyle(\"pX\", \"pHoeniX\")\n  addAzStyle(\"qB\", \"qBittorrent\", VER_AZ_THREE_DIGITS)\n  addAzStyle(\"QD\", \"qqdownload\")\n  addAzStyle(\"RT\", \"Retriever\")\n  addAzStyle(\"RZ\", \"RezTorrent\")\n  addAzStyle(\"S~\", \"Shareaza alpha/beta\")\n  addAzStyle(\"SB\", \"SwiftBit\")\n  addAzStyle(\"SD\", \"\\u8FC5\\u96F7\\u5728\\u7EBF (Xunlei)\") // Apparently, the English name of the client is \"Thunderbolt\".\n  addAzStyle(\"SG\", \"GS Torrent\", VER_AZ_FOUR_DIGITS)\n  addAzStyle(\"SN\", \"ShareNET\")\n  addAzStyle(\"SP\", \"BitSpirit\") // >= 3.6\n  addAzStyle(\"SS\", \"SwarmScope\")\n  addAzStyle(\"ST\", \"SymTorrent\", \"2.34\")\n  addAzStyle(\"st\", \"SharkTorrent\")\n  addAzStyle(\"SZ\", \"Shareaza\")\n  addAzStyle(\"TN\", \"Torrent.NET\")\n  addAzStyle(\"TR\", \"Transmission\", VER_AZ_TRANSMISSION_STYLE)\n  addAzStyle(\"TS\", \"TorrentStorm\")\n  addAzStyle(\"TT\", \"TuoTu\", VER_AZ_THREE_DIGITS)\n  addAzStyle(\"UL\", \"uLeecher!\")\n  addAzStyle(\"UT\", \"\\u00B5Torrent\", VER_AZ_THREE_DIGITS_PLUS_MNEMONIC)\n  addAzStyle(\"UM\", \"\\u00B5Torrent Mac\", VER_AZ_THREE_DIGITS_PLUS_MNEMONIC)\n  addAzStyle(\"WT\", \"Bitlet\")\n  addAzStyle(\"WW\", \"WebTorrent\") // Go Webtorrent!! :)\n  addAzStyle(\"WY\", \"FireTorrent\") // formerly Wyzo.\n  addAzStyle(\"VG\", \"\\u54c7\\u560E (Vagaa)\", VER_AZ_FOUR_DIGITS)\n  addAzStyle(\"XL\", \"\\u8FC5\\u96F7\\u5728\\u7EBF (Xunlei)\") // Apparently, the English name of the client is \"Thunderbolt\".\n  addAzStyle(\"XT\", \"XanTorrent\")\n  addAzStyle(\"XX\", \"XTorrent\", \"1.2.34\")\n  addAzStyle(\"XC\", \"XTorrent\", \"1.2.34\")\n  addAzStyle(\"ZT\", \"ZipTorrent\")\n  addAzStyle(\"7T\", \"aTorrent\")\n  addAzStyle(\"#@\", \"Invalid PeerID\")\n\n  addShadowStyle('A', \"ABC\")\n  addShadowStyle('O', \"Osprey Permaseed\")\n  addShadowStyle('Q', \"BTQueue\")\n  addShadowStyle('R', \"Tribler\")\n  addShadowStyle('S', \"Shad0w\")\n  addShadowStyle('T', \"BitTornado\")\n  addShadowStyle('U', \"UPnP NAT\")\n\n  addMainlineStyle('M', \"Mainline\")\n  addMainlineStyle('Q', \"Queen Bee\")\n\n  // Simple clients with no version number.\n  addSimpleClient(\"\\u00B5Torrent\", \"1.7.0 RC\", \"-UT170-\") // http://forum.utorrent.com/viewtopic.php?pid=260927#p260927\n  addSimpleClient(\"Azureus\", \"1\", \"Azureus\")\n  addSimpleClient(\"Azureus\", \"2.0.3.2\", \"Azureus\", 5)\n  addSimpleClient(\"Aria\", \"2\", \"-aria2-\")\n  addSimpleClient(\"BitTorrent Plus!\", \"II\", \"PRC.P---\")\n  addSimpleClient(\"BitTorrent Plus!\", \"P87.P---\")\n  addSimpleClient(\"BitTorrent Plus!\", \"S587Plus\")\n  addSimpleClient(\"BitTyrant (Azureus Mod)\", \"AZ2500BT\")\n  addSimpleClient(\"Blizzard Downloader\", \"BLZ\")\n  addSimpleClient(\"BTGetit\", \"BG\", 10)\n  addSimpleClient(\"BTugaXP\", \"btuga\")\n  addSimpleClient(\"BTugaXP\", \"BTuga\", 5)\n  addSimpleClient(\"BTugaXP\", \"oernu\")\n  addSimpleClient(\"Deadman Walking\", \"BTDWV-\")\n  addSimpleClient(\"Deadman\", \"Deadman Walking-\")\n  addSimpleClient(\"External Webseed\", \"Ext\")\n  addSimpleClient(\"G3 Torrent\", \"-G3\")\n  addSimpleClient(\"GreedBT\", \"2.7.1\", \"271-\")\n  addSimpleClient(\"Hurricane Electric\", \"arclight\")\n  addSimpleClient(\"HTTP Seed\", \"-WS\" )\n  addSimpleClient(\"JVtorrent\", \"10-------\")\n  addSimpleClient(\"Limewire\", \"LIME\")\n  addSimpleClient(\"Martini Man\", \"martini\")\n  addSimpleClient(\"Pando\", \"Pando\")\n  addSimpleClient(\"PeerApp\", \"PEERAPP\")\n  addSimpleClient(\"SimpleBT\", \"btfans\", 4)\n  addSimpleClient(\"Swarmy\", \"a00---0\")\n  addSimpleClient(\"Swarmy\", \"a02---0\")\n  addSimpleClient(\"Teeweety\", \"T00---0\")\n  addSimpleClient(\"TorrentTopia\", \"346-\")\n  addSimpleClient(\"XanTorrent\", \"DansClient\")\n  addSimpleClient(\"MediaGet\", \"-MG1\")\n  addSimpleClient(\"MediaGet\", \"2.1\", \"-MG21\")\n\n  /**\n   * This is interesting - it uses Mainline style, except uses two characters instead of one.\n   * And then - the particular numbering style it uses would actually break the way we decode\n   * version numbers (our code is too hardcoded to \"-x-y-z--\" style version numbers).\n   *\n   * This should really be declared as a Mainline style peer ID, but I would have to\n   * make my code more generic. Not a bad thing - just something I'm not doing right\n   * now.\n   */\n  addSimpleClient(\"Amazon AWS S3\", \"S3-\")\n\n  // Simple clients with custom version schemes\n  // TODO: support custom version schemes\n  addSimpleClient(\"BitTorrent DNA\", \"DNA\")\n  addSimpleClient(\"Opera\", \"OP\") // Pre build 10000 versions\n  addSimpleClient(\"Opera\", \"O\") // Post build 10000 versions\n  addSimpleClient(\"Burst!\", \"Mbrst\")\n  addSimpleClient(\"TurboBT\", \"turbobt\")\n  addSimpleClient(\"BT Protocol Daemon\", \"btpd\")\n  addSimpleClient(\"Plus!\", \"Plus\")\n  addSimpleClient(\"XBT\", \"XBT\")\n  addSimpleClient(\"BitsOnWheels\", \"-BOW\")\n  addSimpleClient(\"eXeem\", \"eX\")\n  addSimpleClient(\"MLdonkey\", \"-ML\")\n  addSimpleClient(\"Bitlet\", \"BitLet\")\n  addSimpleClient(\"AllPeers\", \"AP\")\n  addSimpleClient(\"BTuga Revolution\", \"BTM\")\n  addSimpleClient(\"Rufus\", \"RS\", 2)\n  addSimpleClient(\"BitMagnet\", \"BM\", 2) // BitMagnet - predecessor to Rufus\n  addSimpleClient(\"QVOD\", \"QVOD\")\n  // Top-BT is based on BitTornado, but doesn't quite stick to Shadow's naming conventions,\n  // so we'll use substring matching instead.\n  addSimpleClient(\"Top-BT\", \"TB\")\n  addSimpleClient(\"Tixati\", \"TIX\")\n  // seems to have a sub-version encoded in following 3 bytes, not worked out how: \"folx/1.0.456.591\" : 2D 464C 3130 FF862D 486263574A43585F66314D5A\n  addSimpleClient(\"folx\", \"-FL\")\n  addSimpleClient(\"\\u00B5Torrent Mac\", \"-UM\")\n  addSimpleClient(\"\\u00B5Torrent\", \"-UT\") // UT 3.4+\n})()\n\n\n}).call(this,require(\"buffer\").Buffer)\n},{\"./lib/utils\":2,\"buffer\":4}],2:[function(require,module,exports){\n\nif (typeof String.prototype.endsWith !== 'function') {\n  String.prototype.endsWith = function (str){\n    return this.slice(-str.length) === str\n  }\n}\n\nif (typeof String.prototype.startsWith !== 'function') {\n  String.prototype.startsWith = function (str, index) {\n    index = index || 0\n    return this.slice(index, index + str.length) === str\n  }\n}\n\nmodule.exports = {\n  isAzStyle: function (peerId) {\n    if (peerId.charAt(0) !== '-') return false\n    if (peerId.charAt(7) === '-') return true\n\n    /**\n     * Hack for FlashGet - it doesn't use the trailing dash.\n     * Also, LH-ABC has strayed into \"forgetting about the delimiter\" territory.\n     *\n     * In fact, the code to generate a peer ID for LH-ABC is based on BitTornado's,\n     * yet tries to give an Az style peer ID... oh dear.\n     *\n     * BT Next Evolution seems to be in the same boat as well.\n     *\n     * KTorrent 3 appears to use a dash rather than a final character.\n     */\n    if (peerId.substring(1, 3) === \"FG\") return true\n    if (peerId.substring(1, 3) === \"LH\") return true\n    if (peerId.substring(1, 3) === \"NE\") return true\n    if (peerId.substring(1, 3) === \"KT\") return true\n    if (peerId.substring(1, 3) === \"SP\") return true\n\n    return false\n  },\n\n  /**\n   * Checking whether a peer ID is Shadow style or not is a bit tricky.\n   *\n   * The BitTornado peer ID convention code is explained here:\n   *   http://forums.degreez.net/viewtopic.php?t=7070\n   *\n   * The main thing we are interested in is the first six characters.\n   * Although the other characters are base64 characters, there's no\n   * guarantee that other clients which follow that style will follow\n   * that convention (though the fact that some of these clients use\n   * BitTornado in the core does blur the lines a bit between what is\n   * \"style\" and what is just common across clients).\n   *\n   * So if we base it on the version number information, there's another\n   * problem - there isn't the use of absolute delimiters (no fixed dash\n   * character, for example).\n   *\n   * There are various things we can do to determine how likely the peer\n   * ID is to be of that style, but for now, I'll keep it to a relatively\n   * simple check.\n   *\n   * We'll assume that no client uses the fifth version digit, so we'll\n   * expect a dash. We'll also assume that no client has reached version 10\n   * yet, so we expect the first two characters to be \"letter,digit\".\n   *\n   * We've seen some clients which don't appear to contain any version\n   * information, so we need to allow for that.\n   */\n  isShadowStyle: function(peerId) {\n    if (peerId.charAt(5) !== '-') return false\n    if (!isLetter(peerId.charAt(0))) return false\n    if (!(isDigit(peerId.charAt(1)) || peerId.charAt(1) === '-')) return false\n\n    // Find where the version number string ends.\n    var lastVersionNumberIndex = 4\n    for (; lastVersionNumberIndex > 0; lastVersionNumberIndex--) {\n      if (peerId.charAt(lastVersionNumberIndex) !== '-') break\n    }\n\n    // For each digit in the version string, check if it is a valid version identifier.\n    for (var i = 1; i <= lastVersionNumberIndex; i++) {\n      var c = peerId.charAt(i)\n      if (c === '-') return false\n      if (isAlphaNumeric(c) === null) return false\n    }\n\n    return true\n  },\n\n  isMainlineStyle: function (peerId) {\n    /**\n     * One of the following styles will be used:\n     *   Mx-y-z--\n     *   Mx-yy-z-\n     */\n    return peerId.charAt(2) === '-' && peerId.charAt(7) === '-' &&\n      (peerId.charAt(4) === '-' || peerId.charAt(5) === '-')\n  },\n\n  isPossibleSpoofClient: function (peerId) {\n    return peerId.endsWith('UDP0') || peerId.endsWith('HTTPBT')\n  },\n\n  decodeNumericValueOfByte: decodeNumericValueOfByte,\n\n  getAzStyleVersionNumber: function (peerId, version) {\n    // TODO\n    return null\n  },\n\n  getShadowStyleVersionNumber: function (peerId) {\n    // TODO\n    return null\n  },\n\n  decodeBitSpiritClient: function (peerId, buffer) {\n    if (peerId.substring(2, 4) !== 'BS') return null\n    var version = '' + buffer[1]\n    if (version === '0') version = 1\n\n    return {\n      client: \"BitSpirit\",\n      version: version\n    }\n  },\n\n  decodeBitCometClient: function (peerId, buffer) {\n    var modName = \"\"\n    if (peerId.startsWith(\"exbc\")) modName = \"\"\n    else if (peerId.startsWith(\"FUTB\")) modName = \"(Solidox Mod)\"\n    else if (peerId.startsWith(\"xUTB\")) modName = \"(Mod 2)\"\n    else return null\n\n    var isBitlord = (peerId.substring(6, 10) === \"LORD\")\n\n    // Older versions of BitLord are of the form x.yy, whereas new versions (1 and onwards),\n    // are of the form x.y. BitComet is of the form x.yy\n    var clientName = (isBitlord) ? \"BitLord\" : \"BitComet\"\n    var majVersion = decodeNumericValueOfByte(buffer[4])\n    var minVersionLength = (isBitlord && majVersion !== \"0\" ? 1 : 2)\n\n    return {\n      client: clientName + (modName ? \" \" + modName : \"\"),\n      version: majVersion + \".\" + decodeNumericValueOfByte(buffer[5], minVersionLength)\n    }\n  },\n\n  identifyAwkwardClient: function (peerId, buffer) {\n    var firstNonZeroIndex = 20\n    var i\n\n    for (i = 0; i < 20; ++i) {\n      if (buffer[i] > 0) {\n        firstNonZeroIndex = i\n        break\n      }\n    }\n\n    // Shareaza check\n    if (firstNonZeroIndex === 0) {\n      var isShareaza = true\n      for (i = 0; i < 16; ++i) {\n        if (buffer[i] === 0) {\n          isShareaza = false\n          break\n        }\n      }\n\n      if (isShareaza) {\n        for (i = 16; i < 20; ++i) {\n          if (buffer[i] !== (buffer[i % 16] ^ buffer[15 - (i % 16)])) {\n            isShareaza = false\n            break\n          }\n        }\n\n        if (isShareaza) return { client: \"Shareaza\" }\n      }\n    }\n\n    if (firstNonZeroIndex === 9 && buffer[9] === 3 && buffer[10] === 3 && buffer[11] === 3)\n      return { client: \"I2PSnark\" }\n\n    if (firstNonZeroIndex === 12 && buffer[12] === 97 && buffer[13] === 97)\n      return { client: \"Experimental\", version: \"3.2.1b2\" }\n\n    if (firstNonZeroIndex === 12 && buffer[12] === 0 && buffer[13] === 0)\n      return { client: \"Experimental\", version: \"3.1\" }\n\n    if (firstNonZeroIndex === 12)\n      return { client: \"Mainline\" }\n\n    return null\n  }\n}\n\n//\n// Private helper functions for the public utility functions\n//\n\nfunction isDigit (s) {\n  var code = s.charCodeAt(0)\n  return code >= '0'.charCodeAt(0) && code <= '9'.charCodeAt(0)\n}\n\nfunction isLetter (s) {\n  var code = s.toLowerCase().charCodeAt(0)\n  return code >= 'a'.charCodeAt(0) && code <= 'z'.charCodeAt(0)\n}\n\nfunction isAlphaNumeric (s) {\n  return isDigit(s) || isLetter(s) || s === '.'\n}\n\nfunction decodeNumericValueOfByte (b, minDigits) {\n  minDigits = minDigits || 0\n  var result = '' + (b & 0xff)\n  while (result.length < minDigits) { result = '0' + result }\n  return result\n}\n\n\n},{}],3:[function(require,module,exports){\n(function (Buffer){\nvar peerid = require('bittorrent-peerid')\nwindow.format_peerid = function(str) {\n  str = unescape(str);\n  buffer = new Buffer(str, 'binary');\n  return peerid(buffer);\n}\n\n}).call(this,require(\"buffer\").Buffer)\n},{\"bittorrent-peerid\":1,\"buffer\":4}],4:[function(require,module,exports){\n/*!\n * The buffer module from node.js, for the browser.\n *\n * @author   Feross Aboukhadijeh <feross@feross.org> <http://feross.org>\n * @license  MIT\n */\n\nvar base64 = require('base64-js')\nvar ieee754 = require('ieee754')\n\nexports.Buffer = Buffer\nexports.SlowBuffer = Buffer\nexports.INSPECT_MAX_BYTES = 50\nBuffer.poolSize = 8192\n\n/**\n * If `Buffer._useTypedArrays`:\n *   === true    Use Uint8Array implementation (fastest)\n *   === false   Use Object implementation (compatible down to IE6)\n */\nBuffer._useTypedArrays = (function () {\n  // Detect if browser supports Typed Arrays. Supported browsers are IE 10+, Firefox 4+,\n  // Chrome 7+, Safari 5.1+, Opera 11.6+, iOS 4.2+. If the browser does not support adding\n  // properties to `Uint8Array` instances, then that's the same as no `Uint8Array` support\n  // because we need to be able to add all the node Buffer API methods. This is an issue\n  // in Firefox 4-29. Now fixed: https://bugzilla.mozilla.org/show_bug.cgi?id=695438\n  try {\n    var buf = new ArrayBuffer(0)\n    var arr = new Uint8Array(buf)\n    arr.foo = function () { return 42 }\n    return 42 === arr.foo() &&\n        typeof arr.subarray === 'function' // Chrome 9-10 lack `subarray`\n  } catch (e) {\n    return false\n  }\n})()\n\n/**\n * Class: Buffer\n * =============\n *\n * The Buffer constructor returns instances of `Uint8Array` that are augmented\n * with function properties for all the node `Buffer` API functions. We use\n * `Uint8Array` so that square bracket notation works as expected -- it returns\n * a single octet.\n *\n * By augmenting the instances, we can avoid modifying the `Uint8Array`\n * prototype.\n */\nfunction Buffer (subject, encoding, noZero) {\n  if (!(this instanceof Buffer))\n    return new Buffer(subject, encoding, noZero)\n\n  var type = typeof subject\n\n  if (encoding === 'base64' && type === 'string') {\n    subject = base64clean(subject)\n  }\n\n  // Find the length\n  var length\n  if (type === 'number')\n    length = coerce(subject)\n  else if (type === 'string')\n    length = Buffer.byteLength(subject, encoding)\n  else if (type === 'object')\n    length = coerce(subject.length) // assume that object is array-like\n  else\n    throw new Error('First argument needs to be a number, array or string.')\n\n  var buf\n  if (Buffer._useTypedArrays) {\n    // Preferred: Return an augmented `Uint8Array` instance for best performance\n    buf = Buffer._augment(new Uint8Array(length))\n  } else {\n    // Fallback: Return THIS instance of Buffer (created by `new`)\n    buf = this\n    buf.length = length\n    buf._isBuffer = true\n  }\n\n  var i\n  if (Buffer._useTypedArrays && typeof subject.byteLength === 'number') {\n    // Speed optimization -- use set if we're copying from a typed array\n    buf._set(subject)\n  } else if (isArrayish(subject)) {\n    // Treat array-ish objects as a byte array\n    if (Buffer.isBuffer(subject)) {\n      for (i = 0; i < length; i++)\n        buf[i] = subject.readUInt8(i)\n    } else {\n      for (i = 0; i < length; i++)\n        buf[i] = ((subject[i] % 256) + 256) % 256\n    }\n  } else if (type === 'string') {\n    buf.write(subject, 0, encoding)\n  } else if (type === 'number' && !Buffer._useTypedArrays && !noZero) {\n    for (i = 0; i < length; i++) {\n      buf[i] = 0\n    }\n  }\n\n  return buf\n}\n\n// STATIC METHODS\n// ==============\n\nBuffer.isEncoding = function (encoding) {\n  switch (String(encoding).toLowerCase()) {\n    case 'hex':\n    case 'utf8':\n    case 'utf-8':\n    case 'ascii':\n    case 'binary':\n    case 'base64':\n    case 'raw':\n    case 'ucs2':\n    case 'ucs-2':\n    case 'utf16le':\n    case 'utf-16le':\n      return true\n    default:\n      return false\n  }\n}\n\nBuffer.isBuffer = function (b) {\n  return !!(b !== null && b !== undefined && b._isBuffer)\n}\n\nBuffer.byteLength = function (str, encoding) {\n  var ret\n  str = str.toString()\n  switch (encoding || 'utf8') {\n    case 'hex':\n      ret = str.length / 2\n      break\n    case 'utf8':\n    case 'utf-8':\n      ret = utf8ToBytes(str).length\n      break\n    case 'ascii':\n    case 'binary':\n    case 'raw':\n      ret = str.length\n      break\n    case 'base64':\n      ret = base64ToBytes(str).length\n      break\n    case 'ucs2':\n    case 'ucs-2':\n    case 'utf16le':\n    case 'utf-16le':\n      ret = str.length * 2\n      break\n    default:\n      throw new Error('Unknown encoding')\n  }\n  return ret\n}\n\nBuffer.concat = function (list, totalLength) {\n  assert(isArray(list), 'Usage: Buffer.concat(list[, length])')\n\n  if (list.length === 0) {\n    return new Buffer(0)\n  } else if (list.length === 1) {\n    return list[0]\n  }\n\n  var i\n  if (totalLength === undefined) {\n    totalLength = 0\n    for (i = 0; i < list.length; i++) {\n      totalLength += list[i].length\n    }\n  }\n\n  var buf = new Buffer(totalLength)\n  var pos = 0\n  for (i = 0; i < list.length; i++) {\n    var item = list[i]\n    item.copy(buf, pos)\n    pos += item.length\n  }\n  return buf\n}\n\nBuffer.compare = function (a, b) {\n  assert(Buffer.isBuffer(a) && Buffer.isBuffer(b), 'Arguments must be Buffers')\n  var x = a.length\n  var y = b.length\n  for (var i = 0, len = Math.min(x, y); i < len && a[i] === b[i]; i++) {}\n  if (i !== len) {\n    x = a[i]\n    y = b[i]\n  }\n  if (x < y) {\n    return -1\n  }\n  if (y < x) {\n    return 1\n  }\n  return 0\n}\n\n// BUFFER INSTANCE METHODS\n// =======================\n\nfunction hexWrite (buf, string, offset, length) {\n  offset = Number(offset) || 0\n  var remaining = buf.length - offset\n  if (!length) {\n    length = remaining\n  } else {\n    length = Number(length)\n    if (length > remaining) {\n      length = remaining\n    }\n  }\n\n  // must be an even number of digits\n  var strLen = string.length\n  assert(strLen % 2 === 0, 'Invalid hex string')\n\n  if (length > strLen / 2) {\n    length = strLen / 2\n  }\n  for (var i = 0; i < length; i++) {\n    var byte = parseInt(string.substr(i * 2, 2), 16)\n    assert(!isNaN(byte), 'Invalid hex string')\n    buf[offset + i] = byte\n  }\n  return i\n}\n\nfunction utf8Write (buf, string, offset, length) {\n  var charsWritten = blitBuffer(utf8ToBytes(string), buf, offset, length)\n  return charsWritten\n}\n\nfunction asciiWrite (buf, string, offset, length) {\n  var charsWritten = blitBuffer(asciiToBytes(string), buf, offset, length)\n  return charsWritten\n}\n\nfunction binaryWrite (buf, string, offset, length) {\n  return asciiWrite(buf, string, offset, length)\n}\n\nfunction base64Write (buf, string, offset, length) {\n  var charsWritten = blitBuffer(base64ToBytes(string), buf, offset, length)\n  return charsWritten\n}\n\nfunction utf16leWrite (buf, string, offset, length) {\n  var charsWritten = blitBuffer(utf16leToBytes(string), buf, offset, length)\n  return charsWritten\n}\n\nBuffer.prototype.write = function (string, offset, length, encoding) {\n  // Support both (string, offset, length, encoding)\n  // and the legacy (string, encoding, offset, length)\n  if (isFinite(offset)) {\n    if (!isFinite(length)) {\n      encoding = length\n      length = undefined\n    }\n  } else {  // legacy\n    var swap = encoding\n    encoding = offset\n    offset = length\n    length = swap\n  }\n\n  offset = Number(offset) || 0\n  var remaining = this.length - offset\n  if (!length) {\n    length = remaining\n  } else {\n    length = Number(length)\n    if (length > remaining) {\n      length = remaining\n    }\n  }\n  encoding = String(encoding || 'utf8').toLowerCase()\n\n  var ret\n  switch (encoding) {\n    case 'hex':\n      ret = hexWrite(this, string, offset, length)\n      break\n    case 'utf8':\n    case 'utf-8':\n      ret = utf8Write(this, string, offset, length)\n      break\n    case 'ascii':\n      ret = asciiWrite(this, string, offset, length)\n      break\n    case 'binary':\n      ret = binaryWrite(this, string, offset, length)\n      break\n    case 'base64':\n      ret = base64Write(this, string, offset, length)\n      break\n    case 'ucs2':\n    case 'ucs-2':\n    case 'utf16le':\n    case 'utf-16le':\n      ret = utf16leWrite(this, string, offset, length)\n      break\n    default:\n      throw new Error('Unknown encoding')\n  }\n  return ret\n}\n\nBuffer.prototype.toString = function (encoding, start, end) {\n  var self = this\n\n  encoding = String(encoding || 'utf8').toLowerCase()\n  start = Number(start) || 0\n  end = (end === undefined) ? self.length : Number(end)\n\n  // Fastpath empty strings\n  if (end === start)\n    return ''\n\n  var ret\n  switch (encoding) {\n    case 'hex':\n      ret = hexSlice(self, start, end)\n      break\n    case 'utf8':\n    case 'utf-8':\n      ret = utf8Slice(self, start, end)\n      break\n    case 'ascii':\n      ret = asciiSlice(self, start, end)\n      break\n    case 'binary':\n      ret = binarySlice(self, start, end)\n      break\n    case 'base64':\n      ret = base64Slice(self, start, end)\n      break\n    case 'ucs2':\n    case 'ucs-2':\n    case 'utf16le':\n    case 'utf-16le':\n      ret = utf16leSlice(self, start, end)\n      break\n    default:\n      throw new Error('Unknown encoding')\n  }\n  return ret\n}\n\nBuffer.prototype.toJSON = function () {\n  return {\n    type: 'Buffer',\n    data: Array.prototype.slice.call(this._arr || this, 0)\n  }\n}\n\nBuffer.prototype.equals = function (b) {\n  assert(Buffer.isBuffer(b), 'Argument must be a Buffer')\n  return Buffer.compare(this, b) === 0\n}\n\nBuffer.prototype.compare = function (b) {\n  assert(Buffer.isBuffer(b), 'Argument must be a Buffer')\n  return Buffer.compare(this, b)\n}\n\n// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)\nBuffer.prototype.copy = function (target, target_start, start, end) {\n  var source = this\n\n  if (!start) start = 0\n  if (!end && end !== 0) end = this.length\n  if (!target_start) target_start = 0\n\n  // Copy 0 bytes; we're done\n  if (end === start) return\n  if (target.length === 0 || source.length === 0) return\n\n  // Fatal error conditions\n  assert(end >= start, 'sourceEnd < sourceStart')\n  assert(target_start >= 0 && target_start < target.length,\n      'targetStart out of bounds')\n  assert(start >= 0 && start < source.length, 'sourceStart out of bounds')\n  assert(end >= 0 && end <= source.length, 'sourceEnd out of bounds')\n\n  // Are we oob?\n  if (end > this.length)\n    end = this.length\n  if (target.length - target_start < end - start)\n    end = target.length - target_start + start\n\n  var len = end - start\n\n  if (len < 100 || !Buffer._useTypedArrays) {\n    for (var i = 0; i < len; i++) {\n      target[i + target_start] = this[i + start]\n    }\n  } else {\n    target._set(this.subarray(start, start + len), target_start)\n  }\n}\n\nfunction base64Slice (buf, start, end) {\n  if (start === 0 && end === buf.length) {\n    return base64.fromByteArray(buf)\n  } else {\n    return base64.fromByteArray(buf.slice(start, end))\n  }\n}\n\nfunction utf8Slice (buf, start, end) {\n  var res = ''\n  var tmp = ''\n  end = Math.min(buf.length, end)\n\n  for (var i = start; i < end; i++) {\n    if (buf[i] <= 0x7F) {\n      res += decodeUtf8Char(tmp) + String.fromCharCode(buf[i])\n      tmp = ''\n    } else {\n      tmp += '%' + buf[i].toString(16)\n    }\n  }\n\n  return res + decodeUtf8Char(tmp)\n}\n\nfunction asciiSlice (buf, start, end) {\n  var ret = ''\n  end = Math.min(buf.length, end)\n\n  for (var i = start; i < end; i++) {\n    ret += String.fromCharCode(buf[i])\n  }\n  return ret\n}\n\nfunction binarySlice (buf, start, end) {\n  return asciiSlice(buf, start, end)\n}\n\nfunction hexSlice (buf, start, end) {\n  var len = buf.length\n\n  if (!start || start < 0) start = 0\n  if (!end || end < 0 || end > len) end = len\n\n  var out = ''\n  for (var i = start; i < end; i++) {\n    out += toHex(buf[i])\n  }\n  return out\n}\n\nfunction utf16leSlice (buf, start, end) {\n  var bytes = buf.slice(start, end)\n  var res = ''\n  for (var i = 0; i < bytes.length; i += 2) {\n    res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256)\n  }\n  return res\n}\n\nBuffer.prototype.slice = function (start, end) {\n  var len = this.length\n  start = clamp(start, len, 0)\n  end = clamp(end, len, len)\n\n  if (Buffer._useTypedArrays) {\n    return Buffer._augment(this.subarray(start, end))\n  } else {\n    var sliceLen = end - start\n    var newBuf = new Buffer(sliceLen, undefined, true)\n    for (var i = 0; i < sliceLen; i++) {\n      newBuf[i] = this[i + start]\n    }\n    return newBuf\n  }\n}\n\n// `get` will be removed in Node 0.13+\nBuffer.prototype.get = function (offset) {\n  console.log('.get() is deprecated. Access using array indexes instead.')\n  return this.readUInt8(offset)\n}\n\n// `set` will be removed in Node 0.13+\nBuffer.prototype.set = function (v, offset) {\n  console.log('.set() is deprecated. Access using array indexes instead.')\n  return this.writeUInt8(v, offset)\n}\n\nBuffer.prototype.readUInt8 = function (offset, noAssert) {\n  if (!noAssert) {\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset < this.length, 'Trying to read beyond buffer length')\n  }\n\n  if (offset >= this.length)\n    return\n\n  return this[offset]\n}\n\nfunction readUInt16 (buf, offset, littleEndian, noAssert) {\n  if (!noAssert) {\n    assert(typeof littleEndian === 'boolean', 'missing or invalid endian')\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset + 1 < buf.length, 'Trying to read beyond buffer length')\n  }\n\n  var len = buf.length\n  if (offset >= len)\n    return\n\n  var val\n  if (littleEndian) {\n    val = buf[offset]\n    if (offset + 1 < len)\n      val |= buf[offset + 1] << 8\n  } else {\n    val = buf[offset] << 8\n    if (offset + 1 < len)\n      val |= buf[offset + 1]\n  }\n  return val\n}\n\nBuffer.prototype.readUInt16LE = function (offset, noAssert) {\n  return readUInt16(this, offset, true, noAssert)\n}\n\nBuffer.prototype.readUInt16BE = function (offset, noAssert) {\n  return readUInt16(this, offset, false, noAssert)\n}\n\nfunction readUInt32 (buf, offset, littleEndian, noAssert) {\n  if (!noAssert) {\n    assert(typeof littleEndian === 'boolean', 'missing or invalid endian')\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset + 3 < buf.length, 'Trying to read beyond buffer length')\n  }\n\n  var len = buf.length\n  if (offset >= len)\n    return\n\n  var val\n  if (littleEndian) {\n    if (offset + 2 < len)\n      val = buf[offset + 2] << 16\n    if (offset + 1 < len)\n      val |= buf[offset + 1] << 8\n    val |= buf[offset]\n    if (offset + 3 < len)\n      val = val + (buf[offset + 3] << 24 >>> 0)\n  } else {\n    if (offset + 1 < len)\n      val = buf[offset + 1] << 16\n    if (offset + 2 < len)\n      val |= buf[offset + 2] << 8\n    if (offset + 3 < len)\n      val |= buf[offset + 3]\n    val = val + (buf[offset] << 24 >>> 0)\n  }\n  return val\n}\n\nBuffer.prototype.readUInt32LE = function (offset, noAssert) {\n  return readUInt32(this, offset, true, noAssert)\n}\n\nBuffer.prototype.readUInt32BE = function (offset, noAssert) {\n  return readUInt32(this, offset, false, noAssert)\n}\n\nBuffer.prototype.readInt8 = function (offset, noAssert) {\n  if (!noAssert) {\n    assert(offset !== undefined && offset !== null,\n        'missing offset')\n    assert(offset < this.length, 'Trying to read beyond buffer length')\n  }\n\n  if (offset >= this.length)\n    return\n\n  var neg = this[offset] & 0x80\n  if (neg)\n    return (0xff - this[offset] + 1) * -1\n  else\n    return this[offset]\n}\n\nfunction readInt16 (buf, offset, littleEndian, noAssert) {\n  if (!noAssert) {\n    assert(typeof littleEndian === 'boolean', 'missing or invalid endian')\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset + 1 < buf.length, 'Trying to read beyond buffer length')\n  }\n\n  var len = buf.length\n  if (offset >= len)\n    return\n\n  var val = readUInt16(buf, offset, littleEndian, true)\n  var neg = val & 0x8000\n  if (neg)\n    return (0xffff - val + 1) * -1\n  else\n    return val\n}\n\nBuffer.prototype.readInt16LE = function (offset, noAssert) {\n  return readInt16(this, offset, true, noAssert)\n}\n\nBuffer.prototype.readInt16BE = function (offset, noAssert) {\n  return readInt16(this, offset, false, noAssert)\n}\n\nfunction readInt32 (buf, offset, littleEndian, noAssert) {\n  if (!noAssert) {\n    assert(typeof littleEndian === 'boolean', 'missing or invalid endian')\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset + 3 < buf.length, 'Trying to read beyond buffer length')\n  }\n\n  var len = buf.length\n  if (offset >= len)\n    return\n\n  var val = readUInt32(buf, offset, littleEndian, true)\n  var neg = val & 0x80000000\n  if (neg)\n    return (0xffffffff - val + 1) * -1\n  else\n    return val\n}\n\nBuffer.prototype.readInt32LE = function (offset, noAssert) {\n  return readInt32(this, offset, true, noAssert)\n}\n\nBuffer.prototype.readInt32BE = function (offset, noAssert) {\n  return readInt32(this, offset, false, noAssert)\n}\n\nfunction readFloat (buf, offset, littleEndian, noAssert) {\n  if (!noAssert) {\n    assert(typeof littleEndian === 'boolean', 'missing or invalid endian')\n    assert(offset + 3 < buf.length, 'Trying to read beyond buffer length')\n  }\n\n  return ieee754.read(buf, offset, littleEndian, 23, 4)\n}\n\nBuffer.prototype.readFloatLE = function (offset, noAssert) {\n  return readFloat(this, offset, true, noAssert)\n}\n\nBuffer.prototype.readFloatBE = function (offset, noAssert) {\n  return readFloat(this, offset, false, noAssert)\n}\n\nfunction readDouble (buf, offset, littleEndian, noAssert) {\n  if (!noAssert) {\n    assert(typeof littleEndian === 'boolean', 'missing or invalid endian')\n    assert(offset + 7 < buf.length, 'Trying to read beyond buffer length')\n  }\n\n  return ieee754.read(buf, offset, littleEndian, 52, 8)\n}\n\nBuffer.prototype.readDoubleLE = function (offset, noAssert) {\n  return readDouble(this, offset, true, noAssert)\n}\n\nBuffer.prototype.readDoubleBE = function (offset, noAssert) {\n  return readDouble(this, offset, false, noAssert)\n}\n\nBuffer.prototype.writeUInt8 = function (value, offset, noAssert) {\n  if (!noAssert) {\n    assert(value !== undefined && value !== null, 'missing value')\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset < this.length, 'trying to write beyond buffer length')\n    verifuint(value, 0xff)\n  }\n\n  if (offset >= this.length) return\n\n  this[offset] = value\n  return offset + 1\n}\n\nfunction writeUInt16 (buf, value, offset, littleEndian, noAssert) {\n  if (!noAssert) {\n    assert(value !== undefined && value !== null, 'missing value')\n    assert(typeof littleEndian === 'boolean', 'missing or invalid endian')\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset + 1 < buf.length, 'trying to write beyond buffer length')\n    verifuint(value, 0xffff)\n  }\n\n  var len = buf.length\n  if (offset >= len)\n    return\n\n  for (var i = 0, j = Math.min(len - offset, 2); i < j; i++) {\n    buf[offset + i] =\n        (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>>\n            (littleEndian ? i : 1 - i) * 8\n  }\n  return offset + 2\n}\n\nBuffer.prototype.writeUInt16LE = function (value, offset, noAssert) {\n  return writeUInt16(this, value, offset, true, noAssert)\n}\n\nBuffer.prototype.writeUInt16BE = function (value, offset, noAssert) {\n  return writeUInt16(this, value, offset, false, noAssert)\n}\n\nfunction writeUInt32 (buf, value, offset, littleEndian, noAssert) {\n  if (!noAssert) {\n    assert(value !== undefined && value !== null, 'missing value')\n    assert(typeof littleEndian === 'boolean', 'missing or invalid endian')\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset + 3 < buf.length, 'trying to write beyond buffer length')\n    verifuint(value, 0xffffffff)\n  }\n\n  var len = buf.length\n  if (offset >= len)\n    return\n\n  for (var i = 0, j = Math.min(len - offset, 4); i < j; i++) {\n    buf[offset + i] =\n        (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff\n  }\n  return offset + 4\n}\n\nBuffer.prototype.writeUInt32LE = function (value, offset, noAssert) {\n  return writeUInt32(this, value, offset, true, noAssert)\n}\n\nBuffer.prototype.writeUInt32BE = function (value, offset, noAssert) {\n  return writeUInt32(this, value, offset, false, noAssert)\n}\n\nBuffer.prototype.writeInt8 = function (value, offset, noAssert) {\n  if (!noAssert) {\n    assert(value !== undefined && value !== null, 'missing value')\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset < this.length, 'Trying to write beyond buffer length')\n    verifsint(value, 0x7f, -0x80)\n  }\n\n  if (offset >= this.length)\n    return\n\n  if (value >= 0)\n    this.writeUInt8(value, offset, noAssert)\n  else\n    this.writeUInt8(0xff + value + 1, offset, noAssert)\n  return offset + 1\n}\n\nfunction writeInt16 (buf, value, offset, littleEndian, noAssert) {\n  if (!noAssert) {\n    assert(value !== undefined && value !== null, 'missing value')\n    assert(typeof littleEndian === 'boolean', 'missing or invalid endian')\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset + 1 < buf.length, 'Trying to write beyond buffer length')\n    verifsint(value, 0x7fff, -0x8000)\n  }\n\n  var len = buf.length\n  if (offset >= len)\n    return\n\n  if (value >= 0)\n    writeUInt16(buf, value, offset, littleEndian, noAssert)\n  else\n    writeUInt16(buf, 0xffff + value + 1, offset, littleEndian, noAssert)\n  return offset + 2\n}\n\nBuffer.prototype.writeInt16LE = function (value, offset, noAssert) {\n  return writeInt16(this, value, offset, true, noAssert)\n}\n\nBuffer.prototype.writeInt16BE = function (value, offset, noAssert) {\n  return writeInt16(this, value, offset, false, noAssert)\n}\n\nfunction writeInt32 (buf, value, offset, littleEndian, noAssert) {\n  if (!noAssert) {\n    assert(value !== undefined && value !== null, 'missing value')\n    assert(typeof littleEndian === 'boolean', 'missing or invalid endian')\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset + 3 < buf.length, 'Trying to write beyond buffer length')\n    verifsint(value, 0x7fffffff, -0x80000000)\n  }\n\n  var len = buf.length\n  if (offset >= len)\n    return\n\n  if (value >= 0)\n    writeUInt32(buf, value, offset, littleEndian, noAssert)\n  else\n    writeUInt32(buf, 0xffffffff + value + 1, offset, littleEndian, noAssert)\n  return offset + 4\n}\n\nBuffer.prototype.writeInt32LE = function (value, offset, noAssert) {\n  return writeInt32(this, value, offset, true, noAssert)\n}\n\nBuffer.prototype.writeInt32BE = function (value, offset, noAssert) {\n  return writeInt32(this, value, offset, false, noAssert)\n}\n\nfunction writeFloat (buf, value, offset, littleEndian, noAssert) {\n  if (!noAssert) {\n    assert(value !== undefined && value !== null, 'missing value')\n    assert(typeof littleEndian === 'boolean', 'missing or invalid endian')\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset + 3 < buf.length, 'Trying to write beyond buffer length')\n    verifIEEE754(value, 3.4028234663852886e+38, -3.4028234663852886e+38)\n  }\n\n  var len = buf.length\n  if (offset >= len)\n    return\n\n  ieee754.write(buf, value, offset, littleEndian, 23, 4)\n  return offset + 4\n}\n\nBuffer.prototype.writeFloatLE = function (value, offset, noAssert) {\n  return writeFloat(this, value, offset, true, noAssert)\n}\n\nBuffer.prototype.writeFloatBE = function (value, offset, noAssert) {\n  return writeFloat(this, value, offset, false, noAssert)\n}\n\nfunction writeDouble (buf, value, offset, littleEndian, noAssert) {\n  if (!noAssert) {\n    assert(value !== undefined && value !== null, 'missing value')\n    assert(typeof littleEndian === 'boolean', 'missing or invalid endian')\n    assert(offset !== undefined && offset !== null, 'missing offset')\n    assert(offset + 7 < buf.length,\n        'Trying to write beyond buffer length')\n    verifIEEE754(value, 1.7976931348623157E+308, -1.7976931348623157E+308)\n  }\n\n  var len = buf.length\n  if (offset >= len)\n    return\n\n  ieee754.write(buf, value, offset, littleEndian, 52, 8)\n  return offset + 8\n}\n\nBuffer.prototype.writeDoubleLE = function (value, offset, noAssert) {\n  return writeDouble(this, value, offset, true, noAssert)\n}\n\nBuffer.prototype.writeDoubleBE = function (value, offset, noAssert) {\n  return writeDouble(this, value, offset, false, noAssert)\n}\n\n// fill(value, start=0, end=buffer.length)\nBuffer.prototype.fill = function (value, start, end) {\n  if (!value) value = 0\n  if (!start) start = 0\n  if (!end) end = this.length\n\n  assert(end >= start, 'end < start')\n\n  // Fill 0 bytes; we're done\n  if (end === start) return\n  if (this.length === 0) return\n\n  assert(start >= 0 && start < this.length, 'start out of bounds')\n  assert(end >= 0 && end <= this.length, 'end out of bounds')\n\n  var i\n  if (typeof value === 'number') {\n    for (i = start; i < end; i++) {\n      this[i] = value\n    }\n  } else {\n    var bytes = utf8ToBytes(value.toString())\n    var len = bytes.length\n    for (i = start; i < end; i++) {\n      this[i] = bytes[i % len]\n    }\n  }\n\n  return this\n}\n\nBuffer.prototype.inspect = function () {\n  var out = []\n  var len = this.length\n  for (var i = 0; i < len; i++) {\n    out[i] = toHex(this[i])\n    if (i === exports.INSPECT_MAX_BYTES) {\n      out[i + 1] = '...'\n      break\n    }\n  }\n  return '<Buffer ' + out.join(' ') + '>'\n}\n\n/**\n * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance.\n * Added in Node 0.12. Only available in browsers that support ArrayBuffer.\n */\nBuffer.prototype.toArrayBuffer = function () {\n  if (typeof Uint8Array !== 'undefined') {\n    if (Buffer._useTypedArrays) {\n      return (new Buffer(this)).buffer\n    } else {\n      var buf = new Uint8Array(this.length)\n      for (var i = 0, len = buf.length; i < len; i += 1) {\n        buf[i] = this[i]\n      }\n      return buf.buffer\n    }\n  } else {\n    throw new Error('Buffer.toArrayBuffer not supported in this browser')\n  }\n}\n\n// HELPER FUNCTIONS\n// ================\n\nvar BP = Buffer.prototype\n\n/**\n * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods\n */\nBuffer._augment = function (arr) {\n  arr._isBuffer = true\n\n  // save reference to original Uint8Array get/set methods before overwriting\n  arr._get = arr.get\n  arr._set = arr.set\n\n  // deprecated, will be removed in node 0.13+\n  arr.get = BP.get\n  arr.set = BP.set\n\n  arr.write = BP.write\n  arr.toString = BP.toString\n  arr.toLocaleString = BP.toString\n  arr.toJSON = BP.toJSON\n  arr.equals = BP.equals\n  arr.compare = BP.compare\n  arr.copy = BP.copy\n  arr.slice = BP.slice\n  arr.readUInt8 = BP.readUInt8\n  arr.readUInt16LE = BP.readUInt16LE\n  arr.readUInt16BE = BP.readUInt16BE\n  arr.readUInt32LE = BP.readUInt32LE\n  arr.readUInt32BE = BP.readUInt32BE\n  arr.readInt8 = BP.readInt8\n  arr.readInt16LE = BP.readInt16LE\n  arr.readInt16BE = BP.readInt16BE\n  arr.readInt32LE = BP.readInt32LE\n  arr.readInt32BE = BP.readInt32BE\n  arr.readFloatLE = BP.readFloatLE\n  arr.readFloatBE = BP.readFloatBE\n  arr.readDoubleLE = BP.readDoubleLE\n  arr.readDoubleBE = BP.readDoubleBE\n  arr.writeUInt8 = BP.writeUInt8\n  arr.writeUInt16LE = BP.writeUInt16LE\n  arr.writeUInt16BE = BP.writeUInt16BE\n  arr.writeUInt32LE = BP.writeUInt32LE\n  arr.writeUInt32BE = BP.writeUInt32BE\n  arr.writeInt8 = BP.writeInt8\n  arr.writeInt16LE = BP.writeInt16LE\n  arr.writeInt16BE = BP.writeInt16BE\n  arr.writeInt32LE = BP.writeInt32LE\n  arr.writeInt32BE = BP.writeInt32BE\n  arr.writeFloatLE = BP.writeFloatLE\n  arr.writeFloatBE = BP.writeFloatBE\n  arr.writeDoubleLE = BP.writeDoubleLE\n  arr.writeDoubleBE = BP.writeDoubleBE\n  arr.fill = BP.fill\n  arr.inspect = BP.inspect\n  arr.toArrayBuffer = BP.toArrayBuffer\n\n  return arr\n}\n\nvar INVALID_BASE64_RE = /[^+\\/0-9A-z]/g\n\nfunction base64clean (str) {\n  // Node strips out invalid characters like \\n and \\t from the string, base64-js does not\n  str = stringtrim(str).replace(INVALID_BASE64_RE, '')\n  // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not\n  while (str.length % 4 !== 0) {\n    str = str + '='\n  }\n  return str\n}\n\nfunction stringtrim (str) {\n  if (str.trim) return str.trim()\n  return str.replace(/^\\s+|\\s+$/g, '')\n}\n\n// slice(start, end)\nfunction clamp (index, len, defaultValue) {\n  if (typeof index !== 'number') return defaultValue\n  index = ~~index;  // Coerce to integer.\n  if (index >= len) return len\n  if (index >= 0) return index\n  index += len\n  if (index >= 0) return index\n  return 0\n}\n\nfunction coerce (length) {\n  // Coerce length to a number (possibly NaN), round up\n  // in case it's fractional (e.g. 123.456) then do a\n  // double negate to coerce a NaN to 0. Easy, right?\n  length = ~~Math.ceil(+length)\n  return length < 0 ? 0 : length\n}\n\nfunction isArray (subject) {\n  return (Array.isArray || function (subject) {\n    return Object.prototype.toString.call(subject) === '[object Array]'\n  })(subject)\n}\n\nfunction isArrayish (subject) {\n  return isArray(subject) || Buffer.isBuffer(subject) ||\n      subject && typeof subject === 'object' &&\n      typeof subject.length === 'number'\n}\n\nfunction toHex (n) {\n  if (n < 16) return '0' + n.toString(16)\n  return n.toString(16)\n}\n\nfunction utf8ToBytes (str) {\n  var byteArray = []\n  for (var i = 0; i < str.length; i++) {\n    var b = str.charCodeAt(i)\n    if (b <= 0x7F) {\n      byteArray.push(b)\n    } else {\n      var start = i\n      if (b >= 0xD800 && b <= 0xDFFF) i++\n      var h = encodeURIComponent(str.slice(start, i+1)).substr(1).split('%')\n      for (var j = 0; j < h.length; j++) {\n        byteArray.push(parseInt(h[j], 16))\n      }\n    }\n  }\n  return byteArray\n}\n\nfunction asciiToBytes (str) {\n  var byteArray = []\n  for (var i = 0; i < str.length; i++) {\n    // Node's code seems to be doing this and not & 0x7F..\n    byteArray.push(str.charCodeAt(i) & 0xFF)\n  }\n  return byteArray\n}\n\nfunction utf16leToBytes (str) {\n  var c, hi, lo\n  var byteArray = []\n  for (var i = 0; i < str.length; i++) {\n    c = str.charCodeAt(i)\n    hi = c >> 8\n    lo = c % 256\n    byteArray.push(lo)\n    byteArray.push(hi)\n  }\n\n  return byteArray\n}\n\nfunction base64ToBytes (str) {\n  return base64.toByteArray(str)\n}\n\nfunction blitBuffer (src, dst, offset, length) {\n  for (var i = 0; i < length; i++) {\n    if ((i + offset >= dst.length) || (i >= src.length))\n      break\n    dst[i + offset] = src[i]\n  }\n  return i\n}\n\nfunction decodeUtf8Char (str) {\n  try {\n    return decodeURIComponent(str)\n  } catch (err) {\n    return String.fromCharCode(0xFFFD) // UTF 8 invalid char\n  }\n}\n\n/*\n * We have to make sure that the value is a valid integer. This means that it\n * is non-negative. It has no fractional component and that it does not\n * exceed the maximum allowed value.\n */\nfunction verifuint (value, max) {\n  assert(typeof value === 'number', 'cannot write a non-number as a number')\n  assert(value >= 0, 'specified a negative value for writing an unsigned value')\n  assert(value <= max, 'value is larger than maximum value for type')\n  assert(Math.floor(value) === value, 'value has a fractional component')\n}\n\nfunction verifsint (value, max, min) {\n  assert(typeof value === 'number', 'cannot write a non-number as a number')\n  assert(value <= max, 'value larger than maximum allowed value')\n  assert(value >= min, 'value smaller than minimum allowed value')\n  assert(Math.floor(value) === value, 'value has a fractional component')\n}\n\nfunction verifIEEE754 (value, max, min) {\n  assert(typeof value === 'number', 'cannot write a non-number as a number')\n  assert(value <= max, 'value larger than maximum allowed value')\n  assert(value >= min, 'value smaller than minimum allowed value')\n}\n\nfunction assert (test, message) {\n  if (!test) throw new Error(message || 'Failed assertion')\n}\n\n},{\"base64-js\":5,\"ieee754\":6}],5:[function(require,module,exports){\nvar lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n\n;(function (exports) {\n\t'use strict';\n\n  var Arr = (typeof Uint8Array !== 'undefined')\n    ? Uint8Array\n    : Array\n\n\tvar PLUS   = '+'.charCodeAt(0)\n\tvar SLASH  = '/'.charCodeAt(0)\n\tvar NUMBER = '0'.charCodeAt(0)\n\tvar LOWER  = 'a'.charCodeAt(0)\n\tvar UPPER  = 'A'.charCodeAt(0)\n\n\tfunction decode (elt) {\n\t\tvar code = elt.charCodeAt(0)\n\t\tif (code === PLUS)\n\t\t\treturn 62 // '+'\n\t\tif (code === SLASH)\n\t\t\treturn 63 // '/'\n\t\tif (code < NUMBER)\n\t\t\treturn -1 //no match\n\t\tif (code < NUMBER + 10)\n\t\t\treturn code - NUMBER + 26 + 26\n\t\tif (code < UPPER + 26)\n\t\t\treturn code - UPPER\n\t\tif (code < LOWER + 26)\n\t\t\treturn code - LOWER + 26\n\t}\n\n\tfunction b64ToByteArray (b64) {\n\t\tvar i, j, l, tmp, placeHolders, arr\n\n\t\tif (b64.length % 4 > 0) {\n\t\t\tthrow new Error('Invalid string. Length must be a multiple of 4')\n\t\t}\n\n\t\t// the number of equal signs (place holders)\n\t\t// if there are two placeholders, than the two characters before it\n\t\t// represent one byte\n\t\t// if there is only one, then the three characters before it represent 2 bytes\n\t\t// this is just a cheap hack to not do indexOf twice\n\t\tvar len = b64.length\n\t\tplaceHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0\n\n\t\t// base64 is 4/3 + up to two characters of the original data\n\t\tarr = new Arr(b64.length * 3 / 4 - placeHolders)\n\n\t\t// if there are placeholders, only get up to the last complete 4 chars\n\t\tl = placeHolders > 0 ? b64.length - 4 : b64.length\n\n\t\tvar L = 0\n\n\t\tfunction push (v) {\n\t\t\tarr[L++] = v\n\t\t}\n\n\t\tfor (i = 0, j = 0; i < l; i += 4, j += 3) {\n\t\t\ttmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3))\n\t\t\tpush((tmp & 0xFF0000) >> 16)\n\t\t\tpush((tmp & 0xFF00) >> 8)\n\t\t\tpush(tmp & 0xFF)\n\t\t}\n\n\t\tif (placeHolders === 2) {\n\t\t\ttmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4)\n\t\t\tpush(tmp & 0xFF)\n\t\t} else if (placeHolders === 1) {\n\t\t\ttmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2)\n\t\t\tpush((tmp >> 8) & 0xFF)\n\t\t\tpush(tmp & 0xFF)\n\t\t}\n\n\t\treturn arr\n\t}\n\n\tfunction uint8ToBase64 (uint8) {\n\t\tvar i,\n\t\t\textraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes\n\t\t\toutput = \"\",\n\t\t\ttemp, length\n\n\t\tfunction encode (num) {\n\t\t\treturn lookup.charAt(num)\n\t\t}\n\n\t\tfunction tripletToBase64 (num) {\n\t\t\treturn encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F)\n\t\t}\n\n\t\t// go through the array every three bytes, we'll deal with trailing stuff later\n\t\tfor (i = 0, length = uint8.length - extraBytes; i < length; i += 3) {\n\t\t\ttemp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2])\n\t\t\toutput += tripletToBase64(temp)\n\t\t}\n\n\t\t// pad the end with zeros, but make sure to not forget the extra bytes\n\t\tswitch (extraBytes) {\n\t\t\tcase 1:\n\t\t\t\ttemp = uint8[uint8.length - 1]\n\t\t\t\toutput += encode(temp >> 2)\n\t\t\t\toutput += encode((temp << 4) & 0x3F)\n\t\t\t\toutput += '=='\n\t\t\t\tbreak\n\t\t\tcase 2:\n\t\t\t\ttemp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1])\n\t\t\t\toutput += encode(temp >> 10)\n\t\t\t\toutput += encode((temp >> 4) & 0x3F)\n\t\t\t\toutput += encode((temp << 2) & 0x3F)\n\t\t\t\toutput += '='\n\t\t\t\tbreak\n\t\t}\n\n\t\treturn output\n\t}\n\n\texports.toByteArray = b64ToByteArray\n\texports.fromByteArray = uint8ToBase64\n}(typeof exports === 'undefined' ? (this.base64js = {}) : exports))\n\n},{}],6:[function(require,module,exports){\nexports.read = function(buffer, offset, isLE, mLen, nBytes) {\n  var e, m,\n      eLen = nBytes * 8 - mLen - 1,\n      eMax = (1 << eLen) - 1,\n      eBias = eMax >> 1,\n      nBits = -7,\n      i = isLE ? (nBytes - 1) : 0,\n      d = isLE ? -1 : 1,\n      s = buffer[offset + i];\n\n  i += d;\n\n  e = s & ((1 << (-nBits)) - 1);\n  s >>= (-nBits);\n  nBits += eLen;\n  for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8);\n\n  m = e & ((1 << (-nBits)) - 1);\n  e >>= (-nBits);\n  nBits += mLen;\n  for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8);\n\n  if (e === 0) {\n    e = 1 - eBias;\n  } else if (e === eMax) {\n    return m ? NaN : ((s ? -1 : 1) * Infinity);\n  } else {\n    m = m + Math.pow(2, mLen);\n    e = e - eBias;\n  }\n  return (s ? -1 : 1) * m * Math.pow(2, e - mLen);\n};\n\nexports.write = function(buffer, value, offset, isLE, mLen, nBytes) {\n  var e, m, c,\n      eLen = nBytes * 8 - mLen - 1,\n      eMax = (1 << eLen) - 1,\n      eBias = eMax >> 1,\n      rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0),\n      i = isLE ? 0 : (nBytes - 1),\n      d = isLE ? 1 : -1,\n      s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;\n\n  value = Math.abs(value);\n\n  if (isNaN(value) || value === Infinity) {\n    m = isNaN(value) ? 1 : 0;\n    e = eMax;\n  } else {\n    e = Math.floor(Math.log(value) / Math.LN2);\n    if (value * (c = Math.pow(2, -e)) < 1) {\n      e--;\n      c *= 2;\n    }\n    if (e + eBias >= 1) {\n      value += rt / c;\n    } else {\n      value += rt * Math.pow(2, 1 - eBias);\n    }\n    if (value * c >= 2) {\n      e++;\n      c /= 2;\n    }\n\n    if (e + eBias >= eMax) {\n      m = 0;\n      e = eMax;\n    } else if (e + eBias >= 1) {\n      m = (value * c - 1) * Math.pow(2, mLen);\n      e = e + eBias;\n    } else {\n      m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);\n      e = 0;\n    }\n  }\n\n  for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8);\n\n  e = (e << mLen) | m;\n  eLen += mLen;\n  for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8);\n\n  buffer[offset + i - d] |= s * 128;\n};\n\n},{}]},{},[3])\n"
  },
  {
    "path": "statics/common/offline/js/yaaw-1.1.js",
    "content": "/* \n * Copyright (C) 2015 Binux <roy@binux.me>\n *\n * This file is part of YAAW (https://github.com/binux/yaaw).\n *\n * YAAW is free software: you can redistribute it and/or modify\n * it under the terms of the GNU Lesser General Public License as\n * published by the Free Software Foundation, either version 3 of\n * the License, or (at your option) any later version.\n *\n * YAAW is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n * GNU Lesser General Public License for more details.\n *\n * You may get a copy of the GNU Lesser General Public License\n * from http://www.gnu.org/licenses/lgpl.txt\n *\n */\n\nvar YAAW = (function() {\n  var selected_tasks = false;\n  var selected_range_start = null;\n  var selected_range_close = null;\n  var on_gid = null;\n  var torrent_file = null, file_type = null;\n  return {\n    init: function() {\n      $('#main-control').show();\n\n      this.tpl.init();\n      this.setting.init();\n      this.contextmenu.init();\n      this.event_init();\n      this.aria2_init();\n    },\n\n    aria2_init: function() {\n      ARIA2.init(this.setting.jsonrpc_path, function() {\n        if (YAAW.setting.add_task_option) {\n          $(\"#add-task-option-wrap\").empty().append(YAAW.tpl.add_task_option(YAAW.setting.add_task_option));\n        } else {\n          ARIA2.init_add_task_option();\n        }\n        ARIA2.refresh();\n        ARIA2.auto_refresh(YAAW.setting.refresh_interval);\n        ARIA2.finish_notification = YAAW.setting.finish_notification;\n        ARIA2.get_version();\n        ARIA2.global_stat();\n      });\n    },\n\n    event_init: function() {\n\n      $(\"#add-task-submit\").live(\"click\", function() {\n        YAAW.add_task.submit();return false;\n      });\n      $(\"#add-task-uri\").submit(function() {\n        YAAW.add_task.submit();return false;\n      });\n      $(\"#saveSettings\").live(\"click\", function() {\n        YAAW.setting.submit();return false;\n      });\n      $(\"#setting-form\").submit(function() {\n        YAAW.setting.submit();return false;\n      });\n      $(\"#add-task-clear\").live(\"click\", function() {\n        YAAW.add_task.clean();\n      });\n      $(\"#btnRemove\").live(\"click\", function() {\n        YAAW.tasks.remove();YAAW.tasks.unSelectAll();\n      });\n      $(\"#btnPause\").live(\"click\", function() {\n        YAAW.tasks.pause();YAAW.tasks.unSelectAll();\n      });\n      $(\"#btnUnPause\").live(\"click\", function() {\n        YAAW.tasks.unpause();YAAW.tasks.unSelectAll();\n      });\n      $(\"#btnClearAlert\").live(\"click\", function() {\n        $('#main-alert').hide();\n      });\n      $(\"#btnSelectActive\").live(\"click\", function() {\n        YAAW.tasks.selectActive();\n      });\n      $(\"#btnSelectWaiting\").live(\"click\", function() {\n        YAAW.tasks.selectWaiting();\n      });\n      $(\"#btnSelectPaused\").live(\"click\", function() {\n        YAAW.tasks.selectPaused();\n      });\n      $(\"#btnSelectStopped\").live(\"click\", function() {\n        YAAW.tasks.selectStopped();\n      });\n      $(\"#btnStartAll\").live(\"click\", function() {\n        ARIA2.unpause_all();\n      });\n      $(\"#btnPauseAll\").live(\"click\", function() {\n        ARIA2.pause_all();\n      });\n      $(\"#btnRemoveFinished\").live(\"click\", function() {\n        ARIA2.purge_download_result();\n      });\n      $(\"#closeAlert\").live(\"click\", function() {\n        $('#add-task-alert').hide();\n      });\n      $(\"#menuMoveTop\").live(\"click\", function() {\n        if (selected_tasks) {\n          YAAW.tasks.movetop();\n          YAAW.tasks.unSelectAll();\n        } else {\n          YAAW.contextmenu.movetop();\n        }\n      });\n      $(\"#menuMoveUp\").live(\"click\", function() {\n        if (selected_tasks) {\n          YAAW.tasks.moveup();\n          YAAW.tasks.unSelectAll();\n        } else {\n          YAAW.contextmenu.moveup();\n        }\n      });\n      $(\"#menuMoveDown\").live(\"click\", function() {\n        if (selected_tasks) {\n          YAAW.tasks.movedown();\n          YAAW.tasks.unSelectAll();\n        } else {\n          YAAW.contextmenu.movedown();\n        }\n      });\n      $(\"#menuMoveEnd\").live(\"click\", function() {\n        if (selected_tasks) {\n          YAAW.tasks.moveend();\n          YAAW.tasks.unSelectAll();\n        } else {\n          YAAW.contextmenu.moveend();\n        }\n      });\n      $(\"#menuRestart\").live(\"click\", function() {\n        if (selected_tasks) {\n          YAAW.tasks.restart();\n          YAAW.tasks.unSelectAll();\n        } else {\n          YAAW.contextmenu.restart();\n        }\n      });\n      $(\"#menuStart\").live(\"click\", function() {\n        if (selected_tasks) {\n          YAAW.tasks.unpause();\n          YAAW.tasks.unSelectAll();\n        } else {\n          YAAW.contextmenu.unpause();\n        }\n      });\n      $(\"#menuPause\").live(\"click\", function() {\n        if (selected_tasks) {\n          YAAW.tasks.pause();\n          YAAW.tasks.unSelectAll();\n        } else {\n          YAAW.contextmenu.pause();\n        }\n      });\n      $(\"#menuRemove\").live(\"click\", function() {\n        if (selected_tasks) {\n          YAAW.tasks.remove();\n          YAAW.tasks.unSelectAll();\n        } else {\n          YAAW.contextmenu.remove();\n        }\n      });\n\n\n      $(\"[rel=tooltip]\").tooltip({\"placement\": \"bottom\"});\n\n      $(\".task .select-box\").live(\"click\", function(e) {\n        if (!e.shiftKey) {\n          YAAW.tasks.toggle($(this).parents(\".task\"));\n          selected_range_start = $(this).parents(\".task\").hasClass(\"selected\") ? $(this).parents(\".task\")[0] : null;\n          selected_range_close = null;\n        } else {\n          YAAW.tasks.select($(this).parents(\".task\"));\n          if (!selected_range_start)\n            selected_range_start = $(this).parents(\".task\")[0];\n          else if (!selected_range_close)\n            selected_range_close = $(this).parents(\".task\")[0];\n        }\n        if (selected_range_start && selected_range_close) {\n          if (selected_range_start == selected_range_close) {\n            selected_range_close = null;\n          } else {\n            var task_in_range = false;\n            $(\".tasks-table .task\").each(function (i, n) {\n              if (n == selected_range_start || n == selected_range_close) task_in_range = !task_in_range;\n              if (task_in_range) YAAW.tasks.select(n);\n            });\n            selected_range_start = selected_range_close;\n            selected_range_close = null;\n          }\n        }\n        YAAW.tasks.check_select();\n      });\n\n      $(\".task .task-name > span\").live(\"click\", function() {\n        var task = $(this).parents(\".task\");\n        if (task.hasClass(\"info-open\")) {\n          YAAW.tasks.info_close();\n        } else {\n          YAAW.tasks.info_close();\n          YAAW.tasks.info(task);\n        }\n      });\n\n      $(\"#uri-more\").click(function() {\n        $(\"#add-task-uri .input-append\").toggle();\n        $(\"#uri-textarea\").toggle();\n        $(\"#uri-more .or-and\").toggle();\n        $(\"#uri-input\").val(\"\");\n        $(\"#uri-textarea\").val(\"\");\n        $(\"#ati-out\").parents(\".control-group\").val(\"\").toggle();\n      });\n\n      $(\"#ib-files .ib-file-title, #ib-files .select-box\").live(\"click\", function() {\n        if ($(this).parent().find(\".select-box:first\").hasClass(\"icon-ok\")) {\n          $(this).parent().find(\".select-box\").removeClass(\"icon-ok\");\n        } else {\n          $(this).parent().find(\".select-box\").addClass(\"icon-ok\");\n        }\n      });\n\n      $(\"#ib-file-save\").live(\"click\", function() {\n        var indexes = [];\n        $(\"#ib-files .select-box.icon-ok[data-index]\").each(function(i, n) {\n          indexes.push(n.getAttribute(\"data-index\"));\n        });\n        if (indexes.length == 0) {\n          ARIA2.main_alert(\"alert-error\", \"At least one file should be selected. Or just stop the task.\", 5000);\n        } else {\n          var options = {\n            \"select-file\": indexes.join(\",\"),\n          };\n          ARIA2.change_option($(this).parents(\".info-box\").attr(\"data-gid\"), options);\n        };\n      });\n\n      $(\"#ib-options-a\").live(\"click\", function() {\n        ARIA2.get_options($(\".info-box\").attr(\"data-gid\"));\n      });\n\n      $(\"#ib-peers-a\").live(\"click\", function() {\n        ARIA2.get_peers($(\".info-box\").attr(\"data-gid\"));\n      });\n\n      var active_task_allowed_options = [\"max-download-limit\", \"max-upload-limit\"];\n      $(\"#ib-options-save\").live(\"click\", function() {\n        var options = {};\n        var gid = $(this).parents(\".info-box\").attr(\"data-gid\");\n        var status = $(\"#task-gid-\"+gid).attr(\"data-status\");\n        $.each($(\"#ib-options-form input\"), function(n, e) {\n          if (status == \"active\" && active_task_allowed_options.indexOf(e.name) == -1)\n            return;\n          options[e.name] = e.value;\n        });\n        ARIA2.change_options($(\".info-box\").attr(\"data-gid\"), options);\n      });\n\n      $(\"#select-all-btn\").click(function() {\n        if (selected_tasks) {\n          YAAW.tasks.unSelectAll();\n        } else {\n          YAAW.tasks.selectAll();\n        }\n      });\n\n      $(\"#refresh-btn\").click(function() {\n        YAAW.tasks.unSelectAll();\n        YAAW.tasks.info_close();\n        $(\"#main-alert\").hide();\n        ARIA2.refresh();\n        return false;\n      });\n\n      $(\"#setting-modal\").on(\"show\", function() {\n        ARIA2.get_global_option();\n      });\n\n      if (window.FileReader) {\n        var holder = $(\"#add-task-modal .modal-body\").get(0);\n        holder.ondragover = function() {\n          $(this).addClass(\"hover\");\n          return false;\n        }\n        holder.ondragend = function() {\n          $(this).removeClass(\"hover\");\n          return false;\n        }\n        holder.ondrop = function(e) {\n          $(this).removeClass(\"hover\");\n          e.preventDefault();\n          var file = e.dataTransfer.files[0];\n          YAAW.add_task.upload(file);\n          return false;\n        }\n\n        var tup = $(\"#torrent-up-input\").get(0);\n        tup.onchange = function(e) {\n          var file = e.target.files[0];\n          YAAW.add_task.upload(file);\n        }\n      } else {\n        $(\"#torrent-up-input\").remove();\n        $(\"#torrent-up-btn\").addClass(\"disabled\").tooltip({title: \"File API is Not Supported.\"});\n      }\n\n      if (window.applicationCache) {\n        var appcache = window.applicationCache;\n        $(document).ready(function() {\n          if (appcache.status == appcache.IDLE)\n            $(\"#offline-cached\").text(\"cached\");\n        });\n        appcache.addEventListener(\"cached\", function(){\n          $(\"#offline-cached\").text(\"cached\");\n        });\n      }\n    },\n\n    tpl: {\n      init: function() {\n        var _this = this;\n        $(\"script[type='text/mustache-template']\").each(function(i, n) {\n          var key = n.getAttribute(\"id\").replace(/-tpl$/, \"\").replace(/-/g, \"_\");\n          _this[key] = function() {\n            var tpl = Mustache.compile($(n).text());\n            return function(view) {\n              view._v = _this.view;\n              return tpl(view);\n            };\n          }();\n        });\n      },\n\n      files_tree: function(files) {\n        var file_dict = {}, f;\n        for (var i = 0; i < files.length; i++) {\n          var at = files[i].title.split('/');\n          f = file_dict;\n          for (var j = 0; j < at.length; j++) {\n            f[at[j]] = f[at[j]] || {};\n            f = f[at[j]];\n          }\n          f['_file'] = files[i];\n        }\n\n        function render(f) {\n          var content = '<ul>';\n\n          for (var k in f) {\n            if (f[k]['_file'] !== undefined) {\n              continue;\n            }\n\n            content += '<li>';\n            content += '<i class=\"select-box icon-ok\"></i>';\n            content += '<span class=\"ib-file-title\">'+$('<div>').text(k).html()+'</span>';\n            content += render(f[k]);\n            content += '</li>';\n          }\n\n          for (k in f) {\n            if (f[k]['_file'] === undefined) {\n              continue;\n            }\n\n            f[k]['_file']['relative_title'] = k;\n            content += YAAW.tpl.file(f[k]['_file']);\n          }\n          content += '</ul>';\n          return content;\n        }\n\n        //console.log(file_dict);\n        return render(file_dict);\n      },\n\n      view: {\n        bitfield: function() {\n          var graphic = \"░▒▓█\";\n          return function(text) {\n            var len = text.length;\n            var result = \"\";\n            for (var i=0; i<len; i++)\n            result += graphic[Math.floor(parseInt(text[i], 16)/4)] + \"&#8203;\";\n            return result;\n          };\n        },\n\n        bitfield_to_10: function() {\n          var graphic = \"░▒▓█\";\n          return function(text) {\n            var len = text.length;\n            var part_len = Math.ceil(len/10);\n            var result = \"\";\n            for (var i=0; i<10; i++) {\n              p = 0;\n              for (var j=0; j<part_len; j++) {\n                if (i*part_len+j >= len)\n                  p += 16;\n                else\n                  p += parseInt(text[i*part_len+j], 16);\n              }\n              result += graphic[Math.floor(p/part_len/4)] + \"&#8203;\";\n            }\n            return result;\n          };\n        },\n\n        bitfield_to_percent: function() {\n          return function(text) {\n            var len = text.length - 1;\n            var p, one = 0;\n            for (var i=0; i<len; i++) {\n              p = parseInt(text[i], 16);\n              for (var j=0; j<4; j++) {\n                one += (p & 1);\n                p >>= 1;\n              }\n            }\n            return Math.floor(one/(4*len)*100).toString();\n          };\n        },\n\n        format_size: function() {\n          var format_text = [\"B\", \"KB\", \"MB\", \"GB\", \"TB\", ];\n          return function format_size(size) {\n            if (size === '') return '';\n            size = parseInt(size);\n            var i = 0;\n            while (size >= 1024) {\n              size /= 1024;\n              i++;\n            }\n            if (size==0) {\n              return \"0 KB\";\n            } else {\n              return size.toFixed(2)+\" \"+format_text[i];\n            }\n          };\n        },\n\n        format_size_0: function() {\n          var format_text = [\"B\", \"KB\", \"MB\", \"GB\", \"TB\", ];\n          return function format_size(size) {\n            if (size === '') return '';\n            size = parseInt(size);\n            var i = 0;\n            while (size >= 1024) {\n              size /= 1024;\n              i++;\n            }\n            if (size==0) {\n              return \"0 KB\";\n            } else {\n              return size.toFixed(0)+\" \"+format_text[i];\n            }\n          };\n        },\n\n        format_time: function() {\n          var time_interval = [60, 60, 24];\n          var time_text = [\"s\", \"m\", \"h\"];\n          return function format_time(time) {\n            if (time == Infinity) {\n              return \"INF\";\n            } else if (time == 0) {\n              return \"0s\";\n            }\n\n            time = Math.floor(time);\n            var i = 0;\n            var result = \"\";\n            while (time > 0 && i < 3) {\n              result = time % time_interval[i] + time_text[i] + result;\n              time = Math.floor(time/time_interval[i]);\n              i++;\n            }\n            if (time > 0) {\n              result = time + \"d\" + result;\n            }\n            return result;\n          };\n        },\n\n        format_peerid: function() {\n          return function format_peerid(peerid) {\n            try {\n              var ret = window.format_peerid(peerid);\n              if (ret.client == 'unknown') throw 'unknown';\n              return ret.client+(ret.version ? '-'+ret.version : '');\n            } catch(e) {\n              if (peerid == '%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00')\n                return 'unknown';\n              var ret = unescape(peerid).split('-');\n              for (var i=0; i<ret.length; i++) {\n                if (ret[i].trim().length) return ret[i];\n              }\n              return 'unknown';\n            }\n          }\n        },\n\n        error_msg: function() {\n          var error_code_map = {\n            0: \"\",\n            1: \"unknown error occurred.\",\n            2: \"time out occurred.\",\n            3: \"resource was not found.\",\n            4: \"resource was not found. See --max-file-not-found option.\",\n            5: \"resource was not found. See --lowest-speed-limit option.\",\n            6: \"network problem occurred.\",\n            7: \"unfinished download.\",\n            8: \"remote server did not support resume when resume was required to complete download.\",\n            9: \"there was not enough disk space available.\",\n            10: \"piece length was different from one in .aria2 control file. See --allow-piece-length-change option.\",\n            11: \"aria2 was downloading same file at that moment.\",\n            12: \"aria2 was downloading same info hash torrent at that moment.\",\n            13: \"file already existed. See --allow-overwrite option.\",\n            14: \"renaming file failed. See --auto-file-renaming option.\",\n            15: \"aria2 could not open existing file.\",\n            16: \"aria2 could not create new file or truncate existing file.\",\n            17: \"I/O error occurred.\",\n            18: \"aria2 could not create directory.\",\n            19: \"name resolution failed.\",\n            20: \"could not parse Metalink document.\",\n            21: \"FTP command failed.\",\n            22: \"HTTP response header was bad or unexpected.\",\n            23: \"too many redirections occurred.\",\n            24: \"HTTP authorization failed.\",\n            25: \"aria2 could not parse bencoded file(usually .torrent file).\",\n            26: \".torrent file was corrupted or missing information that aria2 needed.\",\n            27: \"Magnet URI was bad.\",\n            28: \"bad/unrecognized option was given or unexpected option argument was given.\",\n            29: \"the remote server was unable to handle the request due to a temporary overloading or maintenance.\",\n            30: \"aria2 could not parse JSON-RPC request.\",\n          };\n          return function(text) {\n            return error_code_map[text] || \"\";\n          };\n        },\n\n        status_icon: function() {\n          var status_icon_map = {\n            active: \"icon-download-alt\",\n            waiting: \"icon-time\",\n            paused: \"icon-pause\",\n            error: \"icon-remove\",\n            complete: \"icon-ok\",\n            removed: \"icon-trash\",\n          };\n          return function(text) {\n            return status_icon_map[text] || \"\";\n          };\n        },\n      },\n    },\n\n    add_task: {\n      submit: function(_this) {\n        var uri = $(\"#uri-input\").val() || $(\"#uri-textarea\").val() && $(\"#uri-textarea\").val().split(\"\\n\");\n        var options = {}, options_save = {};\n        $(\"#add-task-option input[name], #add-task-option textarea[name]\").each(function(i, n) {\n          var name = n.getAttribute(\"name\");\n          var value = (n.type == \"checkbox\" ? n.checked : n.value);\n          if (name && value) {\n            options[name] = String(value);\n            if ($(n).hasClass(\"input-save\")) {\n              options_save[name] = String(value);\n            }\n          }\n        });\n\n        if (uri) {\n          ARIA2.madd_task(uri, options);\n          YAAW.setting.save_add_task_option(options_save);\n        } else if (torrent_file) {\n          if (file_type.indexOf(\"metalink\") != -1) {\n            ARIA2.add_metalink(torrent_file, options);\n          } else {\n            ARIA2.add_torrent(torrent_file, options);\n          }\n          YAAW.setting.save_add_task_option(options_save);\n        }\n      },\n\n      clean: function() {\n        $(\"#uri-input\").attr(\"placeholder\", \"HTTP, FTP or Magnet\");\n        $(\"#add-task-modal .input-clear\").val(\"\");\n        $(\"#add-task-alert\").hide();\n        torrent_file = null;\n        file_type = null;\n      },\n\n      upload: function(file) {\n        var reader = new FileReader();\n        reader.onload = function(e) {\n          $(\"#uri-input\").attr(\"placeholder\", file.name);\n          torrent_file = e.target.result.replace(/.*?base64,/, \"\");\n          file_type = file.type;\n        };\n        reader.onerror = function(e) {\n          $(\"#torrent-up-input\").remove();\n          $(\"#torrent-up-btn\").addClass(\"disabled\");\n        };\n        reader.readAsDataURL(file);\n      },\n    },\n\n    tasks: {\n      check_select: function() {\n        var selected = $(\".tasks-table .task.selected\");\n        if (selected.length == 0) {\n          selected_tasks = false;\n          $(\"#select-btn .select-box\").removeClass(\"icon-minus icon-ok\");\n        } else if (selected.length < $(\".tasks-table .task\").length) {\n          selected_tasks = true;\n          $(\"#select-btn .select-box\").removeClass(\"icon-ok\").addClass(\"icon-minus\");\n        } else {\n          selected_tasks = true;\n          $(\"#select-btn .select-box\").removeClass(\"icon-minus\").addClass(\"icon-ok\");\n        }\n\n        if (selected.length + $(\".info-box\").length == 0) {\n          ARIA2.select_lock(false);\n        } else {\n          ARIA2.select_lock(true);\n        }\n\n        if (selected_tasks) {\n          $(\"#not-selected-grp\").hide();\n          $(\"#selected-grp\").show();\n        } else {\n          $(\"#not-selected-grp\").show();\n          $(\"#selected-grp\").hide();\n        }\n      },\n\n      select: function(task) {\n        $(task).addClass(\"selected\").find(\".select-box\").addClass(\"icon-ok\");\n      },\n\n      unSelect: function(task) {\n        $(task).removeClass(\"selected\").find(\".select-box\").removeClass(\"icon-ok\");\n      },\n\n      toggle: function(task) {\n        $(task).toggleClass(\"selected\").find(\".select-box\").toggleClass(\"icon-ok\");\n      },\n\n      unSelectAll: function(notupdate) {\n        var _this = this;\n        $(\".tasks-table .task.selected\").each(function(i, n) {\n          _this.unSelect(n);\n        });\n        if (!notupdate)\n          this.check_select();\n      },\n\n      selectAll: function() {\n        var _this = this;\n        $(\".tasks-table .task\").each(function(i, n) {\n          _this.select(n);\n        });\n        this.check_select();\n      },\n\n      selectActive: function() {\n        var _this = this;\n        this.unSelectAll(true);\n        $(\".tasks-table .task[data-status=active]\").each(function(i, n) {\n          _this.select(n);\n        });\n        this.check_select();\n      },\n\n      selectWaiting: function() {\n        var _this = this;\n        this.unSelectAll(true);\n        $(\".tasks-table .task[data-status=waiting]\").each(function(i, n) {\n          _this.select(n);\n        });\n        this.check_select();\n      },\n\n      selectPaused: function() {\n        var _this = this;\n        this.unSelectAll(true);\n        $(\".tasks-table .task[data-status=paused]\").each(function(i, n) {\n          _this.select(n);\n        });\n        this.check_select();\n      },\n\n      selectStopped: function() {\n        var _this = this;\n        this.unSelectAll(true);\n        $(\"#stopped-tasks-table .task\").each(function(i, n) {\n          _this.select(n);\n        });\n        this.check_select();\n      },\n\n      getSelectedGids: function() {\n        var gids = new Array();\n        $(\".tasks-table .task.selected\").each(function(i, n) {\n          gids.push(n.getAttribute(\"data-gid\"));\n        });\n        return gids;\n      },\n\n      restart: function() {\n        var gids = new Array();\n        $(\".tasks-table .task.selected\").each(function(i, n) {\n          var status = n.getAttribute(\"data-status\");\n          if (status == \"removed\" || status == \"complete\" || status == \"error\")\n            gids.push(n.getAttribute(\"data-gid\"));\n        });\n        if (gids.length) ARIA2.restart_task(gids);\n      },\n\n      pause: function() {\n        var gids = new Array();\n        $(\".tasks-table .task.selected\").each(function(i, n) {\n          if (n.getAttribute(\"data-status\") == \"active\" ||\n              n.getAttribute(\"data-status\") == \"waiting\")\n            gids.push(n.getAttribute(\"data-gid\"));\n        });\n        if (gids.length) ARIA2.pause(this.getSelectedGids());\n      },\n\n      unpause: function() {\n        var gids = new Array();\n        var stopped_gids = new Array();\n        $(\".tasks-table .task.selected\").each(function(i, n) {\n          var status = n.getAttribute(\"data-status\");\n          if (status == \"paused\") {\n            gids.push(n.getAttribute(\"data-gid\"));\n          } else if (\"removed/error\".indexOf(status) != -1) {\n            stopped_gids.push(n.getAttribute(\"data-gid\"));\n          }\n        });\n        if (gids.length) ARIA2.unpause(gids);\n        if (stopped_gids.length) ARIA2.restart_task(stopped_gids);\n      },\n\n      remove: function() {\n        var gids = new Array();\n        var remove_list = [\"active\", \"waiting\", \"paused\"];\n        var remove_gids = new Array();\n        $(\".tasks-table .task.selected\").each(function(i, n) {\n          if (remove_list.indexOf(n.getAttribute(\"data-status\")) != -1)\n            remove_gids.push(n.getAttribute(\"data-gid\"));\n          else\n            gids.push(n.getAttribute(\"data-gid\"));\n        });\n        if (remove_gids.length) ARIA2.remove(remove_gids);\n        if (gids.length) ARIA2.remove_result(gids);\n      },\n\n      movetop: function() {\n        var gids = new Array();\n        $(\".tasks-table .task.selected\").each(function(i, n) {\n          if (n.getAttribute(\"data-status\") == \"waiting\" ||\n              n.getAttribute(\"data-status\") == \"paused\")\n            gids.push(n.getAttribute(\"data-gid\"));\n        });\n        gids.reverse();\n        ARIA2.change_selected_pos(gids, 0, 'POS_SET');\n      },\n\n      moveup: function() {\n        var gids = new Array();\n        $(\".tasks-table .task.selected\").each(function(i, n) {\n          if (n.getAttribute(\"data-status\") == \"waiting\" ||\n              n.getAttribute(\"data-status\") == \"paused\")\n            gids.push(n.getAttribute(\"data-gid\"));\n        });\n        ARIA2.change_selected_pos(gids, -1, 'POS_CUR');\n      },\n\n      movedown: function() {\n        var gids = new Array();\n        $(\".tasks-table .task.selected\").each(function(i, n) {\n          if (n.getAttribute(\"data-status\") == \"waiting\" ||\n              n.getAttribute(\"data-status\") == \"paused\")\n            gids.push(n.getAttribute(\"data-gid\"));\n        });\n        gids.reverse();\n        ARIA2.change_selected_pos(gids, 1, 'POS_CUR');\n      },\n\n      moveend: function() {\n        var gids = new Array();\n        $(\".tasks-table .task.selected\").each(function(i, n) {\n          if (n.getAttribute(\"data-status\") == \"waiting\" ||\n              n.getAttribute(\"data-status\") == \"paused\")\n            gids.push(n.getAttribute(\"data-gid\"));\n        });\n        ARIA2.change_selected_pos(gids, 0, 'POS_END');\n      },\n\n      info: function(task) {\n        task.addClass(\"info-open\");\n        task.after(YAAW.tpl.info_box({gid: task.attr(\"data-gid\")}));\n        if (task.parents(\"#stopped-tasks-table\").length) {\n          $(\"#ib-options-a\").hide();\n        }\n        ARIA2.get_status(task.attr(\"data-gid\"));\n        ARIA2.select_lock(true);\n      },\n\n      info_close: function(task) {\n        $(\".info-box\").remove();\n        $(\".info-open\").removeClass(\"info-open\");\n\n        if ($(\".tasks-table .task.selected\").length == 0) {\n          ARIA2.select_lock(false);\n        } else {\n          ARIA2.select_lock(true);\n        }\n      },\n    },\n\n    contextmenu: {\n      init: function() {\n        $(\".task\").live(\"contextmenu\", function(ev) {\n          var contextmenu_position_y = ev.clientY;\n          var contextmenu_position_x = ev.clientX;\n          if ($(window).height() - ev.clientY < 200) {\n            contextmenu_position_y = ev.clientY - $(\"#task-contextmenu\").height();\n          }\n          if ($(window).width() - ev.clientX < 200) {\n            contextmenu_position_x = ev.clientX - $(\"#task-contextmenu\").width();\n          }\n          $(\"#task-contextmenu\").css(\"top\", contextmenu_position_y).css(\"left\", contextmenu_position_x).show();\n          on_gid = \"\"+this.getAttribute(\"data-gid\");\n\n          var status = this.getAttribute(\"data-status\");\n          if (status == \"waiting\" || status == \"paused\")\n            $(\"#task-contextmenu .task-move\").show();\n          else\n            $(\"#task-contextmenu .task-move\").hide();\n          if (status == \"removed\" || status == \"complete\" || status == \"error\") {\n            $(\".task-restart\").show();\n            $(\".task-start\").hide();\n            $(\".task-pause\").hide();\n          } else {\n            $(\".task-restart\").hide();\n            if (status == \"active\" || status == \"waiting\") {\n              $(\".task-start\").hide();\n              $(\".task-pause\").show();\n            } else {\n              $(\".task-start\").show();\n              $(\".task-pause\").hide();\n            }\n          }\n          return false;\n        }).live(\"mouseout\", function(ev) {\n          // toElement is not available in Firefox, use relatedTarget instead.\n          var enteredElement = ev.toElement || ev.relatedTarget;\n          if ($.contains(this, enteredElement) ||\n              $(\"#task-contextmenu\").get(0) == enteredElement ||\n                $.contains($(\"#task-contextmenu\").get(0), enteredElement)) {\n            return;\n          }\n          on_gid = null;\n          $(\"#task-contextmenu\").hide();\n        });\n\n        $(\"#task-contextmenu a\").click(function() {\n          $(\"#task-contextmenu\").hide();\n        });\n        var mouse_on = false;\n        $(\"#task-contextmenu\").hover(function() {\n          mouse_on = true;\n        }, function() {\n          if (mouse_on) {\n            on_gid = null;\n            $(\"#task-contextmenu\").hide();\n          }\n        });\n\n      },\n\n      restart: function() {\n        if (on_gid) ARIA2.restart_task([on_gid, ]);\n        on_gid = null;\n      },\n\n      pause: function() {\n        if (on_gid) ARIA2.pause(on_gid);\n        on_gid = null;\n      },\n\n      unpause: function() {\n        if (on_gid) ARIA2.unpause(on_gid);\n        on_gid = null;\n      },\n\n      remove: function() {\n        if (on_gid) {\n          var status = $(\"#task-gid-\"+on_gid).attr(\"data-status\");\n          if (status == \"removed\" || status == \"complete\" || status == \"error\") {\n            ARIA2.remove_result(on_gid);\n          } else {\n            ARIA2.remove(on_gid);\n          }\n        }\n        on_gid = null;\n      },\n\n      movetop: function() {\n        if (on_gid) ARIA2.change_pos(on_gid, 0, 'POS_SET');\n        on_gid = null;\n      },\n\n      moveup: function() {\n        if (on_gid) ARIA2.change_pos(on_gid, -1, 'POS_CUR');\n        on_gid = null;\n      },\n\n      movedown: function() {\n        if (on_gid) ARIA2.change_pos(on_gid, 1, 'POS_CUR');\n        on_gid = null;\n      },\n\n      moveend: function() {\n        if (on_gid) ARIA2.change_pos(on_gid, 0, 'POS_END');\n        on_gid = null;\n      },\n\n    },\n\n    setting: {\n      init: function() {\n        this.jsonrpc_path = $.Storage.get(\"jsonrpc_path\") || location.protocol+\"//\"+(location.host.split(\":\")[0]||\"localhost\")+\"/jsonrpc\";\n        this.refresh_interval = Number($.Storage.get(\"refresh_interval\") || 10000);\n        this.finish_notification = Number($.Storage.get(\"finish_notification\") || 1);\n        this.add_task_option = $.Storage.get(\"add_task_option\");\n        this.jsonrpc_history = JSON.parse($.Storage.get(\"jsonrpc_history\") || \"[]\");\n        if (this.add_task_option) {\n          this.add_task_option = JSON.parse(this.add_task_option);\n        }\n        // overwrite settings with hash\n        if (location.hash && location.hash.length) {\n          var args = location.hash.substring(1).split('&'), kwargs = {};\n          $.each(args, function(i, n) {\n            n = n.split('=', 2);\n            kwargs[n[0]] = n[1];\n          });\n\n          if (kwargs['path']) this.jsonrpc_path = kwargs['path'];\n          this.kwargs = kwargs;\n        }\n\n        var _this = this;\n        $('#setting-modal').on('hidden', function () {\n          _this.update();\n        });\n\n        this.update();\n      },\n\n      save_add_task_option: function(options) {\n        this.add_task_option = options;\n        $.Storage.set(\"add_task_option\", JSON.stringify(options));\n      },\n\n      save: function() {\n        $.Storage.set(\"jsonrpc_path\", this.jsonrpc_path);\n        if (this.jsonrpc_history.indexOf(this.jsonrpc_path) == -1) {\n          if (this.jsonrpc_history.push(this.jsonrpc_path) > 10) {\n            this.jsonrpc_history.shift();\n          }\n          $.Storage.set(\"jsonrpc_history\", JSON.stringify(this.jsonrpc_history));\n        }\n        $.Storage.set(\"refresh_interval\", String(this.refresh_interval));\n        $.Storage.set(\"finish_notification\", String(this.finish_notification));\n      },\n\n      update: function() {\n        $(\"#setting-form #rpc-path\").val(this.jsonrpc_path);\n        $(\"#setting-form input:radio[name=refresh_interval][value=\"+this.refresh_interval+\"]\").attr(\"checked\", true);\n        $(\"#setting-form input:radio[name=finish_notification][value=\"+this.finish_notification+\"]\").attr(\"checked\", true);\n        if (this.jsonrpc_history.length) {\n          $(\".rpc-path-wrap .dropdown-menu\").remove();\n          var content = '<ul class=\"dropdown-menu\">';\n          $.each(this.jsonrpc_history, function(n, e) {\n            content += '<li><a href=\"#\">'+e+'</a></li>';\n          });\n          content += '</ul>';\n          $(\".rpc-path-wrap\").append(content).on(\"click\", \"li>a\", function() {\n            $(\"#setting-form #rpc-path\").val($(this).text());\n          });\n          $(\".rpc-path-wrap .dropdown-toggle\").removeAttr(\"disabled\").dropdown();\n        }\n        if (this.finish_notification && window.Notification && Notification.permission !== \"granted\") {\n          Notification.requestPermission();\n        }\n      },\n\n      submit: function() {\n        _this = $(\"#setting-form\");\n        var _jsonrpc_path = _this.find(\"#rpc-path\").val();\n        var _refresh_interval = Number(_this.find(\"input:radio[name=refresh_interval]:checked\").val());\n        var _finish_notification = Number(_this.find(\"input:radio[name=finish_notification]:checked\").val());\n\n        var changed = false;\n        if (_jsonrpc_path !== undefined && this.jsonrpc_path != _jsonrpc_path) {\n          this.jsonrpc_path = _jsonrpc_path;\n          YAAW.tasks.unSelectAll();\n          $(\"#main-alert\").hide();\n          YAAW.aria2_init();\n          changed = true;\n        }\n        if (_refresh_interval !== undefined && this.refresh_interval != _refresh_interval) {\n          this.refresh_interval = _refresh_interval;\n          ARIA2.auto_refresh(this.refresh_interval);\n          changed = true;\n        }\n        if (_finish_notification !== undefined && this.finish_notification != _finish_notification) {\n          this.finish_notification = _finish_notification;\n          ARIA2.finish_notification = _finish_notification;\n          changed = true;\n        }\n        if (changed) {\n          this.save();\n        }\n        if (this.finish_notification && window.Notification && Notification.permission !== \"granted\") {\n          Notification.requestPermission();\n        }\n\n        // submit aria2 global setting\n        var options = {};\n        $(\"#aria2-gs-form input[name]\").each(function(i, n) {\n          var name = n.getAttribute(\"name\");\n          var value = n.value;\n          if (name && value)\n            options[name] = value;\n        });\n        ARIA2.change_global_option(options);\n        $(\"#setting-modal\").modal('hide');\n      },\n    },\n\n    notification: function(title, content) {\n      if (!window.Notification) {\n        return false;\n      }\n\n      if (Notification.permission !== \"granted\")\n        Notification.requestPermission();\n\n      var notification = new Notification(title, {\n        body: content,\n      });\n\n      return notification;\n    },\n  }\n})();\nYAAW.init();\n"
  },
  {
    "path": "statics/common/search/js/search.js",
    "content": "$ = mdui.JQ;\n$.fn.extend({\n    sortElements: function (comparator, getSortable) {\n        getSortable = getSortable || function () { return this; };\n\n        var placements = this.map(function () {\n            var sortElement = getSortable.call(this),\n                parentNode = sortElement.parentNode,\n                nextSibling = parentNode.insertBefore(\n                    document.createTextNode(''),\n                    sortElement.nextSibling\n                );\n\n            return function () {\n                parentNode.insertBefore(this, nextSibling);\n                parentNode.removeChild(nextSibling);\n            };\n        });\n\n        return [].sort.call(this, comparator).each(function (i) {\n            placements[i].call(getSortable.call(this));\n        });\n    }\n});\n\nfunction downall() {\n     let dl_link_list = Array.from(document.querySelectorAll(\"li a\"))\n         .map(x => x.href) // 所有list中的链接\n         .filter(x => x.slice(-1) != \"/\"); // 筛选出非文件夹的文件下载链接\n\n     let blob = new Blob([dl_link_list.join(\"\\r\\n\")], {\n         type: 'text/plain'\n     }); // 构造Blog对象\n     let a = document.createElement('a'); // 伪造一个a对象\n     a.href = window.URL.createObjectURL(blob); // 构造href属性为Blob对象生成的链接\n     a.download = \"folder_download_link.txt\"; // 文件名称，你可以根据你的需要构造\n     a.click() // 模拟点击\n     a.remove();\n}\n\nfunction thumb(){\n\tif($('#format_list').text() == \"apps\"){\n\t\t$('#format_list').text(\"format_list_bulleted\");\n\t\t$('.nexmoe-item').removeClass('thumb');\n\t\t$('.nexmoe-item .mdui-icon').show();\n\t\t$('.nexmoe-item .mdui-list-item').css(\"background\",\"\");\n\t}else{\n\t\t$('#format_list').text(\"apps\");\n\t\t$('.nexmoe-item').addClass('thumb');\n\t\t$('.mdui-col-xs-12 i.mdui-icon').each(function(){\n\t\t\tif($(this).text() == \"image\" || $(this).text() == \"ondemand_video\"){\n\t\t\t\tvar href = $(this).parent().parent().attr('href');\n\t\t\t\tvar thumb =(href.indexOf('?') == -1)?'?t=220':'&t=220';\n\t\t\t\t$(this).hide();\n\t\t\t\t$(this).parent().parent().parent().css(\"background\",\"url(\"+href+thumb+\")  no-repeat center top\");\n\t\t\t}\n\t\t});\n\t}\n\n}\t\n\n\n$(function(){\n\t$('.file a').each(function(){\n\t\t$(this).on('click', function () {\n\t\t\tvar form = $('<form target=_blank method=post></form>').attr('action', $(this).attr('href')).get(0);\n\t\t\t$(document.body).append(form);\n\t\t\tform.submit();\n\t\t\t$(form).remove();\n\t\t\treturn false;\n\t\t});\n\t});\n\n\t$('.icon-sort').on('click', function () {\n        let sort_type = $(this).attr(\"data-sort\"), sort_order = $(this).attr(\"data-order\");\n        let sort_order_to = (sort_order === \"less\") ? \"more\" : \"less\";\n        $('li[data-sort]').sortElements(function (a, b) {\n            let data_a = $(a).attr(\"data-sort-\" + sort_type), data_b = $(b).attr(\"data-sort-\" + sort_type);\n            let rt = data_a.localeCompare(data_b, undefined, {numeric: true});\n            return (sort_order === \"more\") ? 0-rt : rt;\n        });\n        $(this).attr(\"data-order\", sort_order_to).text(\"expand_\" + sort_order_to);\n    });\n});\n//分享链接\nvar inst4 = new mdui.Dialog('#share');\ndocument.getElementById('sharebtn').addEventListener('click', function () {\n    inst4.open();\n});\nvar sharedialog = document.getElementById('share');\nsharedialog.addEventListener('open.mdui.dialog', function () {\n    var textarea_value=new Array()\n    for(var i=0;i<check_val.length;i++){\n        textarea_value[i] = window.location.protocol+'//'+window.location.host+document.getElementById(check_val[i]).getElementsByTagName('a')[0].getAttribute('href');\n    }\n    document.getElementById('sharelinks').value=textarea_value.join('\\r\\n');\n});\n\n//当前页关键词过滤\nmdui.JQ('#pagesearch').on('click', function () {\n    mdui.prompt('输入过滤的关键词或后缀',\n        function (value) {\n\t\t\tvar dom_items = document.getElementsByClassName('filter');\n\t\t\tfor(var i=0;i<dom_items.length;i++){\n\t\t\t\tif(dom_items[i].getAttribute('data-sort-name').indexOf(value)==-1){\n\t\t\t\t\tdom_items[i].style.display = \"none\";\n\t\t\t\t}else{\n\t\t\t\t\tdom_items[i].style.display = \"\";\n\t\t\t\t}\n\t\t\t}\n        },\n        function (value) {\n        },\n        {\n            confirmText:'确认',\n            cancelText:'取消'\n        }\n    );\n});\n\n//重命名\nmdui.JQ('#rename').on('click', function () {\n    mdui.prompt('输入新名称',\n        function (value) {\n            var httpRequest = new XMLHttpRequest();//第一步：创建需要的对象\n            httpRequest.open('POST', '?/rename', true); //第二步：打开连接\n            httpRequest.setRequestHeader(\"Content-type\",\"application/x-www-form-urlencoded\");//设置请求头 注：post方式必须设置请求头（在建立连接后设置请求头）\n            var query='name='+value+'&itemid='+check_val[0];\n            httpRequest.send(query);//发送请求 将情头体写在send中\n            var item_dom=document.getElementById(check_val[0]);\n            item_dom.getElementsByClassName('loading-gif')[0].style.display='';\n            httpRequest.onreadystatechange = function () {//请求后的回调接口，可将请求成功后要执行的程序写在其中\n                if (httpRequest.readyState == 4 && httpRequest.status == 200) {//验证请求是否发送成功\n                \titem=JSON.parse(httpRequest.responseText);\n                    var a_dom = item_dom.getElementsByTagName('a')[0];\n                    a_href = item.parentReference.path.replace(\"/drive/root:\",\"?\")+\"/\"+item.name;\n                    item_dom.getElementsByTagName('span')[0].innerHTML=value;\n                    item_dom.getElementsByClassName('loading-gif')[0].style.display='none';\n                    item_dom.getElementsByTagName('a')[0].setAttribute('href',a_href);\n                    item_dom.setAttribute('data-sort-name',value);\n                }else{\n                    item_dom.getElementsByClassName('loading-gif')[0].style.display='none';\n                }\n            };\n        },\n        function (value) {\n        }\n        ,\n        {\n            confirmText:'确认',\n            cancelText:'取消'\n        }\n    );\n});\n//删除文件/文件夹\nmdui.JQ('#deleteall').on('click', function(){\n    mdui.confirm('请确认是否删除选中项目',\n        function(){\n            for(var i=0;i<check_val.length;i++){\n            \tdocument.getElementById(check_val[i]).getElementsByClassName('loading-gif')[0].style.display='';\n            }\n            var httpRequest = new XMLHttpRequest();\n            httpRequest.open('POST', '?/deleteitems', true);\n            httpRequest.setRequestHeader(\"Content-type\",\"application/json\");//设置请求头 注：post方式必须设置请求头（在建立连接后设置请求头）\n            var query=JSON.stringify(check_val);\n            httpRequest.send(query);\n            httpRequest.onreadystatechange = function () {//请求后的回调接口，可将请求成功后要执行的程序写在其中\n                if (httpRequest.readyState == 4 && httpRequest.status == 200) {//验证请求是否发送成功\n            \t\t var deleteerror = 0;\n            \t\t var errormessage = '';\n                \tvar resp = JSON.parse(httpRequest.responseText);\n                    for(var i=0;i<check_val.length;i++){\n                    \tif(resp[i]){\n                            deleteerror++;\n                            document.getElementById(check_val[i]).getElementsByClassName('loading-gif')[0].style.display='none';\n                    \t\terrormessage = JSON.parse(resp[i])['error']['message'];\n                    \t}else{\n                    \t\tdocument.getElementById(check_val[i]).style.display = 'none';\n                    \t}\n                    }\n                    if(deleteerror>=1){\n                        alert(deleteerror+'个文件删除失败！请重试。错误代码：'+errormessage);\n                    }\n                }\n                if(httpRequest.status==502&&httpRequest.readyState==4){\n                    alert('服务器无响应！请刷新后查看是否删除成功！');\n                    for(var i=0;i<check_val.length;i++){\n                        document.getElementById(check_val[i]).getElementsByClassName('loading-gif')[0].style.display='none';\n                    }\n                }\n            };\n        },\n        function(){\n        }\n        ,\n        {\n            confirmText:'确认',\n            cancelText:'取消'\n        }\n    );\n});\n\n//点击复制\nfunction copy(){\n    document.cookie=\"copyitems=\"+JSON.stringify(check_val);\n    document.getElementById('copybtn').style.display=\"none\";\n    document.getElementById('cutbtn').style.display=\"none\";\n}\n//点击剪切\nfunction cut(){\n    document.cookie=\"cutitems=\"+JSON.stringify(check_val);\n    document.getElementById('cutbtn').style.display=\"none\";\n    document.getElementById('copybtn').style.display=\"none\";\n}\n\nfunction onClickHander(){\n    checkitems = document.getElementsByName(\"itemid\");\n    check_val = [];\n    for (k in checkitems) {\n        if (checkitems[k].checked) check_val.push(checkitems[k].value);\n    }\n    //alert(check_val);\n    console.log(check_val);\n    var singleopt = document.getElementsByClassName(\"singleopt\");\n    var multiopt = document.getElementsByClassName(\"multiopt\");\n    //单文件操作\n    if(check_val.length==1){\n        for(var i=0;i<singleopt.length;i++){\n            singleopt[i].style.display = \"inline\";\n        }\n    }\n    else{\n        for(var i=0;i<singleopt.length;i++){\n            singleopt[i].style.display = \"none\";\n        }\n    }\n    //多文件操作\n    if(check_val.length>=1){\n        for(var i=0;i<multiopt.length;i++){\n            multiopt[i].style.display = \"inline\";\n        }\n    }else{\n        for(var i=0;i<multiopt.length;i++){\n            multiopt[i].style.display = \"none\";\n        }\n    }\n}\nfunction checkall(){\n    var checkall = document.getElementById(\"checkall\");\n    var itemsbox = document.getElementsByName(\"itemid\");\n    if (checkall.checked == false) {\n        for (var i = 0; i < itemsbox.length; i++) {\n            itemsbox[i].checked = false;\n        }\n    } else {\n        for (var i = 0; i < itemsbox.length; i++) {\n            itemsbox[i].checked = true;\n        }\n    }\n    onClickHander();\n}\n\n//获取新的dom\nfunction getListDom(item){\n\tvar $domstr='';\n\tvar path=item.parentReference.path.replace(\"/drive/root:\",\"?\")+\"/\"+item.name;\n\tif(item['folder']){\n\t\t$domstr='<li class=\"mdui-list-item mdui-ripple filter\" data-sort data-sort-name=\"'+item.name+'\" data-sort-date=\"'+item.lastModifiedDateTime+'\" data-sort-size=\"'+item.size+'\" id=\"'+item.id+'\"><label class=\"mdui-checkbox\"><input type=\"checkbox\" value=\"'+item.id+'\" name=\"itemid\" onclick=\"onClickHander()\"><i class=\"mdui-checkbox-icon\"></i></label><a href=\"'+path+'\"><div class=\"mdui-col-xs-12 mdui-col-sm-7 mdui-text-truncate\"><i class=\"mdui-icon material-icons\">folder_open</i><span>'+item.name+'</span></div><div class=\"mdui-col-sm-3 mdui-text-right\">'+item.lastModifiedDateTime.replace(/[a-zA-Z]/g,' ')+'</div><div class=\"mdui-col-sm-2 mdui-text-right\">'+item.size+'</div></a></li>';\n\t}else{\n\t\t$domstr='<li class=\"mdui-list-item file mdui-ripple filter\" data-sort data-sort-name=\"'+item.name+'\" data-sort-date=\"'+item.lastModifiedDateTime+'\" data-sort-size=\"'+item.size+'\" id=\"'+path+'\"><label class=\"mdui-checkbox\"><input type=\"checkbox\" value=\"'+item.id+'\" name=\"itemid\" onclick=\"onClickHander()\"><i class=\"mdui-checkbox-icon\"></i></label><a href=\"'+path+'\" target=\"_blank\"><div class=\"mdui-col-xs-12 mdui-col-sm-7 mdui-text-truncate\"><i class=\"mdui-icon material-icons\">insert_drive_file</i><span>'+item.name+'</span></div><div class=\"mdui-col-sm-3 mdui-text-right\">'+item.lastModifiedDateTime.replace(/[a-zA-Z]/g,' ')+'</div><div class=\"mdui-col-sm-2 mdui-text-right\">'+item.size+'</div></a></li>';\n\t}\n\treturn $domstr;\n}"
  },
  {
    "path": "statics/themes/nexmoe/css/forkGh.css",
    "content": "/*!\n * \"Fork me on GitHub\" CSS ribbon v0.2.3 | MIT License\n * https://github.com/simonwhitaker/github-fork-ribbon-css\n*/\n\n.github-fork-ribbon {\n  width: 12.1em;\n  height: 12.1em;\n  position: absolute;\n  overflow: hidden;\n  top: 0;\n  right: 0;\n  z-index: 9999;\n  pointer-events: none;\n  font-size: 13px;\n  text-decoration: none;\n  text-indent: -999999px;\n}\n\n.github-fork-ribbon.fixed {\n  position: fixed;\n}\n\n.github-fork-ribbon:hover, .github-fork-ribbon:active {\n  background-color: rgba(0, 0, 0, 0.0);\n}\n\n.github-fork-ribbon:before, .github-fork-ribbon:after {\n  /* The right and left classes determine the side we attach our banner to */\n  position: absolute;\n  display: block;\n  width: 15.38em;\n  height: 1.54em;\n\n  top: 3.23em;\n  right: -3.23em;\n\n  -webkit-box-sizing: content-box;\n  -moz-box-sizing: content-box;\n  box-sizing: content-box;\n\n  -webkit-transform: rotate(45deg);\n  -moz-transform: rotate(45deg);\n  -ms-transform: rotate(45deg);\n  -o-transform: rotate(45deg);\n  transform: rotate(45deg);\n}\n\n.github-fork-ribbon:before {\n  content: \"\";\n\n  /* Add a bit of padding to give some substance outside the \"stitching\" */\n  padding: .38em 0;\n\n  /* Set the base colour */\n  background-color: #424242;\n\n  /* Set a gradient: transparent black at the top to almost-transparent black at the bottom */\n  background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(0, 0, 0, 0)), to(rgba(0, 0, 0, 0.15)));\n  background-image: -webkit-linear-gradient(top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15));\n  background-image: -moz-linear-gradient(top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15));\n  background-image: -ms-linear-gradient(top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15));\n  background-image: -o-linear-gradient(top, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15));\n  background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.15));\n\n  /* Add a drop shadow */\n  -webkit-box-shadow: 0 .15em .23em 0 rgba(0, 0, 0, 0.5);\n  -moz-box-shadow: 0 .15em .23em 0 rgba(0, 0, 0, 0.5);\n  box-shadow: 0 .15em .23em 0 rgba(0, 0, 0, 0.5);\n\n  pointer-events: auto;\n}\n\n.github-fork-ribbon:after {\n  /* Set the text from the data-ribbon attribute */\n  content: attr(data-ribbon);\n\n  /* Set the text properties */\n  color: #fff;\n  font: 700 1em \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n  line-height: 1.54em;\n  text-decoration: none;\n  text-shadow: 0 -.08em rgba(0, 0, 0, 0.5);\n  text-align: center;\n  text-indent: 0;\n\n  /* Set the layout properties */\n  padding: .15em 0;\n  margin: .15em 0;\n\n  /* Add \"stitching\" effect */\n  border-width: .08em 0;\n  border-style: dotted;\n  border-color: #fff;\n  border-color: rgba(255, 255, 255, 0.7);\n}\n\n.github-fork-ribbon.left-top, .github-fork-ribbon.left-bottom {\n  right: auto;\n  left: 0;\n}\n\n.github-fork-ribbon.left-bottom, .github-fork-ribbon.right-bottom {\n  top: auto;\n  bottom: 0;\n}\n\n.github-fork-ribbon.left-top:before, .github-fork-ribbon.left-top:after, .github-fork-ribbon.left-bottom:before, .github-fork-ribbon.left-bottom:after {\n  right: auto;\n  left: -3.23em;\n}\n\n.github-fork-ribbon.left-bottom:before, .github-fork-ribbon.left-bottom:after, .github-fork-ribbon.right-bottom:before, .github-fork-ribbon.right-bottom:after {\n  top: auto;\n  bottom: 3.23em;\n}\n\n.github-fork-ribbon.left-top:before, .github-fork-ribbon.left-top:after, .github-fork-ribbon.right-bottom:before, .github-fork-ribbon.right-bottom:after {\n  -webkit-transform: rotate(-45deg);\n  -moz-transform: rotate(-45deg);\n  -ms-transform: rotate(-45deg);\n  -o-transform: rotate(-45deg);\n  transform: rotate(-45deg);\n}"
  },
  {
    "path": "statics/themes/nexmoe/js/nexmoe.js",
    "content": "$ = mdui.JQ;\n$.fn.extend({\n    sortElements: function (comparator, getSortable) {\n        getSortable = getSortable || function () { return this; };\n\n        var placements = this.map(function () {\n            var sortElement = getSortable.call(this),\n                parentNode = sortElement.parentNode,\n                nextSibling = parentNode.insertBefore(\n                    document.createTextNode(''),\n                    sortElement.nextSibling\n                );\n\n            return function () {\n                parentNode.insertBefore(this, nextSibling);\n                parentNode.removeChild(nextSibling);\n            };\n        });\n\n        return [].sort.call(this, comparator).each(function (i) {\n            placements[i].call(getSortable.call(this));\n        });\n    }\n});\n\nfunction downall() {\n     let dl_link_list = Array.from(document.querySelectorAll(\"li a\"))\n         .map(x => x.href) // 所有list中的链接\n         .filter(x => x.slice(-1) != \"/\"); // 筛选出非文件夹的文件下载链接\n\n     let blob = new Blob([dl_link_list.join(\"\\r\\n\")], {\n         type: 'text/plain'\n     }); // 构造Blog对象\n     let a = document.createElement('a'); // 伪造一个a对象\n     a.href = window.URL.createObjectURL(blob); // 构造href属性为Blob对象生成的链接\n     a.download = \"folder_download_link.txt\"; // 文件名称，你可以根据你的需要构造\n     a.click() // 模拟点击\n     a.remove();\n}\n\nfunction thumb(){\n\tif($('#format_list').text() == \"apps\"){\n\t\t$('#format_list').text(\"format_list_bulleted\");\n\t\t$('.nexmoe-item').removeClass('thumb');\n\t\t$('.nexmoe-item .mdui-icon').show();\n\t\t$('.nexmoe-item .mdui-list-item').css(\"background\",\"\");\n\t}else{\n\t\t$('#format_list').text(\"apps\");\n\t\t$('.nexmoe-item').addClass('thumb');\n\t\t$('.mdui-col-xs-12 i.mdui-icon').each(function(){\n\t\t\tif($(this).text() == \"image\" || $(this).text() == \"ondemand_video\"){\n\t\t\t\tvar href = $(this).parent().parent().attr('href');\n\t\t\t\tvar thumb =(href.indexOf('?') == -1)?'?t=220':'&t=220';\n\t\t\t\t$(this).hide();\n\t\t\t\t$(this).parent().parent().parent().css(\"background\",\"url(\"+href+thumb+\")  no-repeat center top\");\n\t\t\t}\n\t\t});\n\t}\n\n}\t\n\n\n$(function(){\n\t$('.file a').each(function(){\n\t\t$(this).on('click', function () {\n\t\t\tvar form = $('<form target=_blank method=post></form>').attr('action', $(this).attr('href')).get(0);\n\t\t\t$(document.body).append(form);\n\t\t\tform.submit();\n\t\t\t$(form).remove();\n\t\t\treturn false;\n\t\t});\n\t});\n\n\t$('.icon-sort').on('click', function () {\n        let sort_type = $(this).attr(\"data-sort\"), sort_order = $(this).attr(\"data-order\");\n        let sort_order_to = (sort_order === \"less\") ? \"more\" : \"less\";\n        $('li[data-sort]').sortElements(function (a, b) {\n            let data_a = $(a).attr(\"data-sort-\" + sort_type), data_b = $(b).attr(\"data-sort-\" + sort_type);\n            let rt = data_a.localeCompare(data_b, undefined, {numeric: true});\n            return (sort_order === \"more\") ? 0-rt : rt;\n        });\n        $(this).attr(\"data-order\", sort_order_to).text(\"expand_\" + sort_order_to);\n    });\n});\nvar inst1 = new mdui.Fab('#myFab');\n\n//文件在线上传对话框\nvar inst2 = new mdui.Dialog('#onlineupload-dialog');\n//文件远程上传对话框\nvar inst6 = new mdui.Dialog('#remoteupload-dialog');\nvar inst7 = new mdui.Dialog('#progress');\n//文件上传方式选择\nvar inst5 = new mdui.Select('#file_upload');\n$('#file_upload').on('closed.mdui.select', function () {\n    var  myselect=document.getElementById(\"file_upload\");\n    var index=myselect.selectedIndex ;\n    var option = myselect.options[index].value;\n    if(option == \"online_upload\"){\n        inst2.open();\n    }else if(option == \"remote_upload\"){\n        inst6.open();\n    }else if(option==\"offline_upload\"){\n        window.open('/?/offline','_blank'); \n    }\n  });\n\n//全局搜索\nvar inst3 = new mdui.Dialog('#search_form');\ndocument.getElementById('search').addEventListener('click', function () {\n    inst3.open();\n});\n\n//分享链接\nvar inst4 = new mdui.Dialog('#share');\ndocument.getElementById('sharebtn').addEventListener('click', function () {\n    inst4.open();\n});\nvar sharedialog = document.getElementById('share');\nsharedialog.addEventListener('open.mdui.dialog', function () {\n    var textarea_value=new Array()\n    for(var i=0;i<check_val.length;i++){\n        textarea_value[i] = window.location.protocol+'//'+window.location.host+document.getElementById(check_val[i]).getElementsByTagName('a')[0].getAttribute('href');\n    }\n    document.getElementById('sharelinks').value=textarea_value.join('\\r\\n');\n});\n\n//当前页关键词过滤\nmdui.JQ('#pagesearch').on('click', function () {\n    mdui.prompt('输入过滤的关键词或后缀',\n        function (value) {\n\t\t\tvar dom_items = document.getElementsByClassName('filter');\n\t\t\tfor(var i=0;i<dom_items.length;i++){\n\t\t\t\tif(dom_items[i].getAttribute('data-sort-name') != null&&\n\t\t\t\tdom_items[i].getAttribute('data-sort-name').indexOf(value)==-1){\n\t\t\t\t\tdom_items[i].style.display = \"none\";\n\t\t\t\t}else{\n\t\t\t\t\tdom_items[i].style.display = \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t\t    $('#pending').css('display','none');\n\n        },\n        function (value) {\n        },\n        {\n            confirmText:'确认',\n            cancelText:'取消'\n        }\n    );\n});\n//新建文件夹\nmdui.JQ('#newfolder').on('click', function () {\n    mdui.prompt('输入文件夹名称',\n        function (value) {\n            var httpRequest = new XMLHttpRequest();//第一步：创建需要的对象\n            $('#pending').css('display',null);\n            httpRequest.open('POST', '?/create_folder', true); //第二步：打开连接\n            httpRequest.setRequestHeader(\"Content-type\",\"application/x-www-form-urlencoded\");//设置请求头 注：post方式必须设置请求头（在建立连接后设置请求头）\n            var query='foldername='+value+'&uploadurl='+window.location.href;\n            httpRequest.send(query);\n            httpRequest.onreadystatechange = function () {\n                if(httpRequest.readyState == 4 && httpRequest.status == 200) {\n                    var item = JSON.parse(httpRequest.responseText);\n                    if(item.id){\n\t                    var $folder_domstr = $('<li class=\"mdui-list-item mdui-ripple filter\" data-sort data-sort-name=\"'+item.name+'\" data-sort-date=\"'+item.lastModifiedDateTime+'\" data-sort-size=\"'+item.size+'\" id=\"'+item.id+'\"><label class=\"mdui-checkbox\"><input type=\"checkbox\" value=\"'+item.id+'\" name=\"itemid\" onclick=\"onClickHander()\"><i class=\"mdui-checkbox-icon\"></i></label><a href=\"'+window.location.href+item.name+'\"><div class=\"mdui-col-xs-12 mdui-col-sm-7 mdui-text-truncate\"><i class=\"mdui-icon material-icons\">folder_open</i><span>'+item.name+'</span></div><div class=\"mdui-col-sm-3 mdui-text-right\">'+item.lastModifiedDateTime.replace(/[a-zA-Z]/g,' ')+'</div><div class=\"mdui-col-sm-2 mdui-text-right\">'+item.size+'</div></a></li>');\n\t                    if($('#backtolast').length>0){\n\t                    \t$('#backtolast').after($folder_domstr);\n\t                    \tconsole.log('存在返回上一级');\n\t                    }else{\n\t                \t\t $('#indexsort').after($folder_domstr);\n\t                \t\t console.log('不存在返回上一级');\n                        }\n                        $('#pending').css('display','none');\n\t                    console.log('新建文件夹成功');\n                    }else if(item.error){\n                        $('#pending').css('display','none');\n                    \talert('新建文件夹失败,错误代码:'+item.error.message);\n                    }\n                }\n                if(httpRequest.status==502&&httpRequest.readyState==4){\n                \talert('服务器无响应！请刷新后查看是否新建成功！');\n                \t$('#pending').css('display','none');\n                }\n            };\n        },\n        function (value) {\n        }\n        ,\n        {\n            confirmText:'确认',\n            cancelText:'取消'\n        }\n    );\n});\n//重命名\nmdui.JQ('#rename').on('click', function () {\n    mdui.prompt('输入新名称',\n        function (value) {\n            var httpRequest = new XMLHttpRequest();//第一步：创建需要的对象\n            httpRequest.open('POST', '?/rename', true); //第二步：打开连接\n            httpRequest.setRequestHeader(\"Content-type\",\"application/x-www-form-urlencoded\");//设置请求头 注：post方式必须设置请求头（在建立连接后设置请求头）\n            var query='name='+value+'&itemid='+check_val[0];\n            httpRequest.send(query);//发送请求 将情头体写在send中\n            var item_dom=document.getElementById(check_val[0]);\n            item_dom.getElementsByClassName('loading-gif')[0].style.display='';\n           \n            /**\n             * 获取数据后的处理程序\n             */\n            httpRequest.onreadystatechange = function () {//请求后的回调接口，可将请求成功后要执行的程序写在其中\n                if (httpRequest.readyState == 4 && httpRequest.status == 200) {//验证请求是否发送成功\n                \titem=JSON.parse(httpRequest.responseText);\n                    var a_dom = item_dom.getElementsByTagName('a')[0];\n                    a_href = item.parentReference.path.replace(\"/drive/root:\",\"?\")+\"/\"+item.name;\n                    item_dom.getElementsByTagName('span')[0].innerHTML=value;\n                    item_dom.getElementsByClassName('loading-gif')[0].style.display='none';\n                    item_dom.getElementsByTagName('a')[0].setAttribute('href',a_href);\n                    item_dom.setAttribute('data-sort-name',value);\n                }else{\n                    item_dom.getElementsByClassName('loading-gif')[0].style.display='none';\n                }\n            };\n        },\n        function (value) {\n        }\n        ,\n        {\n            confirmText:'确认',\n            cancelText:'取消'\n        }\n    );\n});\n//删除文件/文件夹\nmdui.JQ('#deleteall').on('click', function(){\n    mdui.confirm('请确认是否删除选中项目',\n        function(){\n            for(var i=0;i<check_val.length;i++){\n            \tdocument.getElementById(check_val[i]).getElementsByClassName('loading-gif')[0].style.display='';\n            }\n            var httpRequest = new XMLHttpRequest();\n            httpRequest.open('POST', '?/deleteitems', true);\n            httpRequest.setRequestHeader(\"Content-type\",\"application/json\");//设置请求头 注：post方式必须设置请求头（在建立连接后设置请求头）\n            var query=JSON.stringify(check_val);\n            httpRequest.send(query);\n            httpRequest.onreadystatechange = function () {//请求后的回调接口，可将请求成功后要执行的程序写在其中\n                if (httpRequest.readyState == 4 && httpRequest.status == 200) {//验证请求是否发送成功\n            \t\t var deleteerror = 0;\n            \t\t var errormessage = '';\n                \tvar resp = JSON.parse(httpRequest.responseText);\n                    for(var i=0;i<check_val.length;i++){\n                    \tif(resp[i]){\n                            deleteerror++;\n                            document.getElementById(check_val[i]).getElementsByClassName('loading-gif')[0].style.display='none';\n                    \t\terrormessage = JSON.parse(resp[i])['error']['message'];\n                    \t}else{\n                    \t\tdocument.getElementById(check_val[i]).style.display = 'none';\n                    \t}\n                    }\n                    if(deleteerror>=1){\n                        alert(deleteerror+'个文件删除失败！请重试。错误代码：'+errormessage);\n                    }\n                }\n                if(httpRequest.status==502&&httpRequest.readyState==4){\n                    alert('服务器无响应！请刷新后查看是否删除成功！');\n                    for(var i=0;i<check_val.length;i++){\n                        document.getElementById(check_val[i]).getElementsByClassName('loading-gif')[0].style.display='none';\n                    }\n                }\n            };\n        },\n        function(){\n        }\n        ,\n        {\n            confirmText:'确认',\n            cancelText:'取消'\n        }\n    );\n});\n\n\n\n//文件选中某个文件后\nfunction onClickHander(){\n    checkitems = document.getElementsByName(\"itemid\");\n    check_val = [];\n    for (k in checkitems) {\n        if (checkitems[k].checked) check_val.push(checkitems[k].value);\n    }\n    //选中一个文件时显示可以重命名按钮\n    var singleopt = document.getElementsByClassName(\"singleopt\");\n    //选中多个文件时，可以复制移动等\n    var multiopt = document.getElementsByClassName(\"multiopt\");\n    //单文件操作\n    if(check_val.length==1){\n        for(var i=0;i<singleopt.length;i++){\n            singleopt[i].style.display = \"inline\";\n        }\n    }\n    else{\n        for(var i=0;i<singleopt.length;i++){\n            singleopt[i].style.display = \"none\";\n        }\n    }\n    //多文件操作\n    if(check_val.length>=1){\n        for(var i=0;i<multiopt.length;i++){\n            multiopt[i].style.display = \"inline\";\n        }\n    }else{\n        for(var i=0;i<multiopt.length;i++){\n            multiopt[i].style.display = \"none\";\n        }\n    }\n}\n//选中所有文件\nfunction checkall(){\n    var checkall = document.getElementById(\"checkall\");\n    var itemsbox = document.getElementsByName(\"itemid\");\n    if (checkall.checked == false) {\n        for (var i = 0; i < itemsbox.length; i++) {\n            itemsbox[i].checked = false;\n        }\n    } else {\n        for (var i = 0; i < itemsbox.length; i++) {\n            itemsbox[i].checked = true;\n        }\n    }\n    onClickHander();\n}\n//在线上传小文件,需要一个id为filesubmit的表单，有类型为file的input\nfunction submitForm() {\n    var formData = new FormData($(\"#filesubmit\")[0]);  //重点：要用这种方法接收表单的参数\n    inst2.close();\n    $('#pending').css('display',null);\n    const req = new XMLHttpRequest();\n    req.open('post', '?/onlinefileupload', true);\n    req.send(formData);\n    req.onreadystatechange = function () {//请求后的回调接口，可将请求成功后要执行的程序写在其中\n        if (req.readyState == 4 && req.status == 200) {//验证请求是否发送成功\n            var item=JSON.parse(req.responseText);\n            // console.log(JSON.parse(req.responseText).parentReference.path);\n            if(item.id){\n            \t$('#pending').css('display','none');\n                var $dom_items=getListDom(item);\n                 if($('#backtolast').length>0){\n                    $('#backtolast').after($dom_items);\n                    console.log('存在返回上一级');\n                }else{\n                     $('#indexsort').after($dom_items);\n                     console.log('不存在返回上一级');\n                }\n                console.log('上传成功');\n            }else if(item.error){\n            \t$('#pending').css('display','none');\n                alert('新建文件夹失败,错误代码:'+item.error.message);\n            }\n        }else{\n            $('#pending').css('display','none');\n        }\n    };\n}\n\n//远程url上传文件\nfunction submitRemoteFile() {\n    var formData = new FormData($(\"#remoteupload\")[0]);  //重点：要用这种方法接收表单的参数\n    inst6.close();\n    const req = new XMLHttpRequest();\n    req.open('post', '?/upload_url', true);\n    req.send(formData);\n    req.onreadystatechange = function () {//请求后的回调接口，可将请求成功后要执行的程序写在其中\n        if (req.readyState == 4 && req.status == 200) {//验证请求是否发送成功\n            if(req.responseText=='0'){\n                alert('远程上传仅支持Onedrive个人版');\n            }else{\n                var progress_url = req.responseText;\n                showProgress(progress_url);\n            }\n        }\n    };\n}\n\n//展示进度条\nfunction showProgress(url){\n    inst7.open();\n    var num=-1;\n    width = 0;\n    myInterval = setInterval(function(){\n        if (100.0-width <= 1e-5) {\n            // console.log('100');\n            clearInterval(myInterval);\n            inst7.close();\n            location.reload();\n            alert('加载完成！即将刷新页面。');\n        } else {\n            num=getProgress(url);\n        }\n    }, 1000);\n    \n}\n//获取进度并更新。返回获取的进度值。\nfunction getProgress(url){\n    var url=url;\n    var httpRequest = new XMLHttpRequest();\n    httpRequest.open('GET', url, true);\n    httpRequest.send();\n    httpRequest.onreadystatechange=function(){\n        if (httpRequest.readyState == 4 && (httpRequest.status==200|| httpRequest.status == 202||httpRequest.status == 303)) {\n            console.log(httpRequest.responseText);\n            var data=JSON.parse(httpRequest.responseText);\n            if(data.percentageComplete>=width){\n                width=data.percentageComplete;\n                updateProgress(width);\n            }\n            return data.percentageComplete;\n        }\n    };\n    return -1;\n}\n//更新进度条dom\nfunction updateProgress(width){\n    var dom = document.getElementById(\"progress_width\");\n    dom.style.width = width+'%';\n}\n\n//自动填写url上传文件名\nfunction getRemoteUrl(){\n\tvar filename_dom = document.getElementById(\"filename\");\n\tvar fileurl_dom = document.getElementById('fileurl');\n\tvar url = fileurl_dom.value;\n\tfilename = fileNameFromUrl(url);\n\tfilename_dom.value = filename;\n}\n\nfunction fileNameFromUrl(url)\n{ \n\t\n\treturn url?url.split('/').pop().split('#').shift().split('?').shift():null; \n\t\n}\n\n\n//点击复制\nfunction copy(){\n    document.cookie=\"copyitems=\"+JSON.stringify(check_val);\n    document.getElementById('copybtn').style.display=\"none\";\n    document.getElementById('pastebtn').style.display=\"\";\n    document.getElementById('cutbtn').style.display=\"none\";\n}\n//点击剪切\nfunction cut(){\n    document.cookie=\"cutitems=\"+JSON.stringify(check_val);\n    document.getElementById('pastebtn').style.display=\"\";\n    document.getElementById('cutbtn').style.display=\"none\";\n    document.getElementById('copybtn').style.display=\"none\";\n}\n//判断cookie是否有复制和粘贴\nvar pastebtn = document.getElementById('pastebtn');\nif(!getCookie('cutitems')&&!getCookie('copyitems')){\n    pastebtn.style.display=\"none\";\n}else{\n    pastebtn.style.display=\"\";\n}\n//点击粘贴\nfunction paste(){\n    $('#pending').css('display',null);\n    if(getCookie('cutitems')){\n    \t// var json_data = {cutitems:getCookie('cutitems'),url:window.location.href};\n    \tvar json_data = '{\"cutitems\":'+getCookie('cutitems')+',\"url\":\"'+window.location.href+'\"}';\n        var httpRequest = new XMLHttpRequest();\n            httpRequest.open('POST', '?/paste', true);\n            httpRequest.setRequestHeader(\"Content-type\",\"application/json\");//设置请求头 注：post方式必须设置请求头（在建立连接后设置请求头）\n            // var query=JSON.stringify(json_data);\n            httpRequest.send(json_data);\n            var itemsid=JSON.parse(getCookie('cutitems'));\n            httpRequest.onreadystatechange = function () {\n                if (httpRequest.readyState == 4 && httpRequest.status == 200) {\n                    var resp_json = JSON.parse(httpRequest.responseText);\n                    var resperror = 0;\n                    var errormsg ='';\n                    for(var i=0;i<resp_json.length;i++){\n                    \tvar item_json=JSON.parse(resp_json[i]);\n                    \tif(item_json.id){\n                    \t\tvar $item_domstr = getListDom(item_json);\n                    \t\tif($('#backtolast').length>0){\n\t\t\t                    $('#backtolast').after($item_domstr);\n\t\t\t                }else{\n\t\t\t                     $('#indexsort').after($item_domstr);\n\t\t\t                }\n                    \t}\n                    \telse if(item_json.error){\n                    \t\tresperror = 1;\n                    \t\terrormsg = item_json['error']['message'];\n                    \t}\n                    }\n                    if(resperror==1){\n                    \talert('移动失败，错误代码：'+errormsg);\n                    }\n                    $('#pending').css('display','none');\n                    document.getElementById('pastebtn').style.display='none';\n                    document.getElementById('cutbtn').style.display=\"\";\n                    document.getElementById('copybtn').style.display=\"\";    \n                }\n                if(httpRequest.status==502&&httpRequest.readyState==4){\n                \t$('#pending').css('display','none');\n                \t\n                    document.getElementById('pastebtn').style.display='none';\n                    document.getElementById('cutbtn').style.display=\"\";\n                    document.getElementById('copybtn').style.display=\"\"; \n                    alert('服务器无响应！');\n                }\n                document.cookie = \"cutitems=; expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n            };\n    }else if(getCookie('copyitems')){\n    \t// var json_data = {cutitems:getCookie('cutitems'),url:window.location.href};\n    \tvar json_data = '{\"copyitems\":'+getCookie('copyitems')+',\"url\":\"'+window.location.href+'\"}';\n        var httpRequest = new XMLHttpRequest();\n        httpRequest.open('POST', '?/paste', true);\n        httpRequest.setRequestHeader(\"Content-type\",\"application/json\");\n        httpRequest.send(json_data);\n        var resperror=0;\n        var respsuccess=0\n        httpRequest.onreadystatechange = function () {\n            if (httpRequest.readyState == 4 && httpRequest.status == 200) {\n                var resp = JSON.parse(httpRequest.responseText);\n                for(var i=0;i<resp.length;i++){\n                    var resp_data = resp[i];\n                    if(resp_data.http_code!=202){\n                        resperror++;\n                    }else if(resp_data.http_code==202){\n                        respsuccess++;\n                    }\n                }\n                \n                document.getElementById('pastebtn').style.display='none';\n                document.getElementById('cutbtn').style.display=\"\";\n                document.getElementById('copybtn').style.display=\"\";\n                $('#pending').css('display','none');\n                alert('共'+respsuccess+'个文件复制成功,'+resperror+'个文件复制失败,大文件复制时间较长，请自行刷新页面！');\n            }else{\n                //需要删除\n                $('#pending').css('display','none');\n                \n                document.getElementById('pastebtn').style.display='none';\n                document.getElementById('cutbtn').style.display=\"\";\n                document.getElementById('copybtn').style.display=\"\";  \n            }\n            document.cookie = \"copyitems=; expires=Thu, 01 Jan 1970 00:00:00 GMT\";\n            \n        };\n    }\n    \n}\n//获取cookie\nfunction getCookie(cname){\n    var name = cname + \"=\";\n    var ca = document.cookie.split(';');\n    for(var i=0; i<ca.length; i++) {\n        var c = ca[i].trim();\n        if (c.indexOf(name)==0) { \n            return c.substring(name.length,c.length); \n        }\n    }\n    return false;\n}\n//获取新的dom\nfunction getListDom(item){\n\tvar $domstr='';\n\tvar path=item.parentReference.path.replace(\"/drive/root:\",\"?\")+\"/\"+item.name;\n\tif(item['folder']){\n\t\t$domstr='<li class=\"mdui-list-item mdui-ripple filter\" data-sort data-sort-name=\"'+item.name+'\" data-sort-date=\"'+item.lastModifiedDateTime+'\" data-sort-size=\"'+item.size+'\" id=\"'+item.id+'\"><label class=\"mdui-checkbox\"><input type=\"checkbox\" value=\"'+item.id+'\" name=\"itemid\" onclick=\"onClickHander()\"><i class=\"mdui-checkbox-icon\"></i></label><a href=\"'+path+'\"><div class=\"mdui-col-xs-12 mdui-col-sm-7 mdui-text-truncate\"><i class=\"mdui-icon material-icons\">folder_open</i><span>'+item.name+'</span></div><div class=\"mdui-col-sm-3 mdui-text-right\">'+item.lastModifiedDateTime.replace(/[a-zA-Z]/g,' ')+'</div><div class=\"mdui-col-sm-2 mdui-text-right\">'+item.size+'</div></a></li>';\n\t}else{\n\t\t$domstr='<li class=\"mdui-list-item file mdui-ripple filter\" data-sort data-sort-name=\"'+item.name+'\" data-sort-date=\"'+item.lastModifiedDateTime+'\" data-sort-size=\"'+item.size+'\" id=\"'+path+'\"><label class=\"mdui-checkbox\"><input type=\"checkbox\" value=\"'+item.id+'\" name=\"itemid\" onclick=\"onClickHander()\"><i class=\"mdui-checkbox-icon\"></i></label><a href=\"'+path+'\" target=\"_blank\"><div class=\"mdui-col-xs-12 mdui-col-sm-7 mdui-text-truncate\"><i class=\"mdui-icon material-icons\">insert_drive_file</i><span>'+item.name+'</span></div><div class=\"mdui-col-sm-3 mdui-text-right\">'+item.lastModifiedDateTime.replace(/[a-zA-Z]/g,' ')+'</div><div class=\"mdui-col-sm-2 mdui-text-right\">'+item.size+'</div></a></li>';\n\t}\n\treturn $domstr;\n}\n\n"
  },
  {
    "path": "statics/themes/nexmoe/js/personjs.js",
    "content": "var documentWidth=window.screen.availWidth;\nvar documentHeight=window.screen.availHeight;\nif(documentWidth>documentHeight){\n    document.getElementsByTagName(\"body\")[0].setAttribute(\"style\",\"background-size:100% auto\")\n}else{\n    document.getElementsByTagName(\"body\")[0].setAttribute(\"style\",\"background-size:auto 100%\")\n}"
  },
  {
    "path": "view/admin/cache.php",
    "content": "<?php view::layout('layout')?>\n<?php \nfunction getPHPExecutableFromPath() {\n  $paths = explode(PATH_SEPARATOR, getenv('PATH'));\n  foreach ($paths as $path) {\n    if (strstr($path, 'php.exe') && isset($_SERVER[\"WINDIR\"]) && file_exists($path) && is_file($path)) {\n        return $path;\n    }\n    else {\n        $php_executable = $path . DIRECTORY_SEPARATOR . \"php\" . (isset($_SERVER[\"WINDIR\"]) ? \".exe\" : \"\");\n        if (file_exists($php_executable) && is_file($php_executable)) {\n           return $php_executable;\n        }\n    }\n  }\n  return 'php'; // not found\n}\n$php_path = getPHPExecutableFromPath();\n$script_path = $_SERVER['DOCUMENT_ROOT'].'/one.php';\n?>\n<?php view::begin('content');?>\n<div class=\"mdui-container-fluid\">\n\n\t<div class=\"mdui-typo\">\n\t  <h1> 页面缓存 <small>清除所有页面缓存</small></h1>\n\t</div>\n\t<br>\n\t<br>\n\t<br>\n\t<div class=\"mdui-row-xs-3\">\n\t  <form action=\"\" method=\"post\">\n\t\t  <div class=\"mdui-col\">\n\t\t\t    <button type=\"submit\" name=\"clear\" class=\"mdui-btn mdui-btn-block mdui-color-theme-accent mdui-ripple\">\n\t\t\t    \t<i class=\"mdui-icon material-icons\">&#xe14c;</i>\n\t\t\t\t\t清除所有缓存\n\t\t\t    </button>\n\t\t  </div>\n\n\t\t  <div class=\"mdui-col\">\n\t\t  </div>\n\n\t\t  <div class=\"mdui-col\">\n\t\t\t  <button type=\"submit\" name=\"refresh\" class=\"mdui-btn mdui-btn-block mdui-color-green-600 mdui-ripple\">\n\t      \t\t\t<i class=\"mdui-icon material-icons\">&#xe028;</i>\n\t\t\t\t\t重建所有缓存\n\t\t\t  </button>\n\t\t  </div>\n\t  </form>\n\t</div>\n\n\t<div class=\"mdui-typo\">\n      <h4 class=\"doc-article-title\">crontab定时刷新缓存 <small>能极大提高系统访问性能</small></h4>\n      <p>\n        添加以下命令到crontab<Br>\n      \t<code>*/10 * * * *  <?php echo \"{$php_path} {$script_path} cache:refresh\";?></code>\n      </p>\n    </div>\n\t\n</div>\n<script>\n$('button[name=refresh]').on('click',function(){\n\tmdui.snackbar({\n\t\tposition: 'right-top',\n\t\tmessage: '正在重建缓存，请耐心等待...'\n\t});\n});\n</script>\n<?php view::end('content');?>"
  },
  {
    "path": "view/admin/images.php",
    "content": "<?php view::layout('layout')?>\n\n<?php view::begin('content');?>\n<div class=\"mdui-container-fluid\">\n\n\t<div class=\"mdui-typo\">\n\t  <h1> <a href=\"?/images/\" target=\"_blank\">图床</a> <small>OneImages</small></h1>\n\t</div>\n\t<form action=\"\" method=\"post\">\n\t\t<div class=\"mdui-textfield\">\n\t\t  <h4>作为网站首页</h4>\n\t\t  <label class=\"mdui-textfield-label\"></label>\n\t\t  <label class=\"mdui-switch\">\n\t\t\t  <input type=\"checkbox\" name=\"home\" value=\"1\" <?php echo empty($config['home'])?'':'checked';?>/>\n\t\t\t  <i class=\"mdui-switch-icon\"></i>\n\t\t  </label>\n\t\t</div>\n\t\t<div class=\"mdui-textfield\">\n\t\t  <h4>允许游客上传图片</h4>\n\t\t  <label class=\"mdui-textfield-label\"></label>\n\t\t  <label class=\"mdui-switch\">\n\t\t\t  <input type=\"checkbox\" name=\"public\" value=\"1\" <?php echo empty($config['public'])?'':'checked';?>/>\n\t\t\t  <i class=\"mdui-switch-icon\"></i>\n\t\t  </label>\n\t\t</div>\n\t\t<div class=\"mdui-textfield\">\n\t\t  <h4>允许上传文件类型</h4>\n\t\t  <input class=\"mdui-textfield-input\" type=\"text\" name=\"exts\" value=\"<?php echo join(' ',$config['exts']);?>\"/>\n\t\t</div>\n\t   <Br>\n\t   <button type=\"submit\" class=\"mdui-btn mdui-color-theme-accent mdui-ripple mdui-float-right\">\n\t   \t<i class=\"mdui-icon material-icons\">&#xe161;</i> 保存\n\t   </button>\n\t   <Br>\n\t</form>\n</div>\n<?php view::end('content');?>"
  },
  {
    "path": "view/admin/install/install_0.php",
    "content": "<?php view::layout('install/layout')?>\n\n<?php view::begin('content');?>\n\n<div class=\"mdui-container-fluid\">\n\t<div class=\"mdui-typo\">\n\t  <h1>程序安装 <small>环境检测</small></h1>\n\t</div>\n\n\t<div class=\"mdui-table-fluid\">\n\t  <table class=\"mdui-table\">\n\t    <thead>\n\t      <tr>\n\t        <th>#</th>\n\t        <th>环境需求</th>\n\t        <th>当前环境</th>\n\t      </tr>\n\t    </thead>\n\t    <tbody>\n\t      <tr>\n\t        <td>1</td>\n\t        <td>PHP > 5.5</td>\n\t        <?php if($check['php']): ?>\n\t        <td><i class=\"mdui-icon material-icons\" style=\"color:#4caf50;\">&#xe5ca;</i></td>\n\t        <?php else:?>\n\t        <td><i class=\"mdui-icon material-icons\" style=\"color:#f44336;\">&#xe5cd;</i></td>\n\t        <?php endif;?>\n\t      </tr>\n\t      <tr>\n\t        <td>2</td>\n\t        <td>curl 支持</td>\n\t        <?php if($check['curl']): ?>\n\t        <td><i class=\"mdui-icon material-icons\" style=\"color:#4caf50;\">&#xe5ca;</i></td>\n\t        <?php else:?>\n\t        <td><i class=\"mdui-icon material-icons\" style=\"color:#f44336;\">&#xe5cd;</i></td>\n\t        <?php endif;?>\n\t      </tr>\n\t      <tr>\n\t        <td>3</td>\n\t        <td>config/ 目录可读可写</td>\n\t        <?php if($check['config']): ?>\n\t        <td><i class=\"mdui-icon material-icons\" style=\"color:#4caf50;\">&#xe5ca;</i></td>\n\t        <?php else:?>\n\t        <td><i class=\"mdui-icon material-icons\" style=\"color:#f44336;\">&#xe5cd;</i></td>\n\t        <?php endif;?>\n\t      </tr>\n\t      <tr>\n\t        <td>4</td>\n\t        <td>cache/ 目录可读可写</td>\n\t        <?php if($check['cache']): ?>\n\t        <td><i class=\"mdui-icon material-icons\" style=\"color:#4caf50;\">&#xe5ca;</i></td>\n\t        <?php else:?>\n\t        <td><i class=\"mdui-icon material-icons\" style=\"color:#f44336;\">&#xe5cd;</i></td>\n\t        <?php endif;?>\n\t      </tr>\n\t      <tr>\n\t        <td>Tips</td>\n\t        <td rowspan=2>建议配合Mintimate's Blog文章和视频操作：<a href=\"https://www.mintimate.cn/2020/09/22/oneindex/\" target=\"_blank\">博客文章</a>、\n\t        <a href=\"https://www.bilibili.com/video/BV1ph41197aa\" target=\"_blank\">视频教程</a></td>\n\t      </tr>\n\t    </tbody>\n\t  </table>\n\t</div>\n\t<br><br>\n\t<!--<a class=\"mdui-btn mdui-color-theme-accent mdui-ripple mdui-float-left\" href=\"?step=1\">上一步</a>-->\n\t<?php if(array_sum($check) == count($check)):?>\n\t<a class=\"mdui-btn mdui-color-theme-accent mdui-ripple mdui-float-right\" href=\"?step=1\">下一步</a>\n\t<?php else:?>\n\t<button class=\"mdui-btn mdui-btn-raised  mdui-float-right disabled\" disabled>下一步</button>\n\t<?php endif;?>\n</div>\n\n<?php view::end('content');?>\n"
  },
  {
    "path": "view/admin/install/install_1.php",
    "content": "<?php view::layout('install/layout')?>\n\n<?php view::begin('content');?>\n\t\n<div class=\"mdui-container-fluid\">\n\t<div class=\"mdui-typo\">\n\t  <h1>程序安装 <small>设置应用ID和机密</small></h1>\n\t</div>\n\n\t<div class=\"mdui-typo\">\n      <h4 class=\"doc-article-title\">\n\t    填入<code>client_id</code>和<code>client_secret</code>,\n      \t<span>根据你的Onedrive供应商选择：</span>\n      </h4>\n    </div>\n\n\t<form action=\"\" method=\"post\">\n\n\t\t<div class=\"mdui-textfield mdui-textfield-floating-label\">\n\t\t\t<label class=\"mdui-radio\">\n\t\t\t\t<input type=\"radio\" name=\"area\" value=\"us\" checked/>\n\t\t\t\t<i class=\"mdui-radio-icon\"></i>\n\t\t\t\t国际版\n\t\t\t</label>\n\t\t\t\n\t\t\t<label class=\"mdui-radio\">\n\t\t\t\t<input type=\"radio\" name=\"area\" value=\"cn\"/>\n\t\t\t\t<i class=\"mdui-radio-icon\"></i>\n\t\t\t\t世纪互联版\n\t\t\t</label>\n\t\t</div>\n\t\t<div class=\"mdui-textfield mdui-textfield-floating-label\">\n\t\t\t<i class=\"mdui-icon material-icons\">https</i>\n\t\t\t<label class=\"mdui-textfield-label\">应用机密(client secret)</label>\n\t\t\t<input type=\"text\" type=\"text\" class=\"mdui-textfield-input\" name=\"client_secret\" required value=\"<?php echo config('client_secret');?>\"/>\n\t\t\t<div class=\"mdui-textfield-error\">应用机密不能为空</div>\n\t\t</div>\n\t\t<br>\n\t\t<div class=\"mdui-textfield mdui-textfield-floating-label\">\n\t\t  \t<i class=\"mdui-icon material-icons\">&#xe5c3;</i>\n\t\t  \t<label class=\"mdui-textfield-label\">应用 ID(client_id)</label>\n\t\t  \t<input type=\"text\" class=\"mdui-textfield-input\" name=\"client_id\" required value=\"<?php echo config('client_id');?>\"/>\n\t\t  \t<div class=\"mdui-textfield-error\">应用 ID不能为空</div>\n\t\t</div>\n\t\t<br>\n\n\t\t<div class=\"mdui-textfield mdui-textfield-floating-label\">\n\t\t   <i class=\"mdui-icon material-icons\">&#xe41a;</i>\n\t\t   <?php if($redirect_uri == 'https://ju.tn/'):?>\n\t\t   <label class=\"mdui-textfield-label\">由于你的网站不是<b>http://localhost/</b>。将通过ju.tn进行中转</label>\n\t\t   <?php endif;?>\n\t\t   <label class=\"mdui-textfield-label\"><?php echo $redirect_uri;?></label>\n\t\t   <input type=\"text\" class=\"mdui-textfield-input\" disabled  value=\"<?php echo $redirect_uri;?>\"/>\n\t\t   <input type=\"hidden\" class=\"mdui-textfield-input\" name=\"redirect_uri\" value=\"<?php echo $redirect_uri;?>\"/>\n\t\t   <div class=\"mdui-textfield-error\">重定向URL不能为空</div>\n\t\t</div>\n\t\t<br>\n\t <a class=\"mdui-btn mdui-btn-raised mdui-float-left\" href=\"?step=0\">上一步</a>\n\t <button class=\"mdui-btn mdui-color-theme-accent mdui-ripple mdui-float-right\" type=\"submit\">下一步</button>\n\t</form>\n\n\t\n</div>\n\n<?php view::end('content');?>"
  },
  {
    "path": "view/admin/install/install_2.php",
    "content": "<?php view::layout('install/layout')?>\n\n<?php view::begin('content');?>\n<?php ?>\n<div class=\"mdui-container-fluid\">\n\t<div class=\"mdui-typo\">\n\t  <h1>程序安装 <small>绑定微软账号</small></h1>\n\t</div>\n\n\n\t <a class=\"mdui-btn mdui-btn-raised mdui-float-left\" href=\"?step=1\">上一步</a>\n\t <a href=\"<?php echo onedrive::authorize_url();?>\" class=\"mdui-btn mdui-color-theme-accent mdui-ripple mdui-float-right\"><i class=\"mdui-icon material-icons\">&#xeb3d;</i> 绑定账号</a>\n      \n\t</form>\n\n\t\n</div>\n\n<?php view::end('content');?>\n"
  },
  {
    "path": "view/admin/install/install_3.php",
    "content": "<?php view::layout('install/layout')?>\n\n<?php view::begin('content');?>\n\t\n<div class=\"mdui-container-fluid\">\n\t<div class=\"mdui-typo\">\n\t  <h1>程序安装 <small>完成安装</small></h1>\n\t</div>\n\n<?php if($refresh_token):?>\n\t<h1 class='mdui-text-color-green'>程序安装成功!</h1>\n\t<br><br>\n\t<a class=\"mdui-btn mdui-color-theme-accent mdui-ripple mdui-float-left\" href=\"?/admin/\" ><i class=\"mdui-icon material-icons\">&#xe8b8;</i> 管理后台</a>(初始密码:MintimateBlog)\n\t<a class=\"mdui-btn mdui-color-theme-accent mdui-ripple mdui-float-right\" href=\"./\"><i class=\"mdui-icon material-icons\">&#xe2c7;</i> 访问网站</a>\n<?php else:?>\n\t<h1  class='mdui-text-color-red'>程序安装失败!</h1>\n\t<br><br>\n\t<a class=\"mdui-btn mdui-btn-raised mdui-float-left\" href=\"?step=2\">重新绑定</a>\n<?php endif;?>\n\n\n\t\n</div>\n\n<?php view::end('content');?>"
  },
  {
    "path": "view/admin/install/layout.php",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<meta charset=\"utf-8\">\n    <link rel=\"apple-touch-icon\" sizes=\"76x76\" href=\"/statics/themes/nexmoe/IMG/OneIndexM.svg\">\n    <link rel=\"icon\" href=\"/statics/themes/nexmoe/IMG/OneIndexM.svg\">\n\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0,maximum-scale=1.0, user-scalable=no\"/>\n\t<title>OneIndex <?php e($title);?></title>\n\t<link rel=\"stylesheet\" href=\"//cdnjs.loli.net/ajax/libs/mdui/0.4.3/css/mdui.min.css\">\n    <script src=\"/statics/themes/nexmoe/js/mdui.min.js\"></script>\n\t\t<style>\n\t\t.mdui-appbar .mdui-toolbar{\n\t\t\theight:56px;\n\t\t\tfont-size: 16px;\n\t\t}\n\t\t.mdui-toolbar>*{\n\t\t\tpadding: 0 6px;\n\t\t\tmargin: 0 2px;\n\t\t\topacity:0.5;\n\t\t}\n\t\t.mdui-toolbar>.mdui-typo-headline{\n\t\t\tpadding: 0 16px 0 0;\n\t\t}\n\t\t.mdui-toolbar>i{\n\t\t\tpadding: 0;\n\t\t}\n\t\t.mdui-toolbar>a:hover,a.mdui-typo-headline,a.active{\n\t\t\topacity:1;\n\t\t}\n\t\t.mdui-container{\n\t\t\tmax-width:980px;\n\t\t}\n\t\t.mdui-list-item{\n\t\t\t-webkit-transition:none;\n\t\t\ttransition:none;\n\t\t}\n\t\t.mdui-list>.th{\n\t\t\tbackground-color:initial;\n\t\t}\n\t\t.mdui-list-item>a{\n\t\t\twidth:100%;\n\t\t\tline-height: 48px\n\t\t}\n\t\t.mdui-list-item{\n\t\t\tmargin: 2px 0px;\n\t\t\tpadding:0;\n\t\t}\n\t\t.mdui-toolbar>a:last-child{\n\t\t\topacity:1;\n\t\t}\n\t\t@media screen and (max-width:980px){\n\t\t\t.mdui-list-item .mdui-text-right{\n\t\t\t\tdisplay: none;\n\t\t\t}\n\t\t\t.mdui-container{\n\t\t\t\twidth:100% !important;\n\t\t\t\tmargin:0px;\n\t\t\t}\n\t\t\t.mdui-toolbar>*{\n\t\t\t\tdisplay: none;\n\t\t\t}\n\t\t\t.mdui-toolbar>a:last-child,.mdui-toolbar>.mdui-typo-headline,.mdui-toolbar>i:first-child{\n\t\t\t\tdisplay: block;\n\t\t\t}\n\t\t}\n\t</style>\n</head>\n<body class=\"mdui-theme-primary-blue-grey mdui-theme-accent-blue\">\n\t<header class=\"mdui-appbar mdui-color-theme\">\n\t\t<div class=\"mdui-toolbar mdui-container\">\n\t\t\t<a href=\"/\" class=\"mdui-typo-headline\">OneIndex</a>\n\t\t\t<?php foreach((array)$navs as $n=>$l):?>\n\t\t\t<i class=\"mdui-icon material-icons mdui-icon-dark\" style=\"margin:0;\">chevron_right</i>\n\t\t\t<a href=\"<?php e($l);?>\"><?php e($n);?></a>\n\t\t\t<?php endforeach;?>\n\t\t\t<!--<a href=\"javascript:;\" class=\"mdui-btn mdui-btn-icon\"><i class=\"mdui-icon material-icons\">refresh</i></a>-->\n\t\t</div>\n\t</header>\n\t\n\t<div class=\"mdui-container\">\n    \t<?php view::section('content');?>\n  \t</div>\n</body>\n</html>\n"
  },
  {
    "path": "view/admin/layout.php",
    "content": "\n<html>\n<head>\n\t<meta charset=\"utf-8\">\n\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0,maximum-scale=1.0, user-scalable=no\"/>\n    <link rel=\"apple-touch-icon\" sizes=\"76x76\" href=\"/statics/themes/nexmoe/IMG/OneIndexM.svg\">\n    <link rel=\"icon\" href=\"/statics/themes/nexmoe/IMG/OneIndexM.svg\">\n\t<meta http-equiv=\"Access-Control-Allow-Origin\" content=\"*\" />\n\t<title>OneIndex 系统管理</title>\n\t<link rel=\"stylesheet\" href=\"//cdnjs.loli.net/ajax/libs/mdui/0.4.3/css/mdui.min.css\">\n\t<script src=\"https://cdn.jsdelivr.net/gh/xieqifei/StaticsResources/oneindexn/mdui/mdui.min.js\"></script>\n\t<script>$ = mdui.JQ;</script>\n</head>\n<body class=\"mdui-drawer-body-left mdui-appbar-with-toolbar  mdui-theme-primary-indigo mdui-theme-accent-blue\">\n<header class=\"mdui-appbar mdui-appbar-fixed\">\n  <div class=\"mdui-toolbar mdui-color-theme\">\n    <span class=\"mdui-btn mdui-btn-icon mdui-ripple mdui-ripple-white\" mdui-drawer=\"{target: '#main-drawer', swipe: true}\"><i class=\"mdui-icon material-icons\">menu</i></span>\n    <a href=\"./\" target=\"_blank\" class=\"mdui-typo-headline mdui-hidden-xs\">OneIndex</a>\n    <div class=\"mdui-toolbar-spacer\"></div>\n    <a href=\"<?php echo $root?>?/logout\"><i class=\"mdui-icon material-icons\">&#xe8ac;</i> 登出</a>\n  </div>\n</header>\n<div class=\"mdui-drawer\" id=\"main-drawer\">\n\t<?php $root = get_absolute_path(dirname($_SERVER['SCRIPT_NAME']));?>\n  <div class=\"mdui-list\">\n\t<br><br>  \n\t<a href=\"<?php echo $root?>?/admin\" class=\"mdui-list-item\">\n      <i class=\"mdui-list-item-icon mdui-icon material-icons\">&#xe8b8;</i>\n      <div class=\"mdui-list-item-content\">基本设置</div>\n    </a>\n\n    <a href=\"<?php echo $root?>?/admin/cache\" class=\"mdui-list-item\">\n      <i class=\"mdui-list-item-icon mdui-icon material-icons\">&#xe53b;</i>\n      <div class=\"mdui-list-item-content\">页面缓存</div>\n    </a>\n\n    <a href=\"<?php echo $root?>?/admin/show\" class=\"mdui-list-item\">\n      <i class=\"mdui-list-item-icon mdui-icon material-icons\">&#xe3a5;</i>\n      <div class=\"mdui-list-item-content\">文件展示设置</div>\n    </a>\n    <a href=\"<?php echo $root?>?/admin/images\" class=\"mdui-list-item\">\n      <i class=\"mdui-list-item-icon mdui-icon material-icons\">&#xe410;</i>\n      <div class=\"mdui-list-item-content\">图床设置(OneImages)</div>\n    </a>\n\n    <a href=\"<?php echo $root?>?/admin/upload\" class=\"mdui-list-item\">\n      <i class=\"mdui-list-item-icon mdui-icon material-icons\">&#xe2c6;</i>\n      <div class=\"mdui-list-item-content\">网站目录上传</div>\n    </a>\n    \n    <a href=\"<?php echo $root?>?/admin/offline\" class=\"mdui-list-item\">\n      <i class=\"mdui-list-item-icon mdui-icon material-icons\">&#xe2c3;</i>\n      <div class=\"mdui-list-item-content\">上传管理</div>\n    </a>\n\n    <a href=\"<?php echo $root?>?/admin/setpass\" class=\"mdui-list-item\">\n      <i class=\"mdui-list-item-icon mdui-icon material-icons\">&#xe88d;</i>\n      <div class=\"mdui-list-item-content\">密码修改</div>\n    </a>\n\n    <a href=\"https://onedrive.live.com/\" class=\"mdui-list-item\" target=\"_blank\">\n      <i class=\"mdui-list-item-icon mdui-icon material-icons\">&#xe2bf;</i>\n      <div class=\"mdui-list-item-content\">文件管理(OneDrive)</div>\n    </a>\n  </div>\n</div>\n\n<a id=\"anchor-top\"></a>\n\n<div class=\"mdui-container\">\n\t<?php view::section('content');?>\n</div>\n<script>\n\t$(\"a[href='<?php echo'?'.(route::get_uri());?>']\").addClass(\"mdui-text-color-blue\");\n  // 消息提示\n  <?php echo (isset($message) && !empty($message)) ? \"mdui.snackbar({position: 'right-top', message: '{$message}'});\" : '';?>\n</script>\n</body>\n\n</html>\n"
  },
  {
    "path": "view/admin/login.php",
    "content": "<?php view::layout('install/layout')?>\n\n<?php view::begin('content');?>\n\t\n<div class=\"mdui-container-fluid\">\n\t<div class=\"mdui-col-md-6 mdui-col-offset-md-3\">\n\t  <center><h4 class=\"mdui-typo-display-2-opacity\">系统管理</h4></center>\n\t  <form action=\"\" method=\"post\">\n\t\t  <div class=\"mdui-textfield mdui-textfield-floating-label\">\n\t\t    <i class=\"mdui-icon material-icons\">https</i>\n\t\t    <label class=\"mdui-textfield-label\">密码</label>\n\t\t    <input name=\"password\" class=\"mdui-textfield-input\" type=\"password\"/>\n\t\t  </div>\n\t\t  <br>\n\t\t  <button type=\"submit\" class=\"mdui-center mdui-btn mdui-btn-raised mdui-ripple mdui-color-theme\">\n\t\t  \t<i class=\"mdui-icon material-icons\">fingerprint</i>\n\t\t  \t登录\n\t\t  </button>\n\t  </form>\n\t</div>\n\t\n</div>\n\n<?php view::end('content');?>"
  },
  {
    "path": "view/admin/offline.php",
    "content": "<?php view::layout('layout')?>\n\n<?php view::begin('content');?>\n<div class=\"mdui-container-fluid\">\n\n\t<div class=\"mdui-typo\">\n\t  <h1> 上传管理<small>游客前台离线和在线上传</small></h1>\n  </div>\n  <form action=\"\" method=\"post\">\n\t\t<div class=\"mdui-textfield\">\n\t\t  <h4>允许游客离线上传<small>（需安装aria2和rclone，输入远程url即可上传）</small></h4>\n\t\t  <label class=\"mdui-textfield-label\"></label>\n\t\t  <label class=\"mdui-switch\">\n\t\t\t  <input type=\"checkbox\" name=\"offline\" value=\"1\" <?php echo ($config['offline']==false)?'':'checked';?>/>\n\t\t\t  <i class=\"mdui-switch-icon\"></i>\n\t\t  </label>\n\t\t</div>\n\t   <Br>\n\t   <div class=\"mdui-textfield\">\n\t\t  <h4>允许游客在线上传<small> （上传游客计算机里的文件）</small></h4>\n\t\t  <label class=\"mdui-textfield-label\"></label>\n\t\t  <label class=\"mdui-switch\">\n\t\t\t  <input type=\"checkbox\" name=\"online\" value=\"1\" <?php echo ($config['online']==false)?'':'checked';?>/>\n\t\t\t  <i class=\"mdui-switch-icon\"></i>\n\t\t  </label>\n\t\t</div>\n\t\t<br>\n\t\t<div class=\"mdui-textfield\">\n\t\t  <h4>游客在线上传目录限制<small>（注意：管理员不受此限制）</small></h4>\n\t\t  <input class=\"mdui-textfield-input\" type=\"text\" name=\"upload_path\" value=\"<?php echo $config['upload_path'];?>\"/>\n\t\t  <small>此目录下的readme index head文件无法被渲染</small>\n\t\t</div>\n\t   <button type=\"submit\" class=\"mdui-btn mdui-color-theme-accent mdui-ripple mdui-float-right\">\n\t   \t<i class=\"mdui-icon material-icons\">&#xe161;</i> 保存\n     </button>\n\t</form>\n</div>\n<?php view::end('content');?>"
  },
  {
    "path": "view/admin/setpass.php",
    "content": "<?php view::layout('layout')?>\n\n<?php view::begin('content');?>\n<div class=\"mdui-container-fluid\">\n\n\t<div class=\"mdui-typo\">\n\t  <h1> 修改密码 <small>后台密码修改(与文件夹密码无关)</small></h1>\n\t</div>\n\t<form action=\"\" method=\"post\">\n\t\t<div class=\"mdui-textfield\">\n\t\t  <h4>旧密码</h4>\n\t\t  <input class=\"mdui-textfield-input\" type=\"password\" name=\"old_pass\" />\n\t\t</div>\n\n\t\t<div class=\"mdui-textfield\">\n\t\t  <h4>新密码</h4>\n\t\t  <input class=\"mdui-textfield-input\" type=\"password\" name=\"password\" />\n\t\t</div>\n\n\t\t<div class=\"mdui-textfield\">\n\t\t  <h4>重复新密码</h4>\n\t\t  <input class=\"mdui-textfield-input\" type=\"password\" name=\"password2\" />\n\t\t</div>\n\t\t\n\t   <button type=\"submit\" class=\"mdui-btn mdui-color-theme-accent mdui-ripple mdui-float-right\">\n\t   \t<i class=\"mdui-icon material-icons\">&#xe161;</i> 保存\n\t   </button>\n\t</form>\n</div>\n<?php view::end('content');?>"
  },
  {
    "path": "view/admin/settings.php",
    "content": "<?php view::layout('layout')?>\n\n<?php view::begin('content');?>\n<div class=\"mdui-container-fluid\">\n\n\t<div class=\"mdui-typo\">\n\t  <h1> 基本设置 <small>设置OneIndex基本参数</small></h1>\n\t</div>\n\t<form action=\"\" method=\"post\">\n\t\t<div class=\"mdui-textfield\">\n\t\t  <h4>网站名称</h4>\n\t\t  <input class=\"mdui-textfield-input\" type=\"text\" name=\"site_name\" value=\"<?php echo $config['site_name'];?>\"/>\n\t\t</div>\n\n\t\t<div class=\"mdui-textfield\">\n\t\t  <h4>网站主题<small></small></h4>\n\t\t  <select name=\"style\" class=\"mdui-select\">\n\t\t\t  <?php \n\t\t\t\tforeach(scandir(ROOT.'/view/themes') as $k=>$s){\n\t\t\t\t    $styles[$k] = trim($s, '/');\n\t\t\t\t}\n\t\t\t\t$styles = array_diff($styles, [\".\", \"..\", \"admin\"]);\n\t\t\t\t$style = config(\"style\")?config(\"style\"):'nexmoe';\n\t\t\t\t$cache_type  = config(\"cache_type\")?config(\"cache_type\"):'secache';\n\t\t\t \tforeach($styles as $style_name):\n\t\t\t  ?>\n\t\t\t  <option value =\"<?php echo $style_name;?>\" <?php echo ($style==$style_name)?'selected':'';?>><?php echo $style_name;?></option>\n\t\t\t  <?php endforeach;?>\n\t\t  </select>\n\t\t</div>\n\n\t\t<div class=\"mdui-textfield\">\n\t\t  <h4>OneDrive起始目录(空为根目录)<small>例：仅共享share目录 /share</small></h4>\n\t\t  <input class=\"mdui-textfield-input\" type=\"text\" name=\"onedrive_root\" value=\"<?php echo $config['onedrive_root'];?>\"/>\n\t\t</div>\n\n\t\t<div class=\"mdui-textfield\">\n\t\t  <h4>不渲染目录<small> 该目录下index.html、readme.md、head.md文件不会被渲染</small></h4>\n\t\t  <input class=\"mdui-textfield-input\" type=\"text\" name=\"except_path\" value=\"<?php echo $config['except_path'];?>\"/>\n\t\t  <small>设置所有目录都不渲染输入all，设置名为all的目录不渲染，输入/all</small>\n\t\t</div>\n\n\t\t<div class=\"mdui-textfield\">\n\t\t  <h4>需要隐藏的目录<small> 不需要列出的目录(一行一个) 清空缓存后生效</small></h4>\n\t\t  <textarea class=\"mdui-textfield-input\" placeholder=\"输入后回车换行\" name=\"onedrive_hide\"><?=@$config['onedrive_hide'];?></textarea>\n\t\t  <small>这里是通配识别，就是存在以上字符文件夹一律会隐藏</small>\n\t\t</div>\n\n\n\t\t<div class=\"mdui-textfield\">\n\t\t  <h4>防盗链(白名单)<small> 不填写则不启用, 多个用英文 <code>;</code> 分割</small></h4>\n\t\t  <input class=\"mdui-textfield-input\" name=\"onedrive_hotlink\" value=\"<?=@$config['onedrive_hotlink'];?>\"/>\n\t\t  <small>支持通配符 例: <code>*.domain.com</code></small>\n\t\t</div>\n\n\t\t<div class=\"mdui-textfield\">\n\t\t  <h4>缓存类型<small></small></h4>\n\t\t  <select name=\"cache_type\" class=\"mdui-select\">\n\t\t\t  <?php \n\t\t\t \tforeach(['secache', 'filecache', 'memcache', 'redis'] as $type):\n\t\t\t  ?>\n\t\t\t  <option value =\"<?php echo $type;?>\" <?php echo ($type==$cache_type)?'selected':'';?>><?php echo $type;?></option>\n\t\t\t  <?php endforeach;?>\n\t\t  </select>\n\t\t</div>\n\n\t\t<div class=\"mdui-textfield\">\n\t\t  <h4>缓存过期时间(秒)</h4>\n\t\t  <input class=\"mdui-textfield-input\" type=\"text\" name=\"cache_expire_time\" value=\"<?php echo $config['cache_expire_time'];?>\"/>\n\t\t</div>\n\n\t\t<div class=\"mdui-textfield\">\n\t\t  <h4>去掉地址栏中的<code style=\"color: #c7254e;background-color: #f7f7f9;font-size:16px;\">/?/</code> (需配合伪静态使用!!)</h4>\n\t\t  <label class=\"mdui-textfield-label\"></label>\n\t\t  <label class=\"mdui-switch\">\n\t\t\t  <input type=\"checkbox\" name=\"root_path\" value=\"?\" <?php echo empty($config['root_path'])?'checked':'';?>/>\n\t\t\t  <i class=\"mdui-switch-icon\"></i>\n\t\t  </label>\n\t\t</div>\n\t\t\n\n\t\t\n\n\t   <button type=\"submit\" class=\"mdui-btn mdui-color-theme-accent mdui-ripple mdui-float-right\">\n\t   \t<i class=\"mdui-icon material-icons\">&#xe161;</i> 保存\n\t   </button>\n\t</form>\n</div>\n<?php view::end('content');?>\n"
  },
  {
    "path": "view/admin/show.php",
    "content": "<?php view::layout('layout')?>\n\n<?php view::begin('content');?>\n<div class=\"mdui-container-fluid\">\n\n\t<div class=\"mdui-typo\">\n\t  <h1> 文件展示设置 <small>根据不同后缀进行展示。无设置后缀，直连下载</small></h1>\n\t</div>\n\t<form action=\"\" method=\"post\">\n\t\t<?php foreach($show as $n=>$ext):?>\n\t\t\t<div class=\"mdui-textfield\">\n\t\t\t  <h4><?php echo $names[$n];?></h4>\n\t\t\t  <input class=\"mdui-textfield-input\" type=\"text\" name=\"<?php echo $n;?>\" value=\"<?php echo join(' ', $ext);?>\"/>\n\t\t\t</div>\n\t\t<?php endforeach;?>\n\n\t   <button type=\"submit\" class=\"mdui-btn mdui-color-theme-accent mdui-ripple mdui-float-right\">\n\t   \t<i class=\"mdui-icon material-icons\">&#xe161;</i> 保存\n\t   </button>\n\t</form>\n</div>\n<?php view::end('content');?>"
  },
  {
    "path": "view/admin/upload.php",
    "content": "<?php view::layout('layout')?>\n<?php view::begin('content');?>\n<div class=\"mdui-container-fluid\">\n\n\t<div class=\"mdui-typo\">\n\t  <h1> 网站目录上传 <small>文件上传添加和管理</small></h1>\n\t</div>\n\n\t<div class=\"mdui-row\">\n\t  <form action=\"\" method=\"post\">\n\t\t  <div class=\"mdui-col-xs-7\">\n\t\t\t<div class=\"mdui-textfield\">\n\t\t\t  <label class=\"mdui-textfield-label\">网站目录下的文件或文件夹</label>\n\t\t\t  <input name=\"local\" class=\"mdui-textfield-input\" type=\"text\"/>\n\t\t\t</div>\n\t\t  </div>\n\t\t  <div class=\"mdui-col-xs-3\">\n\t\t\t<div class=\"mdui-textfield\">\n\t\t\t  <label class=\"mdui-textfield-label\">远程目录</label>\n\t\t\t  <input name=\"remote\" class=\"mdui-textfield-input\" type=\"text\" value=\"/upload/\"/>\n\t\t\t</div>\n\t\t  </div>\n\t\t  <div class=\"mdui-col-xs-2\" style=\"padding-top: 34px;\">\n\t\t\t\t<button type=\"submit\" name=\"upload\" value=\"1\" class=\"mdui-btn mdui-btn-block mdui-color-green-600 mdui-ripple\">\n\t\t      \t\t<i class=\"mdui-icon material-icons\">&#xe2c3;</i>\n\t\t\t\t\t上传\n\t\t\t\t</button>\n\t\t  </div>\n\t  </form>\n\t</div>\n\t<br>\n\t<div class=\"mdui-typo\">\n\t  <h5>上传进度 <small></small></h5>\n\t</div>\n\n\t<div class=\"mdui-table-fluid\">\n\t  <table class=\"mdui-table\">\n\t    <thead>\n\t      <tr>\n\t        <th>远程路径</th>\n\t        <th>上传速度</th>\n\t        <th>进度</th>\n\t        <th>状态</th>\n\t        <th>操作</th>\n\t      </tr>\n\t    </thead>\n\t    <tbody>\n\t\t  <form action=\"\" method=\"post\">\n\t\t  <?php foreach( (array)$uploading as $i => $task ):?>\n\t\t      <tr>\n\t\t        <td><?php echo $task['remotepath'];?></td>\n\t\t        <td><?php echo onedrive::human_filesize($task['speed']).'/s';?></td>\n\t\t        <td><?php echo @floor($task['offset']/$task['filesize']*100).'%'; ?></td>\n\t\t        <?php if( $task['update_time'] == 0 ):?>\n\t\t        \t<td>\n\t\t\t        \t等待上传中\n\t\t        \t</td>\n\t\t        \t<td>\n\t\t\t        \t<button name=\"begin_task\"  class=\"mdui-btn mdui-color-green-600 mdui-ripple\" type=\"submit\" name=\"remotepath\" value=\"<?php echo $task['remotepath'];?>\">上传</button>\n\t\t        \t</td>\n\t\t        <?php elseif(time() > ($task['update_time']+60)):?>\n\t\t        \t<td>已暂停</td>\n\t\t        \t<td>\n\t\t\t        \t<button name=\"begin_task\"  class=\"mdui-btn mdui-color-green-600 mdui-ripple\" type=\"submit\" name=\"remotepath\" value=\"<?php echo $task['remotepath'];?>\">上传</button>\n\t\t        \t</td>\n\t\t        <?php else:?>\n\t\t        \t<td>上传中</td>\n\t\t        \t<td>\n\t\t\t        \t<button name=\"delete_task\" class=\"mdui-btn mdui-color-red mdui-ripple\" type=\"submit\" name=\"remotepath\" value=\"<?php echo $task['remotepath'];?>\">删除</button>\n\t\t        \t</td>\n\t\t        <?php endif;?>\n\t\t      </tr>\n\t\t  <?php endforeach;?>\n\t\t  </form>\n\t    </tbody>\n\t  </table>\n\t</div>\n\n\t<br>\n\t<div class=\"mdui-typo\">\n\t <form action=\"\" method=\"post\">\n\t  <h5>已上传 \n\t  \t<small>\n\t\t  \t\n\t\t  \t<button name=\"empty_uploaded\" value=\"1\" class=\"mdui-btn mdui-color-red mdui-ripple\" type=\"submit\" name=\"remotepath\">清空已上传记录</button>\n\t\t  \t\n\t  \t</small>\n\t  </h5>\n\t </form>\n\t</div>\n\n\t<div class=\"mdui-table-fluid\">\n\t  <table class=\"mdui-table\">\n\t    <thead>\n\t      <tr>\n\t        <th>远程路径</th>\n\t        <th>状态</th>\n\t      </tr>\n\t    </thead>\n\t    <tbody>\n\t\t  <?php foreach( (array)$uploaded as $name => $status ):?>\n\t\t      <tr>\n\t\t        <td><?php echo $name;?></td>\n\t\t        <td><?php echo $status;?></td>\n\t\t  <?php endforeach;?>\n\t    </tbody>\n\t  </table>\n\t</div>\n\t\n</div>\n<script>\n$('button[name=refresh]').on('click',function(){$('center').html('正在重建缓存，请耐心等待...');});\n</script>\n<?php view::end('content');?>"
  },
  {
    "path": "view/common/offline.php",
    "content": "<?php view::layout('themes/'.(config('style')?config('style'):'material').'/layout')?>\n\n<?php view::begin('content');?>\n  <link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/gh/xieqifei/StaticsResources@v1.0/oneindexn/common/offline/css/bootstrap.min.css\">\n  <link href=\"https://cdn.jsdelivr.net/gh/xieqifei/StaticsResources@v1.0/oneindexn/common/offline/css/bootstrap-responsive.min.css\" rel=\"stylesheet\" type=\"text/css\"/>\n  <link href=\"https://cdn.jsdelivr.net/gh/xieqifei/StaticsResources@v1.0/oneindexn/common/offline/css/main.css\" rel=\"stylesheet\" type=\"text/css\"/>\n  <body>\n      <header class=\"main-head page-header\">\n        <h1>Aria2前端工具</h1>\n        <span id=\"offline-cached\"></span>\n        <div id=\"global-info\" class=\"pull-right\">\n          <div id=\"global-version\"></div>\n          <div id=\"global-speed\"></div>\n        </div>\n      </header>\n\n      <div class=\"clearfix hide\" id=\"main-control\">\n        <div id=\"main-alert\" class=\"hide\">\n          <div id=\"main-alert-inline\" class=\"alert\">\n            <a href=\"#\" id=\"btnClearAlert\"  class=\"close\">×</a>\n            <span class=\"alert-msg\">Loading</span>\n          </div>\n        </div>\n\n        <div class=\"pull-left\">\n          <div class=\"btn-group\" id=\"select-btn\">\n            <button id=\"select-all-btn\" class=\"btn\" rel=\"tooltip\" title=\"Select All\">\n              <i class=\"select-box\"></i>\n            </button>\n            <a class=\"btn dropdown-toggle\" data-toggle=\"dropdown\" href=\"#\">\n              <span class=\"caret\"></span>\n            </a>\n            <ul class=\"dropdown-menu\">\n              <li><a href=\"#\" id=\"btnSelectActive\" >进行中</a></li>\n              <li><a href=\"#\" id=\"btnSelectWaiting\">等待中</a></li>\n              <li><a href=\"#\" id=\"btnSelectPaused\" >暂停中</a></li>\n              <li><a href=\"#\" id=\"btnSelectStopped\" >已完成</a></li>\n            </ul>\n          </div>\n        </div>\n\n        <div class=\"pull-left\" id=\"not-selected-grp\">\n          <div class=\"pull-left btn-group\">\n            <a class=\"btn\" id=\"add-task-btn\" data-toggle=\"modal\" href=\"#add-task-modal\" rel=\"tooltip\" title=\"Add Task\">\n              <i class=\"icon-plus\"></i> 添加\n            </a>\n          </div>\n          <div class=\"pull-left btn-group\" id=\"do-all-btn\">\n            <a href=\"#\" id=\"btnStartAll\" class=\"btn\" id=\"unpause-all\" rel=\"tooltip\" title=\"Start All\">\n              <i class=\"icon-forward\"></i>\n            </a>\n            <a href=\"#\" id=\"btnPauseAll\"  class=\"btn\" id=\"pause-all\" rel=\"tooltip\" title=\"Pause All\">\n              <i class=\"icon-stop\"></i>\n            </a>\n            <a href=\"#\" id=\"btnRemoveFinished\"  class=\"btn\" id=\"pure-all\" rel=\"tooltip\" title=\"Remove Finished Tasks\">\n              <i class=\"icon-trash\"></i>\n            </a>\n          </div>\n        </div>\n\n        <div class=\"pull-left hide\" id=\"selected-grp\">\n          <div class=\"btn-group\">\n            <a href=\"#\" id=\"btnUnPause\" class=\"btn\" rel=\"tooltip\" title=\"Start\">\n              <i class=\"icon-play\"></i>\n            </a>\n            <a href=\"#\" id=\"btnPause\"   class=\"btn\" rel=\"tooltip\" title=\"Pause\">\n              <i class=\"icon-pause\"></i>\n            </a>\n            <a href=\"#\" id=\"btnRemove\"  class=\"btn\" rel=\"tooltip\" title=\"Remove\">\n              <i class=\"icon-remove\"></i>\n            </a>\n          </div>\n          <!--<button class=\"btn pull-left\" id=\"info-btn\" rel=\"tooltip\" title=\"Task Info\">-->\n            <!--<i class=\"icon-info-sign\"></i> Info-->\n          <!--</button>-->\n        </div>\n\n        <div class=\"pull-right\" id=\"other-grp\">\n          <div class=\"btn-group\">\n            <a href=\"#\" class=\"btn\" id=\"refresh-btn\" rel=\"tooltip\" title=\"Refresh\">\n              <i class=\"icon-refresh\"></i> 刷新\n            </a>\n            <a class=\"btn\" id=\"setting-btn\" data-toggle=\"modal\" href=\"#setting-modal\" rel=\"tooltip\" title=\"Settings\">\n              <i class=\"icon-wrench\"></i>\n            </a>\n          </div>\n        </div>\n      </div>\n\n      <section id=\"active-tasks\">\n      <div class=\"section-header\">\n        <i class=\"icon-chevron-down\"></i><b>活动任务</b>\n      </div>\n      <ul class=\"tasks-table\" id=\"active-tasks-table\">\n        <li>\n          <div class=\"empty-tasks\">\n            <strong>无活动任务</strong>\n          </div>\n        </li>\n      </ul>\n      </section>\n\n      <section id=\"other-tasks\">\n      <div class=\"section-header\">\n        <i class=\"icon-chevron-down\"></i><b>其他任务</b>\n      </div>\n      <ul id=\"waiting-tasks-table\" class=\"tasks-table\">\n        <li>\n          <div class=\"empty-tasks\">\n            <strong>无任务</strong>\n          </div>\n        </li>\n      </ul>\n      <ul id=\"stopped-tasks-table\" class=\"tasks-table\"> </ul>\n      </section>\n\n    <ul id=\"task-contextmenu\" class=\"dropdown-menu\">\n      <li class=\"task-restart\"><a href=\"#\" id=\"menuRestart\" >重启</a></li>\n      <li class=\"task-start\"><a href=\"#\" id=\"menuStart\" >启动</a></li>\n      <li class=\"task-pause\"><a href=\"#\" id=\"menuPause\" >暂停</a></li>\n      <li><a href=\"#\" id=\"menuRemove\" >移动</a></li>\n      <li class=\"task-move divider\"></li>\n      <li class=\"task-move\"><a href=\"#\" id=\"menuMoveTop\" >移至顶部</a></li>\n      <li class=\"task-move\"><a href=\"#\" id=\"menuMoveUp\" >向上移动</a></li>\n      <li class=\"task-move\"><a href=\"#\" id=\"menuMoveDown\" >向下移动</a></li>\n      <li class=\"task-move\"><a href=\"#\" id=\"menuMoveEnd\" >移至底部</a></li>\n    </ul>\n\n    <section class=\"modal hide fade\" id=\"add-task-modal\">\n    <div class=\"modal-header\">\n      <button class=\"close\" data-dismiss=\"modal\">×</button>\n      <h3>添加任务</h3>\n    </div>\n    <div class=\"modal-body\">\n      <div id=\"add-task-alert\" class=\"alert alert-error hide\">\n        <a href=\"#\" id=\"closeAlert\"  class=\"close\">×</a>\n        <strong>Error:</strong> <span class=\"alert-msg\"></span>\n      </div>\n      <form id=\"add-task-uri\">\n        <div class=\"input-append\">\n          <input type=\"text\" name=\"uri\" id=\"uri-input\" class=\"input-clear\" placeholder=\"HTTP, FTP or Magnet\" /><span><a id=\"torrent-up-btn\" class=\"btn\">Upload Torrent<input type=\"file\" id=\"torrent-up-input\" /></a></span>\n        </div>\n        <textarea id=\"uri-textarea\" rows=5 class=\"input-clear hide\" placeholder=\"HTTP, FTP or Magnet\"></textarea>\n      </form>\n      <div id=\"uri-more\"><span class=\"or-and\">&or;&or;&or;&or;&or;&or;</span><span class=\"or-and\" style=\"display:none;\">&and;&and;&and;&and;&and;&and;</span></div>\n      <div id=\"add-task-option-wrap\"></div>\n    </div>\n    <div class=\"modal-footer\">\n      <a href=\"#\" id=\"add-task-submit\" class=\"btn btn-primary\">添加</a>\n      <a href=\"#\" id=\"add-task-clear\" class=\"btn\" data-dismiss=\"modal\">取消</a>\n    </div>\n    </section>\n\n    <section class=\"modal hide fade\" id=\"setting-modal\">\n    <div class=\"modal-header\">\n      <button class=\"close\" data-dismiss=\"modal\">×</button>\n      <h2>设置</h2>\n    </div>\n    <div class=\"modal-body\">\n      <form id=\"setting-form\" class=\"form-horizontal\">\n        <fieldset>\n          <div class=\"control-group rpc-path-group\">\n            <label class=\"control-label\" for=\"rpc-path\">JSON-RPC 路径</label>\n            <div class=\"controls\">\n              <div class=\"input-append btn-group rpc-path-wrap\">\n                <input type=\"text\" class=\"input-xlarge\" id=\"rpc-path\"><a class=\"add-on btn dropdown-toggle\" href=\"#\" disabled><b class=\"caret\"></b></a>\n              </div>\n            </div>\n          </div>\n          <div class=\"control-group\">\n            <label class=\"control-label\">自动刷新</label>\n            <div class=\"controls\">\n              <label class=\"radio inline\">\n                <input type=\"radio\" name=\"refresh_interval\" value=\"1000\"> 1s\n              </label>\n              <label class=\"radio inline\">\n                <input type=\"radio\" name=\"refresh_interval\" value=\"5000\" checked> 5s\n              </label>\n              <label class=\"radio inline\">\n                <input type=\"radio\" name=\"refresh_interval\" value=\"10000\"> 10s\n              </label>\n              <label class=\"radio inline\">\n                <input type=\"radio\" name=\"refresh_interval\" value=\"60000\"> 1min\n              </label>\n              <label class=\"radio inline\">\n                <input type=\"radio\" name=\"refresh_interval\" value=\"0\"> off \n              </label>\n            </div>\n          </div>\n          <div class=\"control-group\">\n            <label class=\"control-label\">完成时提醒</label>\n            <div class=\"controls\">\n              <label class=\"radio inline\">\n                <input type=\"radio\" name=\"finish_notification\" value=\"1\" checked> 开启提醒\n              </label>\n              <label class=\"radio inline\">\n                <input type=\"radio\" name=\"finish_notification\" value=\"0\"> 关闭提醒\n              </label>\n            </div>\n          </div>\n        </fieldset>\n      </form>\n      <div id=\"aria2-gsetting\">\n      </div>\n    </div>\n    <div class=\"modal-footer\">\n      <div id=\"copyright\">© Copyright <a href=\"https://github.com/binux/yaaw\">Binux</a></div>\n      <a href=\"#\" id=\"saveSettings\"  class=\"btn btn-success\">保存</a>\n      <a href=\"#\" class=\"btn\" data-dismiss=\"modal\">取消</a>\n    </div>\n    </section>\n    \n    <script id=\"global-speed-tpl\" type=\"text/mustache-template\">\n      <i class=\"icon-download\"></i> <span>{{#_v.format_size}}{{downloadSpeed}}{{/_v.format_size}}</span>/s\n        / \n      <i class=\"icon-upload\"></i>  <span>{{#_v.format_size}}{{uploadSpeed}}{{/_v.format_size}}</span>/s\n    </script>\n\n    <script id=\"active-task-tpl\" type=\"text/mustache-template\">\n      {{#tasks}}\n      <li class=\"task\" id=\"task-gid-{{gid}}\" data-status=\"{{status}}\" data-gid=\"{{gid}}\">\n        <div class=\"left-area\">\n          <div class=\"task-name\">\n            <i class=\"select-box\"></i>\n            <span title=\"{{title}}\">{{title}}</span>\n          </div>\n          <div class=\"task-info\">\n            <span class=\"task-status\" rel=\"tooltip\" title=\"{{status}} {{#_v.error_msg}}{{errorCode}}{{/_v.error_msg}}\"><i class=\"{{#_v.status_icon}}{{status}}{{/_v.status_icon}}\"></i></span>\n            <span>{{#_v.format_size}}{{completedLength}}{{/_v.format_size}} / {{#_v.format_size}}{{totalLength}}{{/_v.format_size}}</span>\n            {{#uploadLength}}<span>(uploaded {{#_v.format_size}}{{uploadLength}}{{/_v.format_size}})</span>{{/uploadLength}}\n            {{#eta}}<span>ETA: {{#_v.format_time}}{{eta}}{{/_v.format_time}}</span>{{/eta}}\n          </div>\n        </div>\n        <div class=\"right-area\">\n          <div class=\"progress {{progressStatus}}\">\n            <div class=\"bar\" style=\"width: {{progress}}%\">{{progress}}%</div>\n          </div>\n          <div class=\"progress-info\">\n            {{#downloadSpeed}}<span class=\"download-speed\"><i class=\"icon-download\"></i> {{#_v.format_size}}{{downloadSpeed}}{{/_v.format_size}}/s</span>{{/downloadSpeed}}\n            {{#uploadSpeed}}<span class=\"upload-speed\"><i class=\"icon-upload\"></i> {{#_v.format_size}}{{uploadSpeed}}{{/_v.format_size}}/s</span>{{/uploadSpeed}}\n            {{#connections}}<span class=\"seeders\"><i class=\"icon-signal\" rel=\"tooltip\" title=\"Connections\"></i> {{connections}}</span>{{/connections}}\n            {{#numSeeders}}<span class=\"seeders\"><i class=\"icon-magnet\" rel=\"tooltip\" title=\"Seeders\"></i> {{numSeeders}}</span>{{/numSeeders}}\n          </div>\n        </div>\n      </li>\n      {{/tasks}}\n      {{^tasks}}\n      <li>\n        <div class=\"empty-tasks\">\n          <strong>无活动任务</strong>\n        </div>\n      </li>\n      {{/tasks}}\n    </script>\n    \n    <script id=\"other-task-tpl\" type=\"text/mustache-template\">\n      {{#tasks}}\n      <li class=\"task\" id=\"task-gid-{{gid}}\" data-status=\"{{status}}\" data-gid=\"{{gid}}\" data-infohash=\"{{infoHash}}\">\n        <div class=\"left-area\">\n          <div class=\"task-name\">\n            <i class=\"select-box\"></i>\n            <span title=\"{{title}}\">{{title}}</span>\n          </div>\n        </div>\n        <div class=\"right-area\">\n          <div class=\"task-info pull-left\">\n            <span class=\"task-status\" rel=\"tooltip\" title=\"{{status}} {{#_v.error_msg}}{{errorCode}}{{/_v.error_msg}}\"><i class=\"{{#_v.status_icon}}{{status}}{{/_v.status_icon}}\"></i></span>\n            <span>{{#_v.format_size}}{{totalLength}}{{/_v.format_size}}</span>\n            {{#uploadLength}}<span>(up {{#_v.format_size}}{{uploadLength}}{{/_v.format_size}})</span>{{/uploadLength}}\n          </div>\n          <div class=\"pull-right\">\n            <div class=\"progress {{progressStatus}}\">\n              <div class=\"bar\" style=\"width: {{progress}}%\">{{progress}}%</div>\n            </div>\n          </div>\n          <div class=\"clearfix\"></div>\n        </div>\n      </li>\n      {{/tasks}}\n    </script>\n\n    <script id=\"info-box-tpl\" type=\"text/mustache-template\">\n      <div class=\"info-box\" data-gid=\"{{gid}}\">\n        <div class=\"tabbable tabs-left\">\n          <ul class=\"nav nav-tabs\">\n            <li class=\"active\"><a href=\"#ib-status\" data-toggle=\"tab\">Status</a></li>\n            <li><a href=\"#ib-files\" data-toggle=\"tab\">Files</a></li>\n            <li><a id=\"ib-options-a\" href=\"#ib-options\" data-toggle=\"tab\">Options</a></li>\n            <li><a id=\"ib-peers-a\" class=\"hide\" style=\"display:none;\" href=\"#ib-peers\" data-toggle=\"tab\">Peers</a></li>\n          </ul>\n          <div class=\"tab-content\">\n            <div class=\"tab-pane active\" id=\"ib-status\"> </div>\n            <div class=\"tab-pane\" id=\"ib-files\">\n              <div id=\"ib-file-btn\">\n                <button id=\"ib-file-save\" class=\"btn btn-primary\">Save</button>\n              </div>\n              <div class=\"file-list\">\n              </div>\n            </div>\n            <div class=\"tab-pane\" id=\"ib-options\"> </div>\n            <div class=\"tab-pane\" id=\"ib-peers\"> </div>\n          </div>\n        </div>\n      </div>\n    </script>      \n\n    <script id=\"ib-status-tpl\" type=\"text/mustache-template\">\n      <ul>\n        {{#uris}}<li><strong>Url: </strong><a target=_blank href=\"{{.}}\">{{.}}</a>{{/uris}}\n        {{#infoHash}}<li><strong>Infohash: </strong><a target=_blank href=\"magnet:?xt=urn:btih:{{infoHash}}\">{{infoHash}}</a></li>{{/infoHash}}\n        <li><strong>Size: </strong>{{#_v.format_size}}{{totalLength}}{{/_v.format_size}} ({{numPieces}} @ {{#_v.format_size}}{{pieceLength}}{{/_v.format_size}})</li>\n        <li><strong>Status: </strong>{{status}} {{error_msg}}</li>\n        <li><strong>Dir: </strong>{{dir}}</li>\n        {{#bittorrent}}\n          {{#creationDate}}<li>Torrent Created At {{creationDate}}</li>{{/creationDate}}\n          {{#comment}}<li><strong>Comment: </strong>{{comment}}</li>{{/comment}}\n        {{/bittorrent}}\n        <li class=\"bitfield\"><strong>Bitfield: </strong>{{#_v.bitfield}}{{bitfield}}{{/_v.bitfield}}</li>\n      </ul>\n    </script>\n\n    <script id=\"file-tpl\" type=\"text/mustache-template\">\n        <li>\n          <i class=\"select-box{{#selected}} icon-ok{{/selected}}\" data-index=\"{{index}}\"></i>\n          <span class=\"ib-file-title\">{{relative_title}}</span>\n          <span class=\"ib-file-size\"> {{#_v.format_size}}{{completedLength}}{{/_v.format_size}} / {{#_v.format_size}}{{length}}{{/_v.format_size}}</span>\n        </li>\n    </script>\n\n    <script id=\"ib-options-tpl\" type=\"text/mustache-template\">\n      <form id=\"ib-options-form\" class=\"form-horizontal\" onsubmit=\"false\">\n      <ul>\n        <li id=\"ib-options-btn\">\n          <button id=\"ib-options-save\" class=\"btn btn-primary\">Save</button>\n        </li>\n        <li><span>Download Limit:</span><input name=\"max-download-limit\" class=\"active-allowed\" value=\"{{max-download-limit}}\" /></li>\n        <li><span>Upload Limit:</span><input name=\"max-upload-limit\" class=\"active-allowed\" value=\"{{max-upload-limit}}\" /></li>\n        <li><span>Split:</span><input name=\"split\" value=\"{{split}}\" /></li>\n        <li><span>Conn per Serv:</span><input name=\"max-connection-per-server\" value=\"{{max-connection-per-server}}\" /></li>\n        <li><span>Split Size:</span><input name=\"min-split-size\" value=\"{{min-split-size}}\" /></li>\n      </form>\n    </script>\n\n    <script id=\"ib-peers-tpl\" type=\"text/mustache-template\">\n      {{#.}}\n      <li><span class=\"ip_port\">{{ip}}:{{port}} - <span class=\"peerid\">{{#_v.format_peerid}}{{peerId}}{{/_v.format_peerid}}</span></span> <b>{{#_v.bitfield_to_percent}}{{bitfield}}{{/_v.bitfield_to_percent}}%</b> <i class=\"icon-download\"></i>{{#_v.format_size}}{{downloadSpeed}}{{/_v.format_size}}/s <i class=\"icon-upload\"></i>{{#_v.format_size}}{{uploadSpeed}}{{/_v.format_size}}/s</li>\n      {{/.}}\n    </script>\n\n    <script id=\"other-task-empty\" type=\"text/mustache-template\">\n      <li>\n        <div class=\"empty-tasks\">\n          <strong>无任务</strong>\n        </div>\n      </li>\n    </script>\n\n    <script id=\"add-task-option-tpl\" type=\"text/mustache-template\">\n      <hr />\n      <form id=\"add-task-option\" class=\"form-horizontal\" onsubmit=\"$('#add-task-uri').submit();return false\">\n\t  <input type=\"submit\" style=\"position:fixed;top:0;visibility:hidden\"/>\n        <div class=\"control-group\">\n          <label class=\"control-label\" for=\"ati-out\">File Name</label>\n          <div class=\"controls\">\n            <input id=\"ati-out\" class=\"input-xlarge input-clear\" name=\"out\" />\n          </div>\n        </div>\n        <div class=\"control-group\">\n          <label class=\"control-label\" for=\"ati-dir\">Dir</label>\n          <div class=\"controls\">\n            <input id=\"ati-dir\" class=\"input-xlarge\" name=\"dir\" />\n          </div>\n        </div>\n        <div class=\"clearfix\"></div>\n        <div class=\"control-group half\">\n          <div class=\"controls\">\n            <label class=\"checkbox\">\n              <input type=\"checkbox\" name=\"pause\" class=\"input-save\" {{#pause}}checked{{/pause}} />\n              Pause When Added\n            </label>\n          </div>\n        </div>\n        <div class=\"control-group half\">\n          <div class=\"controls\">\n            <label class=\"checkbox\">\n              <input type=\"checkbox\" name=\"parameterized-uri\" class=\"input-save\" {{#parameterized-uri}}checked{{/parameterized-uri}} />\n              Parameterized URI\n            </label>\n          </div>\n        </div>\n        <div class=\"clearfix\"></div>\n        <div class=\"control-group half\">\n          <label class=\"control-label\" for=\"ati-split\">Split</label>\n          <div class=\"controls\">\n            <input id=\"ati-split\" class=\"input-small input-save\" name=\"split\" value=\"{{split}}\" />\n          </div>\n        </div>\n        <div class=\"control-group half\">\n          <label class=\"control-label\" for=\"ati-cps\">Conn/Serv</label>\n          <div class=\"controls\">\n            <input id=\"ati-cps\" class=\"input-small input-save\" name=\"max-connection-per-server\" value=\"{{max-connection-per-server}}\" />\n          </div>\n        </div>\n        <div class=\"control-group half\">\n          <label class=\"control-label\" for=\"ati-sr\">Seed Ratio</label>\n          <div class=\"controls\">\n            <input id=\"ati-sr\" class=\"input-small input-save\" name=\"seed-ratio\" value=\"{{seed-ratio}}\" />\n          </div>\n        </div>\n        <div class=\"control-group half\">\n          <label class=\"control-label\" for=\"ati-st\">Seed Time</label>\n          <div class=\"controls\">\n            <input id=\"ati-st\" class=\"input-small input-save\" name=\"seed-time\" value=\"{{seed-time}}\" />\n          </div>\n        </div>\n        <div class=\"clearfix\"></div>\n        <div class=\"control-group\">\n          <label class=\"control-label\" for=\"ati-header\">Header</label>\n          <div class=\"controls\">\n            <textarea id=\"ati-header\" class=\"input-xlarge input-save\" name=\"header\" warp=\"off\">{{header}}</textarea>\n          </div>\n        </div>\n      </form>\n    </script>\n\n    <script id=\"aria2-global-setting-tpl\" type=\"text/mustache-template\">\n      <hr />\n      <form id=\"aria2-gs-form\" class=\"form-horizontal\" onsubmit=\"false\">\n        <div class=\"control-group half\">\n          <label class=\"control-label\" for=\"gsi-dl\">Download Limit</label>\n          <div class=\"controls\">\n            <input id=\"gsi-dl\" name=\"max-overall-download-limit\" class=\"input-small\" value=\"{{max-overall-download-limit}}\" />\n          </div>\n        </div>\n        <div class=\"control-group half\">\n          <label class=\"control-label\" for=\"gsi-ul\">Upload Limit</label>\n          <div class=\"controls\">\n            <input id=\"gsi-ul\" name=\"max-overall-upload-limit\" class=\"input-small\" value=\"{{max-overall-upload-limit}}\" />\n          </div>\n        </div>\n        <div class=\"control-group half\">\n          <label class=\"control-label\" for=\"gsi-cd\">Concurrent Downs</label>\n          <div class=\"controls\">\n            <input id=\"gsi-cd\" name=\"max-concurrent-downloads\" class=\"input-small\" value=\"{{max-concurrent-downloads}}\" />\n          </div>\n        </div>\n        <div class=\"control-group half\">\n          <label class=\"control-label\" for=\"gsi-mss\">Min Split Size</label>\n          <div class=\"controls\">\n            <input id=\"gsi-mss\" name=\"min-split-size\" class=\"input-small\" value=\"{{#_v.format_size_0}}{{min-split-size}}{{/_v.format_size_0}}\" />\n          </div>\n        </div>\n        <div class=\"clearfix\"></div>\n\n        <div class=\"control-group\">\n          <label class=\"control-label\" for=\"gsi-ua\">User Agent</label>\n          <div class=\"controls\">\n            <input id=\"gsi-ua\" name=\"user-agent\" class=\"input-xlarge\" value=\"{{user-agent}}\" />\n          </div>\n        </div>\n        <div class=\"control-group\">\n          <label class=\"control-label\" for=\"gsi-dir\">Base Dir</label>\n          <div class=\"controls\">\n            <input id=\"gsi-dir\" name=\"dir\" class=\"input-xlarge\" value=\"{{dir}}\" disabled />\n          </div>\n        </div>\n      </form>\n    </script>\n\n    <script src=\"https://cdn.jsdelivr.net/gh/xieqifei/StaticsResources@v1.0/oneindexn/common/offline/js/jquery-1.7.2.min.js\"></script>\n    <script src=\"https://cdn.jsdelivr.net/gh/xieqifei/StaticsResources@v1.0/oneindexn/common/offline/js/bootstrap.min.js\"></script>\n    <script src=\"https://cdn.jsdelivr.net/gh/xieqifei/StaticsResources@v1.0/oneindexn/common/offline/js/jquery.jsonrpc.js\"></script>\n    <script src=\"https://cdn.jsdelivr.net/gh/xieqifei/StaticsResources@v1.0/oneindexn/common/offline/js/jquery.Storage.js\"></script>\n    <script src=\"https://cdn.jsdelivr.net/gh/xieqifei/StaticsResources@v1.0/oneindexn/common/offline/js/jquery.base64.min.js\"></script>\n    <script src=\"https://cdn.jsdelivr.net/gh/xieqifei/StaticsResources@v1.0/oneindexn/common/offline/js/mustache.js\"></script>\n    <script src=\"https://cdn.jsdelivr.net/gh/xieqifei/StaticsResources@v1.0/oneindexn/common/offline/js/peerid.js\"></script>\n    <script src=\"https://cdn.jsdelivr.net/gh/xieqifei/StaticsResources@v1.0/oneindexn/common/offline/js/aria2.js\"></script>\n    <script src=\"https://cdn.jsdelivr.net/gh/xieqifei/StaticsResources@v1.0/oneindexn/common/offline/js/yaaw-1.1.js\"></script>\n  </body>\n<?php view::end('content');?>\n"
  },
  {
    "path": "view/common/search.php",
    "content": "<?php view::layout('themes/'.(config('style')?config('style'):'material').'/layout')?>\n<?php \n\tfunction file_ico($item){\n\t$ext = strtolower(pathinfo($item['name'], PATHINFO_EXTENSION));\n\tif(in_array($ext,['bmp','jpg','jpeg','png','gif'])){\n\t\treturn \"image\";\n\t}\n\tif(in_array($ext,['mp4','mkv','webm','avi','mpg', 'mpeg', 'rm', 'rmvb', 'mov', 'wmv', 'mkv', 'asf'])){\n\t\treturn \"ondemand_video\";\n\t}\n\tif(in_array($ext,['ogg','mp3','wav'])){\n\t\treturn \"audiotrack\";\n\t}\n\treturn \"insert_drive_file\";\n\t}\n?>\n<?php view::begin('content');?>\n<?php if(is_login()):?>\n\t<div class=\"mdui-container-fluid\" >\n\t\t<div class=\"nexmoe-item\">\n\t\t<button class=\"mdui-btn mdui-ripple\" id=\"pagesearch\">过滤</button>\n\t\t<button class=\"mdui-btn mdui-ripple singleopt\" id=\"rename\" style=\"display: none;\">重命名</button>\n\t\t<button class=\"mdui-btn mdui-ripple multiopt\" id=\"deleteall\" style=\"display: none;\">删除</button>\n\t\t<button class=\"mdui-btn mdui-ripple multiopt\" id=\"copybtn\" onclick=\"copy()\" style=\"display: none;\">复制</button>\n\t\t<button class=\"mdui-btn mdui-ripple multiopt\" id=\"cutbtn\" onclick=\"cut()\" style=\"display: none;\">剪切</button>\n\t\t<button class=\"mdui-btn mdui-ripple multiopt\" id=\"sharebtn\" style=\"display: none;\">分享</button>\n\t\t</div>\n\t</div>\n<?php endif;?> \n\n\n<div class=\"mdui-container-fluid\">\n\t<style>\n\t.thumb .th{\n\t\tdisplay: none;\n\t}\n\t.thumb .mdui-text-right{\n\t\tdisplay: none;\n\t}\n\t.thumb .mdui-list-item a ,.thumb .mdui-list-item {\n\t\twidth:217px;\n\t\theight: 230px;\n\t\tfloat: left;\n\t\tmargin: 10px 10px !important;\n\t}\n\n\t.thumb .mdui-col-xs-12,.thumb .mdui-col-sm-7{\n\t\twidth:100% !important;\n\t\theight:230px;\n\t}\n\n\t.thumb .mdui-list-item .mdui-icon{\n\t\tfont-size:100px;\n\t\tdisplay: block;\n\t\tmargin-top: 40px;\n\t\tcolor: #7ab5ef;\n\t}\n\t.thumb .mdui-list-item span{\n\t\tfloat: left;\n\t\tdisplay: block;\n\t\ttext-align: center;\n\t\twidth:100%;\n\t\tposition: absolute;\n\t\ttop: 180px;\n\t}\n\t/*loading动画*/\n\t.simple-spinner {\n\theight: 100%;\n\tborder: 8px solid rgba(150, 150, 150, 0.2);\n\tborder-radius: 50%;\n\tborder-top-color: rgb(150, 150, 150);\n\tanimation: rotate 1s 0s infinite ease-in-out alternate;\n\t}\n\t@keyframes rotate {\n\t0%   { transform: rotate(0);      }\n\t100% { transform: rotate(360deg); }\n\t}\n\t</style>\n\n\t<div class=\"nexmoe-item\">\n\t\t<div class=\"mdui-row\">\n\t\t\t<ul class=\"mdui-list\">\n\t\t\t\t<li class=\"mdui-list-item th\">\n\t\t\t\t\t<?php if(is_login()):?>\n\t\t\t\t\t\t<label class=\"mdui-checkbox\"><input type=\"checkbox\" value=\"\" id=\"checkall\" onclick=\"checkall()\"><i\n\t\t\t\t\t\t\t\tclass=\"mdui-checkbox-icon\"></i></label>\n\t\t\t\t\t\t<?php endif;?> \n\t\t\t\t\t<div class=\"mdui-col-xs-12 mdui-col-sm-7\">文件 <i class=\"mdui-icon material-icons icon-sort\" data-sort=\"name\" data-order=\"downward\">expand_more</i></div>\n\t\t\t\t\t<div class=\"mdui-col-sm-3 mdui-text-right\">修改时间 <i class=\"mdui-icon material-icons icon-sort\" data-sort=\"date\" data-order=\"downward\">expand_more</i></div>\n\t\t\t\t\t<div class=\"mdui-col-sm-2 mdui-text-right\">大小 <i class=\"mdui-icon material-icons icon-sort\" data-sort=\"size\" data-order=\"downward\">expand_more</i></div>\n\t\t\t\t</li>\n\t\t\t\t\n\t\t\t\t<?php foreach($items as $item):?>\n\t\t\t\t\t<?php if(!empty($item['folder'])):?>\n\t\t\t\t\t\t<li class=\"mdui-list-item mdui-ripple\" data-sort \n\t\t\t\t\t\t\t\t\tdata-sort-name=\"<?php echo $item['name'] ;?>\"\n\t\t\t\t\t\t\t\t\tdata-sort-date=\"<?php echo $item['lastModifiedDateTime'];?>\"\n\t\t\t\t\t\t\t\t\tdata-sort-size=\"<?php echo $item['size'];?>\" \n\t\t\t\t\t\t\t\t\tid=\"<?php echo $item[\"id\"] ?>\">\n\t\t\t\t\t\t\t<div class=\"simple-spinner loading-gif\" style=\"display: none;\"></div>\n\t\t\t\t\t\t\t<?php if(is_login()):?>\n\t\t\t\t\t\t\t\t<label class=\"mdui-checkbox\">\n\t\t\t\t\t\t\t\t<input type=\"checkbox\" value=\"<?php echo $item[\"id\"] ?>\" name=\"itemid\" onclick=\"onClickHander()\">\n\t\t\t\t\t\t\t\t<i class=\"mdui-checkbox-icon\"></i></label>\n\t\t\t\t\t\t\t<?php endif;?> \t\t\n\t\t\t\t\t\t\t<a href=\"<?php echo $item['path'];?>\" target=\"_blank\">\n\t\t\t\t\t\t\t<div class=\"mdui-col-xs-12 mdui-col-sm-7 mdui-text-truncate\">\n\t\t\t\t\t\t\t\t<i class=\"mdui-icon material-icons\">folder_open</i>\n\t\t\t\t\t\t\t\t<span><?php echo $item['name'];?></span>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div class=\"mdui-col-sm-3 mdui-text-right\"><?php echo date(\"Y-m-d H:i:s\", $item['lastModifiedDateTime']);?></div>\n\t\t\t\t\t\t\t<div class=\"mdui-col-sm-2 mdui-text-right\"><?php echo onedrive::human_filesize($item['size']);?></div>\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t</li>\n\t\t\t\t\t<?php else:?>\n\t\t\t\t\t\t<li class=\"mdui-list-item file mdui-ripple\" data-sort\n\t\t\t\t\t\t\t\t\tdata-sort-name=\"<?php echo $item['name'];?>\"\n\t\t\t\t\t\t\t\t\tdata-sort-date=\"<?php echo $item['lastModifiedDateTime'];?>\"\n\t\t\t\t\t\t\t\t\tdata-sort-size=\"<?php echo $item['size'];?>\" \n\t\t\t\t\t\t\t\t\tid=\"<?php echo $item[\"id\"] ?>\">\n\t\t\t\t\t\t\t<div class=\"simple-spinner loading-gif\" style=\"display: none;\"></div>\n\t\t\t\t\t\t\t<?php if(is_login()):?>\n\t\t\t\t\t\t\t\t<label class=\"mdui-checkbox\">\n\t\t\t\t\t\t\t\t<input type=\"checkbox\" value=\"<?php echo $item[\"id\"] ?>\" name=\"itemid\" onclick=\"onClickHander()\">\n\t\t\t\t\t\t\t\t<i class=\"mdui-checkbox-icon\"></i></label>\n\t\t\t\t\t\t\t<?php endif;?> \t\n\t\t\t\t\t\t\t<a href=\"<?php echo $item['path'];?>\" target=\"_blank\">\n\t\t\t\t\t\t\t<div class=\"mdui-col-xs-12 mdui-col-sm-7 mdui-text-truncate\">\n\t\t\t\t\t\t\t\t<i class=\"mdui-icon material-icons\"><?php echo file_ico($item);?></i>\n\t\t\t\t\t\t\t\t<span><?php e($item['name']);?></span>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t<div class=\"mdui-col-sm-3 mdui-text-right\"><?php echo date(\"Y-m-d H:i:s\", $item['lastModifiedDateTime']);?></div>\n\t\t\t\t\t\t\t<div class=\"mdui-col-sm-2 mdui-text-right\"><?php echo onedrive::human_filesize($item['size']);?></div>\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t</li>\n\t\t\t\t\t<?php endif;?>\n\t\t\t\t<?php endforeach;?>\n\t\t\t</ul>\n\t\t</div>\n\t</div>\n</div>\n\n\n<div class=\"mdui-container\">\n <div class=\"mdui-dialog\" id=\"search_form\">\n    <div class=\"mdui-dialog-content\">\n\t\t<form action=\"?/search\" method=\"post\">\n\t\t\t<div class=\"mdui-textfield mdui-textfield-floating-label\">\n\t\t\t\t<label class=\"mdui-textfield-label\">输入关键词</label>\n\t\t\t\t<input class=\"mdui-textfield-input\" type=\"text\" style=\"margin: 50px 0;\" name=\"keyword\" />\n\t\t\t\t<div class=\"mdui-row-xs-3\">\n\t\t\t\t<div class=\"mdui-col\"></div>\n\t\t\t\t\t<div class=\"mdui-col\">\n\t\t\t\t\t\t<button class=\"mdui-btn mdui-btn-block mdui-color-theme-accent mdui-ripple\">提交</button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</form>\n\t</div>\n\n    <div class=\"mdui-dialog-actions\">\n      <button class=\"mdui-btn mdui-ripple\" mdui-dialog-cancel>取消</button>\n    </div>\n  </div>\n</div>\n<div class=\"mdui-container\">\n <div class=\"mdui-dialog\" id=\"share\">\n    <div class=\"mdui-dialog-content\">\n\t\t\t<div class=\"mdui-textfield mdui-textfield-floating-label\">\n\t\t\t\t<label class=\"mdui-textfield-label\">选中的项目链接</label>\n\t\t\t\t<textarea class=\"mdui-textfield-input\" style=\"margin: 20px 0;\" rows=\"5\" readonly id=\"sharelinks\"></textarea>\n\t\t\t</div>\n\t</div>\n  </div>\n</div>\n<script src=\"https://cdn.jsdelivr.net/gh/xieqifei/StaticsResources@v1.0/oneindexn/common/search/js/search.js\"></script>\n<?php view::end('content');?>"
  },
  {
    "path": "view/common/tips.php",
    "content": "<?php view::layout('themes/'.(config('style')?config('style'):'material').'/layout')?>\n\n<?php view::begin('content');?>\n    <div class=\"mdui-typo-display-2\" style=\"margin: 100px auto;text-align: center;\"><?php echo $tip ?></div>\n<?php view::end('content');?>"
  },
  {
    "path": "view/themes/classic/404.php",
    "content": "<!DOCTYPE html>\n<html>\n\t<head>\n\t    <meta charset=\"utf-8\" />\n\t\t<title>404 Not Found</title>\n\t\t<meta charset=\"utf-8\">\n        <style>\n\t\t*{box-sizing:border-box}h1{border-bottom:1px solid silver;margin-bottom:10px;padding-bottom:10px;white-space:nowrap}table{border-collapse:collapse;font-family:Consolas,monaco,monospace}th{font-weight:700}.file-name{text-align:left}.file-size{padding-left:4em}.file-date-created,.file-date-modified{padding-left:2em}.file-date-created,.file-date-modified,.file-size{text-align:end;white-space:nowrap}.icon{padding-left:1.5em;text-decoration:none}.icon:hover{text-decoration:underline}.icon-file{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAABnRSTlMAAAAAAABupgeRAAABHUlEQVR42o2RMW7DIBiF3498iHRJD5JKHurL+CRVBp+i2T16tTynF2gO0KSb5ZrBBl4HHDBuK/WXACH4eO9/CAAAbdvijzLGNE1TVZXfZuHg6XCAQESAZXbOKaXO57eiKG6ft9PrKQIkCQqFoIiQFBGlFIB5nvM8t9aOX2Nd18oDzjnPgCDpn/BH4zh2XZdlWVmWiUK4IgCBoFMUz9eP6zRN75cLgEQhcmTQIbl72O0f9865qLAAsURAAgKBJKEtgLXWvyjLuFsThCSstb8rBCaAQhDYWgIZ7myM+TUBjDHrHlZcbMYYk34cN0YSLcgS+wL0fe9TXDMbY33fR2AYBvyQ8L0Gk8MwREBrTfKe4TpTzwhArXWi8HI84h/1DfwI5mhxJamFAAAAAElFTkSuQmCC) left top no-repeat}.icon-dir{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAd5JREFUeNqMU79rFUEQ/vbuodFEEkzAImBpkUabFP4ldpaJhZXYm/RiZWsv/hkWFglBUyTIgyAIIfgIRjHv3r39MePM7N3LcbxAFvZ2b2bn22/mm3XMjF+HL3YW7q28YSIw8mBKoBihhhgCsoORot9d3/ywg3YowMXwNde/PzGnk2vn6PitrT+/PGeNaecg4+qNY3D43vy16A5wDDd4Aqg/ngmrjl/GoN0U5V1QquHQG3q+TPDVhVwyBffcmQGJmSVfyZk7R3SngI4JKfwDJ2+05zIg8gbiereTZRHhJ5KCMOwDFLjhoBTn2g0ghagfKeIYJDPFyibJVBtTREwq60SpYvh5++PpwatHsxSm9QRLSQpEVSd7/TYJUb49TX7gztpjjEffnoVw66+Ytovs14Yp7HaKmUXeX9rKUoMoLNW3srqI5fWn8JejrVkK0QcrkFLOgS39yoKUQe292WJ1guUHG8K2o8K00oO1BTvXoW4yasclUTgZYJY9aFNfAThX5CZRmczAV52oAPoupHhWRIUUAOoyUIlYVaAa/VbLbyiZUiyFbjQFNwiZQSGl4IDy9sO5Wrty0QLKhdZPxmgGcDo8ejn+c/6eiK9poz15Kw7Dr/vN/z6W7q++091/AQYA5mZ8GYJ9K0AAAAAASUVORK5CYII=) left top no-repeat}.icon-up{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAmlJREFUeNpsU0toU0EUPfPysx/tTxuDH9SCWhUDooIbd7oRUUTMouqi2iIoCO6lceHWhegy4EJFinWjrlQUpVm0IIoFpVDEIthm0dpikpf3ZuZ6Z94nrXhhMjM3c8895977BBHB2PznK8WPtDgyWH5q77cPH8PpdXuhpQT4ifR9u5sfJb1bmw6VivahATDrxcRZ2njfoaMv+2j7mLDn93MPiNRMvGbL18L9IpF8h9/TN+EYkMffSiOXJ5+hkD+PdqcLpICWHOHc2CC+LEyA/K+cKQMnlQHJX8wqYG3MAJy88Wa4OLDvEqAEOpJd0LxHIMdHBziowSwVlF8D6QaicK01krw/JynwcKoEwZczewroTvZirlKJs5CqQ5CG8pb57FnJUA0LYCXMX5fibd+p8LWDDemcPZbzQyjvH+Ki1TlIciElA7ghwLKV4kRZstt2sANWRjYTAGzuP2hXZFpJ/GsxgGJ0ox1aoFWsDXyyxqCs26+ydmagFN/rRjymJ1898bzGzmQE0HCZpmk5A0RFIv8Pn0WYPsiu6t/Rsj6PauVTwffTSzGAGZhUG2F06hEc9ibS7OPMNp6ErYFlKavo7MkhmTqCxZ/jwzGA9Hx82H2BZSw1NTN9Gx8ycHkajU/7M+jInsDC7DiaEmo1bNl1AMr9ASFgqVu9MCTIzoGUimXVAnnaN0PdBBDCCYbEtMk6wkpQwIG0sn0PQIUF4GsTwLSIFKNqF6DVrQq+IWVrQDxAYQC/1SsYOI4pOxKZrfifiUSbDUisif7XlpGIPufXd/uvdvZm760M0no1FZcnrzUdjw7au3vu/BVgAFLXeuTxhTXVAAAAAElFTkSuQmCC) left top no-repeat}\n        </style>\n\t</head>\n\t<body>\n        <h1><?php echo $path;?> is not found.</h1>\n\t</body>\n</html>"
  },
  {
    "path": "view/themes/classic/layout.php",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<meta charset=\"utf-8\">\n\t<title><?php _($title);?></title>\n\t<link rel=\"stylesheet\" href=\"//cdnjs.loli.net/ajax/libs/mdui/0.4.3/css/mdui.min.css\">\n\t<script src=\"https://cdn.jsdelivr.net/gh/xieqifei/StaticsResources/oneindexn/mdui/mdui.min.js\"></script>\n\t<style>\n\t\t.mdui-appbar .mdui-toolbar{\n\t\t\t/*height:56px;*/\n\t\t\tfont-size: 16px;\n\t\t}\n\t\t.mdui-toolbar>*{\n\t\t\tpadding: 0 16px;\n\t\t\tmargin: 0 2px;\n\t\t\topacity:0.5;\n\t\t}\n\t\t.mdui-toolbar>.mdui-typo-headline{\n\t\t\tpadding: 0 16px 0 0;\n\t\t}\n\t\t.mdui-toolbar>i{\n\t\t\tpadding: 0;\n\t\t}\n\t\t.mdui-toolbar>a:hover,a.mdui-typo-headline,a.active{\n\t\t\topacity:1;\n\t\t}\n\t\t.mdui-container{\n\t\t\tmax-width:980px;\n\t\t}\n\t</style>\n</head>\n<body class=\"mdui-theme-primary-blue-grey mdui-theme-accent-blue\">\n\t<header class=\"mdui-appbar mdui-color-theme\">\n\t\t<div class=\"mdui-toolbar mdui-container\">\n\t\t\t<a href=\"/\" class=\"mdui-typo-headline\">oneindex</a>\n\t\t\t<i class=\"mdui-icon material-icons mdui-icon-dark\" style=\"margin:0;\">chevron_right</i>\n\t\t\t<a href=\"javascript:;\" >admin</a>\n\t\t\t<i class=\"mdui-icon material-icons mdui-icon-dark\" style=\"margin:0;\">chevron_right</i>\n\t\t\t<a href=\"javascript:;\" class=\"active\">setpass</a>\n\t\t\t<div class=\"mdui-toolbar-spacer\"></div>\n\t\t\t<a href=\"javascript:;\" class=\"mdui-btn mdui-btn-icon\"><i class=\"mdui-icon material-icons\">refresh</i></a>\n\t\t</div>\n\t</header>\n\t\n\t<div class=\"mdui-container\">\n    \t<?php view::section('content');?>\n  \t</div>\n\n\t\n</body>\n</html>"
  },
  {
    "path": "view/themes/classic/list.php",
    "content": "<!DOCTYPE html>\n<html>\n    <head>\n\t    <title>Index of <?php echo urldecode($path);?></title>\n        <meta charset=\"utf-8\">\n        <style>\n\t\t*{box-sizing:border-box}h1{border-bottom:1px solid silver;margin-bottom:10px;padding-bottom:10px;white-space:nowrap}table{border-collapse:collapse;font-family:Consolas,monaco,monospace}th{font-weight:700}.file-name{text-align:left}.file-size{padding-left:4em}.file-date-created,.file-date-modified{padding-left:2em}.file-date-created,.file-date-modified,.file-size{text-align:end;white-space:nowrap}.icon{padding-left:1.5em;text-decoration:none}.icon:hover{text-decoration:underline}.icon-file{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAABnRSTlMAAAAAAABupgeRAAABHUlEQVR42o2RMW7DIBiF3498iHRJD5JKHurL+CRVBp+i2T16tTynF2gO0KSb5ZrBBl4HHDBuK/WXACH4eO9/CAAAbdvijzLGNE1TVZXfZuHg6XCAQESAZXbOKaXO57eiKG6ft9PrKQIkCQqFoIiQFBGlFIB5nvM8t9aOX2Nd18oDzjnPgCDpn/BH4zh2XZdlWVmWiUK4IgCBoFMUz9eP6zRN75cLgEQhcmTQIbl72O0f9865qLAAsURAAgKBJKEtgLXWvyjLuFsThCSstb8rBCaAQhDYWgIZ7myM+TUBjDHrHlZcbMYYk34cN0YSLcgS+wL0fe9TXDMbY33fR2AYBvyQ8L0Gk8MwREBrTfKe4TpTzwhArXWi8HI84h/1DfwI5mhxJamFAAAAAElFTkSuQmCC) left top no-repeat}.icon-dir{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAd5JREFUeNqMU79rFUEQ/vbuodFEEkzAImBpkUabFP4ldpaJhZXYm/RiZWsv/hkWFglBUyTIgyAIIfgIRjHv3r39MePM7N3LcbxAFvZ2b2bn22/mm3XMjF+HL3YW7q28YSIw8mBKoBihhhgCsoORot9d3/ywg3YowMXwNde/PzGnk2vn6PitrT+/PGeNaecg4+qNY3D43vy16A5wDDd4Aqg/ngmrjl/GoN0U5V1QquHQG3q+TPDVhVwyBffcmQGJmSVfyZk7R3SngI4JKfwDJ2+05zIg8gbiereTZRHhJ5KCMOwDFLjhoBTn2g0ghagfKeIYJDPFyibJVBtTREwq60SpYvh5++PpwatHsxSm9QRLSQpEVSd7/TYJUb49TX7gztpjjEffnoVw66+Ytovs14Yp7HaKmUXeX9rKUoMoLNW3srqI5fWn8JejrVkK0QcrkFLOgS39yoKUQe292WJ1guUHG8K2o8K00oO1BTvXoW4yasclUTgZYJY9aFNfAThX5CZRmczAV52oAPoupHhWRIUUAOoyUIlYVaAa/VbLbyiZUiyFbjQFNwiZQSGl4IDy9sO5Wrty0QLKhdZPxmgGcDo8ejn+c/6eiK9poz15Kw7Dr/vN/z6W7q++091/AQYA5mZ8GYJ9K0AAAAAASUVORK5CYII=) left top no-repeat}.icon-up{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAmlJREFUeNpsU0toU0EUPfPysx/tTxuDH9SCWhUDooIbd7oRUUTMouqi2iIoCO6lceHWhegy4EJFinWjrlQUpVm0IIoFpVDEIthm0dpikpf3ZuZ6Z94nrXhhMjM3c8895977BBHB2PznK8WPtDgyWH5q77cPH8PpdXuhpQT4ifR9u5sfJb1bmw6VivahATDrxcRZ2njfoaMv+2j7mLDn93MPiNRMvGbL18L9IpF8h9/TN+EYkMffSiOXJ5+hkD+PdqcLpICWHOHc2CC+LEyA/K+cKQMnlQHJX8wqYG3MAJy88Wa4OLDvEqAEOpJd0LxHIMdHBziowSwVlF8D6QaicK01krw/JynwcKoEwZczewroTvZirlKJs5CqQ5CG8pb57FnJUA0LYCXMX5fibd+p8LWDDemcPZbzQyjvH+Ki1TlIciElA7ghwLKV4kRZstt2sANWRjYTAGzuP2hXZFpJ/GsxgGJ0ox1aoFWsDXyyxqCs26+ydmagFN/rRjymJ1898bzGzmQE0HCZpmk5A0RFIv8Pn0WYPsiu6t/Rsj6PauVTwffTSzGAGZhUG2F06hEc9ibS7OPMNp6ErYFlKavo7MkhmTqCxZ/jwzGA9Hx82H2BZSw1NTN9Gx8ycHkajU/7M+jInsDC7DiaEmo1bNl1AMr9ASFgqVu9MCTIzoGUimXVAnnaN0PdBBDCCYbEtMk6wkpQwIG0sn0PQIUF4GsTwLSIFKNqF6DVrQq+IWVrQDxAYQC/1SsYOI4pOxKZrfifiUSbDUisif7XlpGIPufXd/uvdvZm760M0no1FZcnrzUdjw7au3vu/BVgAFLXeuTxhTXVAAAAAElFTkSuQmCC) left top no-repeat}\n        </style>\n    </head>\n    <body>\n\t\t<h1 id=\"heading\">Index of <?php echo urldecode($path);?></h1>\n\t\t<table id=\"table\">\n\t\t\t<tr><th class=\"file-name\">Name</th><th class=\"file-size\">Size</th><th class=\"file-date-created\">Date Created</th><th class=\"file-date-modified\">Date Modified</th></tr>\n\t\t\t<?php if($path != '/'):?>\n\t\t\t\t<tr>\n\t\t\t\t\t<td class=\"file-name\">\n\t\t\t\t\t\t<a class=\"icon icon-up\" href=\"<?php echo get_absolute_path($root.$path.'../');?>\">..</a>\n\t\t\t\t\t</td>\n\t\t\t\t\t<td class=\"file-size\"></td>\n\t\t\t\t\t<td class=\"file-date-modified\"></td>\n\t\t\t\t</tr>\n\t\t\t<?php endif;?>\n\t\t\t<?php foreach((array)$items as $item):?>\n\t\t\t\t<?php if(!empty($item['folder'])):?>\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t<td class=\"file-name\"><a class=\"icon icon-dir\" href=\"<?php echo get_absolute_path($root.$path.rawurlencode($item['name']));?>\"><?php echo $item['name'];?>/</a></td>\n\t\t\t\t\t\t<td class=\"file-size\"><?php echo onedrive::human_filesize($item['size']);?></td>\n\t\t\t\t\t\t<td class=\"file-date-modified\"><?php echo date(\"Y-m-d H:i:s\", $item['lastModifiedDateTime']);?></td>\n\t\t\t\t\t</tr>\n\t\t\t\t<?php else:?>\n\t\t\t\t\t<tr>\n\t\t\t\t\t\t<td class=\"file-name\"><a class=\"icon icon-file\" href=\"<?php echo get_absolute_path($root.$path).rawurlencode($item['name']);?>\"><?php echo $item['name'];?></a></td>\n\t\t\t\t\t\t<td class=\"file-size\"><?php echo onedrive::human_filesize($item['size']);?></td>\n\t\t\t\t\t\t<td class=\"file-date-modified\"><?php echo date(\"Y-m-d H:i:s\", $item['lastModifiedDateTime']);?></td>\n\t\t\t\t\t</tr>\n\t\t\t\t<?php endif;?>\n\t\t\t<?php endforeach;?>\n\t\t</table>\n    </body>\n</html>"
  },
  {
    "path": "view/themes/material/404.php",
    "content": "<?php view::layout('layout')?>\n\n<?php view::begin('content');?>\n\t<div class=\"mdui-typo-display-4\" style=\"margin: 100px auto;text-align: center;\">404 not found.</div>\n<?php view::end('content');?>"
  },
  {
    "path": "view/themes/material/images/index.php",
    "content": "<?php view::layout('layout')?>\n\n<?php view::begin('content');?>\n\t\n<div class=\"mdui-container-fluid\" style=\"padding-top: 100px;\">\n\n<center>\n\t<div class=\"mdui-typo-display-3-opacity\">OneImages</div>\n</center>\n\n\n<center>\n\t<form action=\"\" method=\"post\" enctype=\"multipart/form-data\">\n\t\t<input type=\"file\" style=\"margin: 50px 0;\" name=\"file\" />\n\n\n\t<div class=\"mdui-row-xs-3\">\n\t  <div class=\"mdui-col\"></div>\n\t  <div class=\"mdui-col\">\n\t    <button class=\"mdui-btn mdui-btn-block mdui-color-theme-accent mdui-ripple\">上传</button>\n\t  </div>\n\t</div>\n\n\t</form>\n</center>\n\n</div>\n\n<?php view::end('content');?>"
  },
  {
    "path": "view/themes/material/images/layout.php",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<meta charset=\"utf-8\">\n\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0,maximum-scale=1.0, user-scalable=no\"/>\n\t<title><?php e($title.' - '.config('site_name'));?></title>\n\t<link rel=\"stylesheet\" href=\"//cdnjs.loli.net/ajax/libs/mdui/0.4.3/css/mdui.min.css\">\n\t<script src=\"https://cdn.jsdelivr.net/gh/xieqifei/StaticsResources/oneindexn/mdui/mdui.min.js\"></script>\n\t<style>\n\t\t.mdui-appbar .mdui-toolbar{\n\t\t\theight:56px;\n\t\t\tfont-size: 16px;\n\t\t}\n\t\t.mdui-toolbar>*{\n\t\t\tpadding: 0 6px;\n\t\t\tmargin: 0 2px;\n\t\t\topacity:0.5;\n\t\t}\n\t\t.mdui-toolbar>.mdui-typo-headline{\n\t\t\tpadding: 0 16px 0 0;\n\t\t}\n\t\t.mdui-toolbar>i{\n\t\t\tpadding: 0;\n\t\t}\n\t\t.mdui-toolbar>a:hover,a.mdui-typo-headline,a.active{\n\t\t\topacity:1;\n\t\t}\n\t\t.mdui-container{\n\t\t\tmax-width:980px;\n\t\t}\n\t\t.mdui-list-item{\n\t\t\t-webkit-transition:none;\n\t\t\ttransition:none;\n\t\t}\n\t\t.mdui-list>.th{\n\t\t\tbackground-color:initial;\n\t\t}\n\t\t.mdui-list-item>a{\n\t\t\twidth:100%;\n\t\t\tline-height: 48px\n\t\t}\n\t\t.mdui-list-item{\n\t\t\tmargin: 2px 0px;\n\t\t\tpadding:0;\n\t\t}\n\t\t.mdui-toolbar>a:last-child{\n\t\t\topacity:1;\n\t\t}\n\t\t@media screen and (max-width:980px){\n\t\t\t.mdui-list-item .mdui-text-right{\n\t\t\t\tdisplay: none;\n\t\t\t}\n\t\t\t.mdui-container{\n\t\t\t\twidth:100% !important;\n\t\t\t\tmargin:0px;\n\t\t\t}\n\t\t\t.mdui-toolbar>*{\n\t\t\t\tdisplay: none;\n\t\t\t}\n\t\t\t.mdui-toolbar>a:last-child,.mdui-toolbar>.mdui-typo-headline,.mdui-toolbar>i:first-child{\n\t\t\t\tdisplay: block;\n\t\t\t}\n\t\t}\n\t</style>\n</head>\n<body class=\"mdui-theme-primary-blue-grey mdui-theme-accent-blue\">\n\t<header class=\"mdui-appbar mdui-color-theme\">\n\t\t<div class=\"mdui-toolbar mdui-container\">\n\t\t\t<a href=\"/\" class=\"mdui-typo-headline\"><?php e(config('site_name'));?></a>\n\t\t\t<?php foreach((array)$navs as $n=>$l):?>\n\t\t\t<i class=\"mdui-icon material-icons mdui-icon-dark\" style=\"margin:0;\">chevron_right</i>\n\t\t\t<a href=\"<?php e($l);?>\"><?php e($n);?></a>\n\t\t\t<?php endforeach;?>\n\t\t\t<!--<a href=\"javascript:;\" class=\"mdui-btn mdui-btn-icon\"><i class=\"mdui-icon material-icons\">refresh</i></a>-->\n\t\t</div>\n\t</header>\n\t\n\t<div class=\"mdui-container\">\n    \t<?php view::section('content');?>\n  \t</div>\n</body>\n</html>"
  },
  {
    "path": "view/themes/material/layout.php",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<meta charset=\"utf-8\">\n\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0,maximum-scale=1.0, user-scalable=no\"/>\n\t<title><?php e($title.' - '.config('site_name'));?></title>\n\t<link rel=\"stylesheet\" href=\"//cdnjs.loli.net/ajax/libs/mdui/0.4.3/css/mdui.min.css\">s\n\t<script src=\"https://cdn.jsdelivr.net/gh/xieqifei/StaticsResources/oneindexn/mdui/mdui.min.js\"></script>\n\t<style>\n\t\t.mdui-appbar .mdui-toolbar{\n\t\t\theight:56px;\n\t\t\tfont-size: 16px;\n\t\t}\n\t\t.mdui-toolbar>*{\n\t\t\tpadding: 0 6px;\n\t\t\tmargin: 0 2px;\n\t\t\topacity:0.5;\n\t\t}\n\t\t.mdui-toolbar>.mdui-typo-headline{\n\t\t\tpadding: 0 16px 0 0;\n\t\t}\n\t\t.mdui-toolbar>i{\n\t\t\tpadding: 0;\n\t\t}\n\t\t.mdui-toolbar>a:hover,a.mdui-typo-headline,a.active{\n\t\t\topacity:1;\n\t\t}\n\t\t.mdui-container{\n\t\t\tmax-width:980px;\n\t\t}\n\t\t.mdui-list-item{\n\t\t\t-webkit-transition:none;\n\t\t\ttransition:none;\n\t\t}\n\t\t.mdui-list>.th{\n\t\t\tbackground-color:initial;\n\t\t}\n\t\t.mdui-list-item>a{\n\t\t\twidth:100%;\n\t\t\tline-height: 48px\n\t\t}\n\t\t.mdui-list-item{\n\t\t\tmargin: 2px 0px;\n\t\t\tpadding:0;\n\t\t}\n\t\t.mdui-toolbar>a:last-child{\n\t\t\topacity:1;\n\t\t}\n\t\t@media screen and (max-width:980px){\n\t\t\t.mdui-list-item .mdui-text-right{\n\t\t\t\tdisplay: none;\n\t\t\t}\n\t\t\t.mdui-container{\n\t\t\t\twidth:100% !important;\n\t\t\t\tmargin:0px;\n\t\t\t}\n\t\t\t.mdui-toolbar>*{\n\t\t\t\tdisplay: none;\n\t\t\t}\n\t\t\t.mdui-toolbar>a:last-child,.mdui-toolbar>.mdui-typo-headline,.mdui-toolbar>i:first-child{\n\t\t\t\tdisplay: block;\n\t\t\t}\n\t\t}\n\t</style>\n</head>\n<body class=\"mdui-theme-primary-blue-grey mdui-theme-accent-blue\">\n\t<header class=\"mdui-appbar mdui-color-theme\">\n\t\t<div class=\"mdui-toolbar mdui-container\">\n\t\t\t<a href=\"/\" class=\"mdui-typo-headline\"><?php e(config('site_name'));?></a>\n\t\t\t<?php foreach((array)$navs as $n=>$l):?>\n\t\t\t<i class=\"mdui-icon material-icons mdui-icon-dark\" style=\"margin:0;\">chevron_right</i>\n\t\t\t<a href=\"<?php e($l);?>\"><?php e($n);?></a>\n\t\t\t<?php endforeach;?>\n\t\t\t<!--<a href=\"javascript:;\" class=\"mdui-btn mdui-btn-icon\"><i class=\"mdui-icon material-icons\">refresh</i></a>-->\n\t\t</div>\n\t</header>\n\t\n\t<div class=\"mdui-container\">\n    \t<?php view::section('content');?>\n  \t</div>\n</body>\n</html>"
  },
  {
    "path": "view/themes/material/list.php",
    "content": "<?php view::layout('layout')?>\n<?php \nfunction file_ico($item){\n  $ext = strtolower(pathinfo($item['name'], PATHINFO_EXTENSION));\n  if(in_array($ext,['bmp','jpg','jpeg','png','gif'])){\n  \treturn \"image\";\n  }\n  if(in_array($ext,['mp4','mkv','webm','avi','mpg', 'mpeg', 'rm', 'rmvb', 'mov', 'wmv', 'mkv', 'asf'])){\n  \treturn \"ondemand_video\";\n  }\n  if(in_array($ext,['ogg','mp3','wav'])){\n  \treturn \"audiotrack\";\n  }\n  return \"insert_drive_file\";\n}\n?>\n\n<?php view::begin('content');?>\n\t\n<div class=\"mdui-container-fluid\">\n\n<?php if($head):?>\n<div class=\"mdui-typo\" style=\"padding: 20px;\">\n\t<?php e($head);?>\n</div>\n<?php endif;?>\n\n\t\n<div class=\"mdui-row\">\n\t<ul class=\"mdui-list\">\n\t\t<li class=\"mdui-list-item th\">\n\t\t  <div class=\"mdui-col-xs-12 mdui-col-sm-7\">文件 <i class=\"mdui-icon material-icons icon-sort\" data-sort=\"name\" data-order=\"downward\">expand_more</i></div>\n\t\t  <div class=\"mdui-col-sm-3 mdui-text-right\">修改时间 <i class=\"mdui-icon material-icons icon-sort\" data-sort=\"date\" data-order=\"downward\">expand_more</i></div>\n\t\t  <div class=\"mdui-col-sm-2 mdui-text-right\">大小 <i class=\"mdui-icon material-icons icon-sort\" data-sort=\"size\" data-order=\"downward\">expand_more</i></div>\n\t\t</li>\n\t\t<?php if($path != '/'):?>\n\t\t<li class=\"mdui-list-item mdui-ripple\">\n\t\t\t<a href=\"<?php echo get_absolute_path($root.$path.'../');?>\">\n\t\t\t  <div class=\"mdui-col-xs-12 mdui-col-sm-7\">\n\t\t\t\t<i class=\"mdui-icon material-icons\">arrow_upward</i>\n\t\t    \t..\n\t\t\t  </div>\n\t\t\t  <div class=\"mdui-col-sm-3 mdui-text-right\"></div>\n\t\t\t  <div class=\"mdui-col-sm-2 mdui-text-right\"></div>\n\t\t  \t</a>\n\t\t</li>\n\t\t<?php endif;?>\n\n\t\t<?php foreach((array)$items as $item):?>\n\t\t\t<?php if(!empty($item['folder'])):?>\n\n\t\t<li class=\"mdui-list-item mdui-ripple\" data-sort data-sort-name=\"<?php e($item['name']);?>\" data-sort-date=\"<?php echo $item['lastModifiedDateTime'];?>\" data-sort-size=\"<?php echo $item['size'];?>\">\n\t\t\t<a href=\"<?php echo get_absolute_path($root.$path.rawurlencode($item['name']));?>\">\n\t\t\t  <div class=\"mdui-col-xs-12 mdui-col-sm-7 mdui-text-truncate\">\n\t\t\t\t<i class=\"mdui-icon material-icons\">folder_open</i>\n\t\t    \t<?php e($item['name']);?>\n\t\t\t  </div>\n\t\t\t  <div class=\"mdui-col-sm-3 mdui-text-right\"><?php echo date(\"Y-m-d H:i:s\", $item['lastModifiedDateTime']);?></div>\n\t\t\t  <div class=\"mdui-col-sm-2 mdui-text-right\"><?php echo onedrive::human_filesize($item['size']);?></div>\n\t\t  \t</a>\n\t\t</li>\n\t\t\t<?php else:?>\n\t\t<li class=\"mdui-list-item file mdui-ripple\" data-sort data-sort-name=\"<?php e($item['name']);?>\" data-sort-date=\"<?php echo $item['lastModifiedDateTime'];?>\" data-sort-size=\"<?php echo $item['size'];?>\">\n\t\t\t<a href=\"<?php echo get_absolute_path($root.$path).rawurlencode($item['name']);?>\" target=\"_blank\">\n\t\t\t  <div class=\"mdui-col-xs-12 mdui-col-sm-7 mdui-text-truncate\">\n\t\t\t\t<i class=\"mdui-icon material-icons\"><?php echo file_ico($item);?></i>\n\t\t    \t<?php e($item['name']);?>\n\t\t\t  </div>\n\t\t\t  <div class=\"mdui-col-sm-3 mdui-text-right\"><?php echo date(\"Y-m-d H:i:s\", $item['lastModifiedDateTime']);?></div>\n\t\t\t  <div class=\"mdui-col-sm-2 mdui-text-right\"><?php echo onedrive::human_filesize($item['size']);?></div>\n\t\t  \t</a>\n\t\t</li>\n\t\t\t<?php endif;?>\n\t\t<?php endforeach;?>\n\t</ul>\n</div>\n<?php if($readme):?>\n<div class=\"mdui-typo mdui-shadow-3\" style=\"padding: 20px;margin: 20px 0;\">\n\t<div class=\"mdui-chip\">\n\t  <span class=\"mdui-chip-icon\"><i class=\"mdui-icon material-icons\">face</i></span>\n\t  <span class=\"mdui-chip-title\">README.md</span>\n\t</div>\n\t<?php e($readme);?>\n</div>\n<?php endif;?>\n</div>\n<script>\n$ = mdui.JQ;\n\n$.fn.extend({\n    sortElements: function (comparator, getSortable) {\n        getSortable = getSortable || function () { return this; };\n\n        var placements = this.map(function () {\n            var sortElement = getSortable.call(this),\n                parentNode = sortElement.parentNode,\n                nextSibling = parentNode.insertBefore(\n                    document.createTextNode(''),\n                    sortElement.nextSibling\n                );\n\n            return function () {\n                parentNode.insertBefore(this, nextSibling);\n                parentNode.removeChild(nextSibling);\n            };\n        });\n\n        return [].sort.call(this, comparator).each(function (i) {\n            placements[i].call(getSortable.call(this));\n        });\n    }\n});\n\n$(function () {\n    $('.file a').each(function () {\n        $(this).on('click', function () {\n            var form = $('<form target=_blank method=post></form>').attr('action', $(this).attr('href')).get(0);\n            $(document.body).append(form);\n            form.submit();\n            $(form).remove();\n            return false;\n        });\n    });\n\n    $('.icon-sort').on('click', function () {\n        var sort_type = $(this).attr(\"data-sort\"), sort_order = $(this).attr(\"data-order\");\n        var sort_order_to = (sort_order === \"less\") ? \"more\" : \"less\";\n\n        $('li[data-sort]').sortElements(function (a, b) {\n            var data_a = $(a).attr(\"data-sort-\" + sort_type), data_b = $(b).attr(\"data-sort-\" + sort_type);\n            var rt = data_a.localeCompare(data_b, undefined, {numeric: true});\n            return (sort_order === \"less\") ? 0-rt : rt;\n        });\n\n        $(this).attr(\"data-order\", sort_order_to).text(\"expand_\" + sort_order_to);\n    })\n\n});\n</script>\n<div class=\"mdui-fab-wrapper\" id=\"myFab\">\n    <button class=\"mdui-fab mdui-ripple mdui-color-theme-accent\">\n      <i class=\"mdui-icon material-icons\">add</i>\n      <i class=\"mdui-icon mdui-fab-opened material-icons\">mode_edit</i>\n    </button>\n    <div class=\"mdui-fab-dial\">\n      <button class=\"mdui-fab mdui-fab-mini mdui-ripple mdui-color-pink\" onclick=\"location.href='/?/offline'\"><i class=\"mdui-icon material-icons\">cloud_upload</i>\n      </button>\n      <button class=\"mdui-fab mdui-fab-mini mdui-ripple mdui-color-red\" onclick=\"addFavorite2()\"><i class=\"mdui-icon material-icons\">bookmark</i>\n      </button>\n      <button class=\"mdui-fab mdui-fab-mini mdui-ripple mdui-color-orange\" onclick=\"location.href='/?/admin'\"><i class=\"mdui-icon material-icons\">account_circle</i>\n      </button>\n    </div>\n  </div>\n<script>\n    var inst = new mdui.Fab('#myFab');\n</script>\n<?php view::end('content');?>\n"
  },
  {
    "path": "view/themes/material/password.php",
    "content": "<?php view::layout('layout')?>\n\n<?php view::begin('content');?>\n\t\n<div class=\"mdui-container-fluid\">\n\t<div class=\"mdui-col-md-6 mdui-col-offset-md-3\">\n\t  <center><h1 class=\"mdui-typo-display-2-opacity\">这是一个受保护的文件夹，您需要提供访问密码才能查看。</h1></center>\n\t  <form action=\"\" method=\"post\">\n\t\t  <div class=\"mdui-textfield mdui-textfield-floating-label\">\n\t\t    <i class=\"mdui-icon material-icons\">https</i>\n\t\t    <label class=\"mdui-textfield-label\">密码</label>\n\t\t    <input name=\"password\" class=\"mdui-textfield-input\" type=\"password\"/>\n\t\t  </div>\n\t\t  <br>\n\t\t  <button type=\"submit\" class=\"mdui-center mdui-btn mdui-btn-raised mdui-ripple mdui-color-theme\">\n\t\t  \t<i class=\"mdui-icon material-icons\">fingerprint</i>\n\t\t  \t查看\n\t\t  </button>\n\t  </form>\n\t</div>\n\t\n</div>\n\n<?php view::end('content');?>"
  },
  {
    "path": "view/themes/material/show/audio.php",
    "content": "<?php view::layout('layout')?>\n\n<?php view::begin('content');?>\n<link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css\">\n<div class=\"mdui-container-fluid\">\n\t<br>\n\t<center>\n\t<div id=\"aplayer\"></div>\n\t</audio>\n\t</center>\n\t<br>\n\t<!-- 固定标签 -->\n\t<div class=\"mdui-textfield\">\n\t  <label class=\"mdui-textfield-label\">下载地址</label>\n\t  <input class=\"mdui-textfield-input\" type=\"text\" value=\"<?php e($url);?>\"/>\n\t</div>\n\t<div class=\"mdui-textfield\">\n\t  <label class=\"mdui-textfield-label\">引用地址</label>\n\t  <textarea class=\"mdui-textfield-input\"><audio src=\"<?php e($url);?>\"></audio></textarea>\n\t</div>\n</div>\n<a href=\"<?php e($url);?>\" class=\"mdui-fab mdui-fab-fixed mdui-ripple mdui-color-theme-accent\"><i class=\"mdui-icon material-icons\">file_download</i></a>\n<script src=\"https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.js\"></script>\n<script>\nconst ap = new APlayer({\n    container: document.getElementById('aplayer'),\n    audio: [{\n        name: '<?php e(pathinfo($item[\"name\"], PATHINFO_FILENAME)); ?>',\n        artist: 'Oneindex Preview',\n        url: '<?php e($item['downloadUrl']);?>',\n        cover: '<?php e( !empty($item['thumb'] ) ? $item['thumb'].'&width=176&height=176' : null);?>'\n    }]\n});\n</script>\n\n<?php view::end('content');?>\n"
  },
  {
    "path": "view/themes/material/show/code.php",
    "content": "<?php view::layout('layout')?>\n<?php \n\tfunction code_type($ext){\n\t\t$code_type['html'] = 'html';\n\t\t$code_type['htm'] = 'html';\n\t\t$code_type['php'] = 'php';\n\t\t$code_type['css'] = 'css';\n\t\t$code_type['go'] = 'golang';\n\t\t$code_type['java'] = 'java';\n\t\t$code_type['js'] = 'javascript';\n\t\t$code_type['json'] = 'json';\n\t\t$code_type['txt'] = 'Text';\n\t\t$code_type['sh'] = 'sh';\n\t\t$code_type['md'] = 'Markdown';\n\t\t\n\t\treturn @$code_type[$ext];\n\t}\n\t$language = code_type($ext);\n\n\t$content = IndexController::get_content($item);\n?>\n<?php view::begin('content');?>\n<style type=\"text/css\" media=\"screen\">\n    #editor { \n        /*height:800px;*/\n    }\n</style>\n<div class=\"mdui-container\">\n<pre id=\"editor\" ><?php echo htmlentities($content);?></pre>\n</div>\n<div class=\"mdui-textfield\">\n\t<label class=\"mdui-textfield-label\">下载地址</label>\n\t<input class=\"mdui-textfield-input\" type=\"text\" value=\"<?php e($url);?>\"/>\n</div>\n<a href=\"<?php e($url);?>\" class=\"mdui-fab mdui-fab-fixed mdui-ripple mdui-color-theme-accent\"><i class=\"mdui-icon material-icons\">file_download</i></a>\n\n<script src=\"https://cdn.bootcss.com/ace/1.2.9/ace.js\"></script>\n<script src=\"https://cdn.bootcss.com/ace/1.2.9/ext-language_tools.js\"></script>\n<script>\n    var editor = ace.edit(\"editor\");\n    editor.setTheme(\"ace/theme/ambiance\");\n    editor.setFontSize(18);\n    editor.session.setMode(\"ace/mode/<?php e($language);?>\");\n    \n    //Autocompletion\n    editor.setOptions({\n        enableBasicAutocompletion: true,\n        enableSnippets: true,\n        enableLiveAutocompletion: true,\n        maxLines: Infinity\n    });\n</script>\n<?php view::end('content');?>"
  },
  {
    "path": "view/themes/material/show/doc.php",
    "content": "<?php \n        if ($item[\"size\"] < 10000000) {\n                $url = 'https://view.officeapps.live.com/op/view.aspx?src='.urlencode($item['downloadUrl']);\n                view::direct($url);\n        } else {\n                view::direct($item['downloadUrl']);\n        }\n        exit();\n?>\n"
  },
  {
    "path": "view/themes/material/show/image.php",
    "content": "<?php view::layout('layout')?>\n\n<?php view::begin('content');?>\n\t\n<div class=\"mdui-container-fluid\">\n\t<br>\n\t<img class=\"mdui-img-fluid\" src=\"<?php e($item['downloadUrl']);?>\"/>\n\t<br>\n\t<div class=\"mdui-textfield\">\n\t  <label class=\"mdui-textfield-label\">下载地址</label>\n\t  <input class=\"mdui-textfield-input\" type=\"text\" value=\"<?php e($url);?>\"/>\n\t</div>\n\t<div class=\"mdui-textfield\">\n\t  <label class=\"mdui-textfield-label\">HTML 引用地址</label>\n\t  <input class=\"mdui-textfield-input\" type=\"text\" value=\"<img src='<?php e($url);?>' />\"/>\n\t</div>\n        <div class=\"mdui-textfield\">\n\t  <label class=\"mdui-textfield-label\">Markdown 引用地址</label>\n\t  <input class=\"mdui-textfield-input\" type=\"text\" value=\"![](<?php e($url);?>)\"/>\n\t</div>\n        <br>\n</div>\n<a href=\"<?php e($url);?>\" class=\"mdui-fab mdui-fab-fixed mdui-ripple mdui-color-theme-accent\"><i class=\"mdui-icon material-icons\">file_download</i></a>\n<?php view::end('content');?>\n"
  },
  {
    "path": "view/themes/material/show/pdf.php",
    "content": "<?php view::layout('layout')?>\n\n<?php view::begin('content');?>\n\t<iframe id=\"mask\" src='<?php echo str_replace('transform/thumbnail?', 'transform/pdf?',$item['thumb']);?>' \n\t\tallowfullscreen=\"allowfullscreen\"\n        mozallowfullscreen=\"mozallowfullscreen\"\n        msallowfullscreen=\"msallowfullscreen\"\n        oallowfullscreen=\"oallowfullscreen\"\n        webkitallowfullscreen=\"webkitallowfullscreen\"\n        width=\"100%\"\n        style=\"position: absolute;top:0;left:0; z-index:10;\"\n        ></iframe>\n<a href=\"<?php e($url);?>\" class=\"mdui-fab mdui-fab-fixed mdui-ripple mdui-color-theme-accent\" style=\"z-index:99;\"><i class=\"mdui-icon material-icons\">file_download</i></a>\n<script>\n$ = mdui.JQ;\n$(function(){  \n      \n    var sWidth=document.documentElement.clientWidth;  \n    var sHeight=document.documentElement.clientHeight;  \n    //获取页面的可视区域高度和宽度  \n    var wHeight=document.documentElement.clientHeight;  \n    var oMask=document.getElementById(\"mask\");  \n    var oMaskIframe=document.getElementById(\"maskIframe\");  \n      \n    oMask.style.height=(sHeight-1)+\"px\";  \n    oMask.style.width=(sWidth-4)+\"px\";  \n      \n});  \n</script>\n<?php view::end('content');?>"
  },
  {
    "path": "view/themes/material/show/stream.php",
    "content": "<?php \nheader(\"ALLOW-CONTROL-ALLOW-ORIGIN:*\");\n$types = [\n\t'chm'=>'application/octet-stream',\n\t'ppt'=>'application/vnd.ms-powerpoint',\n\t'xls'=>'application/vnd.ms-excel',\n\t'doc'=>'application/msword',\n\t'exe'=>'application/octet-stream',\n\t'rar'=>'application/octet-stream',\n\t'js'=>\"javascrīpt/js\",\n\t'css'=>\"text/css\",\n\t'hqx'=>\"application/mac-binhex40\",\n\t'bin'=>\"application/octet-stream\",\n\t'oda'=>\"application/oda\",\n\t'pdf'=>\"application/pdf\",\n\t'ai'=>\"application/postsrcipt\",\n\t'eps'=>\"application/postsrcipt\",\n\t'es'=>\"application/postsrcipt\",\n\t'rtf'=>\"application/rtf\",\n\t'mif'=>\"application/x-mif\",\n\t'csh'=>\"application/x-csh\",\n\t'dvi'=>\"application/x-dvi\",\n\t'hdf'=>\"application/x-hdf\",\n\t'nc'=>\"application/x-netcdf\",\n\t'cdf'=>\"application/x-netcdf\",\n\t'latex'=>\"application/x-latex\",\n\t'ts'=>\"application/x-troll-ts\",\n\t'src'=>\"application/x-wais-source\",\n\t'zip'=>\"application/zip\",\n\t'bcpio'=>\"application/x-bcpio\",\n\t'cpio'=>\"application/x-cpio\",\n\t'gtar'=>\"application/x-gtar\",\n\t'shar'=>\"application/x-shar\",\n\t'sv4cpio'=>\"application/x-sv4cpio\",\n\t'sv4crc'=>\"application/x-sv4crc\",\n\t'tar'=>\"application/x-tar\",\n\t'ustar'=>\"application/x-ustar\",\n\t'man'=>\"application/x-troff-man\",\n\t'sh'=>\"application/x-sh\",\n\t'tcl'=>\"application/x-tcl\",\n\t'tex'=>\"application/x-tex\",\n\t'texi'=>\"application/x-texinfo\",\n\t'texinfo'=>\"application/x-texinfo\",\n\t't'=>\"application/x-troff\",\n\t'tr'=>\"application/x-troff\",\n\t'roff'=>\"application/x-troff\",\n\t'shar'=>\"application/x-shar\",\n\t'me'=>\"application/x-troll-me\",\n\t'ts'=>\"application/x-troll-ts\",\n\t'gif'=>\"image/gif\",\n\t'jpeg'=>\"image/pjpeg\",\n\t'jpg'=>\"image/pjpeg\",\n\t'jpe'=>\"image/pjpeg\",\n\t'ras'=>\"image/x-cmu-raster\",\n\t'pbm'=>\"image/x-portable-bitmap\",\n\t'ppm'=>\"image/x-portable-pixmap\",\n\t'xbm'=>\"image/x-xbitmap\",\n\t'xwd'=>\"image/x-xwindowdump\",\n\t'ief'=>\"image/ief\",\n\t'tif'=>\"image/tiff\",\n\t'tiff'=>\"image/tiff\",\n\t'pnm'=>\"image/x-portable-anymap\",\n\t'pgm'=>\"image/x-portable-graymap\",\n\t'rgb'=>\"image/x-rgb\",\n\t'xpm'=>\"image/x-xpixmap\",\n\t'txt'=>\"text/plain\",\n\t'c'=>\"text/plain\",\n\t'cc'=>\"text/plain\",\n\t'h'=>\"text/plain\",\n\t'html'=>\"text/html\",\n\t'htm'=>\"text/html\",\n\t'htl'=>\"text/html\",\n\t'txt'=>\"text/html\",\n\t'php'=>\"text/html\",\n\t'rtx'=>\"text/richtext\",\n\t'etx'=>\"text/x-setext\",\n\t'tsv'=>\"text/tab-separated-values\",\n\t'mpeg'=>\"video/mpeg\",\n\t'mpg'=>\"video/mpeg\",\n\t'mpe'=>\"video/mpeg\",\n\t'avi'=>\"video/x-msvideo\",\n\t'qt'=>\"video/quicktime\",\n\t'mov'=>\"video/quicktime\",\n\t'moov'=>\"video/quicktime\",\n\t'movie'=>\"video/x-sgi-movie\",\n\t'au'=>\"audio/basic\",\n\t'snd'=>\"audio/basic\",\n\t'wav'=>\"audio/x-wav\",\n\t'aif'=>\"audio/x-aiff\",\n\t'aiff'=>\"audio/x-aiff\",\n\t'aifc'=>\"audio/x-aiff\",\n\t'swf'=>\"application/x-shockwave-flash\",\n\t'myz'=>\"application/myz\"\n];\n//大于 5M 跳转为直连下载\nif($item['size'] > 5242880){\n\theader('Location: '.$item['downloadUrl']);exit();\n}\n$type = empty($types[$ext])?\"application/octet-stream\":$types[$ext];\n$content = IndexController::get_content($item);\n\nheader('Content-type: '.$type);\necho $content;\nexit();\n?>\n"
  },
  {
    "path": "view/themes/material/show/video.php",
    "content": "<?php view::layout('layout')?>\n<?php\n$item['thumb'] = onedrive::thumbnail($item['path']);\n?>\n<?php view::begin('content');?>\n<link class=\"dplayer-css\" rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/dplayer/dist/DPlayer.min.css\">\n<div class=\"mdui-container-fluid\">\n\t<br>\n\t<div id=\"dplayer\"></div>\n\t<br>\n\t<!-- 固定标签 -->\n\t<div class=\"mdui-textfield\">\n\t  <label class=\"mdui-textfield-label\">下载地址</label>\n\t  <input class=\"mdui-textfield-input\" type=\"text\" value=\"<?php e($url);?>\"/>\n\t</div>\n\t<div class=\"mdui-textfield\">\n\t  <label class=\"mdui-textfield-label\">引用地址</label>\n\t  <textarea class=\"mdui-textfield-input\"><video><source src=\"<?php e($url);?>\" type=\"video/mp4\"></video></textarea>\n\t</div>\n</div>\n<?php if(pathinfo($item[\"name\"], PATHINFO_EXTENSION) === 'flv') { e('<script src=\"https://cdn.jsdelivr.net/npm/flv.js/dist/flv.min.js\"></script>'); } ?>\n<script src=\"https://cdn.jsdelivr.net/npm/dplayer/dist/DPlayer.min.js\"></script>\n<script>\nconst dp = new DPlayer({\n\tcontainer: document.getElementById('dplayer'),\n\tlang:'zh-cn',\n\tvideo: {\n\t    url: '<?php e($item['downloadUrl']);?>',\n\t    pic: '<?php @e($item['thumb']);?>',\n\t    type: '<?php e((pathinfo($item[\"name\"], PATHINFO_EXTENSION) === 'flv') ? 'flv' : 'auto'); ?>'\n\t}\n});\n</script>\n<a href=\"<?php e($url);?>\" class=\"mdui-fab mdui-fab-fixed mdui-ripple mdui-color-theme-accent\"><i class=\"mdui-icon material-icons\">file_download</i></a>\n<?php view::end('content');?>\n"
  },
  {
    "path": "view/themes/material/show/video2.php",
    "content": "<?php view::layout('layout')?>\n\n<?php \n//仅支持教育版和企业版\nif(strpos($item['downloadUrl'],\"sharepoint.com\") == false){\n\theader('Location: '.$item['downloadUrl']);exit();\n}\n$item['thumb'] = onedrive::thumbnail($item['path']);\n$mpd =  str_replace(\"thumbnail\",\"videomanifest\",$item['thumb']).\"&part=index&format=dash&useScf=True&pretranscode=0&transcodeahead=0\";\n?>\n\n<?php view::begin('content');?>\n<link class=\"dplayer-css\" rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/dplayer/dist/DPlayer.min.css\">\n<script src=\"https://cdn.jsdelivr.net/npm/dashjs/dist/dash.all.min.js\"></script>\n<script src=\"https://cdn.jsdelivr.net/npm/dplayer/dist/DPlayer.min.js\"></script>\n<div class=\"mdui-container-fluid\">\n\t<br>\n\t<div id=\"dplayer\"></div>\n\t<br>\n\t<!-- 固定标签 -->\n\t<div class=\"mdui-textfield\">\n\t  <label class=\"mdui-textfield-label\">下载地址</label>\n\t  <input class=\"mdui-textfield-input\" type=\"text\" value=\"<?php e($url);?>\"/>\n\t</div>\n\t<div class=\"mdui-textfield\">\n\t  <label class=\"mdui-textfield-label\">引用地址</label>\n\t  <textarea class=\"mdui-textfield-input\"><video><source src=\"<?php e($url);?>\" type=\"video/mp4\"></video></textarea>\n\t</div>\n</div>\n<script>\nconst dp = new DPlayer({\n\tcontainer: document.getElementById('dplayer'),\n\tlang:'zh-cn',\n\tvideo: {\n\t    url: '<?php echo $mpd;?>',\n\t    pic: '<?php @e($item['thumb']);?>',\n\t    type: 'dash'\n\t}\n});\n</script>\n<a href=\"<?php e($url);?>\" class=\"mdui-fab mdui-fab-fixed mdui-ripple mdui-color-theme-accent\"><i class=\"mdui-icon material-icons\">file_download</i></a>\n<?php view::end('content');?>"
  },
  {
    "path": "view/themes/material/show/video5.php",
    "content": "<?php view::layout('layout')?>\n\n<?php \n$item['thumb'] = onedrive::thumbnail($item['path']);\n?>\n\n<?php view::begin('content');?>\n<div class=\"mdui-container-fluid\">\n\t<br>\n\t<video class=\"mdui-video-fluid mdui-center\" preload controls poster=\"<?php @e($item['thumb']);?>\">\n\t  <source src=\"<?php e($item['downloadUrl']);?>\" type=\"video/mp4\">\n\t</video>\n\t<br>\n\t<!-- 固定标签 -->\n\t<div class=\"mdui-textfield\">\n\t  <label class=\"mdui-textfield-label\">下载地址</label>\n\t  <input class=\"mdui-textfield-input\" type=\"text\" value=\"<?php e($url);?>\"/>\n\t</div>\n\t<div class=\"mdui-textfield\">\n\t  <label class=\"mdui-textfield-label\">引用地址</label>\n\t  <textarea class=\"mdui-textfield-input\"><video><source src=\"<?php e($url);?>\" type=\"video/mp4\"></video></textarea>\n\t</div>\n</div>\n<a href=\"<?php e($url);?>\" class=\"mdui-fab mdui-fab-fixed mdui-ripple mdui-color-theme-accent\"><i class=\"mdui-icon material-icons\">file_download</i></a>\n<?php view::end('content');?>"
  },
  {
    "path": "view/themes/nexmoe/404.php",
    "content": "<?php view::layout('layout')?>\n\n<?php view::begin('content');?>\n\t<div class=\"mdui-typo-display-4\" style=\"margin: 100px auto;text-align: center;\">404 not found.</div>\n<?php view::end('content');?>"
  },
  {
    "path": "view/themes/nexmoe/images/index.php",
    "content": "<?php view::layout('layout')?>\n\n<?php view::begin('content');?>\n\t\n<div class=\"mdui-container-fluid\">\n\n<div class=\"nexmoe-item\" style=\"padding: 100px!important;\">\n\t<div class=\"mdui-typo-display-3-opacity\" style=\"text-align:center;\">OneImages</div>\n\n\t<form action=\"\" method=\"post\" enctype=\"multipart/form-data\">\n\t\t<input class=\"mdui-center\" type=\"file\" style=\"margin: 50px 0;\" name=\"file\" />\n\n\n\t<div class=\"mdui-row-xs-3\">\n\t  <div class=\"mdui-col\"></div>\n\t  <div class=\"mdui-col\">\n\t    <button class=\"mdui-btn mdui-btn-block mdui-color-theme-accent mdui-ripple\">上传</button>\n\t  </div>\n\t</div>\n\n\t</form>\n\t\n</div>\n\n</div>\n\n<?php view::end('content');?>"
  },
  {
    "path": "view/themes/nexmoe/images/layout.php",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<meta charset=\"utf-8\">\n\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0,maximum-scale=1.0, user-scalable=no\"/>\n\t<title><?php e($title.' - '.config('site_name'));?></title>\n\t<link rel=\"stylesheet\" href=\"https://cloud.i.chainwon.com/data/User/admin/home/css/main.css\">\n\t<link rel=\"stylesheet\" href=\"//cdnjs.loli.net/ajax/libs/mdui/0.4.3/css/mdui.min.css\">\n\t<script src=\"https://cdn.jsdelivr.net/gh/xieqifei/StaticsResources/oneindexn/mdui/mdui.min.js\"></script>\n</head>\n<body class=\"mdui-theme-primary-blue-grey mdui-theme-accent-blue\">\n\t<header class=\"mdui-appbar mdui-color-theme\">\n\t\t<div class=\"mdui-toolbar mdui-container\">\n\t\t\t<a href=\"/\" class=\"mdui-typo-headline\"><?php e(config('site_name'));?></a>\n\t\t\t<?php foreach((array)$navs as $n=>$l):?>\n\t\t\t<i class=\"mdui-icon material-icons mdui-icon-dark\" style=\"margin:0;\">chevron_right</i>\n\t\t\t<a href=\"<?php e($l);?>\"><?php e($n);?></a>\n\t\t\t<?php endforeach;?>\n\t\t\t<!--<a href=\"javascript:;\" class=\"mdui-btn mdui-btn-icon\"><i class=\"mdui-icon material-icons\">refresh</i></a>-->\n\t\t</div>\n\t</header>\n\t\n\t<div class=\"mdui-container\">\n    \t<?php view::section('content');?>\n  \t</div>\n</body>\n</html>"
  },
  {
    "path": "view/themes/nexmoe/layout.php",
    "content": "<!DOCTYPE html>\r\n<html>\r\n\t<head>\r\n\t\t<meta charset=\"utf-8\">\r\n\t\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0,maximum-scale=1.0, user-scalable=no\" />\r\n\t\t<title><?php e($title.' - '.config('site_name'));?></title>\r\n\t\t<link rel=\"stylesheet\" href=\"/statics/themes/nexmoe/css/forkGh.css\" />\r\n\t\t<!--Safari浏览器-->\r\n\t\t<link rel=\"apple-touch-icon\" sizes=\"64x64\" href=\"/statics/themes/nexmoe/IMG/OneIndexM.svg\">\r\n\t\t<!--Chrome等浏览器-->\r\n\t\t<link rel=\"icon\" href=\"/statics/themes/nexmoe/img/OneIndexM.svg\">\r\n        <!-- 视频Flv加载插件 -->\r\n        <script crossorigin=\"anonymous\" integrity=\"sha512-49OFf+8jaHx4Vb7iFNb46Loq1pIxXlEYeVOQRIx0KLBRF4KSV6E7QK2Vw5r416TQDyBJW+DFh2CyTV7+gCWd6g==\" src=\"https://lib.baomitu.com/flv.js/1.6.2/flv.min.js\"></script>\r\n        <!-- 视频播放器加载插件 -->\r\n        <link crossorigin=\"anonymous\" integrity=\"sha384-tLMkTWh2pfXNWGFlUS0w1TFtRG5xZ9lPWFOooj+vDDLIL+xBGQU/voDBY5XE2lVh\" href=\"https://lib.baomitu.com/aplayer/1.10.1/APlayer.min.css\" rel=\"stylesheet\">\r\n        <script crossorigin=\"anonymous\" integrity=\"sha384-gdGYZwHnfJM54evoZhpO0s6ZF5BQiybkiyW7VXr+h5UfruuRL/aORyw+5+HZoU6e\" src=\"https://lib.baomitu.com/aplayer/1.10.1/APlayer.min.js\"></script>\r\n        <!-- 音乐加载插件 -->\r\n        <!-- <script src=\"https://cdn.jsdelivr.net/npm/meting@2/dist/Meting.min.js\"></script> -->\r\n        <script src=\"/statics/themes/nexmoe/js/Meting.min.js\"></script>\r\n        <link crossorigin=\"anonymous\" href=\"https://lib.baomitu.com/mdui/0.4.3/css/mdui.min.css\" rel=\"stylesheet\">\r\n\t\t<style>\r\n\t\t\tbody {\r\n\t\t\t\tbackground-color: #f2f5fa;\r\n\t\t\t\tpadding-bottom: 3rem;\r\n\t\t\t\tbackground-position: center bottom;\r\n\t\t\t\tbackground-repeat: no-repeat;\r\n\t\t\t\tbackground-attachment: fixed\r\n\t\t\t}\r\n\r\n\t\t\t.nexmoe-item {\r\n\t\t\t\tmargin: 20px -8px 0 !important;\r\n\t\t\t\tpadding: 15px !important;\r\n\t\t\t\tborder-radius: 5px;\r\n\t\t\t\tbackground-color: #fff;\r\n\t\t\t\t-webkit-box-shadow: 0 .5em 3em rgba(161, 177, 204, .4);\r\n\t\t\t\tbox-shadow: 0 .5em 3em rgba(161, 177, 204, .4);\r\n\t\t\t\tbackground-color: #fff\r\n\t\t\t}\r\n\r\n\t\t\t.mdui-img-fluid,\r\n\t\t\t.mdui-video-fluid {\r\n\t\t\t\tborder-radius: 5px;\r\n\t\t\t\tborder: 1px solid #eee\r\n\t\t\t}\r\n\r\n\t\t\t.mdui-list {\r\n\t\t\t\tpadding: 0\r\n\t\t\t}\r\n\r\n\t\t\t.mdui-list-item {\r\n\t\t\t\tmargin: 0 !important;\r\n\t\t\t\tborder-radius: 5px;\r\n\t\t\t\tpadding: 0 10px 0 5px !important;\r\n\t\t\t\tborder: 1px solid #eee;\r\n\t\t\t\tmargin-bottom: 10px !important\r\n\t\t\t}\r\n\r\n\t\t\t.mdui-list-item:last-child {\r\n\t\t\t\tmargin-bottom: 0 !important\r\n\t\t\t}\r\n\r\n\t\t\t.mdui-list-item:first-child {\r\n\t\t\t\tborder: none\r\n\t\t\t}\r\n\r\n\t\t\t.mdui-toolbar {\r\n\t\t\t\twidth: auto;\r\n\t\t\t\tmargin-top: 1rem !important\r\n\t\t\t}\r\n\r\n\t\t\t.mdui-appbar .mdui-toolbar {\r\n\t\t\t\theight: 1rem;\r\n\t\t\t\tfont-size: 16px\r\n\t\t\t}\r\n\r\n\t\t\t.mdui-toolbar>* {\r\n\t\t\t\tpadding: 0 6px;\r\n\t\t\t\tmargin: 0 2px;\r\n\t\t\t\topacity: .5\r\n\t\t\t}\r\n\r\n\t\t\t.mdui-toolbar>.mdui-typo-headline {\r\n\t\t\t\tpadding: 0 16px 0 0\r\n\t\t\t}\r\n\r\n\t\t\t.mdui-toolbar>i {\r\n\t\t\t\tpadding: 0\r\n\t\t\t}\r\n\r\n\t\t\t.mdui-toolbar>a:hover,\r\n\t\t\ta.mdui-typo-headline,\r\n\t\t\ta.active {\r\n\t\t\t\topacity: 1\r\n\t\t\t}\r\n\r\n\t\t\t.mdui-container {\r\n\t\t\t\tmax-width: 980px\r\n\t\t\t}\r\n\r\n\t\t\t.mdui-list>.th {\r\n\t\t\t\tbackground-color: initial\r\n\t\t\t}\r\n\r\n\t\t\t.mdui-list-item>a {\r\n\t\t\t\twidth: 100%;\r\n\t\t\t\tline-height: 48px\r\n\t\t\t}\r\n\r\n\t\t\t.mdui-toolbar>a {\r\n\t\t\t\tpadding: 0 16px;\r\n\t\t\t\tline-height: 30px;\r\n\t\t\t\tborder-radius: 30px;\r\n\t\t\t\tborder: 1px solid #eee\r\n\t\t\t}\r\n\r\n\t\t\t.mdui-toolbar>a:last-child {\r\n\t\t\t\topacity: 1;\r\n\t\t\t\tbackground-color: #1e89f2;\r\n\t\t\t\tcolor: #ffff\r\n\t\t\t}\r\n\r\n\t\t\t@media screen and (max-width:980px) {\r\n\t\t\t\t.mdui-list-item .mdui-text-right {\r\n\t\t\t\t\tdisplay: none\r\n\t\t\t\t}\r\n\r\n\t\t\t\t.mdui-container {\r\n\t\t\t\t\twidth: 100% !important;\r\n\t\t\t\t\tmargin: 0\r\n\t\t\t\t}\r\n\r\n\t\t\t\t.mdui-toolbar>* {\r\n\t\t\t\t\tdisplay: none\r\n\t\t\t\t}\r\n\r\n\t\t\t\t.mdui-toolbar>a:last-child,\r\n\t\t\t\t.mdui-toolbar>.mdui-typo-headline,\r\n\t\t\t\t.mdui-toolbar>i:first-child {\r\n\t\t\t\t\tdisplay: block\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t</style>\r\n\t\t<!-- <script src=\"https://cdn.jsdelivr.net/gh/xieqifei/StaticsResources/oneindexn/mdui/mdui.min.js\"></script> -->\r\n        <script crossorigin=\"anonymous\" integrity=\"sha384-GXQQyAWEQJOklZd/6CWH3BbffdVqZ85WoDiENXxSqLpjrdWzpX15CKmya8HIdM4r\" src=\"https://lib.baomitu.com/mdui/0.4.3/js/mdui.min.js\"></script>\r\n\t</head>\r\n\t<body class=\"mdui-theme-primary-blue-grey mdui-theme-accent-blue\">\r\n\t\t<a class=\"github-fork-ribbon\" href=\"https://github.com/Mintimate/OneindexM\" data-ribbon=\"Fork me on GitHub\"\r\n\t\t\ttitle=\"Fork me on GitHub\">Fork me on GitHub</a>\r\n\t\t<div class=\"mdui-container\">\r\n\t\t\t<div class=\"mdui-container-fluid\">\r\n\t\t\t\t<div class=\"mdui-toolbar nexmoe-item\">\r\n\t\t\t\t\t<a href=\"/\"><?php e(config('site_name'));?></a>\r\n\t\t\t\t\t<?php foreach((array)$navs as $n=>$l):?>\r\n\t\t\t\t\t<i class=\"mdui-icon material-icons mdui-icon-dark\" style=\"margin:0;\">chevron_right</i>\r\n\t\t\t\t\t<a href=\"<?php e($l);?>\"><?php e($n);?></a>\r\n\t\t\t\t\t<?php endforeach;?>\r\n\t\t\t\t\t<!--<a href=\"javascript:;\" class=\"mdui-btn mdui-btn-icon\"><i class=\"mdui-icon material-icons\">refresh</i></a>-->\r\n\t\t\t\t</div>\r\n\t\t\t</div>\r\n\t\t\t<?php view::section('content');?>\r\n\t\t</div>\r\n\t\t<meting-js server=\"netease\" type=\"playlist\" id=\"2485662712\" fixed=\"true\">\r\n\t\t</meting-js>\r\n\t\t<!-- id改成自己的歌单号 -->\r\n\t\t<script src=\"/statics/themes/nexmoe/js/personjs.js\">\r\n\t\t</script>\r\n\t\t<script src=\"/statics/themes/nexmoe/js/nexmoe.js\"></script>\r\n\r\n\t</body>\r\n</html>\r\n"
  },
  {
    "path": "view/themes/nexmoe/list.php",
    "content": "<?php view::layout('layout')?>\n<?php \nfunction file_ico($item){\n  $ext = strtolower(pathinfo($item['name'], PATHINFO_EXTENSION));\n  if(in_array($ext,['bmp','jpg','jpeg','png','gif'])){\n  \treturn \"image\";\n  }\n  if(in_array($ext,['mp4','mkv','webm','avi','mpg', 'mpeg', 'rm', 'rmvb', 'mov', 'wmv', 'mkv', 'asf'])){\n  \treturn \"ondemand_video\";\n  }\n  if(in_array($ext,['ogg','mp3','wav'])){\n  \treturn \"audiotrack\";\n  }\n  return \"insert_drive_file\";\n}\n?>\n\n<?php view::begin('content');?>\n\n<?php if(is_login()):?>\n<div class=\"mdui-container-fluid\" >\n\t<div class=\"nexmoe-item\">\n\t<select class=\"mdui-select\" id=\"file_upload\">\n\t\t<option value=\"online_upload\">本地上传</option>\n\t\t<option value=\"remote_upload\">远程上传</option>\n\t\t<option value=\"offline_upload\">aria2上传</option>\n  \t</select>\n\t<button class=\"mdui-btn mdui-ripple\" id=\"pagesearch\">过滤</button>\n\t<button class=\"mdui-btn mdui-ripple\" id=\"newfolder\">新建文件夹</button>\n\t<!-- <button class=\"mdui-btn mdui-ripple\" id=\"file_upload\">上传文件</button> -->\n\t<button class=\"mdui-btn mdui-ripple multiopt\" id=\"deleteall\" style=\"display: none;\">删除</button>\n\t<button class=\"mdui-btn mdui-ripple multiopt\" id=\"copybtn\" onclick=\"copy()\" style=\"display: none;\">复制</button>\n\t<button class=\"mdui-btn mdui-ripple multiopt\" id=\"cutbtn\" onclick=\"cut()\" style=\"display: none;\">剪切</button>\n\t<button class=\"mdui-btn mdui-ripple\" id=\"pastebtn\"  onclick=\"paste()\" style=\"display: none;\">粘贴</button>\n\t<button class=\"mdui-btn mdui-ripple singleopt\" id=\"rename\" style=\"display: none;\">重命名</button>\n\t<button class=\"mdui-btn mdui-ripple multiopt\" id=\"sharebtn\" style=\"display: none;\">分享</button>\n\t</div>\n</div>\n<?php endif;?> \n\n\n<div class=\"mdui-container-fluid\">\n<?php if($head):?>\n<div class=\"mdui-typo\" style=\"padding: 20px;\">\n\t<?php e($head);?>\n</div>\n<?php endif;?>\n<style>\n.thumb .th{\n\tdisplay: none;\n}\n.thumb .mdui-text-right{\n\tdisplay: none;\n}\n.thumb .mdui-list-item a ,.thumb .mdui-list-item {\n\twidth:217px;\n\theight: 230px;\n\tfloat: left;\n\tmargin: 10px 10px !important;\n}\n\n.thumb .mdui-col-xs-12,.thumb .mdui-col-sm-7{\n\twidth:100% !important;\n\theight:230px;\n}\n\n.thumb .mdui-list-item .mdui-icon{\n\tfont-size:100px;\n\tdisplay: block;\n\tmargin-top: 40px;\n\tcolor: #7ab5ef;\n}\n.thumb .mdui-list-item span{\n\tfloat: left;\n\tdisplay: block;\n\ttext-align: center;\n\twidth:100%;\n\tposition: absolute;\n    top: 180px;\n}\n/*loading动画*/\n.simple-spinner {\n  height: 100%;\n  border: 8px solid rgba(150, 150, 150, 0.2);\n  border-radius: 50%;\n  border-top-color: rgb(150, 150, 150);\n  animation: rotate 1s 0s infinite ease-in-out alternate;\n}\n@keyframes rotate {\n  0%   { transform: rotate(0);      }\n  100% { transform: rotate(360deg); }\n}\n</style>\n<div class=\"nexmoe-item\">\n\t<div class=\"mdui-row\">\n\t\t<ul class=\"mdui-list\">\n\t\t\t<li class=\"mdui-list-item th\" id=\"indexsort\">\n\t\t\t<?php if(is_login()):?>\n\t\t\t\t<label class=\"mdui-checkbox\"><input type=\"checkbox\" value=\"\" id=\"checkall\" onclick=\"checkall()\"><i\n\t\t\t\t\t\tclass=\"mdui-checkbox-icon\"></i></label>\n\t\t\t\t<?php endif;?> \n\t\t\t<div class=\"mdui-col-xs-12 mdui-col-sm-7\">文件 <i class=\"mdui-icon material-icons icon-sort\" data-sort=\"name\" data-order=\"downward\">expand_more</i></div>\n\t\t\t<div class=\"mdui-col-sm-3 mdui-text-right\">修改时间 <i class=\"mdui-icon material-icons icon-sort\" data-sort=\"date\" data-order=\"downward\">expand_more</i></div>\n\t\t\t<div class=\"mdui-col-sm-2 mdui-text-right\">大小 <i class=\"mdui-icon material-icons icon-sort\" data-sort=\"size\" data-order=\"downward\">expand_more</i></div>\n\t\t\t</li>\n\t\t\t<?php if($path != '/'):?>\n\t\t\t<li class=\"mdui-list-item mdui-ripple\" id=\"backtolast\">\n\t\t\t\t<a href=\"<?php echo get_absolute_path($root.$path.'../');?>\">\n\t\t\t\t<div class=\"mdui-col-xs-12 mdui-col-sm-7\">\n\t\t\t\t\t<i class=\"mdui-icon material-icons\">arrow_upward</i>\n\t\t\t\t\t..\n\t\t\t\t</div>\n\t\t\t\t<div class=\"mdui-col-sm-3 mdui-text-right\"></div>\n\t\t\t\t<div class=\"mdui-col-sm-2 mdui-text-right\"></div>\n\t\t\t\t</a>\n\t\t\t</li>\n\t\t\t<?php endif;?>\n\t\t\t\n\t\t\t<li class=\"mdui-list-item mdui-ripple filter\" id=\"pending\" style=\"display:none;\"><div class=\"simple-spinner\" id=\"loading\"></div>文件加载中~~~\n\t\t\t</li>\n\t\t\t<?php foreach((array)$items as $item):?>\n\t\t\t\t<?php if(!empty($item['folder'])):?>\n\n\t\t\t<li class=\"mdui-list-item mdui-ripple filter\" data-sort \n\t\t\t\t\t\tdata-sort-name=\"<?php echo $item['name'] ;?>\"\n\t\t\t\t\t\tdata-sort-date=\"<?php echo $item['lastModifiedDateTime'];?>\"\n\t\t\t\t\t\tdata-sort-size=\"<?php echo $item['size'];?>\" \n\t\t\t\t\t\tid=\"<?php echo $item[\"id\"] ?>\">\n\t\t\t\t<div class=\"simple-spinner loading-gif\" style=\"display: none;\"></div>\n\t\t\t\t<?php if(is_login()):?>\n\t\t\t\t<label class=\"mdui-checkbox\">\n\t\t\t\t\t<input type=\"checkbox\" value=\"<?php echo $item[\"id\"] ?>\" name=\"itemid\" onclick=\"onClickHander()\">\n\t\t\t\t\t<i class=\"mdui-checkbox-icon\"></i></label>\n\t\t\t\t<?php endif;?> \t\t\n\t\t\t\t<a href=\"<?php echo get_absolute_path($root.$path.rawurlencode($item['name']));?>\">\n\t\t\t\t<div class=\"mdui-col-xs-12 mdui-col-sm-7 mdui-text-truncate\">\n\t\t\t\t\t<i class=\"mdui-icon material-icons\">folder_open</i>\n\t\t\t\t\t<span><?php echo $item['name'];?></span>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"mdui-col-sm-3 mdui-text-right\"><?php echo date(\"Y-m-d H:i:s\", $item['lastModifiedDateTime']);?></div>\n\t\t\t\t<div class=\"mdui-col-sm-2 mdui-text-right\"><?php echo onedrive::human_filesize($item['size']);?></div>\n\t\t\t\t</a>\n\t\t\t</li>\n\t\t\t\t<?php else:?>\n\t\t\t<li class=\"mdui-list-item file mdui-ripple filter\" data-sort\n\t\t\t\t\t\tdata-sort-name=\"<?php echo $item['name'];?>\"\n\t\t\t\t\t\tdata-sort-date=\"<?php echo $item['lastModifiedDateTime'];?>\"\n\t\t\t\t\t\tdata-sort-size=\"<?php echo $item['size'];?>\" \n\t\t\t\t\t\tid=\"<?php echo $item[\"id\"] ?>\">\n\t\t\t\t<div class=\"simple-spinner loading-gif\" style=\"display: none;\"></div>\n\t\t\t\t\t\t<?php if(is_login()):?>\n\t\t\t\t<label class=\"mdui-checkbox\">\n\t\t\t\t\t<input type=\"checkbox\" value=\"<?php echo $item[\"id\"] ?>\" name=\"itemid\" onclick=\"onClickHander()\">\n\t\t\t\t\t<i class=\"mdui-checkbox-icon\"></i></label>\n\t\t\t\t<?php endif;?> \t\n\t\t\t\t<a href=\"<?php echo get_absolute_path($root.$path).rawurlencode($item['name']);?>\" target=\"_blank\">\n\t\t\t\t<div class=\"mdui-col-xs-12 mdui-col-sm-7 mdui-text-truncate\">\n\t\t\t\t\t<i class=\"mdui-icon material-icons\"><?php echo file_ico($item);?></i>\n\t\t\t\t\t<span><?php e($item['name']);?></span>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"mdui-col-sm-3 mdui-text-right\"><?php echo date(\"Y-m-d H:i:s\", $item['lastModifiedDateTime']);?></div>\n\t\t\t\t<div class=\"mdui-col-sm-2 mdui-text-right\"><?php echo onedrive::human_filesize($item['size']);?></div>\n\t\t\t\t</a>\n\t\t\t</li>\n\t\t\t\t<?php endif;?>\n\n\t\t\t\t<?php endforeach;?>\n\t\t</ul>\n\t</div>\n</div>\n<?php if($readme):?>\n<div class=\"mdui-typo mdui-shadow-3\" style=\"padding: 20px;margin: 20px; \">\n\t<div class=\"mdui-chip\">\n\t  <span class=\"mdui-chip-icon\"><i class=\"mdui-icon material-icons\">face</i></span>\n\t  <span class=\"mdui-chip-title\">README.md</span>\n\t</div>\n\t<?php e($readme);?>\n</div>\n<?php endif;?>\n</div>\n\n<div class=\"mdui-fab-wrapper\" id=\"myFab\">\n    <button class=\"mdui-fab mdui-ripple mdui-color-theme-accent\">\n      <i class=\"mdui-icon material-icons\">add</i>\n      <i class=\"mdui-icon mdui-fab-opened material-icons\">mode_edit</i>\n    </button>\n    <div class=\"mdui-fab-dial\">\n      <button class=\"mdui-fab mdui-fab-mini mdui-ripple mdui-color-red\" id=\"search\" style=\"display: <?php if(!is_login()) echo \"none\" ;else echo \"inline\" ?>;\"><i class=\"mdui-icon material-icons\">&#xe8b6;</i>\n      </button>\n      <button class=\"mdui-fab mdui-fab-mini mdui-ripple mdui-color-orange\" onclick=\"location.href='/?/admin'\"><i class=\"mdui-icon material-icons\">account_circle</i>\n      </button>\n      <button class=\"mdui-fab mdui-fab-mini mdui-ripple mdui-color-blue\" onclick=\"thumb()\"><i class=\"mdui-icon material-icons\" id=\"format_list\">format_list_bulleted</i>\n      </button>\n    </div>\n</div>\n\n<div class=\"mdui-container\">\n  <div class=\"mdui-dialog\" id=\"onlineupload-dialog\">\n    <div class=\"mdui-dialog-title\">文件在线上传</div>\n    <div class=\"mdui-dialog-content\">\n\t\t<div>最大支持4M文件上传</div>\n\t\t<form id=\"filesubmit\" action=\"?/onlinefileupload\" method=\"post\" enctype=\"multipart/form-data\" >\n\t\t\t<input class=\"mdui-center\" type=\"file\" style=\"margin: 50px 0;\" name=\"onlinefile\" />\n\t\t\t<input type=\"text\" style=\"display: none;\" name=\"uploadurl\" value=\"<?php echo $_SERVER['REQUEST_URI']; ?>\"/>\n\t\t</form>\n\t\t<div class=\"mdui-row-xs-3\">\n\t\t\t<div class=\"mdui-col\"></div>\n\t\t\t\t<div class=\"mdui-col\">\n\t\t\t\t\t<button class=\"mdui-btn mdui-btn-block mdui-color-theme-accent mdui-ripple\" onclick=\"submitForm()\">上传</button>\n\t\t\t\t</div>\n\t\t</div>\n\t</div>\n    <div class=\"mdui-dialog-actions\">\n      <button class=\"mdui-btn mdui-ripple\" mdui-dialog-cancel>取消</button>\n    </div>\n  </div>\n</div>\n\n<div class=\"mdui-container\">\n  <div class=\"mdui-dialog\" id=\"remoteupload-dialog\">\n    <div class=\"mdui-dialog-title\">文件远程上传</div>\n    <div class=\"mdui-dialog-content\">\n\t\t<div>仅支持Onedrive个人版，企业和学校版无法使用此功能</div>\n\t\t<form id=\"remoteupload\" action=\"?/upload_url\" method=\"post\" >\n\t\t\t<div class=\"mdui-textfield mdui-textfield-floating-label mdui-col-xs-10 mdui-col-offset-xs-1\">\n\t\t\t\t<label class=\"mdui-textfield-label\">远程URL</label>\n\t\t\t\t<input class=\"mdui-textfield-input\" type=\"url\" name=\"file_url\" id=\"fileurl\" onblur=\"getRemoteUrl()\"/>\n\t\t\t</div>\n\t\t\t<div class=\"mdui-textfield mdui-textfield-floating-label mdui-col-xs-10 mdui-col-offset-xs-1\">\n\t\t\t\t<label class=\"mdui-textfield-label\">文件名称</label>\n\t\t\t\t<input class=\"mdui-textfield-input\" type=\"text\" id=\"filename\" name=\"file_name\" />\n\t\t\t</div>\n\t\t\t\n\t\t\t<input type=\"text\" style=\"display: none;\" name=\"path_url\" value=\"<?php echo $_SERVER['REQUEST_URI']; ?>\"/>\n\t\t</form>\n\t\t<div class=\"mdui-row-xs-3\">\n\t\t\t<div class=\"mdui-col\"></div>\n\t\t\t\t<div class=\"mdui-col\">\n\t\t\t\t\t<button class=\"mdui-btn mdui-btn-block mdui-color-theme-accent mdui-ripple\" onclick=\"submitRemoteFile()\">提交</button>\n\t\t\t\t</div>\n\t\t</div>\n\t</div>\n    <div class=\"mdui-dialog-actions\">\n      <button class=\"mdui-btn mdui-ripple\" mdui-dialog-cancel>取消</button>\n    </div>\n  </div>\n</div>\n\n<div class=\"mdui-container\">\n <div class=\"mdui-dialog\" id=\"search_form\">\n    <div class=\"mdui-dialog-content\">\n\t\t<form action=\"?/search\" method=\"post\">\n\t\t\t<div class=\"mdui-textfield mdui-textfield-floating-label\">\n\t\t\t\t<label class=\"mdui-textfield-label\">输入关键词</label>\n\t\t\t\t<input class=\"mdui-textfield-input\" type=\"text\" style=\"margin: 20px 0;\" name=\"keyword\" />\n\t\t\t\t<div class=\"mdui-row-xs-3\">\n\t\t\t\t<div class=\"mdui-col\"></div>\n\t\t\t\t\t<div class=\"mdui-col\">\n\t\t\t\t\t\t<button class=\"mdui-btn mdui-btn-block mdui-color-theme-accent mdui-ripple\">提交</button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</form>\n\t</div>\n  </div>\n</div>\n\n\n<div class=\"mdui-container\">\n <div class=\"mdui-dialog\" id=\"share\">\n    <div class=\"mdui-dialog-content\">\n\t\t\t<div class=\"mdui-textfield mdui-textfield-floating-label\">\n\t\t\t\t<label class=\"mdui-textfield-label\">选中的项目链接</label>\n\t\t\t\t<textarea class=\"mdui-textfield-input\" style=\"margin: 20px 0;\" rows=\"5\" readonly id=\"sharelinks\"></textarea>\n\t\t\t</div>\n\t</div>\n  </div>\n</div>\n\n<div class=\"mdui-container\">\n\t<div class=\"mdui-dialog\" id=\"progress\">\n\t\t<div class=\"mdui-dialog-content\">\n\t\t\t<span>文件处理进程</span>\n\t\t\t<div class=\"mdui-progress\" >\n\t\t\t\t<div class=\"mdui-progress-determinate\" style=\"width: 0%;\" id=\"progress_width\"></div>\n\t\t\t</div>\n\t\t</div>\n\t\t\n\t</div>\n</div>\n<!-- <script src=\"https://cdn.jsdelivr.net/gh/xieqifei/OneindexN@v1.31/statics/js/nexmoe.js\"></script> -->\n\n<script src=\"https://code.jquery.com/jquery-3.5.1.min.js\" integrity=\"sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=\" crossorigin=\"anonymous\"></script>\n<script src=\"//cdnjs.loli.net/ajax/libs/mdui/0.4.3/js/mdui.min.js\"></script>\n<script src=\"https://cdn.bootcdn.net/ajax/libs/clipboard.js/2.0.6/clipboard.min.js\"></script>\n\n<?php view::end('content');?>\n"
  },
  {
    "path": "view/themes/nexmoe/password.php",
    "content": "<?php view::layout('layout')?>\n\n<?php view::begin('content');?>\n\t\n<div class=\"mdui-container-fluid\">\n\t<div class=\"mdui-col-md-6 mdui-col-offset-md-3\">\n\t  <center><h1 class=\"mdui-typo-display-2-opacity\">请输入密码</h1></center>\n\t  <form action=\"\" method=\"post\">\n\t\t  <div class=\"mdui-textfield mdui-textfield-floating-label\">\n\t\t    <i class=\"mdui-icon material-icons\">https</i>\n\t\t    <label class=\"mdui-textfield-label\">密码</label>\n\t\t    <input name=\"password\" class=\"mdui-textfield-input\" type=\"password\"/>\n\t\t  </div>\n\t\t  <br>\n\t\t  <button type=\"submit\" class=\"mdui-center mdui-btn mdui-btn-raised mdui-ripple mdui-color-theme\">\n\t\t  \t<i class=\"mdui-icon material-icons\">fingerprint</i>\n\t\t  \t查看\n\t\t  </button>\n\t  </form>\n\t</div>\n\t\n</div>\n\n<?php view::end('content');?>"
  },
  {
    "path": "view/themes/nexmoe/readme.html",
    "content": "\n<!DOCTYPE html>\n<html>\n<head>\n\t<meta charset=\"utf-8\">\n\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0,maximum-scale=1.0, user-scalable=no\"/>\n\t<title>根目录 - OneIndex</title>\n\t<link rel=\"icon\" type=\"image/png\" href=\"https://mintimate.cn/img/favicon.png\">\n\t<link rel=\"apple-touch-icon\" sizes=\"76x76\" href=\"https://mintimate.cn/img/favicon.png\">\n\t\t<link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css\">\n\t\t\t<script src=\"https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.js\"></script>\n\t\t\t\t<script src=\"https://cdn.jsdelivr.net/npm/meting@2/dist/Meting.min.js\"></script>\n\n\t<link href=\"https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.2/css/bootstrap.min.css\" rel=\"stylesheet\">\n\t<link rel=\"stylesheet\" href=\"//cdnjs.loli.net/ajax/libs/mdui/0.4.3/css/mdui.min.css\">\n\t<style>\n\t\tbody{background-color:#f2f5fa;padding-bottom:60px;background-position:center bottom;background-repeat:no-repeat;background-attachment:fixed}.nexmoe-item{margin:20px -8px 0!important;padding:15px!important;border-radius:5px;background-color:#fff;-webkit-box-shadow:0 .5em 3em rgba(161,177,204,.4);box-shadow:0 .5em 3em rgba(161,177,204,.4);background-color:#fff}.mdui-img-fluid,.mdui-video-fluid{border-radius:5px;border:1px solid #eee}.mdui-list{padding:0}.mdui-list-item{margin:0!important;border-radius:5px;padding:0 10px 0 5px!important;border:1px solid #eee;margin-bottom:10px!important}.mdui-list-item:last-child{margin-bottom:0!important}.mdui-list-item:first-child{border:none}.mdui-toolbar{width:auto;margin-top:60px!important}.mdui-appbar .mdui-toolbar{height:56px;font-size:16px}.mdui-toolbar>*{padding:0 6px;margin:0 2px;opacity:.5}.mdui-toolbar>.mdui-typo-headline{padding:0 16px 0 0}.mdui-toolbar>i{padding:0}.mdui-toolbar>a:hover,a.mdui-typo-headline,a.active{opacity:1}.mdui-container{max-width:980px}.mdui-list>.th{background-color:initial}.mdui-list-item>a{width:100%;line-height:48px}.mdui-toolbar>a{padding:0 16px;line-height:30px;border-radius:30px;border:1px solid #eee}.mdui-toolbar>a:last-child{opacity:1;background-color:#1e89f2;color:#ffff}@media screen and (max-width:980px){.mdui-list-item .mdui-text-right{display:none}.mdui-container{width:100%!important;margin:0}.mdui-toolbar>*{display:none}.mdui-toolbar>a:last-child,.mdui-toolbar>.mdui-typo-headline,.mdui-toolbar>i:first-child{display:block}}\n\t</style>\n\t<script src=\"https://cdn.jsdelivr.net/gh/xieqifei/StaticsResources/oneindexn/mdui/mdui.min.js\"></script>\t\n</head>\n<body class=\"mdui-theme-primary-blue-grey mdui-theme-accent-blue\">\n\n<nav class=\"navbar navbar-light bg-light\">\n  <a class=\"navbar-brand ml-lg-5 pl-lg-5\" href=\"/\">\n    <img src=\"https://cdn.jsdelivr.net/gh/Mintimate/OneIndex-theme-nexmoes@latest/nexmoes/picture/logo.png\" width=\"30\" height=\"30\" class=\"d-inline-block align-top\" alt=\"\">\n    <span class=\"ml-2\">OneIndex</span>\n  </a>\n  <a class=\"nav-link mr-lg-5 pr-lg-5\" href=\"https://www.mintimate.cn/about\">技术支持</a>\n</nav>\n\t\n\t<div class=\"mdui-container\">\n\t    <div class=\"mdui-container-fluid\">\n\t    <div class=\"mdui-toolbar nexmoe-item\">\n\t\t\t<a href=\"/\">OneIndex</a>\n\t\t\t\t\t\t<i class=\"mdui-icon material-icons mdui-icon-dark\" style=\"margin:0;\">chevron_right</i>\n\t\t\t<a href=\"/?/\">/</a>\n\t\t\t\t\t\t<!--<a href=\"javascript:;\" class=\"mdui-btn mdui-btn-icon\"><i class=\"mdui-icon material-icons\">refresh</i></a>-->\n\t\t</div>\n\t\t</div>\n    \t\n \n\n\n<div class=\"mdui-container-fluid\">\n<style>\n.thumb .th{\n\tdisplay: none;\n}\n.thumb .mdui-text-right{\n\tdisplay: none;\n}\n.thumb .mdui-list-item a ,.thumb .mdui-list-item {\n\twidth:217px;\n\theight: 230px;\n\tfloat: left;\n\tmargin: 10px 10px !important;\n}\n\n.thumb .mdui-col-xs-12,.thumb .mdui-col-sm-7{\n\twidth:100% !important;\n\theight:230px;\n}\n\n.thumb .mdui-list-item .mdui-icon{\n\tfont-size:100px;\n\tdisplay: block;\n\tmargin-top: 40px;\n\tcolor: #7ab5ef;\n}\n.thumb .mdui-list-item span{\n\tfloat: left;\n\tdisplay: block;\n\ttext-align: center;\n\twidth:100%;\n\tposition: absolute;\n    top: 180px;\n}\n/*loading动画*/\n.simple-spinner {\n  height: 100%;\n  border: 8px solid rgba(150, 150, 150, 0.2);\n  border-radius: 50%;\n  border-top-color: rgb(150, 150, 150);\n  animation: rotate 1s 0s infinite ease-in-out alternate;\n}\n@keyframes rotate {\n  0%   { transform: rotate(0);      }\n  100% { transform: rotate(360deg); }\n}\n</style>\n<div class=\"nexmoe-item\">\n\t<div class=\"mdui-row\">\n\t\t<ul class=\"mdui-list\">\n\t\t\t<li class=\"mdui-list-item th\" id=\"indexsort\">\n\t\t\t \n\t\t\t<div class=\"mdui-col-xs-12 mdui-col-sm-7\">文件 <i class=\"mdui-icon material-icons icon-sort\" data-sort=\"name\" data-order=\"downward\">expand_more</i></div>\n\t\t\t<div class=\"mdui-col-sm-3 mdui-text-right\">修改时间 <i class=\"mdui-icon material-icons icon-sort\" data-sort=\"date\" data-order=\"downward\">expand_more</i></div>\n\t\t\t<div class=\"mdui-col-sm-2 mdui-text-right\">大小 <i class=\"mdui-icon material-icons icon-sort\" data-sort=\"size\" data-order=\"downward\">expand_more</i></div>\n\t\t\t</li>\n\t\t\t\t\t\t\n\t\t\t<li class=\"mdui-list-item mdui-ripple filter\" id=\"pending\" style=\"display:none;\"><div class=\"simple-spinner\" id=\"loading\"></div>文件加载中~~~\n\t\t\t</li>\n\t\t\t\t\t\t\t\n\t\t\t<li class=\"mdui-list-item mdui-ripple filter\" data-sort \n\t\t\t\t\t\tdata-sort-name=\"Mac\"\n\t\t\t\t\t\tdata-sort-date=\"1599626781\"\n\t\t\t\t\t\tdata-sort-size=\"8616521996\" \n\t\t\t\t\t\tid=\"1DD95BD0077CA497!3204\">\n\t\t\t\t<div class=\"simple-spinner loading-gif\" style=\"display: none;\"></div>\n\t\t\t\t \t\t\n\t\t\t\t<a href=\"/?/Mac/\">\n\t\t\t\t<div class=\"mdui-col-xs-12 mdui-col-sm-7 mdui-text-truncate\">\n\t\t\t\t\t<i class=\"mdui-icon material-icons\">folder_open</i>\n\t\t\t\t\t<span>Mac</span>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"mdui-col-sm-3 mdui-text-right\">2020-09-09 12:46:21</div>\n\t\t\t\t<div class=\"mdui-col-sm-2 mdui-text-right\">8GB</div>\n\t\t\t\t</a>\n\t\t\t</li>\n\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t<li class=\"mdui-list-item mdui-ripple filter\" data-sort \n\t\t\t\t\t\tdata-sort-name=\"Videos\"\n\t\t\t\t\t\tdata-sort-date=\"1599464478\"\n\t\t\t\t\t\tdata-sort-size=\"59124736600\" \n\t\t\t\t\t\tid=\"1DD95BD0077CA497!3173\">\n\t\t\t\t<div class=\"simple-spinner loading-gif\" style=\"display: none;\"></div>\n\t\t\t\t \t\t\n\t\t\t\t<a href=\"/?/Videos/\">\n\t\t\t\t<div class=\"mdui-col-xs-12 mdui-col-sm-7 mdui-text-truncate\">\n\t\t\t\t\t<i class=\"mdui-icon material-icons\">folder_open</i>\n\t\t\t\t\t<span>Videos</span>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"mdui-col-sm-3 mdui-text-right\">2020-09-07 15:41:18</div>\n\t\t\t\t<div class=\"mdui-col-sm-2 mdui-text-right\">55.1GB</div>\n\t\t\t\t</a>\n\t\t\t</li>\n\t\t\t\t\n\t\t\t\t\t\t\t\t\n\t\t\t<li class=\"mdui-list-item mdui-ripple filter\" data-sort \n\t\t\t\t\t\tdata-sort-name=\"Wallpapers\"\n\t\t\t\t\t\tdata-sort-date=\"1599362878\"\n\t\t\t\t\t\tdata-sort-size=\"2564491\" \n\t\t\t\t\t\tid=\"1DD95BD0077CA497!3174\">\n\t\t\t\t<div class=\"simple-spinner loading-gif\" style=\"display: none;\"></div>\n\t\t\t\t \t\t\n\t\t\t\t<a href=\"/?/Wallpapers/\">\n\t\t\t\t<div class=\"mdui-col-xs-12 mdui-col-sm-7 mdui-text-truncate\">\n\t\t\t\t\t<i class=\"mdui-icon material-icons\">folder_open</i>\n\t\t\t\t\t<span>Wallpapers</span>\n\t\t\t\t</div>\n\t\t\t\t<div class=\"mdui-col-sm-3 mdui-text-right\">2020-09-06 11:27:58</div>\n\t\t\t\t<div class=\"mdui-col-sm-2 mdui-text-right\">2.4MB</div>\n\t\t\t\t</a>\n\t\t\t</li>\n\t\t\t\t\n\t\t\t\t\t\t</ul>\n\t</div>\n</div>\n</div>\n\n<div class=\"mdui-fab-wrapper\" id=\"myFab\">\n    <button class=\"mdui-fab mdui-ripple mdui-color-theme-accent\">\n      <i class=\"mdui-icon material-icons\">add</i>\n      <i class=\"mdui-icon mdui-fab-opened material-icons\">mode_edit</i>\n    </button>\n    <div class=\"mdui-fab-dial\">\n      <button class=\"mdui-fab mdui-fab-mini mdui-ripple mdui-color-red\" id=\"search\" style=\"display: none;\"><i class=\"mdui-icon material-icons\">&#xe8b6;</i>\n      </button>\n      <button class=\"mdui-fab mdui-fab-mini mdui-ripple mdui-color-orange\" onclick=\"location.href='/?/admin'\"><i class=\"mdui-icon material-icons\">account_circle</i>\n      </button>\n      <button class=\"mdui-fab mdui-fab-mini mdui-ripple mdui-color-blue\" onclick=\"thumb()\"><i class=\"mdui-icon material-icons\" id=\"format_list\">format_list_bulleted</i>\n      </button>\n    </div>\n</div>\n\n<div class=\"mdui-container\">\n  <div class=\"mdui-dialog\" id=\"onlineupload-dialog\">\n    <div class=\"mdui-dialog-title\">文件在线上传</div>\n    <div class=\"mdui-dialog-content\">\n\t\t<div>最大支持4M文件上传</div>\n\t\t<form id=\"filesubmit\" action=\"?/onlinefileupload\" method=\"post\" enctype=\"multipart/form-data\" >\n\t\t\t<input class=\"mdui-center\" type=\"file\" style=\"margin: 50px 0;\" name=\"onlinefile\" />\n\t\t\t<input type=\"text\" style=\"display: none;\" name=\"uploadurl\" value=\"/\"/>\n\t\t</form>\n\t\t<div class=\"mdui-row-xs-3\">\n\t\t\t<div class=\"mdui-col\"></div>\n\t\t\t\t<div class=\"mdui-col\">\n\t\t\t\t\t<button class=\"mdui-btn mdui-btn-block mdui-color-theme-accent mdui-ripple\" onclick=\"submitForm()\">上传</button>\n\t\t\t\t</div>\n\t\t</div>\n\t</div>\n    <div class=\"mdui-dialog-actions\">\n      <button class=\"mdui-btn mdui-ripple\" mdui-dialog-cancel>取消</button>\n    </div>\n  </div>\n</div>\n\n<div class=\"mdui-container\">\n  <div class=\"mdui-dialog\" id=\"remoteupload-dialog\">\n    <div class=\"mdui-dialog-title\">文件远程上传</div>\n    <div class=\"mdui-dialog-content\">\n\t\t<div>仅支持Onedrive个人版，企业和学校版无法使用此功能</div>\n\t\t<form id=\"remoteupload\" action=\"?/upload_url\" method=\"post\" >\n\t\t\t<div class=\"mdui-textfield mdui-textfield-floating-label mdui-col-xs-10 mdui-col-offset-xs-1\">\n\t\t\t\t<label class=\"mdui-textfield-label\">远程URL</label>\n\t\t\t\t<input class=\"mdui-textfield-input\" type=\"url\" name=\"file_url\" id=\"fileurl\" onblur=\"getRemoteUrl()\"/>\n\t\t\t</div>\n\t\t\t<div class=\"mdui-textfield mdui-textfield-floating-label mdui-col-xs-10 mdui-col-offset-xs-1\">\n\t\t\t\t<label class=\"mdui-textfield-label\">文件名称</label>\n\t\t\t\t<input class=\"mdui-textfield-input\" type=\"text\" id=\"filename\" name=\"file_name\" />\n\t\t\t</div>\n\t\t\t\n\t\t\t<input type=\"text\" style=\"display: none;\" name=\"path_url\" value=\"/\"/>\n\t\t</form>\n\t\t<div class=\"mdui-row-xs-3\">\n\t\t\t<div class=\"mdui-col\"></div>\n\t\t\t\t<div class=\"mdui-col\">\n\t\t\t\t\t<button class=\"mdui-btn mdui-btn-block mdui-color-theme-accent mdui-ripple\" onclick=\"submitRemoteFile()\">提交</button>\n\t\t\t\t</div>\n\t\t</div>\n\t</div>\n    <div class=\"mdui-dialog-actions\">\n      <button class=\"mdui-btn mdui-ripple\" mdui-dialog-cancel>取消</button>\n    </div>\n  </div>\n</div>\n\n<div class=\"mdui-container\">\n <div class=\"mdui-dialog\" id=\"search_form\">\n    <div class=\"mdui-dialog-content\">\n\t\t<form action=\"?/search\" method=\"post\">\n\t\t\t<div class=\"mdui-textfield mdui-textfield-floating-label\">\n\t\t\t\t<label class=\"mdui-textfield-label\">输入关键词</label>\n\t\t\t\t<input class=\"mdui-textfield-input\" type=\"text\" style=\"margin: 20px 0;\" name=\"keyword\" />\n\t\t\t\t<div class=\"mdui-row-xs-3\">\n\t\t\t\t<div class=\"mdui-col\"></div>\n\t\t\t\t\t<div class=\"mdui-col\">\n\t\t\t\t\t\t<button class=\"mdui-btn mdui-btn-block mdui-color-theme-accent mdui-ripple\">提交</button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</form>\n\t</div>\n  </div>\n</div>\n\n\n<div class=\"mdui-container\">\n <div class=\"mdui-dialog\" id=\"share\">\n    <div class=\"mdui-dialog-content\">\n\t\t\t<div class=\"mdui-textfield mdui-textfield-floating-label\">\n\t\t\t\t<label class=\"mdui-textfield-label\">选中的项目链接</label>\n\t\t\t\t<textarea class=\"mdui-textfield-input\" style=\"margin: 20px 0;\" rows=\"5\" readonly id=\"sharelinks\"></textarea>\n\t\t\t</div>\n\t</div>\n  </div>\n</div>\n\n<div class=\"mdui-container\">\n\t<div class=\"mdui-dialog\" id=\"progress\">\n\t\t<div class=\"mdui-dialog-content\">\n\t\t\t<span>文件处理进程</span>\n\t\t\t<div class=\"mdui-progress\" >\n\t\t\t\t<div class=\"mdui-progress-determinate\" style=\"width: 0%;\" id=\"progress_width\"></div>\n\t\t\t</div>\n\t\t</div>\n\t\t\n\t</div>\n</div>\n<!-- <script src=\"https://cdn.jsdelivr.net/gh/xieqifei/OneindexN@v1.31/statics/js/nexmoe.js\"></script> -->\n\n<script src=\"https://code.jquery.com/jquery-3.5.1.min.js\" integrity=\"sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=\" crossorigin=\"anonymous\"></script>\n<script src=\"//cdnjs.loli.net/ajax/libs/mdui/0.4.3/js/mdui.min.js\"></script>\n<script src=\"https://cdn.bootcdn.net/ajax/libs/clipboard.js/2.0.6/clipboard.min.js\"></script>\n<script src=\"https://cdn.jsdelivr.net/gh/xieqifei/StaticsResources@v1.4/oneindexn/themes/nexmoe/js/nexmoe.js\"></script>\n\n  \t</div>\n  \t\t<meting-js\n\t\tserver=\"netease\"\n\t\ttype=\"playlist\"\n\t\tid=\"2485662712\"\n\t\tfixed=\"true\">\n\t</meting-js>\n\t<!-- id改成自己的歌单号 -->\n\t<script src=\"https://cdn.jsdelivr.net/gh/Mintimate/OneIndex-theme-nexmoes@latest/nexmoes/theme/personjs.js\"></script>\n  \t<script src=\"https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js\"></script>\n</body>\n</html>\n"
  },
  {
    "path": "view/themes/nexmoe/show/audio.php",
    "content": "<?php view::layout('layout')?>\n\n<?php view::begin('content');?>\n<div class=\"mdui-container-fluid\">\n    <div class=\"nexmoe-item\">\n\t\n\t<audio class=\"mdui-center\" src=\"<?php e($item['downloadUrl']);?>\" controls autoplay style=\"width: 100%;\"  poster=\"<?php @e($item['thumb'].'&width=176&height=176');?>\">\n\t</audio>\n\t\n\t<br>\n\t<!-- 固定标签 -->\n\t<div class=\"mdui-textfield\">\n\t  <label class=\"mdui-textfield-label\">下载地址</label>\n\t  <input class=\"mdui-textfield-input\" type=\"text\" value=\"<?php e($url);?>\"/>\n\t</div>\n\t<div class=\"mdui-textfield\">\n\t  <label class=\"mdui-textfield-label\">引用地址</label>\n\t  <textarea class=\"mdui-textfield-input\"><audio src=\"<?php e($url);?>\"></audio></textarea>\n\t</div>\n\t</div>\n</div>\n<a href=\"<?php e($url);?>\" class=\"mdui-fab mdui-fab-fixed mdui-ripple mdui-color-theme-accent\"><i class=\"mdui-icon material-icons\">file_download</i></a>\n<?php view::end('content');?>"
  },
  {
    "path": "view/themes/nexmoe/show/code.php",
    "content": "<?php view::layout('layout')?>\n<?php \n\tfunction code_type($ext){\n\t\t$code_type['html'] = 'html';\n\t\t$code_type['htm'] = 'html';\n\t\t$code_type['php'] = 'php';\n\t\t$code_type['css'] = 'css';\n\t\t$code_type['go'] = 'golang';\n\t\t$code_type['java'] = 'java';\n\t\t$code_type['js'] = 'javascript';\n\t\t$code_type['json'] = 'json';\n\t\t$code_type['txt'] = 'Text';\n\t\t$code_type['sh'] = 'sh';\n\t\t$code_type['md'] = 'Markdown';\n\t\t\n\t\treturn @$code_type[$ext];\n\t}\n\t$language = code_type($ext);\n\n\t$content = IndexController::get_content($item);\n?>\n<?php view::begin('content');?>\n<style type=\"text/css\" media=\"screen\">\n    #editor { \n        /*height:800px;*/\n    }\n</style>\n<div class=\"mdui-container-fluid\">\n    <div class=\"nexmoe-item\">\n\n        <pre id=\"editor\" ><?php echo htmlentities($content);?></pre>\n\n        <div class=\"mdui-textfield\">\n\t        <label class=\"mdui-textfield-label\">下载地址</label>\n\t        <input class=\"mdui-textfield-input\" type=\"text\" value=\"<?php e($url);?>\"/>\n        </div>\n    \n    </div>\n</div>\n<a href=\"<?php e($url);?>\" class=\"mdui-fab mdui-fab-fixed mdui-ripple mdui-color-theme-accent\"><i class=\"mdui-icon material-icons\">file_download</i></a>\n\n<script src=\"https://cdn.bootcss.com/ace/1.2.9/ace.js\"></script>\n<script src=\"https://cdn.bootcss.com/ace/1.2.9/ext-language_tools.js\"></script>\n<script>\n    var editor = ace.edit(\"editor\");\n    editor.setTheme(\"ace/theme/ambiance\");\n    editor.setFontSize(18);\n    editor.session.setMode(\"ace/mode/<?php e($language);?>\");\n    \n    //Autocompletion\n    editor.setOptions({\n        enableBasicAutocompletion: true,\n        enableSnippets: true,\n        enableLiveAutocompletion: true,\n        maxLines: Infinity\n    });\n</script>\n<?php view::end('content');?>"
  },
  {
    "path": "view/themes/nexmoe/show/doc.php",
    "content": "<?php \n\t$url = 'https://view.officeapps.live.com/op/view.aspx?src='.urlencode($item['downloadUrl']);\n\tview::direct($url);\n\texit();\n?>\n"
  },
  {
    "path": "view/themes/nexmoe/show/image.php",
    "content": "<?php view::layout('layout')?>\n\n<?php view::begin('content');?>\n\n\n<div class=\"mdui-container-fluid\">\n    <div class=\"nexmoe-item\">\n\t\n\t<img class=\"mdui-img-fluid mdui-center\" src=\"<?php e($item['downloadUrl']);?>\"/>\n\t\n\t<div class=\"mdui-textfield\">\n\t  <label class=\"mdui-textfield-label\">下载地址</label>\n\t  <input class=\"mdui-textfield-input\" type=\"text\" value=\"<?php e($url);?>\"/>\n\t</div>\n\t<div class=\"mdui-textfield\">\n\t  <label class=\"mdui-textfield-label\">HTML 引用地址</label>\n\t  <input class=\"mdui-textfield-input\" type=\"text\" value=\"<img src='<?php e($url);?>' />\"/>\n\t</div>\n        <div class=\"mdui-textfield\">\n\t  <label class=\"mdui-textfield-label\">Markdown 引用地址</label>\n\t  <input class=\"mdui-textfield-input\" type=\"text\" value=\"![](<?php e($url);?>)\"/>\n\t</div>\n       \n    </div>\n</div>\n\n<a href=\"<?php e($url);?>\" class=\"mdui-fab mdui-fab-fixed mdui-ripple mdui-color-theme-accent\"><i class=\"mdui-icon material-icons\">file_download</i></a>\n<?php view::end('content');?>\n"
  },
  {
    "path": "view/themes/nexmoe/show/pdf.php",
    "content": "<?php view::layout('layout')?>\n\n<?php view::begin('content');?>\n\t<iframe id=\"mask\" src='<?php echo str_replace('transform/thumbnail?', 'transform/pdf?',$item['thumb']);?>' \n\t\tallowfullscreen=\"allowfullscreen\"\n        mozallowfullscreen=\"mozallowfullscreen\"\n        msallowfullscreen=\"msallowfullscreen\"\n        oallowfullscreen=\"oallowfullscreen\"\n        webkitallowfullscreen=\"webkitallowfullscreen\"\n        width=\"100%\"\n        style=\"position: absolute;top:0;left:0; z-index:10;\"\n        ></iframe>\n<a href=\"<?php e($url);?>\" class=\"mdui-fab mdui-fab-fixed mdui-ripple mdui-color-theme-accent\" style=\"z-index:99;\"><i class=\"mdui-icon material-icons\">file_download</i></a>\n<script>\n$ = mdui.JQ;\n$(function(){  \n      \n    var sWidth=document.documentElement.clientWidth;  \n    var sHeight=document.documentElement.clientHeight;  \n    //获取页面的可视区域高度和宽度  \n    var wHeight=document.documentElement.clientHeight;  \n    var oMask=document.getElementById(\"mask\");  \n    var oMaskIframe=document.getElementById(\"maskIframe\");  \n      \n    oMask.style.height=(sHeight-1)+\"px\";  \n    oMask.style.width=(sWidth-4)+\"px\";  \n      \n});  \n</script>\n<?php view::end('content');?>"
  },
  {
    "path": "view/themes/nexmoe/show/stream.php",
    "content": "<?php \n\n$types = [\n\t'chm'=>'application/octet-stream',\n\t'ppt'=>'application/vnd.ms-powerpoint',\n\t'xls'=>'application/vnd.ms-excel',\n\t'doc'=>'application/msword',\n\t'exe'=>'application/octet-stream',\n\t'rar'=>'application/octet-stream',\n\t'js'=>\"javascrīpt/js\",\n\t'css'=>\"text/css\",\n\t'hqx'=>\"application/mac-binhex40\",\n\t'bin'=>\"application/octet-stream\",\n\t'oda'=>\"application/oda\",\n\t'pdf'=>\"application/pdf\",\n\t'ai'=>\"application/postsrcipt\",\n\t'eps'=>\"application/postsrcipt\",\n\t'es'=>\"application/postsrcipt\",\n\t'rtf'=>\"application/rtf\",\n\t'mif'=>\"application/x-mif\",\n\t'csh'=>\"application/x-csh\",\n\t'dvi'=>\"application/x-dvi\",\n\t'hdf'=>\"application/x-hdf\",\n\t'nc'=>\"application/x-netcdf\",\n\t'cdf'=>\"application/x-netcdf\",\n\t'latex'=>\"application/x-latex\",\n\t'ts'=>\"application/x-troll-ts\",\n\t'src'=>\"application/x-wais-source\",\n\t'zip'=>\"application/zip\",\n\t'bcpio'=>\"application/x-bcpio\",\n\t'cpio'=>\"application/x-cpio\",\n\t'gtar'=>\"application/x-gtar\",\n\t'shar'=>\"application/x-shar\",\n\t'sv4cpio'=>\"application/x-sv4cpio\",\n\t'sv4crc'=>\"application/x-sv4crc\",\n\t'tar'=>\"application/x-tar\",\n\t'ustar'=>\"application/x-ustar\",\n\t'man'=>\"application/x-troff-man\",\n\t'sh'=>\"application/x-sh\",\n\t'tcl'=>\"application/x-tcl\",\n\t'tex'=>\"application/x-tex\",\n\t'texi'=>\"application/x-texinfo\",\n\t'texinfo'=>\"application/x-texinfo\",\n\t't'=>\"application/x-troff\",\n\t'tr'=>\"application/x-troff\",\n\t'roff'=>\"application/x-troff\",\n\t'shar'=>\"application/x-shar\",\n\t'me'=>\"application/x-troll-me\",\n\t'ts'=>\"application/x-troll-ts\",\n\t'gif'=>\"image/gif\",\n\t'jpeg'=>\"image/pjpeg\",\n\t'jpg'=>\"image/pjpeg\",\n\t'jpe'=>\"image/pjpeg\",\n\t'ras'=>\"image/x-cmu-raster\",\n\t'pbm'=>\"image/x-portable-bitmap\",\n\t'ppm'=>\"image/x-portable-pixmap\",\n\t'xbm'=>\"image/x-xbitmap\",\n\t'xwd'=>\"image/x-xwindowdump\",\n\t'ief'=>\"image/ief\",\n\t'tif'=>\"image/tiff\",\n\t'tiff'=>\"image/tiff\",\n\t'pnm'=>\"image/x-portable-anymap\",\n\t'pgm'=>\"image/x-portable-graymap\",\n\t'rgb'=>\"image/x-rgb\",\n\t'xpm'=>\"image/x-xpixmap\",\n\t'txt'=>\"text/plain\",\n\t'c'=>\"text/plain\",\n\t'cc'=>\"text/plain\",\n\t'h'=>\"text/plain\",\n\t'html'=>\"text/html\",\n\t'htm'=>\"text/html\",\n\t'htl'=>\"text/html\",\n\t'txt'=>\"text/html\",\n\t'php'=>\"text/html\",\n\t'rtx'=>\"text/richtext\",\n\t'etx'=>\"text/x-setext\",\n\t'tsv'=>\"text/tab-separated-values\",\n\t'mpeg'=>\"video/mpeg\",\n\t'mpg'=>\"video/mpeg\",\n\t'mpe'=>\"video/mpeg\",\n\t'avi'=>\"video/x-msvideo\",\n\t'qt'=>\"video/quicktime\",\n\t'mov'=>\"video/quicktime\",\n\t'moov'=>\"video/quicktime\",\n\t'movie'=>\"video/x-sgi-movie\",\n\t'au'=>\"audio/basic\",\n\t'snd'=>\"audio/basic\",\n\t'wav'=>\"audio/x-wav\",\n\t'aif'=>\"audio/x-aiff\",\n\t'aiff'=>\"audio/x-aiff\",\n\t'aifc'=>\"audio/x-aiff\",\n\t'swf'=>\"application/x-shockwave-flash\",\n\t'myz'=>\"application/myz\"\n];\n//大于 5M 跳转为直连下载\nif($item['size'] > 5242880){\n\theader('Location: '.$item['downloadUrl']);exit();\n}\n$type = empty($types[$ext])?\"application/octet-stream\":$types[$ext];\n$content = IndexController::get_content($item);\n\nheader('Content-type: '.$type);\necho $content;\nexit();\n?>"
  },
  {
    "path": "view/themes/nexmoe/show/video.php",
    "content": "<?php view::layout('layout')?>\n<?php\n$item['thumb'] = onedrive::thumbnail($item['path']);\n?>\n<?php view::begin('content');?>\n<link crossorigin=\"anonymous\" integrity=\"sha384-WBkDouo/0CCXxPpQ0M6rTUkTGZL30VNhKNg07BZy/8Le4IXY4jv/ihAvI1J9+s4b\" href=\"https://lib.baomitu.com/dplayer/1.25.0/DPlayer.min.css\" rel=\"stylesheet\">\n<script crossorigin=\"anonymous\" integrity=\"sha384-6CyF/JZDLd9z4fvRApunnpxkvVlYkSK1WPTbA9u3v2e/HgviJP3b9HVX2gD+/1CC\" src=\"https://lib.baomitu.com/dplayer/1.25.0/DPlayer.min.js\"></script>\n<div class=\"mdui-container-fluid\">\n\t<div class=\"nexmoe-item\">\n\t<div class=\"mdui-center\" id=\"dplayer\"></div>\n\t<div class=\"mdui-p-t-5 \">\n\t\t<ul class=\"mdui-menu\" id=\"menu\">\n\t\t\t<li class=\"mdui-menu-item\">\n\t\t\t<a href=\"intent:<?php e($url);?>;end\" class=\"mdui-ripple\">MXPlayer(FREE)</a>\n\t\t\t</li>\n\t\t\t<li class=\"mdui-menu-item\">\n\t\t\t<a href=\"vlc://<?php e($url);?>\" class=\"mdui-ripple\">VLC</a>\n\t\t\t</li>\n\t\t\t<li class=\"mdui-menu-item\">\n\t\t\t<a href=\"potplayer://<?php e($url);?>\" class=\"mdui-ripple\">PotPlayer</a>\n\t\t\t</li>\n\t\t\t<li class=\"mdui-menu-item\">\n\t\t\t<a href=\"nplayer-<?php e($url);?>\" class=\"mdui-ripple\">PotPlayer</a>\n\t\t\t</li>\n\t\t\t\n\t\t</ul>\n\n\t\t<button id=\"appplayers\" class=\"mdui-btn mdui-ripple mdui-color-theme-accent\"><i class=\"mdui-icon material-icons\">&#xe039;</i>外部播放器播放<i class=\"mdui-icon material-icons\">&#xe313;</i></button>\n\t</div>\n\t<!-- 固定标签 -->\n\t<div class=\"mdui-textfield\">\n\t  <label class=\"mdui-textfield-label\">下载地址</label>\n\t  <input class=\"mdui-textfield-input\" type=\"text\" value=\"<?php e($url);?>\"/>\n\t</div>\n\t<div class=\"mdui-textfield\">\n\t  <label class=\"mdui-textfield-label\">引用地址</label>\n\t  <textarea class=\"mdui-textfield-input\"><video><source src=\"<?php e($url);?>\" type=\"video/mp4\"></video></textarea>\n\t</div>\n\t</div>\n</div>\n<script>\nconst dp = new DPlayer({\n\tcontainer: document.getElementById('dplayer'),\n\tlang:'zh-cn',\n\tvideo: {\n\t    url: '<?php e($item['downloadUrl']);?>',\n\t    pic: '<?php @e($item['thumb']);?>',\n\t    type: '<?php e((pathinfo($item[\"name\"], PATHINFO_EXTENSION) === 'flv') ? 'flv' : 'auto'); ?>'\n\t}\n});\nvar inst = new mdui.Menu('#appplayers', '#menu');\n\n// method\ndocument.getElementById('appplayers').addEventListener('click', function () {\n  inst.open();\n});\n</script>\n<a href=\"<?php e($url);?>\" class=\"mdui-fab mdui-fab-fixed mdui-ripple mdui-color-theme-accent\"><i class=\"mdui-icon material-icons\">file_download</i></a>\n<?php view::end('content');?>\n"
  },
  {
    "path": "view/themes/nexmoe/show/video2.php",
    "content": "<?php view::layout('layout')?>\n\n<?php \n//仅支持教育版和企业版\nif(strpos($item['downloadUrl'],\"sharepoint.com\") == false){\n\theader('Location: '.$item['downloadUrl']);exit();\n}\n$item['thumb'] = onedrive::thumbnail($item['path']);\n$mpd =  str_replace(\"thumbnail\",\"videomanifest\",$item['thumb']).\"&part=index&format=dash&useScf=True&pretranscode=0&transcodeahead=0\";\n?>\n\n<?php view::begin('content');?>\n<script crossorigin=\"anonymous\" integrity=\"sha512-WHtkQz1iePtUjmTfBntzMsr+u7Gn94FklVz/nWz5ueOHutXzsRnbU4BsAmpizvysAqdPU1tMRYn7JdJgdyVuaQ==\" src=\"https://lib.baomitu.com/dashjs/4.4.1/dash.all.min.js\"></script>\n<link crossorigin=\"anonymous\" integrity=\"sha384-WBkDouo/0CCXxPpQ0M6rTUkTGZL30VNhKNg07BZy/8Le4IXY4jv/ihAvI1J9+s4b\" href=\"https://lib.baomitu.com/dplayer/1.25.0/DPlayer.min.css\" rel=\"stylesheet\">\n<script crossorigin=\"anonymous\" integrity=\"sha384-6CyF/JZDLd9z4fvRApunnpxkvVlYkSK1WPTbA9u3v2e/HgviJP3b9HVX2gD+/1CC\" src=\"https://lib.baomitu.com/dplayer/1.25.0/DPlayer.min.js\"></script>\n<div class=\"mdui-container-fluid\">\n\t<div class=\"nexmoe-item\">\n\t<div class=\"mdui-center\" id=\"dplayer\"></div>\n\t<div class=\"mdui-p-t-5 \">\n\t\t<ul class=\"mdui-menu\" id=\"menu\">\n\t\t\t<li class=\"mdui-menu-item\">\n\t\t\t<a href=\"intent:<?php e($url);?>;end\" class=\"mdui-ripple\">MXPlayer(FREE)</a>\n\t\t\t</li>\n\t\t\t<li class=\"mdui-menu-item\">\n\t\t\t<a href=\"vlc://<?php e($url);?>\" class=\"mdui-ripple\">VLC</a>\n\t\t\t</li>\n\t\t\t<li class=\"mdui-menu-item\">\n\t\t\t<a href=\"potplayer://<?php e($url);?>\" class=\"mdui-ripple\">PotPlayer</a>\n\t\t\t</li>\n\t\t\t<li class=\"mdui-menu-item\">\n\t\t\t<a href=\"nplayer-<?php e($url);?>\" class=\"mdui-ripple\">PotPlayer</a>\n\t\t\t</li>\n\t\t\t\n\t\t</ul>\n\n\t\t<button id=\"appplayers\" class=\"mdui-btn mdui-ripple mdui-color-theme-accent\"><i class=\"mdui-icon material-icons\">&#xe039;</i>外部播放器播放<i class=\"mdui-icon material-icons\">&#xe313;</i></button>\n\t</div>\n\t<!-- 固定标签 -->\n\t<div class=\"mdui-textfield\">\n\t  <label class=\"mdui-textfield-label\">下载地址</label>\n\t  <input class=\"mdui-textfield-input\" type=\"text\" value=\"<?php e($url);?>\"/>\n\t</div>\n\t<div class=\"mdui-textfield\">\n\t  <label class=\"mdui-textfield-label\">引用地址</label>\n\t  <textarea class=\"mdui-textfield-input\"><video><source src=\"<?php e($url);?>\" type=\"video/mp4\"></video></textarea>\n\t</div>\n\t</div>\n</div>\n<script>\nconst dp = new DPlayer({\n\tcontainer: document.getElementById('dplayer'),\n\tlang:'zh-cn',\n\tvideo: {\n\t    url: '<?php echo $mpd;?>',\n\t    pic: '<?php @e($item['thumb']);?>',\n\t    type: 'dash'\n\t}\n});\nvar inst = new mdui.Menu('#appplayers', '#menu');\n\n// method\ndocument.getElementById('appplayers').addEventListener('click', function () {\n  inst.open();\n});\n</script>\n<a href=\"<?php e($url);?>\" class=\"mdui-fab mdui-fab-fixed mdui-ripple mdui-color-theme-accent\"><i class=\"mdui-icon material-icons\">file_download</i></a>\n<?php view::end('content');?>\n"
  },
  {
    "path": "view/themes/nexmoe/show/video5.php",
    "content": "<?php view::layout('layout')?>\n\n<?php \n$item['thumb'] = onedrive::thumbnail($item['path']);\n?>\n\n<?php view::begin('content');?>\n<div class=\"mdui-container-fluid\">\n\t<div class=\"nexmoe-item\">\n\t<video class=\"mdui-video-fluid mdui-center\" preload controls poster=\"<?php @e($item['thumb']);?>\">\n\t  <source src=\"<?php e($item['downloadUrl']);?>\" type=\"video/mp4\">\n\t</video>\n\t<div class=\"mdui-p-t-5 \">\n\t\t<ul class=\"mdui-menu\" id=\"menu\">\n\t\t\t<li class=\"mdui-menu-item\">\n\t\t\t<a href=\"intent:<?php e($url);?>;end\" class=\"mdui-ripple\">MXPlayer(FREE)</a>\n\t\t\t</li>\n\t\t\t<li class=\"mdui-menu-item\">\n\t\t\t<a href=\"vlc://<?php e($url);?>\" class=\"mdui-ripple\">VLC</a>\n\t\t\t</li>\n\t\t\t<li class=\"mdui-menu-item\">\n\t\t\t<a href=\"potplayer://<?php e($url);?>\" class=\"mdui-ripple\">PotPlayer</a>\n\t\t\t</li>\n\t\t\t<li class=\"mdui-menu-item\">\n\t\t\t<a href=\"nplayer-<?php e($url);?>\" class=\"mdui-ripple\">PotPlayer</a>\n\t\t\t</li>\n\t\t\t\n\t\t</ul>\n\n\t\t<button id=\"appplayers\" class=\"mdui-btn mdui-ripple mdui-color-theme-accent\"><i class=\"mdui-icon material-icons\">&#xe039;</i>外部播放器播放<i class=\"mdui-icon material-icons\">&#xe313;</i></button>\n\t</div>\n\t<!-- 固定标签 -->\n\t<div class=\"mdui-textfield\">\n\t  <label class=\"mdui-textfield-label\">下载地址</label>\n\t  <input class=\"mdui-textfield-input\" type=\"text\" value=\"<?php e($url);?>\"/>\n\t</div>\n\t<div class=\"mdui-textfield\">\n\t  <label class=\"mdui-textfield-label\">引用地址</label>\n\t  <textarea class=\"mdui-textfield-input\"><video><source src=\"<?php e($url);?>\" type=\"video/mp4\"></video></textarea>\n\t</div>\n\t</div>\n</div>\n<script>\n\tvar inst = new mdui.Menu('#appplayers', '#menu');\n\n// method\ndocument.getElementById('appplayers').addEventListener('click', function () {\n  inst.open();\n});\n</script>\n<a href=\"<?php e($url);?>\" class=\"mdui-fab mdui-fab-fixed mdui-ripple mdui-color-theme-accent\"><i class=\"mdui-icon material-icons\">file_download</i></a>\n<?php view::end('content');?>"
  },
  {
    "path": "使用及免责协议.md",
    "content": "用户须知：无论您是个人或组织、盈利与否、用途如何（包括以学习和研究为目的），均需仔细阅读本协议，包括免除oneindex开发者责任的免责条款及对您的权利限制。请您审阅并接受或不接受本服务条款。如您不同意本服务条款及/或oneindex开发者随时对其的修改，您应不使用或主动取消使用本程序。否则，您的任何对本程序的使用和修改等行为将被视为您对本服务条款全部的完全接受，包括接受oneindex开发者对服务条款随时所做的任何修改。  \n  \n在理解、同意、并遵守本协议的全部条款后，方可开始使用本软件。  \n  \nI. 前置条件  \n您应完全遵守中国大陆和您提供服务地区的相关法律法规，不得将使用本软件以任何形式用于任何违法用途。  \n  \nII. 协议许可的权利  \n  \n您可以在完全遵守本许可协议的基础上，将本软件应用于非商业用途。  \n  \n本软件及所附带的文件是作为不提供任何明确的或隐含的赔偿或担保的形式提供的。  \n   \n用户出于自愿而使用本软件，您必须了解使用本软件的风险，oneindex开发者不提供任何形式的技术支持、使用担保，也不承担任何因使用本软件而产生问题的相关责任。  \n   \noneindex开发者不对使用本软件构建的网站或者网站中的展示的文件及内容信息承担责任，，oneindex开发者不承担任何直接、间接或者连带的责任，全部责任由您自行承担。  \n  \noneindex开发者无法全面监控您下载的程序完整性，因此不保证应用程序的合法性、安全性、完整性、真实性或品质等；您同意自行判断并承担所有风险。由此对您及第三人可能造成的损失，oneindex开发者不承担任何直接、间接或者连带的责任。  \n  \nIII. 代码修改和发布\n  \n基于本程序代码修改和发布的代码、软件、及构建的网站，与oneindex开发者无关，其产生的责任和后果与oneindex开发者无关，oneindex开发者不承担任何责任。  \n  \n一旦您开始安装、使用、修改oneindex，即被视为完全理解并接受本协议的各项条款，在享有上述条款授予的权利的同时，受到相关的约束和限制。 \n"
  }
]