mirror of
https://github.com/cloudreve/Cloudreve.git
synced 2024-04-21 12:31:40 +00:00
Compare commits
192
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a530f5d58 | ||
|
|
88fac85ca5 | ||
|
|
9f658e86ec | ||
|
|
ebee2b09d9 | ||
|
|
836cb1a9c7 | ||
|
|
3c7aedc195 | ||
|
|
a11f81966d | ||
|
|
2c2e8b6052 | ||
|
|
3b7e9298b5 | ||
|
|
b341d3bc2c | ||
|
|
fd03047ed2 | ||
|
|
f15499d274 | ||
|
|
889b65163b | ||
|
|
1c05b9a0d3 | ||
|
|
00a2b452c4 | ||
|
|
721dad4abe | ||
|
|
ebb95b31c2 | ||
|
|
d854913cd2 | ||
|
|
94c3dd7420 | ||
|
|
9d8646c6f6 | ||
|
|
560e455618 | ||
|
|
51f8be8681 | ||
|
|
df8581e238 | ||
|
|
bf2f5e621f | ||
|
|
a4439ba210 | ||
|
|
822d9b4bba | ||
|
|
18bcd93d97 | ||
|
|
76ea49890d | ||
|
|
74d0afb441 | ||
|
|
b2d5547199 | ||
|
|
ef636bc2d1 | ||
|
|
3a4912083c | ||
|
|
737665c62c | ||
|
|
df42ac0e96 | ||
|
|
4880972d77 | ||
|
|
84e2ec0f19 | ||
|
|
53c79bfa65 | ||
|
|
41d1294ebf | ||
|
|
d84b00f35d | ||
|
|
da4f152438 | ||
|
|
3d82929a3b | ||
|
|
2e2357e794 | ||
|
|
c94e17a4da | ||
|
|
c741d79677 | ||
|
|
e0b4b42ec6 | ||
|
|
65dcedb3ca | ||
|
|
422f9d8d6a | ||
|
|
1fc4956a3f | ||
|
|
564578aefb | ||
|
|
12f98dd0f5 | ||
|
|
c33b6d587f | ||
|
|
277f882e8d | ||
|
|
68399a5877 | ||
|
|
6b4f999bc4 | ||
|
|
3514ff437c | ||
|
|
8c344b456d | ||
|
|
ff4fa3f9b2 | ||
|
|
d9fa51a615 | ||
|
|
6dd49fce09 | ||
|
|
ddc0b6ad4b | ||
|
|
75cbbcaa10 | ||
|
|
060f7a2081 | ||
|
|
a67185c750 | ||
|
|
38b11c1651 | ||
|
|
96b7f4c97d | ||
|
|
f600b21faa | ||
|
|
1693bf800b | ||
|
|
f39334125b | ||
|
|
9ee144d870 | ||
|
|
755fe7331f | ||
|
|
78f4a1eae9 | ||
|
|
55ea76e35e | ||
|
|
c2a05d3f6c | ||
|
|
8c43f1fe1c | ||
|
|
f81a433cbc | ||
|
|
f2d94ea499 | ||
|
|
ca30b650fc | ||
|
|
62eca52fe7 | ||
|
|
3462e6665b | ||
|
|
2b646fb6e3 | ||
|
|
e29c94d8d0 | ||
|
|
044ece0b80 | ||
|
|
195d747c5d | ||
|
|
16fe5d7f7d | ||
|
|
732d04c0a7 | ||
|
|
6593cb7de9 | ||
|
|
7a34a5ffb8 | ||
|
|
e989aa47d9 | ||
|
|
159ee86b60 | ||
|
|
61910ccf35 | ||
|
|
1fe7be12c6 | ||
|
|
72ab679dd5 | ||
|
|
946408b642 | ||
|
|
1d5f742ba7 | ||
|
|
84c6e1a74c | ||
|
|
a4cef20c01 | ||
|
|
5faea8f5ae | ||
|
|
899ee59c73 | ||
|
|
2807c1c79e | ||
|
|
d5f5cbc05b | ||
|
|
a1a9f7cdb0 | ||
|
|
c7f7e20978 | ||
|
|
c11710325d | ||
|
|
a3599b399d | ||
|
|
8992627c48 | ||
|
|
07fef77c4c | ||
|
|
81abe89e84 | ||
|
|
514ad474ea | ||
|
|
b33df3da72 | ||
|
|
fd8fc70b07 | ||
|
|
91c9870f49 | ||
|
|
f93edcc82b | ||
|
|
b1f2774d41 | ||
|
|
487f4e3139 | ||
|
|
9651caa219 | ||
|
|
f5d69ebdae | ||
|
|
36e6526259 | ||
|
|
334d25833c | ||
|
|
412541a540 | ||
|
|
3326c9232e | ||
|
|
6d9b67ac20 | ||
|
|
ccbb6c7778 | ||
|
|
b8b63662ea | ||
|
|
1b87365b8a | ||
|
|
ee56919747 | ||
|
|
4877a8e292 | ||
|
|
1af411daee | ||
|
|
c4ecee4897 | ||
|
|
f4a4ca02b5 | ||
|
|
f3ff61cbc6 | ||
|
|
aabc32efb5 | ||
|
|
126aacca63 | ||
|
|
2ade8861c9 | ||
|
|
32ca1132f2 | ||
|
|
7536c8695b | ||
|
|
622b80a680 | ||
|
|
0fe4e8a8db | ||
|
|
37b4357435 | ||
|
|
45ea9404ba | ||
|
|
764fdd7e36 | ||
|
|
219d894a08 | ||
|
|
7d5e8fb2a1 | ||
|
|
956deac89f | ||
|
|
4964f53dac | ||
|
|
037e6ad0b3 | ||
|
|
9c7494256c | ||
|
|
21518300b4 | ||
|
|
99759b5a77 | ||
|
|
d58b824d8b | ||
|
|
33e56ca287 | ||
|
|
c7901d55f0 | ||
|
|
53d01e5f6e | ||
|
|
4b58719e7c | ||
|
|
a82bee0216 | ||
|
|
0ea0902059 | ||
|
|
a57dd79319 | ||
|
|
228b898e9d | ||
|
|
8f8b9df5a5 | ||
|
|
36925a63ef | ||
|
|
df03461892 | ||
|
|
6361d4bd2e | ||
|
|
937dfc77fd | ||
|
|
31f1eb839f | ||
|
|
12f7f691eb | ||
|
|
2d183acd0d | ||
|
|
363da22bda | ||
|
|
28d8d02508 | ||
|
|
662c3019d4 | ||
|
|
f5502b3666 | ||
|
|
4e550dcdb2 | ||
|
|
59f8a9b58d | ||
|
|
b0898fcab4 | ||
|
|
8c8561dc31 | ||
|
|
141de8ba54 | ||
|
|
159098decf | ||
|
|
24789ca8a9 | ||
|
|
544769bf04 | ||
|
|
85119bc54d | ||
|
|
d3061f0526 | ||
|
|
4492991bbb | ||
|
|
1e79428425 | ||
|
|
c28f08c210 | ||
|
|
0e0f7d5258 | ||
|
|
d2ca69b945 | ||
|
|
9cb572f0da | ||
|
|
9994f12aa8 | ||
|
|
20b7d67adc | ||
|
|
63cc404d74 | ||
|
|
47f334b6f4 | ||
|
|
1431f433d1 | ||
|
|
b6c1382e73 | ||
|
|
02ce111717 |
@@ -0,0 +1,5 @@
|
||||
*.map
|
||||
composer.lock
|
||||
*.chunk.js
|
||||
*.chunk.css
|
||||
runtime~*.js
|
||||
@@ -6,3 +6,4 @@
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteRule ^(.*)$ index.php?/$1 [QSA,PT,L]
|
||||
</IfModule>
|
||||
SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
|
||||
@@ -0,0 +1,7 @@
|
||||
language: php
|
||||
php:
|
||||
- 7.1
|
||||
before_script:
|
||||
- composer install
|
||||
- chmod +x ./deploy.sh
|
||||
script: ./deploy.sh
|
||||
@@ -16,10 +16,11 @@ class Installer{
|
||||
/ /___| | (_) | |_| | (_| | | | __/\ V / __/
|
||||
\____/|_|\___/ \__,_|\__,_|_| \___| \_/ \___|
|
||||
|
||||
Ver $version
|
||||
Ver $version
|
||||
================================================
|
||||
";
|
||||
$ioContext->write($welcomMsg);
|
||||
self::prepareStatic($event);
|
||||
$sqlInfo = self::getSqlInformation($event);
|
||||
$ioContext->write("");
|
||||
$siteUrl=$ioContext->ask("The full-url to access to your Cloudreve (e.g. https://pan.aoaoao.me/ , 'http' must be included in the front and '/' must be included at the end):");
|
||||
@@ -60,10 +61,60 @@ class Installer{
|
||||
$ioContext->write("IMPORTANT! You may still have to configure the URL Rewrite to set everthing to work.");
|
||||
$ioContext->write("Refer to the install manual for more informatioin.");
|
||||
$ioContext->write("=======================");
|
||||
self::sendFeedBack($siteUrl);
|
||||
}
|
||||
|
||||
public static function prepareStatic(Event $event){
|
||||
$ioContext = $event->getIO();
|
||||
$ioContext->write("Fetching static files from cloudreve.org...");
|
||||
if(!is_writable("runtime") || !is_writable("static")){
|
||||
$ioContext->writeError("[Error] 'runtime' or 'static' directory is not writable. To retry, run 'composer install'");
|
||||
exit();
|
||||
}
|
||||
if(file_exists("runtime/static.zip")){
|
||||
$ioContext->writeError("[Error] 'runtime/static.zip' already exist. To retry, run 'composer install'");
|
||||
exit();
|
||||
}
|
||||
if(file_exists("runtime/static")){
|
||||
$ioContext->writeError("[Error] directory 'runtime/static' already exist. To retry, run 'composer install'");
|
||||
exit();
|
||||
}
|
||||
try{
|
||||
file_put_contents("runtime/static.zip",file_get_contents("https://cloudreve.org/download.php?newestStatic"));
|
||||
}catch (Exception $e) {
|
||||
$ioContext->writeError("[Error] Failed to download static file. To retry, run 'composer install'");
|
||||
exit();
|
||||
}
|
||||
$ioContext->write("Unzip static files...");
|
||||
$zip = new \ZipArchive;
|
||||
$res = $zip->open('runtime/static.zip');
|
||||
if ($res === TRUE) {
|
||||
$zip->extractTo('runtime/static/');
|
||||
$zip->close();
|
||||
}else {
|
||||
$ioContext->writeError("[Error] Failed to open runtime/static.zip. To retry, run 'composer install'");
|
||||
exit();
|
||||
}
|
||||
self::recurse_copy("runtime/static/build/static", "static");
|
||||
}
|
||||
|
||||
public static function recurse_copy($src,$dst) {
|
||||
$dir = opendir($src);
|
||||
@mkdir($dst);
|
||||
while(false !== ( $file = readdir($dir)) ) {
|
||||
if (( $file != '.' ) && ( $file != '..' )) {
|
||||
if ( is_dir($src . '/' . $file) ) {
|
||||
self::recurse_copy($src . '/' . $file,$dst . '/' . $file);
|
||||
}else {
|
||||
copy($src . '/' . $file,$dst . '/' . $file);
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir($dir);
|
||||
}
|
||||
|
||||
public static function writrConfig(Event $event,$sqlInfo){
|
||||
$ioContext = $event->getIO();
|
||||
$ioContext = $event->getIO();
|
||||
try {
|
||||
$fileContent = file_get_contents("CloudreveInstaller/database_sample.php");
|
||||
$replacement = array(
|
||||
@@ -86,7 +137,7 @@ class Installer{
|
||||
$hostname=$ioContext->ask("Input the hostname of your MySQL server (Default:127.0.0.1):","127.0.0.1");
|
||||
$database=$ioContext->ask("The database name:","127.0.0.1");
|
||||
$username=$ioContext->ask("The username of your MySQL server (Default:root):","root");
|
||||
$password=$ioContext->askAndHideAnswer("The password of your MySQL server:");
|
||||
$password=$ioContext->ask("The password of your MySQL server:");
|
||||
$hostport=$ioContext->ask("The hostport of your MySQL server (Default:3306):","3306");
|
||||
$mysqli = @new \mysqli($hostname, $username, $password, $database, $hostport);
|
||||
if ($mysqli->connect_error) {
|
||||
@@ -97,13 +148,17 @@ class Installer{
|
||||
return self::getSqlInformation($event);
|
||||
}
|
||||
return [
|
||||
"hostname" => $hostname,
|
||||
"database" => $database,
|
||||
"username" => $username,
|
||||
"password" => $password,
|
||||
"hostport" => $hostport,
|
||||
"hostname" => $hostname,
|
||||
"database" => $database,
|
||||
"username" => $username,
|
||||
"password" => $password,
|
||||
"hostport" => $hostport,
|
||||
];
|
||||
}
|
||||
|
||||
public static function sendFeedBack($url){
|
||||
@file_get_contents("http://toy.aoaoao.me/feedback.php?url=".urlencode($url));
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
File diff suppressed because one or more lines are too long
@@ -6,14 +6,18 @@ Cloudreve - Make the cloud easy for everyone
|
||||
[](https://packagist.org/packages/hfo4/cloudreve)
|
||||
[](https://packagist.org/packages/hfo4/cloudreve)
|
||||
|
||||
基于ThinkPHP构建的网盘系统,能够助您以较低成本快速搭建起公私兼备的网盘。
|
||||
[主页](https://cloudreve.org) | [论坛](https://forum.cloudreve.org) | [演示站](https://drive.aoaoao.me) | [QQ群](https://jq.qq.com/?_wv=1027&k=5TX6sJY)
|
||||
|
||||

|
||||
使用ThinkPHP + React + Redux + Material-UI构建的网盘系统,能够助您以较低成本快速搭建起公私兼备的网盘。
|
||||
|
||||

|
||||
|
||||
目前已经实现的特性:
|
||||
|
||||
* 快速对接多家云存储,支持七牛、又拍云、阿里云OSS、AWS S3,当然,还有本地存储
|
||||
* 快速对接多家云存储,支持七牛、又拍云、阿里云OSS、AWS S3、Onedrive、自建远程服务器,当然,还有本地存储
|
||||
* 可限制单文件最大大小、MIMEType、文件后缀、用户可用容量
|
||||
* 自定义主题配色
|
||||
* 基于Aria2的离线下载
|
||||
* 图片、音频、视频、文本、Markdown、Ofiice文档 在线预览
|
||||
* 移动端全站响应式布局
|
||||
* 文件、目录分享系统,可创建私有分享或公开分享链接
|
||||
@@ -22,9 +26,10 @@ Cloudreve - Make the cloud easy for everyone
|
||||
* 初步完善的后台,方便管理
|
||||
* 拖拽上传、分片上传、断点续传、下载限速(*实验性功能)
|
||||
* 多上传策略,可为不同用户组分配不同策略
|
||||
* 用户组基础权限设置
|
||||
* 用户组基础权限设置、二步验证
|
||||
* WebDAV协议支持
|
||||
|
||||
|
||||
安装需求
|
||||
------------
|
||||
* LNMP/AMP With PHP5.6+
|
||||
@@ -46,7 +51,7 @@ $ composer create-project hfo4/cloudreve:dev-master
|
||||
/ __\ | ___ _ _ __| |_ __ _____ _____
|
||||
/ / | |/ _ \| | | |/ _` | '__/ _ \ \ / / _ \
|
||||
/ /___| | (_) | |_| | (_| | | | __/\ V / __/
|
||||
\____/|_|\___/ \__,_|\__,_|_| \___| \_/ \___|
|
||||
\____/|_|\___/ \__,_|\__,_|_| \___| \_/ \___|
|
||||
|
||||
Ver XX
|
||||
================================================
|
||||
@@ -88,7 +93,7 @@ location / {
|
||||
* 到 设置-基础设置 中更改站点URL,如果不更改,程序无法正常接受回调请求
|
||||
* 添加Crontab定时任务 :你的域名/Cron
|
||||
* 如果你打算使用本地上传策略并且不准备开启外链功能,请将·public/uploads·目录设置为禁止外部访问
|
||||
* 如需启用二步验证功能,请依次执行`composer require phpgangsta/googleauthenticator:dev-master` `composer require endroid/qrcode`安装二步验证支持库
|
||||
* 如需启用二步验证功能,请依次执行`composer require phpgangsta/googleauthenticator:dev-master` `composer require endroid/qr-code`安装二步验证支持库
|
||||
* 给本项目一个Star~
|
||||
|
||||
文档
|
||||
|
||||
@@ -9,4 +9,6 @@
|
||||
// | Author: yunwuxin <448901948@qq.com>
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
return [];
|
||||
return [
|
||||
'app\index\command\Task',
|
||||
];
|
||||
|
||||
@@ -18,7 +18,7 @@ return [
|
||||
// 应用命名空间
|
||||
'app_namespace' => 'app',
|
||||
// 应用调试模式
|
||||
'app_debug' => false,
|
||||
'app_debug' => true,
|
||||
// 应用Trace
|
||||
'app_trace' => false,
|
||||
// 应用模式状态
|
||||
@@ -156,7 +156,7 @@ return [
|
||||
'exception_tmpl' => THINK_PATH . 'tpl' . DS . 'think_exception.tpl',
|
||||
|
||||
// 错误显示信息,非调试模式有效
|
||||
'error_message' => '页面错误!请稍后再试~',
|
||||
'error_message' => '很抱歉,出现错误 :(',
|
||||
// 显示错误信息
|
||||
'show_error_msg' => false,
|
||||
// 异常处理handle类 留空使用 \think\exception\Handle
|
||||
@@ -240,6 +240,12 @@ return [
|
||||
'var_page' => 'page',
|
||||
'list_rows' => 15,
|
||||
],
|
||||
|
||||
//分片上传大小(只对本地策略有效)
|
||||
'upload'=>[
|
||||
'chunk_size' => 10*1024*1024,
|
||||
],
|
||||
|
||||
// +----------------------------------------------------------------------
|
||||
// | 验证码设置
|
||||
// +----------------------------------------------------------------------
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
namespace app\index\command;
|
||||
|
||||
use think\Db;
|
||||
use think\console\Command;
|
||||
use think\console\Input;
|
||||
use think\console\Output;
|
||||
|
||||
class Task extends Command
|
||||
{
|
||||
|
||||
const SLEEP_TIME = 1;
|
||||
|
||||
protected function configure()
|
||||
{
|
||||
$this->setName('run')->setDescription('Start processing tasks for Cloudreve');
|
||||
}
|
||||
|
||||
protected function Init(Output $output){
|
||||
$output->writeln("Cloudreve tasks processor started.");
|
||||
}
|
||||
|
||||
protected function setComplete($taskId,Output $output){
|
||||
$output->writeln("Cloudreve tasks processor started.");
|
||||
}
|
||||
|
||||
protected function execute(Input $input, Output $output)
|
||||
{
|
||||
self::Init($output);
|
||||
while (1){
|
||||
$newTaskInfo = Db::name("task")->where("status","todo")->find();
|
||||
if(empty($newTaskInfo)){
|
||||
sleep(self::SLEEP_TIME);
|
||||
continue;
|
||||
}
|
||||
Db::name("task")->where("id",$newTaskInfo["id"])->update(["status"=>"processing"]);
|
||||
$output->writeln("[New task] Name:".$newTaskInfo["task_name"]." Type:".$newTaskInfo["type"]);
|
||||
$task = new \app\index\model\Task();
|
||||
$task->taskModel = $newTaskInfo;
|
||||
$task->input = $input;
|
||||
$task->output = $output;
|
||||
$task->Doit();
|
||||
if($task->status=="error"){
|
||||
$output->writeln("[Error] ".$task->errorMsg);
|
||||
Db::name("task")->where("id",$newTaskInfo["id"])->update(["status"=>"error|".$task->errorMsg]);
|
||||
}else{
|
||||
$output->writeln("[Complete]");
|
||||
Db::name("task")->where("id",$newTaskInfo["id"])->update(["status"=>"complete"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -29,12 +29,50 @@ class Admin extends Controller{
|
||||
}
|
||||
|
||||
public function index(){
|
||||
if($this->adminObj->checkDbVersion()){
|
||||
$this->redirect(url('/Admin/UpdateDb','',''));
|
||||
exit();
|
||||
}
|
||||
if($this->adminObj->checkCron()){
|
||||
$isCronOk = true;
|
||||
}else{
|
||||
$isCronOk = false;
|
||||
}
|
||||
return view('admin_index', [
|
||||
'options' => $this->siteOptions,
|
||||
'statics' => $this->adminObj->getStatics(),
|
||||
'isCronOk' => $isCronOk,
|
||||
]);
|
||||
}
|
||||
|
||||
public function UpdateDb(){
|
||||
if(!$this->adminObj->checkDbVersion()){
|
||||
$this->redirect(url('/Admin','',''));
|
||||
exit();
|
||||
}
|
||||
echo "<meta charset='utf-8'>";
|
||||
echo "准备升级数据库,当前数据库版本:".$this->adminObj->dbVerInfo["now"];
|
||||
echo ", 目标数据库版本:".$this->adminObj->dbVerInfo["require"].";<br>";
|
||||
$updatePath = ROOT_PATH . "update_".$this->adminObj->dbVerInfo["now"]."to".$this->adminObj->dbVerInfo["require"].".sql";
|
||||
if(!file_exists($updatePath)){
|
||||
die("数据库更新文件(".$updatePath.")不存在,升级中止.");
|
||||
}
|
||||
echo "获取升级SQL文件(".$updatePath.")<br>";
|
||||
$updateContent = file_get_contents($updatePath);
|
||||
echo "将执行以下指令:<br>";
|
||||
echo "<code>".htmlspecialchars($updateContent)."</code><br>";
|
||||
$sqlSingle = explode(";", $updateContent);
|
||||
foreach ($sqlSingle as $key => $value){
|
||||
if(empty($value)){
|
||||
continue;
|
||||
}
|
||||
if(!Db::execute($value)){
|
||||
echo "<strong>执行$value 时出现错误</strong><br>";
|
||||
}
|
||||
}
|
||||
echo "<strong>升级完成,<a href='/Admin'>返回管理面板</a></strong>";
|
||||
}
|
||||
|
||||
public function Setting(){
|
||||
return view('basic_setting', [
|
||||
'options' => $this->siteOptions,
|
||||
@@ -64,6 +102,15 @@ class Admin extends Controller{
|
||||
]);
|
||||
}
|
||||
|
||||
public function Color(){
|
||||
$options = Option::getValues(["basic"]);
|
||||
return view('color', [
|
||||
'options' => $this->siteOptions,
|
||||
'optionsForSet' => $options,
|
||||
'colors'=> \json_decode($options["themes"],true)
|
||||
]);
|
||||
}
|
||||
|
||||
public function Theme(){
|
||||
$fileName=input("?param.name") ? input("param.name") : "error";
|
||||
$dir = ROOT_PATH."application/index/view/";
|
||||
@@ -103,6 +150,10 @@ class Admin extends Controller{
|
||||
return $this->adminObj->saveThemeFile(input('post.'));
|
||||
}
|
||||
|
||||
public function SaveColorSetting(){
|
||||
return $this->adminObj->saveColorSetting(input('post.'));
|
||||
}
|
||||
|
||||
public function SettingMail(){
|
||||
return view('mail_setting', [
|
||||
'options' => $this->siteOptions,
|
||||
@@ -120,7 +171,7 @@ class Admin extends Controller{
|
||||
public function SettingOther(){
|
||||
return view('other_setting', [
|
||||
'options' => $this->siteOptions,
|
||||
'optionsForSet' => Option::getValues(["file_edit","share","avatar","admin","storage_policy"]),
|
||||
'optionsForSet' => Option::getValues(["file_edit","share","avatar","admin","storage_policy","download"]),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -216,6 +267,14 @@ class Admin extends Controller{
|
||||
return $this->adminObj->saveMailSetting(input('post.'));
|
||||
}
|
||||
|
||||
public function SaveAria2Setting(){
|
||||
return $this->adminObj->saveAria2Setting(input('post.'));
|
||||
}
|
||||
|
||||
public function SaveTaskOption(){
|
||||
return $this->adminObj->saveTaskOption(input('post.'));
|
||||
}
|
||||
|
||||
public function SendTestMail(){
|
||||
return $this->adminObj->sendTestMail(input('post.'));
|
||||
}
|
||||
@@ -298,7 +357,7 @@ class Admin extends Controller{
|
||||
}
|
||||
|
||||
public function DeleteShareMultiple(){
|
||||
return $this->adminObj->deleteShare(json_decode(input('post.id'),true));
|
||||
return $this->adminObj->deleteShare(\json_decode(input('post.id'),true));
|
||||
}
|
||||
|
||||
public function DeleteMultiple(){
|
||||
@@ -334,7 +393,7 @@ class Admin extends Controller{
|
||||
}
|
||||
|
||||
public function DeleteUsers(){
|
||||
$uidGroup = json_decode(input('post.id'),true);
|
||||
$uidGroup = \json_decode(input('post.id'),true);
|
||||
foreach ($uidGroup as $key => $value) {
|
||||
$this->adminObj->deleteUser($value,$this->userObj->uid);
|
||||
}
|
||||
@@ -409,8 +468,20 @@ class Admin extends Controller{
|
||||
]);
|
||||
}
|
||||
|
||||
public function PolicyAddRemote(){
|
||||
return view('add_policy_remote', [
|
||||
'options' => $this->siteOptions,
|
||||
]);
|
||||
}
|
||||
|
||||
public function PolicyAddOnedrive(){
|
||||
return view('add_policy_onedrive', [
|
||||
'options' => $this->siteOptions,
|
||||
]);
|
||||
}
|
||||
|
||||
public function About(){
|
||||
$verison = json_decode(file_get_contents(ROOT_PATH . "application/version.json"),true);
|
||||
$verison = \json_decode(file_get_contents(ROOT_PATH . "application/version.json"),true);
|
||||
return view('about', [
|
||||
'options' => $this->siteOptions,
|
||||
'programVersion' => $verison,
|
||||
@@ -419,15 +490,24 @@ class Admin extends Controller{
|
||||
}
|
||||
|
||||
public function Purchase(){
|
||||
$packData = json_decode(Option::getValue("pack_data"),true);
|
||||
$packData = \json_decode(Option::getValue("pack_data"),true);
|
||||
return view('purchase', [
|
||||
'options' => $this->siteOptions,
|
||||
'pack' => $packData,
|
||||
]);
|
||||
}
|
||||
|
||||
public function Queue(){
|
||||
$taskOption = Option::getValue("task_queue_token");
|
||||
return view('task', [
|
||||
'options' => $this->siteOptions,
|
||||
'taskOption' => $taskOption,
|
||||
'task' => $this->adminObj->getTasks(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function PurchaseGroup(){
|
||||
$groupData = json_decode(Option::getValue("group_sell_data"),true);
|
||||
$groupData = \json_decode(Option::getValue("group_sell_data"),true);
|
||||
foreach ($groupData as $key => $value) {
|
||||
$groupData[$key]["group"] = Db::name("groups")->where("id",$value["goup_id"])->find();
|
||||
}
|
||||
@@ -444,5 +524,43 @@ class Admin extends Controller{
|
||||
'policy' => $this->adminObj->getAvaliablePolicy(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function RemoteDownload(){
|
||||
$this->adminObj->listDownloads();
|
||||
return view('download', [
|
||||
'options' => $this->siteOptions,
|
||||
'optionsForSet' => Option::getValues(["aria2"]),
|
||||
'list' => $this->adminObj->pageData,
|
||||
'originList' => $this->adminObj->listData,
|
||||
'pageNow' => $this->adminObj->pageNow,
|
||||
'pageTotal' => $this->adminObj->pageTotal,
|
||||
'dataTotal' => $this->adminObj->dataTotal,
|
||||
]);
|
||||
}
|
||||
|
||||
public function CancelDownload(){
|
||||
$aria2Options = Option::getValues(["aria2"]);
|
||||
$aria2 = new \app\index\model\Aria2($aria2Options);
|
||||
$downloadItem = Db::name("download")->where("id",input("post.id"))->find();
|
||||
if(empty($downloadItem)){
|
||||
return json(['error'=>1,'message'=>"未找到下载记录"]);
|
||||
}
|
||||
if($aria2->Remove($downloadItem["pid"],"")){
|
||||
return json(['error'=>0,'message'=>"下载已取消"]);
|
||||
}else{
|
||||
return json(['error'=>1,'message'=>"取消失败"]);
|
||||
}
|
||||
}
|
||||
|
||||
public function UpdateOnedriveToken(){
|
||||
$policyId = input("get.id");
|
||||
$this->adminObj->updateOnedriveToken($policyId);
|
||||
|
||||
}
|
||||
|
||||
public function OneDriveCalllback(){
|
||||
$code = input("get.code");
|
||||
$this->adminObj->oneDriveCalllback($code);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -81,4 +81,11 @@ class Callback extends Controller{
|
||||
$handllerObj -> s3Handler($callbackKey);
|
||||
}
|
||||
|
||||
public function Remote(){
|
||||
ob_end_clean();
|
||||
header('Content-Type: application/json');
|
||||
$handllerObj = new CallbackHandler(file_get_contents("php://input"));
|
||||
$handllerObj -> remoteHandler(Request::instance()->header('Authorization'));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -14,31 +14,24 @@ class Explore extends Controller{
|
||||
public $siteOptions;
|
||||
|
||||
public function _initialize(){
|
||||
$this->siteOptions = Option::getValues(["basic"]);
|
||||
}
|
||||
|
||||
public function Search(){
|
||||
$this->visitorObj = new User(cookie('user_id'),cookie('login_key'));
|
||||
return view("search",[
|
||||
"options" => $this->siteOptions,
|
||||
'loginStatus' => $this->visitorObj->loginStatus,
|
||||
'userData' => $this->visitorObj->userSQLData,
|
||||
]);
|
||||
}
|
||||
|
||||
public function S(){
|
||||
$this->visitorObj = new User(cookie('user_id'),cookie('login_key'));
|
||||
$this->siteOptions = Option::getValues(["basic"],$this->visitorObj->userSQLData);
|
||||
$keyWords=input("param.key");
|
||||
if(empty($keyWords)){
|
||||
$this->redirect('/Explore/Search',302);
|
||||
}
|
||||
$list = Db::name('shares')
|
||||
$this->error("搜索词不为空",200,$this->siteOptions);
|
||||
}else{
|
||||
$list = Db::name('shares')
|
||||
->where('type',"public")
|
||||
->where('origin_name',"like","%".$keyWords."%")
|
||||
->order('id DESC')
|
||||
->paginate(10);
|
||||
$listData = $list->all();
|
||||
->order('share_time DESC')
|
||||
->select();
|
||||
}
|
||||
$listData = $list;
|
||||
foreach ($listData as $key => $value) {
|
||||
unset($listData[$key]["source_name"]);
|
||||
if($value["source_type"]=="file"){
|
||||
$listData[$key]["fileData"] = $value["origin_name"];
|
||||
|
||||
@@ -50,9 +43,8 @@ class Explore extends Controller{
|
||||
return view("result",[
|
||||
"options" => $this->siteOptions,
|
||||
'loginStatus' => $this->visitorObj->loginStatus,
|
||||
'userData' => $this->visitorObj->userSQLData,
|
||||
'list' => $listData,
|
||||
'listOrigin' => $list,
|
||||
'userData' => $this->visitorObj->getInfo(),
|
||||
'list' => json_encode($listData),
|
||||
'keyWords' => $keyWords,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -27,37 +27,33 @@ class File extends Controller{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* [index description]
|
||||
* @Author Aaron
|
||||
* @DateTime 2017-07-03
|
||||
* @return [type] [description]
|
||||
*/
|
||||
public function index(){
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* [List description]
|
||||
* @Author Aaron
|
||||
* @DateTime 2017-07-03
|
||||
*/
|
||||
public function ListFile(){
|
||||
$reqPath = stripslashes(json_decode(file_get_contents("php://input"),true)['path']);
|
||||
return FileManage::ListFile($reqPath,$this->userObj->uid);
|
||||
return json(FileManage::ListFile($reqPath,$this->userObj->uid));
|
||||
}
|
||||
|
||||
public function SearchFile(){
|
||||
$keyWords = stripslashes(json_decode(file_get_contents("php://input"),true)['path']);
|
||||
return json(FileManage::searchFile($keyWords,$this->userObj->uid));
|
||||
}
|
||||
|
||||
public function Delete(){
|
||||
$reqPath = json_decode(file_get_contents("php://input"),true)['items'];
|
||||
$dirPath = json_decode(file_get_contents("php://input"),true)['dirs'];
|
||||
$reqData = json_decode(file_get_contents("php://input"),true);
|
||||
$reqPath = array_key_exists("dirs",$reqData)?$reqData["items"]:array();
|
||||
$dirPath = array_key_exists("dirs",$reqData)?$reqData["dirs"]:array();
|
||||
FileManage::DirDeleteHandler($dirPath,$this->userObj->uid);
|
||||
return FileManage::DeleteHandler($reqPath,$this->userObj->uid);
|
||||
return json(FileManage::DeleteHandler($reqPath,$this->userObj->uid));
|
||||
}
|
||||
|
||||
public function Move(){
|
||||
$reqPath = json_decode(file_get_contents("php://input"),true)['items'];
|
||||
$dirPath = json_decode(file_get_contents("php://input"),true)['dirs'];
|
||||
$newPath = json_decode(file_get_contents("php://input"),true)['newPath'];
|
||||
$reqData = json_decode(file_get_contents("php://input"),true);
|
||||
$reqPath = array_key_exists("dirs",$reqData)?$reqData["items"]:array();
|
||||
$dirPath = array_key_exists("dirs",$reqData)?$reqData["dirs"]:array();
|
||||
$newPath = $reqData['newPath'];
|
||||
return FileManage::MoveHandler($reqPath,$dirPath,$newPath,$this->userObj->uid);
|
||||
}
|
||||
|
||||
@@ -68,7 +64,7 @@ class File extends Controller{
|
||||
}
|
||||
|
||||
public function Preview(){
|
||||
$reqPath = $_GET["path"];
|
||||
$reqPath =$_GET["path"];
|
||||
$fileObj = new FileManage($reqPath,$this->userObj->uid);
|
||||
$Redirect = $fileObj->PreviewHandler();
|
||||
if($Redirect[0]){
|
||||
@@ -78,7 +74,7 @@ class File extends Controller{
|
||||
|
||||
public function ListPic(){
|
||||
$reqPath = $_GET["path"];
|
||||
return FileManage::listPic($reqPath,$this->userObj->uid);
|
||||
return json(FileManage::listPic($reqPath,$this->userObj->uid));
|
||||
}
|
||||
|
||||
public function Download(){
|
||||
@@ -91,19 +87,22 @@ class File extends Controller{
|
||||
}
|
||||
|
||||
public function Share(){
|
||||
$reqPath = json_decode(file_get_contents("php://input"),true)['item'];
|
||||
$shareType = json_decode(file_get_contents("php://input"),true)['shareType'];
|
||||
ShareHandler::createShare($reqPath,$shareType,$this->userObj->getSQLData(),$this->userObj->getGroupData());
|
||||
$reqData = json_decode(file_get_contents("php://input"),true);
|
||||
$reqPath = $reqData['item'];
|
||||
$shareType = $reqData['shareType'];
|
||||
$sharePwd = $reqData['pwd'];
|
||||
ShareHandler::createShare($reqPath,$shareType,$sharePwd,$this->userObj->getSQLData(),$this->userObj->getGroupData());
|
||||
}
|
||||
|
||||
public function gerSource(){
|
||||
$reqPath = $_POST["path"];
|
||||
$reqData = json_decode(file_get_contents("php://input"),true);
|
||||
$reqPath = $reqData['path'];
|
||||
$fileObj = new FileManage($reqPath,$this->userObj->uid);
|
||||
$FileHandler = $fileObj->Source();
|
||||
}
|
||||
|
||||
public function Content(){
|
||||
$reqPath = json_decode(file_get_contents("php://input"),true)['item'];
|
||||
$reqPath = urldecode(input("get.path"));
|
||||
$fileObj = new FileManage($reqPath,$this->userObj->uid);
|
||||
$FileHandler = $fileObj->getContent();
|
||||
}
|
||||
@@ -170,6 +169,6 @@ class File extends Controller{
|
||||
}
|
||||
|
||||
}
|
||||
return FileManage::createFolder($dirName,$dirPosition,$this->userObj->uid);
|
||||
return json(FileManage::createFolder($dirName,$dirPosition,$this->userObj->uid));
|
||||
}
|
||||
}
|
||||
@@ -30,45 +30,23 @@ class Home extends Controller{
|
||||
}
|
||||
$policyData["max_size"] = $policyData["max_size"]/(1024*1024);
|
||||
return view('home', [
|
||||
'options' => Option::getValues(['basic','upload']),
|
||||
'options' => Option::getValues(['basic','upload'],$this->userObj->userSQLData),
|
||||
'userInfo' => $userInfo,
|
||||
'extLimit' => $extLimit,
|
||||
'policyData' => $policyData,
|
||||
'groupData' => $groupData,
|
||||
'chunkSize' => config('upload.chunk_size'),
|
||||
'path' => empty(input("get.path"))?"/":input("get.path"),
|
||||
]);
|
||||
}
|
||||
|
||||
public function Album(){
|
||||
public function Download(){
|
||||
$userInfo = $this->userObj->getInfo();
|
||||
$list = Db::name("files")->where("upload_user",$this->userObj->uid)
|
||||
->where(function ($query) {
|
||||
$query->where('orign_name', "like","%jpg")
|
||||
->whereor('orign_name', "like","%png")
|
||||
->whereor('orign_name', "like","%gif")
|
||||
->whereor('orign_name', "like","%bmp");
|
||||
})
|
||||
->order('id DESC')
|
||||
->paginate(9);
|
||||
$pageCount = ceil(Db::name("files")->where("upload_user",$this->userObj->uid)
|
||||
->where(function ($query) {
|
||||
$query->where('orign_name', "like","%jpg")
|
||||
->whereor('orign_name', "like","%png")
|
||||
->whereor('orign_name', "like","%gif")
|
||||
->whereor('orign_name', "like","%bmp");
|
||||
})
|
||||
->order('id DESC')->count()/9);
|
||||
$listData = $list->all();
|
||||
$pageNow = input("?get.page")?input("get.page"):1;
|
||||
if($pageNow>$pageCount){
|
||||
$this->error('页面不存在',404,Option::getValues(['basic','group_sell']));
|
||||
}
|
||||
return view('album', [
|
||||
'options' => Option::getValues(['basic','group_sell']),
|
||||
$groupData = $this->userObj->getGroupData();
|
||||
return view('download', [
|
||||
'options' => Option::getValues(['basic','group_sell'],$this->userObj->userSQLData),
|
||||
'userInfo' => $userInfo,
|
||||
'list' => $listData,
|
||||
'listOrigin' => $list,
|
||||
'pageCount' => $pageCount,
|
||||
'page' => $pageNow,
|
||||
'groupData' => $groupData,
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,10 @@ class Index extends Controller{
|
||||
public function index(){
|
||||
|
||||
$this->userObj = new User(cookie('user_id'),cookie('login_key'));
|
||||
if($this->userObj->loginStatus){
|
||||
$this->redirect(url('/Home','',''));
|
||||
exit();
|
||||
}
|
||||
$userInfo = $this->userObj->getInfo();
|
||||
return view('index', [
|
||||
'options' => Option::getValues(['basic']),
|
||||
|
||||
@@ -14,17 +14,11 @@ class Member extends Controller{
|
||||
|
||||
public $userObj;
|
||||
|
||||
/**
|
||||
* [index description]
|
||||
* @return [type] [description]
|
||||
*/
|
||||
|
||||
public function index(){
|
||||
echo "hello";
|
||||
echo "Pong";
|
||||
}
|
||||
|
||||
/**
|
||||
* [Register description]
|
||||
*/
|
||||
public function Register(){
|
||||
if(input('?post.username-reg') && input('?post.password-reg')){
|
||||
$regAction = User::register(input('post.username-reg'),input('post.password-reg'),input('post.captchaCode'));
|
||||
@@ -51,9 +45,6 @@ class Member extends Controller{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* [Login description]
|
||||
*/
|
||||
public function Login(){
|
||||
if(input('?post.userMail') && input('?post.userPass')){
|
||||
$logAction = User::login(input('post.userMail'),input('post.userPass'),input('post.captchaCode'));
|
||||
@@ -67,9 +58,6 @@ class Member extends Controller{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* [LogOut description]
|
||||
*/
|
||||
public function LogOut(){
|
||||
$this->userObj = new User(cookie('user_id'),cookie('login_key'));
|
||||
$this->userObj->clear();
|
||||
@@ -82,13 +70,36 @@ class Member extends Controller{
|
||||
$this->userObj->getMemory();
|
||||
}
|
||||
|
||||
public function SignUp(){
|
||||
$this->userObj = new User(cookie('user_id'),cookie('login_key'));
|
||||
$this->isLoginStatusCheck();
|
||||
return view('login', [
|
||||
'options' => Option::getValues(['basic'],$this->userObj->userSQLData),
|
||||
'RegOptions' => Option::getValues(['register','login']),
|
||||
'loginStatus' => $this->userObj->loginStatus,
|
||||
'pageId' => "register",
|
||||
]);
|
||||
}
|
||||
|
||||
public function FindPwd(){
|
||||
$this->userObj = new User(cookie('user_id'),cookie('login_key'));
|
||||
$this->isLoginStatusCheck();
|
||||
return view('login', [
|
||||
'options' => Option::getValues(['basic'],$this->userObj->userSQLData),
|
||||
'RegOptions' => Option::getValues(['register','login']),
|
||||
'loginStatus' => $this->userObj->loginStatus,
|
||||
'pageId' => "resetPwd",
|
||||
]);
|
||||
}
|
||||
|
||||
public function LoginForm(){
|
||||
$this->userObj = new User(cookie('user_id'),cookie('login_key'));
|
||||
$this->isLoginStatusCheck();
|
||||
return view('login', [
|
||||
'options' => Option::getValues(['basic']),
|
||||
'options' => Option::getValues(['basic'],$this->userObj->userSQLData),
|
||||
'RegOptions' => Option::getValues(['register','login']),
|
||||
'loginStatus' => $this->userObj->loginStatus,
|
||||
'pageId' => "login",
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -114,10 +125,11 @@ class Member extends Controller{
|
||||
public function TwoStep(){
|
||||
$this->userObj = new User(cookie('user_id'),cookie('login_key'));
|
||||
$this->isLoginStatusCheck();
|
||||
return view('two_step', [
|
||||
'options' => Option::getValues(['basic']),
|
||||
return view('login', [
|
||||
'options' => Option::getValues(['basic'],$this->userObj->userSQLData),
|
||||
'RegOptions' => Option::getValues(['register','login']),
|
||||
'loginStatus' => $this->userObj->loginStatus,
|
||||
'pageId' => "TwoStep",
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -133,14 +145,16 @@ class Member extends Controller{
|
||||
|
||||
public function emailActivate(){
|
||||
$activationKey = input('param.key');
|
||||
$basicOptions = Option::getValues(['basic']);
|
||||
$this->userObj = new User(cookie('user_id'),cookie('login_key'));
|
||||
$this->isLoginStatusCheck();
|
||||
$basicOptions = Option::getValues(['basic','register','login'],$this->userObj->userSQLData);
|
||||
$activeAction = User::activicateUser($activationKey);
|
||||
if($activeAction[0]){
|
||||
return view('active_user', [
|
||||
return view('login', [
|
||||
'options' => $basicOptions,
|
||||
'RegOptions' => $basicOptions,
|
||||
'loginStatus' => $this->userObj->loginStatus,
|
||||
'pageId' => "emailActivate",
|
||||
]);
|
||||
}else{
|
||||
$this->error($activeAction[1],403,$basicOptions);
|
||||
@@ -150,15 +164,17 @@ class Member extends Controller{
|
||||
public function resetPwd(){
|
||||
$resetKey = input('param.key');
|
||||
$userId = input('get.uid');
|
||||
$basicOptions = Option::getValues(['basic']);
|
||||
$this->userObj = new User(cookie('user_id'),cookie('login_key'));
|
||||
$basicOptions = Option::getValues(['basic','register','login'],$this->userObj->userSQLData);
|
||||
$this->isLoginStatusCheck();
|
||||
$resetAction = User::resetUser($resetKey,$userId);
|
||||
if($resetAction[0]){
|
||||
return view('reset_user', [
|
||||
return view('login', [
|
||||
'options' => $basicOptions,
|
||||
'RegOptions' => $basicOptions,
|
||||
'loginStatus' => $this->userObj->loginStatus,
|
||||
'key' => $resetKey."_".$userId,
|
||||
'pageId' => "resetPwdForm",
|
||||
]);
|
||||
}else{
|
||||
$this->error($resetAction[1],403,$basicOptions);
|
||||
@@ -185,7 +201,7 @@ class Member extends Controller{
|
||||
$policyList[$key] = $value;
|
||||
}
|
||||
$avaliablePolicy = Db::name("policy")->where("id","in",$policyList)->select();
|
||||
$basicOptions = Option::getValues(['basic']);
|
||||
$basicOptions = Option::getValues(['basic'],$this->userObj->userSQLData);
|
||||
return view('setting', [
|
||||
'options' => $basicOptions,
|
||||
'userInfo' => $userInfo,
|
||||
@@ -236,6 +252,17 @@ class Member extends Controller{
|
||||
}
|
||||
}
|
||||
|
||||
public function ChangeThemeColor(){
|
||||
$this->userObj = new User(cookie('user_id'),cookie('login_key'));
|
||||
$this->loginStatusCheck();
|
||||
$saveAction = $this->userObj->changeOption("preferTheme",input("post.theme"));
|
||||
if($saveAction[0]){
|
||||
return json(['error' => '200','msg' => '设置成功']);
|
||||
}else{
|
||||
return json(['error' => '1','msg' => $saveAction[1]]);
|
||||
}
|
||||
}
|
||||
|
||||
public function HomePage(){
|
||||
$this->userObj = new User(cookie('user_id'),cookie('login_key'));
|
||||
$userInfo = $this->userObj->getInfo();
|
||||
|
||||
@@ -14,11 +14,63 @@ class Profile extends Controller{
|
||||
public $siteOptions;
|
||||
|
||||
public function _initialize(){
|
||||
$this->siteOptions = Option::getValues(["basic"]);
|
||||
}
|
||||
|
||||
public function getList(){
|
||||
$userId = (string)input("post.uid");
|
||||
$userData = Db::name("users")->where("id",$userId)->find();
|
||||
$page = (int)input("post.page");
|
||||
if (empty($userId) || empty($userData) || $userData["profile"] == 0){
|
||||
$this->error('用户主页不存或者用户关闭了个人主页',404,$this->siteOptions);
|
||||
}
|
||||
switch (input("post.type")) {
|
||||
case 'all':
|
||||
$list = Db::name('shares')
|
||||
->where('owner',$userId)
|
||||
->where('type',"public")
|
||||
->order('share_time DESC')
|
||||
->page($page.',10')
|
||||
->select();
|
||||
break;
|
||||
case 'hot':
|
||||
$num = Option::getValue("hot_share_num");
|
||||
$list = Db::name('shares')
|
||||
->where('owner',$userId)
|
||||
->where('type',"public")
|
||||
->order('download_num DESC')
|
||||
->limit($num)
|
||||
->select();
|
||||
break;
|
||||
default:
|
||||
$list = Db::name('shares')
|
||||
->where('owner',$userId)
|
||||
->where('type',"public")
|
||||
->order('share_time DESC')
|
||||
->page($page.',10')
|
||||
->select();
|
||||
break;
|
||||
}
|
||||
$listData = $list;
|
||||
foreach ($listData as $key => $value) {
|
||||
unset($listData[$key]["share_pwd"]);
|
||||
unset($listData[$key]["source_name"]);
|
||||
if($value["source_type"]=="file"){
|
||||
$listData[$key]["fileData"] = Db::name('files')->where('id',$value["source_name"])->find()["orign_name"];
|
||||
|
||||
}else{
|
||||
$pathDir = explode("/",$value["source_name"]);
|
||||
$listData[$key]["fileData"] = end($pathDir);
|
||||
}
|
||||
}
|
||||
|
||||
return json($listData);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function index(){
|
||||
$this->visitorObj = new User(cookie('user_id'),cookie('login_key'));
|
||||
$this->siteOptions = Option::getValues(["basic"],$this->visitorObj->userSQLData);
|
||||
$userId = (string)input("param.uid");
|
||||
$userData = Db::name("users")->where("id",$userId)->find();
|
||||
if (empty($userId) || empty($userData) || $userData["profile"] == 0){
|
||||
@@ -30,47 +82,14 @@ class Profile extends Controller{
|
||||
->where('type',"public")
|
||||
->count();
|
||||
$regDays = (int)((time()-strtotime($userData["user_date"]))/86400);
|
||||
switch (input("get.type")) {
|
||||
case 'all':
|
||||
$list = Db::name('shares')
|
||||
->where('owner',$userId)
|
||||
->where('type',"public")
|
||||
->order('id DESC')
|
||||
->paginate(10);
|
||||
break;
|
||||
case 'hot':
|
||||
$num = Option::getValue("hot_share_num");
|
||||
$list = Db::name('shares')
|
||||
->where('owner',$userId)
|
||||
->where('type',"public")
|
||||
->paginate($num);
|
||||
break;
|
||||
default:
|
||||
$list = Db::name('shares')
|
||||
->where('owner',$userId)
|
||||
->where('type',"public")
|
||||
->order('id DESC')
|
||||
->paginate(10);
|
||||
break;
|
||||
}
|
||||
$listData = $list->all();
|
||||
foreach ($listData as $key => $value) {
|
||||
if($value["source_type"]=="file"){
|
||||
$listData[$key]["fileData"] = Db::name('files')->where('id',$value["source_name"])->find()["orign_name"];
|
||||
|
||||
}else{
|
||||
$pathDir = explode("/",$value["source_name"]);
|
||||
$listData[$key]["fileData"] = end($pathDir);
|
||||
}
|
||||
}
|
||||
|
||||
return view("profile",[
|
||||
"options" => $this->siteOptions,
|
||||
'loginStatus' => $this->visitorObj->loginStatus,
|
||||
'userInfo' => $userData,
|
||||
'userData' => $this->visitorObj->userSQLData,
|
||||
'targetUserInfo' => $userData,
|
||||
'userSQL' => $this->visitorObj->userSQLData,
|
||||
'userInfo' => $this->visitorObj->getInfo(),
|
||||
'groupData' => $groupData,
|
||||
'list' => $listData,
|
||||
'listOrigin' => $list,
|
||||
'type' => input("get.type"),
|
||||
'shareCount' => $shareCount,
|
||||
'regDays' => $regDays,
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
namespace app\index\controller;
|
||||
|
||||
use think\Controller;
|
||||
use think\Db;
|
||||
use think\Request;
|
||||
|
||||
use \app\index\model\Task;
|
||||
use \app\index\model\Option;
|
||||
|
||||
class Queue extends Controller{
|
||||
|
||||
public function __construct(\think\Request $request = null){
|
||||
$token = Option::getValue("task_queue_token");
|
||||
if($token==""){
|
||||
abort(403);
|
||||
}
|
||||
if(Request::instance()->header("Authorization") !="Bearer ".$token){
|
||||
abort(403);
|
||||
}
|
||||
}
|
||||
|
||||
public function index(){
|
||||
|
||||
}
|
||||
|
||||
public function basicInfo(){
|
||||
return json_encode([
|
||||
"basePath" => ROOT_PATH,
|
||||
]);
|
||||
}
|
||||
|
||||
public function getList(){
|
||||
$size = input("get.num");
|
||||
$tasks = Db::name("task")->where("status","todo")->limit($size)->select();
|
||||
$taskID = array_column($tasks,"id");
|
||||
Db::name("task")->where("id","in",$taskID)->update(["status"=>"processing"]);
|
||||
if(empty($tasks)){
|
||||
return "none";
|
||||
}else{
|
||||
return json_encode($tasks);
|
||||
}
|
||||
}
|
||||
|
||||
public function getPolicy(){
|
||||
$id = input("get.id");
|
||||
$policy = Db::name("policy")->where("id",$id)->find();
|
||||
if(empty(($policy))){
|
||||
abort(404);
|
||||
}else{
|
||||
return json($policy);
|
||||
}
|
||||
}
|
||||
|
||||
public function setSuccess(){
|
||||
$id = input("get.id");
|
||||
$task = new Task($id);
|
||||
$task->taskModel = Db::name("task")
|
||||
->where("id",$id)
|
||||
//->where("status","processing")
|
||||
->find();
|
||||
if(empty($task->taskModel)){
|
||||
return json(["error"=>true,"msg"=>"未找到任务"]);
|
||||
}
|
||||
return json($task->setSuccess());
|
||||
}
|
||||
|
||||
public function setError(){
|
||||
$id = input("get.id");
|
||||
$task = new Task($id);
|
||||
$task->taskModel = Db::name("task")
|
||||
->where("id",$id)
|
||||
//->where("status","processing")
|
||||
->find();
|
||||
if(empty($task->taskModel)){
|
||||
return json(["error"=>true,"msg"=>"未找到任务"]);
|
||||
}
|
||||
return json($task->Error());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
<?php
|
||||
namespace app\index\controller;
|
||||
|
||||
use think\Controller;
|
||||
use think\Db;
|
||||
use \app\index\model\Option;
|
||||
use \app\index\model\User;
|
||||
use \app\index\model\Aria2;
|
||||
use think\Session;
|
||||
|
||||
|
||||
class RemoteDownload extends Controller{
|
||||
|
||||
public $userObj;
|
||||
|
||||
public function _initialize(){
|
||||
$this->userObj = new User(cookie('user_id'),cookie('login_key'));
|
||||
if(!$this->userObj->loginStatus){
|
||||
echo "Bad request";
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
||||
private function checkPerimission($permissionId){
|
||||
$permissionData = $this->userObj->groupData["aria2"];
|
||||
if(explode(",",$permissionData)[$permissionId] != "1"){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private function insertRecord($aria2,$url,$path){
|
||||
Db::name("download")->insert([
|
||||
"pid" => $aria2->pid,
|
||||
"path_id" => $aria2->pathId,
|
||||
"owner" => $this->userObj->uid,
|
||||
"save_dir" => $path,
|
||||
"status" => "ready",
|
||||
"msg" => "",
|
||||
"info"=>"",
|
||||
"source" =>$url,
|
||||
"file_index" => 0,
|
||||
"is_single" => 1,
|
||||
"total_size" => 0,
|
||||
]);
|
||||
}
|
||||
|
||||
public function addUrl(){
|
||||
$policyData = Db::name("policy")->where("id",$this->userObj->groupData["policy_name"])->find();
|
||||
if(!$this->checkPerimission(0) || ($policyData["policy_type"] != "local" && $policyData["policy_type"] != "onedrive")){
|
||||
return json(["result"=>['success'=>false,'error'=>"您当前的无用户无法执行此操作"]]);
|
||||
}
|
||||
$aria2Options = Option::getValues(["aria2"]);
|
||||
$aria2 = new Aria2($aria2Options);
|
||||
$downloadStart = $aria2->addUrl(input("post.url"));
|
||||
if($aria2->reqStatus){
|
||||
$this->insertRecord($aria2,input("post.url"),input("post.path"));
|
||||
return json(["result"=>['success'=>true,'error'=>null]]);
|
||||
}else{
|
||||
return json(["result"=>['success'=>false,'error'=>$aria2->reqMsg]]);
|
||||
}
|
||||
}
|
||||
|
||||
public function AddTorrent(){
|
||||
$policyData = Db::name("policy")->where("id",$this->userObj->groupData["policy_name"])->find();
|
||||
if(!$this->checkPerimission(0) || $policyData["policy_type"] != "local" && $policyData["policy_type"] != "onedrive"){
|
||||
return json(["result"=>['success'=>false,'error'=>"您当前的无用户无法执行此操作"]]);
|
||||
}
|
||||
$downloadingLength = Db::name("download")
|
||||
->where("owner",$this->userObj->uid)
|
||||
->where("status","<>","complete")
|
||||
->where("status","<>","error")
|
||||
->where("status","<>","canceled")
|
||||
->sum("total_size");
|
||||
if(!\app\index\model\FileManage::sotrageCheck($this->userObj->uid,$downloadingLength)){
|
||||
return json(["result"=>['success'=>false,'error'=>"容量不足"]]);
|
||||
}
|
||||
$aria2Options = Option::getValues(["aria2"]);
|
||||
$aria2 = new Aria2($aria2Options);
|
||||
$torrentObj = new \app\index\model\FileManage(input("post.id"),$this->userObj->uid,true);
|
||||
$downloadStart = $aria2->addTorrent($torrentObj->signTmpUrl());
|
||||
if($aria2->reqStatus){
|
||||
$this->insertRecord($aria2,input("post.id"),input("post.savePath"));
|
||||
return json(["result"=>['success'=>true,'error'=>null]]);
|
||||
}else{
|
||||
return json(["result"=>['success'=>false,'error'=>$aria2->reqMsg]]);
|
||||
}
|
||||
}
|
||||
|
||||
public function FlushStatus(){
|
||||
$aria2Options = Option::getValues(["aria2"]);
|
||||
$aria2 = new Aria2($aria2Options);
|
||||
if(!input("?post.id")){
|
||||
return json(['error'=>1,'message'=>"信息不完整"]);
|
||||
}
|
||||
$policyData = Db::name("policy")->where("id",$this->userObj->groupData["policy_name"])->find();
|
||||
if(!$aria2->flushStatus(input("post.id"),$this->userObj->uid,$policyData)){
|
||||
return json(['error'=>1,'message'=>$aria2->reqMsg]);
|
||||
}
|
||||
}
|
||||
|
||||
public function FlushUser(){
|
||||
$aria2Options = Option::getValues(["aria2"]);
|
||||
$aria2 = new Aria2($aria2Options);
|
||||
$toBeFlushed = Db::name("download")
|
||||
->where("owner",$this->userObj->uid)
|
||||
->where("status","<>","complete")
|
||||
->where("status","<>","error")
|
||||
->where("status","<>","canceled")
|
||||
//取消的
|
||||
->select();
|
||||
foreach ($toBeFlushed as $key => $value) {
|
||||
$aria2->flushStatus($value["id"],$this->userObj->uid,$this->userObj->getPolicy());
|
||||
}
|
||||
}
|
||||
|
||||
public function Cancel(){
|
||||
$aria2Options = Option::getValues(["aria2"]);
|
||||
$aria2 = new Aria2($aria2Options);
|
||||
$downloadItem = Db::name("download")->where("owner",$this->userObj->uid)->where("id",input("post.id"))->find();
|
||||
if(empty($downloadItem)){
|
||||
return json(['error'=>1,'message'=>"未找到下载记录"]);
|
||||
}
|
||||
if($aria2->Remove($downloadItem["pid"],"")){
|
||||
return json(['error'=>0,'message'=>"下载已取消"]);
|
||||
}else{
|
||||
return json(['error'=>1,'message'=>"取消失败"]);
|
||||
}
|
||||
}
|
||||
|
||||
public function ListDownloading(){
|
||||
$downloadItems = Db::name("download")->where("owner",$this->userObj->uid)->where("status","in",["active","ready","waiting"])->order('id desc')->select();
|
||||
foreach ($downloadItems as $key => $value) {
|
||||
$connectInfo = json_decode($value["info"],true);
|
||||
if(isset($connectInfo["dir"])){
|
||||
$downloadItems[$key]["fileName"] = basename($connectInfo["dir"]);
|
||||
$downloadItems[$key]["completedLength"] = $connectInfo["completedLength"];
|
||||
$downloadItems[$key]["totalLength"] = $connectInfo["totalLength"];
|
||||
$downloadItems[$key]["downloadSpeed"] = $connectInfo["downloadSpeed"];
|
||||
}else{
|
||||
if(floor($value["source"])==$value["source"]){
|
||||
$downloadItems[$key]["fileName"] = Db::name("files")->where("id",$value["source"])->column("orign_name");
|
||||
}else{
|
||||
$downloadItems[$key]["fileName"] = $value["source"];
|
||||
}
|
||||
$downloadItems[$key]["completedLength"] = 0;
|
||||
$downloadItems[$key]["totalLength"] = 0;
|
||||
$downloadItems[$key]["downloadSpeed"] = 0;
|
||||
}
|
||||
}
|
||||
return json($downloadItems);
|
||||
}
|
||||
|
||||
public function ListFinished(){
|
||||
$page = input("get.page");
|
||||
$downloadItems = Db::name("download")->where("owner",$this->userObj->uid)->where("status","not in",["active","ready","waiting"])->order('id desc')->page($page.',10')->select();
|
||||
foreach ($downloadItems as $key => $value) {
|
||||
$connectInfo = json_decode($value["info"],true);
|
||||
if(isset($connectInfo["dir"])){
|
||||
$downloadItems[$key]["fileName"] = basename($connectInfo["dir"]);
|
||||
$downloadItems[$key]["completedLength"] = $connectInfo["completedLength"];
|
||||
$downloadItems[$key]["totalLength"] = $connectInfo["totalLength"];
|
||||
$downloadItems[$key]["downloadSpeed"] = $connectInfo["downloadSpeed"];
|
||||
}else{
|
||||
if(floor($value["source"])==$value["source"]){
|
||||
$downloadItems[$key]["fileName"] = Db::name("files")->where("id",$value["source"])->column("orign_name");
|
||||
}else{
|
||||
$downloadItems[$key]["fileName"] = $value["source"];
|
||||
}
|
||||
$downloadItems[$key]["completedLength"] = 0;
|
||||
$downloadItems[$key]["totalLength"] = 0;
|
||||
$downloadItems[$key]["downloadSpeed"] = 0;
|
||||
}
|
||||
}
|
||||
return json($downloadItems);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -16,7 +16,7 @@ class Share extends Controller{
|
||||
|
||||
public function _initialize(){
|
||||
$this->userObj = new User(cookie('user_id'),cookie('login_key'));
|
||||
$this->siteOptions = Option::getValues(["basic"]);
|
||||
$this->siteOptions = Option::getValues(["basic","share"]);
|
||||
}
|
||||
|
||||
public function index(){
|
||||
@@ -30,34 +30,36 @@ class Share extends Controller{
|
||||
$shareObj->numIncrease("view_num");
|
||||
if($shareObj->shareData["source_type"] == "dir"){
|
||||
return view('share_dir', [
|
||||
'options' => Option::getValues(['basic','share']),
|
||||
'options' => Option::getValues(['basic','share'],$this->userObj->userSQLData),
|
||||
'userInfo' => $shareObj->shareOwner->userSQLData,
|
||||
'dirData' => $shareObj->dirData,
|
||||
'shareData' => $shareObj->shareData,
|
||||
'loginStatus' => $this->userObj->loginStatus,
|
||||
'userData' => $this->userObj->userSQLData,
|
||||
'userData' => $this->userObj->getInfo(),
|
||||
'groupData' => $shareObj->shareOwner->groupData,
|
||||
'allowPreview' => Option::getValue("allowdVisitorDownload"),
|
||||
'path' => empty(input("get.path"))?"/":input("get.path"),
|
||||
]);
|
||||
}else{
|
||||
return view('share_single', [
|
||||
'options' => Option::getValues(['basic','share']),
|
||||
'options' => Option::getValues(['basic','share'],$this->userObj->userSQLData),
|
||||
'userInfo' => $shareObj->shareOwner->userSQLData,
|
||||
'fileData' => $shareObj->fileData,
|
||||
'shareData' => $shareObj->shareData,
|
||||
'loginStatus' => $this->userObj->loginStatus,
|
||||
'userData' => $this->userObj->userSQLData,
|
||||
'userData' => $this->userObj->getInfo(),
|
||||
'allowPreview' => Option::getValue("allowdVisitorDownload"),
|
||||
'path' => empty(input("get.path"))?"/":input("get.path"),
|
||||
]);
|
||||
}
|
||||
}else{
|
||||
return view('share_lock', [
|
||||
'options' => Option::getValues(['basic','share']),
|
||||
'options' => Option::getValues(['basic','share'],$this->userObj->userSQLData),
|
||||
'userInfo' => $shareObj->shareOwner->userSQLData,
|
||||
'fileData' => $shareObj->fileData,
|
||||
'shareData' => $shareObj->shareData,
|
||||
'loginStatus' => $this->userObj->loginStatus,
|
||||
'userData' => $this->userObj->userSQLData,
|
||||
'userData' => $this->userObj->getInfo(),
|
||||
'pwd' => input("?get.pwd") ? input("get.pwd") : "",
|
||||
]);
|
||||
}
|
||||
@@ -66,12 +68,18 @@ class Share extends Controller{
|
||||
public function getDownloadUrl(){
|
||||
$shareId = input('key');
|
||||
$shareObj = new ShareHandler($shareId,false);
|
||||
return $shareObj->getDownloadUrl($this->userObj);
|
||||
return json($shareObj->getDownloadUrl($this->userObj));
|
||||
}
|
||||
|
||||
public function Download(){
|
||||
$shareId = input('param.key');
|
||||
$filePath = input('get.path');
|
||||
if($this->siteOptions["refererCheck"]=="true"){
|
||||
$check = $this->referCheck();
|
||||
if(!$check){
|
||||
$this->error("来源非法",403,$this->siteOptions);
|
||||
}
|
||||
}
|
||||
$shareObj = new ShareHandler($shareId,false);
|
||||
if(empty($filePath)){
|
||||
$DownloadHandler = $shareObj->Download($this->userObj);
|
||||
@@ -85,6 +93,26 @@ class Share extends Controller{
|
||||
}
|
||||
}
|
||||
|
||||
public function Content(){
|
||||
$shareId = input('param.key');
|
||||
$filePath = input('get.path');
|
||||
if($this->siteOptions["refererCheck"]=="true"){
|
||||
$check = $this->referCheck();
|
||||
if(!$check){
|
||||
$this->error("来源非法",403,$this->siteOptions);
|
||||
}
|
||||
}
|
||||
$shareObj = new ShareHandler($shareId,false);
|
||||
if(empty($filePath)){
|
||||
$contentHandller = $shareObj->getContent($this->userObj,$filePath,false);
|
||||
}else{
|
||||
$contentHandller = $shareObj->getContent($this->userObj,$filePath,true);
|
||||
}
|
||||
if(!$contentHandller[0]){
|
||||
return json(["result"=>["success"=>false,"error"=>$contentHandller[1]]]);
|
||||
}
|
||||
}
|
||||
|
||||
public function chekPwd(){
|
||||
$shareId = input('key');
|
||||
$inputPwd = input('password');
|
||||
@@ -95,12 +123,26 @@ class Share extends Controller{
|
||||
"msg" => "分享不存在"
|
||||
);
|
||||
}
|
||||
return $shareObj->checkPwd($inputPwd);
|
||||
return json($shareObj->checkPwd($inputPwd));
|
||||
}
|
||||
|
||||
private function referCheck(){
|
||||
$agent = Request::instance()->header('referer');
|
||||
if(substr($agent, 0, strlen($this->siteOptions["siteURL"])) !== $this->siteOptions["siteURL"]){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function Preview(){
|
||||
$shareId = input('param.key');
|
||||
$filePath = input('get.path');
|
||||
if($this->siteOptions["refererCheck"]=="true"){
|
||||
$check = $this->referCheck();
|
||||
if(!$check){
|
||||
$this->error("来源非法",403,$this->siteOptions);
|
||||
}
|
||||
}
|
||||
$shareObj = new ShareHandler($shareId,false);
|
||||
if(empty($filePath)){
|
||||
$previewHandler = $shareObj->Preview($this->userObj);
|
||||
@@ -122,7 +164,7 @@ class Share extends Controller{
|
||||
$shareId = input('param.key');
|
||||
$reqPathTo = stripslashes(json_decode(file_get_contents("php://input"),true)['path']);
|
||||
$shareObj = new ShareHandler($shareId,false);
|
||||
return $shareObj->ListFile($reqPathTo);
|
||||
return json($shareObj->ListFile($reqPathTo));
|
||||
}
|
||||
|
||||
public function ListPic(){
|
||||
@@ -132,28 +174,95 @@ class Share extends Controller{
|
||||
return $shareObj->listPic($shareId,$filePath);
|
||||
}
|
||||
|
||||
public function Thumb(){
|
||||
$shareId = input('param.key');
|
||||
$filePath = urldecode(input('get.path'));
|
||||
if(input("get.isImg") != "true"){
|
||||
return "";
|
||||
}
|
||||
if($this->siteOptions["refererCheck"]=="true"){
|
||||
$check = $this->referCheck();
|
||||
if(!$check){
|
||||
$this->error("来源非法",403,$this->siteOptions);
|
||||
}
|
||||
}
|
||||
$shareObj = new ShareHandler($shareId,false);
|
||||
$Redirect = $shareObj->getThumb($this->userObj,$filePath);
|
||||
if($Redirect[0]){
|
||||
$this->redirect($Redirect[1],302);
|
||||
}else{
|
||||
$this->error($Redirect[1],403,$this->siteOptions);
|
||||
}
|
||||
}
|
||||
|
||||
public function DocPreview(){
|
||||
$shareId = input('param.key');
|
||||
$filePath = urldecode(input('get.path'));
|
||||
if($this->siteOptions["refererCheck"]=="true"){
|
||||
$check = $this->referCheck();
|
||||
if(!$check){
|
||||
$this->error("来源非法",403,$this->siteOptions);
|
||||
}
|
||||
}
|
||||
$shareObj = new ShareHandler($shareId,false);
|
||||
if(empty($filePath)){
|
||||
$Redirect = $shareObj->getDocPreview($this->userObj,$filePath,false);
|
||||
}else{
|
||||
$Redirect = $shareObj->getDocPreview($this->userObj,$filePath,true);
|
||||
}
|
||||
|
||||
if($Redirect[0]){
|
||||
$this->redirect($Redirect[1],302);
|
||||
}else{
|
||||
$this->error($Redirect[1],403,$this->siteOptions);
|
||||
}
|
||||
}
|
||||
|
||||
public function Delete(){
|
||||
$shareId = input('post.id');
|
||||
$shareObj = new ShareHandler($shareId,false);
|
||||
if(!$shareObj->querryStatus){
|
||||
return array(
|
||||
return json(array(
|
||||
"error" => 1,
|
||||
"msg" => "分享不存在"
|
||||
);
|
||||
));
|
||||
}
|
||||
return $shareObj->deleteShare($this->userObj->uid);
|
||||
return json($shareObj->deleteShare($this->userObj->uid));
|
||||
}
|
||||
|
||||
public function ChangePromission(){
|
||||
$shareId = input('post.id');
|
||||
$shareObj = new ShareHandler($shareId,false);
|
||||
if(!$shareObj->querryStatus){
|
||||
return array(
|
||||
return json(array(
|
||||
"error" => 1,
|
||||
"msg" => "分享不存在"
|
||||
);
|
||||
));
|
||||
}
|
||||
return $shareObj->changePromission($this->userObj->uid);
|
||||
return json($shareObj->changePromission($this->userObj->uid));
|
||||
}
|
||||
|
||||
public function ListMyShare(){
|
||||
if(!$this->userObj->loginStatus){
|
||||
$this->redirect(url('/Login','',''));
|
||||
exit();
|
||||
}
|
||||
$list = Db::name('shares')
|
||||
->where('owner',$this->userObj->uid)
|
||||
->order('share_time DESC')
|
||||
->page(input("post.page").",18")
|
||||
->select();
|
||||
$listData = $list;
|
||||
foreach ($listData as $key => $value) {
|
||||
unset($listData[$key]["source_name"]);
|
||||
if($value["source_type"]=="file"){
|
||||
$listData[$key]["fileData"] = Db::name('files')->where('id',$value["source_name"])->find()["orign_name"];
|
||||
|
||||
}else{
|
||||
$listData[$key]["fileData"] = $value["source_name"];
|
||||
}
|
||||
}
|
||||
return json($listData);
|
||||
}
|
||||
|
||||
public function My(){
|
||||
@@ -163,22 +272,10 @@ class Share extends Controller{
|
||||
}
|
||||
$userInfo = $this->userObj->getInfo();
|
||||
$groupData = $this->userObj->getGroupData();
|
||||
$list = Db::name('shares')->where('owner',$this->userObj->uid)->paginate(10);
|
||||
$listData = $list->all();
|
||||
foreach ($listData as $key => $value) {
|
||||
if($value["source_type"]=="file"){
|
||||
$listData[$key]["fileData"] = Db::name('files')->where('id',$value["source_name"])->find()["orign_name"];
|
||||
|
||||
}else{
|
||||
$listData[$key]["fileData"] = $value["source_name"];
|
||||
}
|
||||
}
|
||||
return view('share_home', [
|
||||
'options' => Option::getValues(['basic','share']),
|
||||
'userInfo' => $userInfo,
|
||||
'options' => Option::getValues(['basic','share'],$this->userObj->userSQLData),
|
||||
'userData' => $userInfo,
|
||||
'groupData' => $groupData,
|
||||
'list' => $listData,
|
||||
'listOrigin' => $list
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
namespace app\index\controller;
|
||||
|
||||
use think\Controller;
|
||||
use think\Db;
|
||||
use \app\index\model\Option;
|
||||
use \app\index\model\User;
|
||||
use think\Session;
|
||||
use \app\index\model\FileManage;
|
||||
use \app\index\model\ShareHandler;
|
||||
|
||||
class Viewer extends Controller{
|
||||
|
||||
public $userObj;
|
||||
|
||||
public function _initialize(){
|
||||
// $this->userObj = new User(cookie('user_id'),cookie('login_key'));
|
||||
// if(!$this->userObj->loginStatus){
|
||||
// $this->redirect(url('/Login','',''));
|
||||
// exit();
|
||||
// }
|
||||
$this->userObj = new User(cookie('user_id'),cookie('login_key'));
|
||||
}
|
||||
|
||||
public function Video(){
|
||||
$path = input("get.path");
|
||||
$pathSplit = explode("/",urldecode($path));
|
||||
$userInfo = $this->userObj->getInfo();
|
||||
$groupData = $this->userObj->getGroupData();
|
||||
$url = "/File/Preview?action=preview&path=".$path;
|
||||
if(input("get.share")==true){
|
||||
$url = "/Share/Preview/".input("get.shareKey")."/?path=".$path;
|
||||
}else if(input("get.single")==true){
|
||||
$url = "/Share/Preview/".input("get.shareKey");
|
||||
}
|
||||
return view('video', [
|
||||
'options' => Option::getValues(['basic'],$this->userObj->userSQLData),
|
||||
'userInfo' => $userInfo,
|
||||
'groupData' => $groupData,
|
||||
'url' => $url,
|
||||
'fileName' => end($pathSplit),
|
||||
'isSharePage' => input("?get.share")?"true":"false",
|
||||
]);
|
||||
}
|
||||
|
||||
public function Markdown(){
|
||||
$path = input("get.path");
|
||||
$pathSplit = explode("/",urldecode($path));
|
||||
$userInfo = $this->userObj->getInfo();
|
||||
$groupData = $this->userObj->getGroupData();
|
||||
$url = "/File/Content?action=preview&path=".$path;
|
||||
if(input("get.share")==true){
|
||||
$url = "/Share/Content/".input("get.shareKey")."/?path=".$path;
|
||||
}else if(input("get.single")==true){
|
||||
$url = "/Share/Content/".input("get.shareKey");
|
||||
}
|
||||
return view('markdown', [
|
||||
'options' => Option::getValues(['basic'],$this->userObj->userSQLData),
|
||||
'userInfo' => $userInfo,
|
||||
'groupData' => $groupData,
|
||||
'url' => $url,
|
||||
'fileName' => end($pathSplit),
|
||||
'path' => urldecode($path),
|
||||
'isSharePage' => input("?get.share")?"true":"false",
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -7,7 +7,7 @@ use think\Db;
|
||||
use \app\index\model\Option;
|
||||
use \app\index\model\User;
|
||||
use \app\index\model\Directory;
|
||||
use \app\index\model\Object;
|
||||
use \app\index\model\Objects;
|
||||
use \app\index\model\DavAuth;
|
||||
use \app\index\model\BasicCallBack;
|
||||
|
||||
@@ -28,7 +28,7 @@ class WebDav extends Controller{
|
||||
$publicDir = new Directory($this->uid."/");
|
||||
|
||||
$server = new DAV\Server($publicDir);
|
||||
$server->setBaseUri('/WebDav/Api/uid/'.$this->uid);
|
||||
$server->setBaseUri('/WebDav/Api/uid/'.$this->uid."/");
|
||||
$lockBackend = new DAV\Locks\Backend\File(ROOT_PATH.'public/locks');
|
||||
$lockPlugin = new DAV\Locks\Plugin($lockBackend);
|
||||
$server->addPlugin($lockPlugin);
|
||||
|
||||
@@ -5,6 +5,7 @@ use think\Model;
|
||||
use think\Db;
|
||||
use \app\index\model\Mail;
|
||||
use \app\index\model\FileManage;
|
||||
use \Krizalys\Onedrive\Client;
|
||||
|
||||
class AdminHandler extends Model{
|
||||
|
||||
@@ -14,11 +15,30 @@ class AdminHandler extends Model{
|
||||
public $pageNow;
|
||||
public $pageTotal;
|
||||
public $dataTotal;
|
||||
public $dbVerInfo;
|
||||
|
||||
public function __construct($options){
|
||||
$this->siteOptions = $options;
|
||||
}
|
||||
|
||||
public function checkDbVersion(){
|
||||
$versionInfo = json_decode(@file_get_contents(ROOT_PATH. "application/version.json"),true);
|
||||
$dbVerNow = Option::getValue("database_version");
|
||||
if(!isset($versionInfo["db_version"]) || $dbVerNow < (int)$versionInfo["db_version"]){
|
||||
$this->dbVerInfo = array('now' => $dbVerNow, 'require' => $versionInfo["db_version"]);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function checkCron(){
|
||||
$cronRecord = Db::name("corn")->where("name","delete_unseful_chunks")->find();
|
||||
if($cronRecord["last_excute"]+$cronRecord["interval_s"]+"1800"<time()){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getStatics(){
|
||||
$statics["fileNum"] = Db::name('files')->count();
|
||||
$statics["privateShareNum"] = Db::name('shares')->where("type","private")->count();
|
||||
@@ -82,6 +102,37 @@ class AdminHandler extends Model{
|
||||
return $this->saveOptions($options);
|
||||
}
|
||||
|
||||
public function saveColorSetting($options){
|
||||
$colorOptions = [];
|
||||
foreach ($options["color"] as $key => $value) {
|
||||
$color = \json_decode($value,true);
|
||||
$validate = ($color!==null)&&array_key_exists("palette",$color) &&
|
||||
array_key_exists("common",$color["palette"]) &&
|
||||
array_key_exists("black",$color["palette"]["common"]) &&
|
||||
array_key_exists("white",$color["palette"]["common"]) &&
|
||||
array_key_exists("background",$color["palette"]) &&
|
||||
array_key_exists("primary",$color["palette"]) &&
|
||||
array_key_exists("secondary",$color["palette"]) &&
|
||||
array_key_exists("error",$color["palette"]) &&
|
||||
array_key_exists("text",$color["palette"]) &&
|
||||
array_key_exists("explorer",$color["palette"]) &&
|
||||
array_key_exists("main",$color["palette"]["primary"]) &&
|
||||
array_key_exists("main",$color["palette"]["secondary"]);
|
||||
if(!$validate){
|
||||
return ["error"=>1,"msg"=>"第 ".($key+1)." 行配色方案格式有误"];
|
||||
}
|
||||
$colorOptions[$color["palette"]["primary"]["main"]] = $color;
|
||||
}
|
||||
if(!array_key_exists($options["header"],$colorOptions)){
|
||||
return ["error"=>1,"msg"=>"第 ".($key+1)." 默认配色不存在"];
|
||||
}
|
||||
$optionsForSet = [
|
||||
"defaultTheme" => $options["header"],
|
||||
"themes" => json_encode($colorOptions),
|
||||
];
|
||||
return $this->saveOptions($optionsForSet);
|
||||
}
|
||||
|
||||
public function saveRegSetting($options){
|
||||
foreach(["email_active","login_captcha","reg_captcha","forget_captcha"] as $key){
|
||||
$options[$key] = array_key_exists($key,$options) ? $options[$key] : 0;
|
||||
@@ -93,6 +144,14 @@ class AdminHandler extends Model{
|
||||
return $this->saveOptions($options);
|
||||
}
|
||||
|
||||
public function saveAria2Setting($options){
|
||||
return $this->saveOptions($options);
|
||||
}
|
||||
|
||||
public function saveTaskOption($options){
|
||||
return $this->saveOptions($options);
|
||||
}
|
||||
|
||||
public function saveMailTemplate($options){
|
||||
return $this->saveOptions($options);
|
||||
}
|
||||
@@ -102,6 +161,7 @@ class AdminHandler extends Model{
|
||||
unset($options["sizeTimes"]);
|
||||
$options["grade_policy"] = 0;
|
||||
$options["policy_list"] = $options["policy_name"];
|
||||
$options["aria2"] = $options["aria2"] ? "1,1,1" : "0,0,0";
|
||||
try {
|
||||
Db::name("groups")->insert($options);
|
||||
} catch (Exception $e) {
|
||||
@@ -130,7 +190,7 @@ class AdminHandler extends Model{
|
||||
} catch (Exception $e) {
|
||||
return ["error"=>1,"msg"=>$e->getMessage()];
|
||||
}
|
||||
return ["error"=>200,"msg"=>"设置已保存"];
|
||||
return ["error"=>200,"msg"=>"设置已保存","id"=>Db::name('policy')->getLastInsID()];
|
||||
}
|
||||
|
||||
public function editPolicy($options){
|
||||
@@ -156,6 +216,7 @@ class AdminHandler extends Model{
|
||||
unset($options["id"]);
|
||||
$options["max_storage"] = $options["max_storage"]*$options["sizeTimes"];
|
||||
unset($options["sizeTimes"]);
|
||||
$options["aria2"] = $options["aria2"] ? "1,1,1" : "0,0,0";
|
||||
try {
|
||||
Db::name("groups")->where("id",$groupId)->update($options);
|
||||
} catch (Exception $e) {
|
||||
@@ -336,8 +397,55 @@ class AdminHandler extends Model{
|
||||
return $userData;
|
||||
}
|
||||
|
||||
public function listDownloads(){
|
||||
$pageSize = 10;
|
||||
$this->pageData = Db::name("download")
|
||||
->order("id desc")
|
||||
->paginate($pageSize);
|
||||
$this->dataTotal = Db::name("download")
|
||||
->order("id desc")
|
||||
->count();
|
||||
$this->pageTotal = ceil($this->dataTotal/$pageSize);
|
||||
$this->listData = $this->pageData->all();
|
||||
$userCache=[];
|
||||
$userCacheList=[];
|
||||
foreach ($this->listData as $key => $value) {
|
||||
if(in_array($value["owner"], $userCacheList)){
|
||||
$this->listData[$key]["user"] = $userCache[$value["owner"]];
|
||||
}else{
|
||||
$this->listData[$key]["user"] = Db::name("users")->where("id",$value["owner"])->find();
|
||||
array_push($userCacheList,$value["owner"]);
|
||||
$userCache[$value["owner"]] = $this->listData[$key]["user"];
|
||||
}
|
||||
$connectInfo = json_decode($value["info"],true);
|
||||
if(isset($connectInfo["dir"])){
|
||||
$this->listData[$key]["fileName"] = basename($connectInfo["dir"]);
|
||||
$this->listData[$key]["completedLength"] = $connectInfo["completedLength"];
|
||||
$this->listData[$key]["totalLength"] = $connectInfo["totalLength"];
|
||||
$this->listData[$key]["downloadSpeed"] = $connectInfo["downloadSpeed"];
|
||||
}else{
|
||||
if(floor($value["source"])==$value["source"]){
|
||||
$this->listData[$key]["fileName"] = Db::name("files")->where("id",$value["source"])->column("orign_name");
|
||||
}else{
|
||||
$this->listData[$key]["fileName"] = $value["source"];
|
||||
}
|
||||
$this->listData[$key]["completedLength"] = 0;
|
||||
$this->listData[$key]["totalLength"] = 0;
|
||||
$this->listData[$key]["downloadSpeed"] = 0;
|
||||
}
|
||||
}
|
||||
$this->pageNow = input("?get.page")?input("get.page"):1;
|
||||
}
|
||||
|
||||
public function getTasks(){
|
||||
$taskData = Db::name("task")
|
||||
->order("id DESC")
|
||||
->paginate(10);
|
||||
return $taskData;
|
||||
}
|
||||
|
||||
public function listFile(){
|
||||
$pageSize = empty(cookie('pageSize')) ? 10 : cookie('pageSize');
|
||||
$pageSize = !cookie('?pageSize') ? 10 : cookie('pageSize');
|
||||
$orderType = empty(cookie('orderMethodFile')) ? "id DESC" : cookie('orderMethodFile');
|
||||
$this->pageData = Db::name("files")
|
||||
->where(function ($query) {
|
||||
@@ -392,7 +500,7 @@ class AdminHandler extends Model{
|
||||
}
|
||||
|
||||
public function listUser(){
|
||||
$pageSize = empty(cookie('pageSize')) ? 10 : cookie('pageSize');
|
||||
$pageSize = !cookie('?pageSize') ? 10 : cookie('pageSize');
|
||||
$orderType = empty(cookie('orderMethodUser')) ? "id DESC" : cookie('orderMethodUser');
|
||||
$this->pageData = Db::name("users")
|
||||
->where(function ($query) {
|
||||
@@ -461,8 +569,8 @@ class AdminHandler extends Model{
|
||||
}
|
||||
|
||||
public function listShare(){
|
||||
$pageSize = empty(cookie('pageSize')) ? 10 : cookie('pageSize');
|
||||
$orderType = empty(cookie('orderMethodShare')) ? "id DESC" : cookie('orderMethodShare');
|
||||
$pageSize = !cookie('?pageSize') ? 10 : cookie('pageSize');
|
||||
$orderType = empty(cookie('orderMethodShare')) ? "share_time DESC" : cookie('orderMethodShare');
|
||||
$this->pageData = Db::name("shares")
|
||||
->where(function ($query) {
|
||||
if(!empty(cookie('shareSearch'))){
|
||||
@@ -506,7 +614,7 @@ class AdminHandler extends Model{
|
||||
}
|
||||
|
||||
public function listPolicy(){
|
||||
$pageSize = empty(cookie('pageSize')) ? 10 : cookie('pageSize');
|
||||
$pageSize =!cookie('?pageSize') ? 10 : cookie('pageSize');
|
||||
$this->pageData = Db::name("policy")
|
||||
->where(function ($query) {
|
||||
if(!empty(cookie('policySearch'))){
|
||||
@@ -652,6 +760,52 @@ class AdminHandler extends Model{
|
||||
}
|
||||
return ["error"=>0,"msg"=>"设置已保存"];
|
||||
}
|
||||
|
||||
public function updateOnedriveToken($policyId){
|
||||
$policyData = Db::name("policy")->where("id",$policyId)->find();
|
||||
|
||||
if(empty($policyData)){
|
||||
throw new \think\Exception("Policy not found");
|
||||
}
|
||||
$onedrive = new Client([
|
||||
'client_id' => $policyData["bucketname"],
|
||||
]);
|
||||
$url = $onedrive->getLogInUrl([
|
||||
'offline_access',
|
||||
'files.readwrite.all',
|
||||
], Option::getValue("siteURL")."Admin/oneDriveCalllback");
|
||||
echo "<script>location.href='".$url."'</script>正在跳转至Onedrive账号授权页面,如果没有跳转,请<a href='$url'>点击这里</a>。";
|
||||
|
||||
Db::name("policy")->where("id",$policyId)->update([
|
||||
"sk" => json_encode($onedrive->getState()),
|
||||
]);
|
||||
\think\Session::set('onedrive.pid',$policyId);
|
||||
|
||||
}
|
||||
|
||||
public function oneDriveCalllback($code){
|
||||
if(input("?get.error")){
|
||||
throw new \think\Exception(input("get.error_description"));
|
||||
}
|
||||
$policyId = \think\Session::get('onedrive.pid');
|
||||
$policyData = Db::name("policy")->where("id",$policyId)->find();
|
||||
$onedrive = new Client([
|
||||
'client_id' => $policyData["bucketname"],
|
||||
|
||||
// Restore the previous state while instantiating this client to proceed in
|
||||
// obtaining an access token.
|
||||
'state' => json_decode($policyData["sk"]),
|
||||
]);
|
||||
|
||||
// Obtain the token using the code received by the OneDrive API.
|
||||
$onedrive->obtainAccessToken($policyData["ak"], $_GET['code']);
|
||||
|
||||
// Persist the OneDrive client' state for next API requests.
|
||||
Db::name("policy")->where("id",$policyId)->update([
|
||||
"sk" => json_encode($onedrive->getState()),
|
||||
]);
|
||||
echo "<script>location.href='/Admin/PolicyList?page=1'</script>";
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
@@ -0,0 +1,469 @@
|
||||
<?php
|
||||
namespace app\index\model;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
|
||||
class Aria2 extends Model{
|
||||
|
||||
private $authToken;
|
||||
private $apiUrl;
|
||||
private $savePath;
|
||||
private $saveOptions;
|
||||
public $reqStatus;
|
||||
public $reqMsg;
|
||||
public $pathId;
|
||||
public $pid;
|
||||
private $uid;
|
||||
private $policy;
|
||||
|
||||
public function __construct($options){
|
||||
$this->authToken = $options["aria2_token"];
|
||||
$this->apiUrl = rtrim($options["aria2_rpcurl"],"/")."/";
|
||||
$this->saveOptions = json_decode($options["aria2_options"],true);
|
||||
$this->savePath = rtrim(rtrim($options["aria2_tmppath"],"/"),"\\").DS;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新建普通URL下载任务
|
||||
*
|
||||
* @param string $url
|
||||
* @return void
|
||||
*/
|
||||
public function addUrl($url){
|
||||
$this->pathId = uniqid();
|
||||
$reqFileds = [
|
||||
"params" => ["token:".$this->authToken,
|
||||
[$url],["dir" => $this->savePath.$this->pathId],
|
||||
],
|
||||
"jsonrpc" => "2.0",
|
||||
"id" => $this->pathId,
|
||||
"method" => "aria2.addUri"
|
||||
];
|
||||
$reqFileds["params"][2] = array_merge($reqFileds["params"][2],$this->saveOptions);
|
||||
$reqFileds = json_encode($reqFileds,JSON_OBJECT_AS_ARRAY);
|
||||
$respondData = $this->sendReq($reqFileds);
|
||||
if(isset($respondData["result"])){
|
||||
$this->reqStatus = 1;
|
||||
$this->pid = $respondData["result"];
|
||||
}else{
|
||||
$this->reqStatus = 0;
|
||||
$this->reqMsg = isset($respondData["error"]["message"]) ? $respondData["error"]["message"] : $this->reqMsg;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 新建种子下载任务
|
||||
*
|
||||
* @param string $torrentUrl 种子URL
|
||||
* @return void
|
||||
*/
|
||||
public function addTorrent($torrentUrl){
|
||||
$this->pathId = uniqid();
|
||||
$reqFileds = [
|
||||
"params" => ["token:".$this->authToken,
|
||||
[$torrentUrl],["dir" => $this->savePath.$this->pathId],
|
||||
],
|
||||
"jsonrpc" => "2.0",
|
||||
"id" => $this->pathId,
|
||||
"method" => "aria2.addUri"
|
||||
];
|
||||
$reqFileds["params"][2] = array_merge($reqFileds["params"][2],$this->saveOptions);
|
||||
$reqFileds = json_encode($reqFileds,JSON_OBJECT_AS_ARRAY);
|
||||
$respondData = $this->sendReq($reqFileds);
|
||||
if(isset($respondData["result"])){
|
||||
$this->reqStatus = 1;
|
||||
$this->pid = $respondData["result"];
|
||||
}else{
|
||||
$this->reqStatus = 0;
|
||||
$this->reqMsg = isset($respondData["error"]["message"]) ? $respondData["error"]["message"] : $this->reqMsg;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新下载状态
|
||||
*
|
||||
* @param int $id 任务ID
|
||||
* @param int $uid 用户ID
|
||||
* @param array $policy 上传策略
|
||||
* @return void
|
||||
*/
|
||||
public function flushStatus($id,$uid,$policy){
|
||||
$this->uid = $uid;
|
||||
if(empty($policy)){
|
||||
$user = Db::name("users")->where("id",$uid)->find();
|
||||
$group = Db::name("groups")->where("id",$user["user_group"])->find();
|
||||
$policy = Db::name("policy")->where("id",$group["policy_name"])->find();
|
||||
}
|
||||
$this->policy = $policy;
|
||||
$downloadInfo = Db::name("download")->where("id",$id)->find();
|
||||
if(empty($downloadInfo)){
|
||||
$this->reqStatus = 0;
|
||||
$this->reqMsg = "未找到下载记录";
|
||||
return false;
|
||||
}
|
||||
if(in_array($downloadInfo["status"], ["error","complete"])){
|
||||
$this->reqStatus = 1;
|
||||
return true;
|
||||
}
|
||||
if($uid != $downloadInfo["owner"]){
|
||||
$this->reqStatus = 0;
|
||||
$this->reqMsg = "无权操作";
|
||||
return false;
|
||||
}
|
||||
$reqFileds = [
|
||||
"params" => ["token:".$this->authToken,$downloadInfo["pid"]],
|
||||
"jsonrpc" => "2.0",
|
||||
"id" => uniqid(),
|
||||
"method" => "aria2.tellStatus"
|
||||
];
|
||||
$reqFileds = json_encode($reqFileds,JSON_OBJECT_AS_ARRAY);
|
||||
$respondData = $this->sendReq($reqFileds);
|
||||
if(isset($respondData["result"])){
|
||||
if($this->storageCheck($respondData["result"],$downloadInfo)){
|
||||
if($downloadInfo["is_single"] && count($respondData["result"]["files"]) >1){
|
||||
$this->updateToMuiltpe($respondData["result"],$downloadInfo);
|
||||
return false;
|
||||
}
|
||||
if(isset($respondData["result"]["followedBy"])){
|
||||
Db::name("download")->where("id",$id)
|
||||
->update([
|
||||
"pid" => $respondData["result"]["followedBy"][0],
|
||||
]);
|
||||
return false;
|
||||
}
|
||||
Db::name("download")->where("id",$id)
|
||||
->update([
|
||||
"status" => $respondData["result"]["status"],
|
||||
"last_update" => date("Y-m-d h:i:s"),
|
||||
"info" => json_encode([
|
||||
"completedLength" => $respondData["result"]["files"][$downloadInfo["file_index"]]["completedLength"],
|
||||
"totalLength" => $respondData["result"]["files"][$downloadInfo["file_index"]]["length"],
|
||||
"dir" => $respondData["result"]["files"][$downloadInfo["file_index"]]["path"],
|
||||
"downloadSpeed" => $respondData["result"]["downloadSpeed"],
|
||||
"errorMessage" => isset($respondData["result"]["errorMessage"]) ? $respondData["result"]["errorMessage"] : "",
|
||||
]),
|
||||
"msg" => isset($respondData["result"]["errorMessage"]) ? $respondData["result"]["errorMessage"] : "",
|
||||
"total_size" => $respondData["result"]["files"][$downloadInfo["file_index"]]["length"],
|
||||
]);
|
||||
switch ($respondData["result"]["status"]) {
|
||||
case 'complete':
|
||||
$this->setComplete($respondData["result"],$downloadInfo);
|
||||
break;
|
||||
case 'removed':
|
||||
$this->setCanceled($respondData["result"],$downloadInfo);
|
||||
break;
|
||||
default:
|
||||
# code...
|
||||
break;
|
||||
}
|
||||
if(($respondData["result"]["files"][$downloadInfo["file_index"]]["completedLength"] == $respondData["result"]["files"][$downloadInfo["file_index"]]["length"] && ($respondData["result"]["files"][$downloadInfo["file_index"]]["length"] !=0 )) && $respondData["result"]["status"]=="active"){
|
||||
$this->setComplete($respondData["result"],$downloadInfo,$downloadInfo["file_index"]);
|
||||
Db::name("download")->where("id",$id)
|
||||
->update([
|
||||
"status" => "complete",
|
||||
]);
|
||||
}
|
||||
}else{
|
||||
$this->reqStatus = 0;
|
||||
$this->reqMsg = "空间容量不足";
|
||||
$this->setError($respondData["result"],$downloadInfo,"空间容量不足");
|
||||
return false;
|
||||
}
|
||||
}else{
|
||||
$this->reqStatus = 0;
|
||||
$this->reqMsg = $respondData["error"]["message"];
|
||||
$this->setError($respondData,$downloadInfo,$respondData["error"]["message"],"error",true);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消任务
|
||||
*
|
||||
* @param array $quenInfo 任务信息(aria2)
|
||||
* @param array $sqlData 任务信息(数据库)
|
||||
* @return void
|
||||
*/
|
||||
private function setCanceled($quenInfo,$sqlData){
|
||||
@self::remove_directory($this->savePath.$sqlData["path_id"]);
|
||||
if(!is_dir($this->savePath.$sqlData["path_id"])){
|
||||
Db::name("download")->where("id",$sqlData["id"])->update([
|
||||
"status" => "canceled",
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除整个目录
|
||||
*
|
||||
* @param string $dir
|
||||
* @return void
|
||||
*/
|
||||
static function remove_directory($dir){
|
||||
if($handle=opendir("$dir")){
|
||||
while(false!==($item=readdir($handle))){
|
||||
if($item!="."&&$item!=".."){
|
||||
if(is_dir("$dir/$item")){
|
||||
self::remove_directory("$dir/$item");
|
||||
}else{
|
||||
unlink("$dir/$item");
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir($handle);
|
||||
rmdir($dir);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将单文件任务升级至多文件任务
|
||||
*
|
||||
* @param array $quenInfo
|
||||
* @param array $sqlData
|
||||
* @return void
|
||||
*/
|
||||
private function updateToMuiltpe($quenInfo,$sqlData){
|
||||
foreach ($quenInfo["files"] as $key => $value) {
|
||||
Db::name("download")->insert([
|
||||
"pid" => $sqlData["pid"],
|
||||
"path_id" => $sqlData["path_id"],
|
||||
"owner" => $sqlData["owner"],
|
||||
"save_dir" => $sqlData["save_dir"],
|
||||
"status" => "ready",
|
||||
"msg" => "",
|
||||
"info"=>"",
|
||||
"source" =>$sqlData["source"],
|
||||
"file_index" => $key,
|
||||
"is_single" => 0,
|
||||
"total_size" => 0,
|
||||
]);
|
||||
}
|
||||
Db::name("download")->where("id",$sqlData["id"])->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载完成后续处理
|
||||
*
|
||||
* @param array $quenInfo
|
||||
* @param array $sqlData
|
||||
* @param int $fileIndex
|
||||
* @return void
|
||||
*/
|
||||
private function setComplete($quenInfo,$sqlData,$fileIndex=null){
|
||||
if($this->policy["policy_type"] != "local" && $this->policy["policy_type"] != "onedrive"){
|
||||
$this->setError($quenInfo,$sqlData,"您当前的上传策略无法使用离线下载");
|
||||
return false;
|
||||
}
|
||||
if($fileIndex==null){
|
||||
$this->forceRemove($sqlData["pid"]);
|
||||
}
|
||||
$suffixTmp = explode('.', $quenInfo["dir"]);
|
||||
$fileSuffix = array_pop($suffixTmp);
|
||||
$uploadHandller = new UploadHandler($this->policy["id"],$this->uid);
|
||||
$allowedSuffix = explode(',', $uploadHandller->getAllowedExt(json_decode($this->policy["filetype"],true)));
|
||||
$sufficCheck = !in_array($fileSuffix,$allowedSuffix);
|
||||
if(empty($uploadHandller->getAllowedExt(json_decode($this->policy["filetype"],true)))){
|
||||
$sufficCheck = false;
|
||||
}
|
||||
if($sufficCheck){
|
||||
//取消任务
|
||||
$this->setError($quenInfo,$sqlData,"文件类型不被允许");
|
||||
return false;
|
||||
}
|
||||
if($this->policy['autoname']){
|
||||
$fileName = $uploadHandller->getObjName($this->policy['namerule'],"local",basename($quenInfo["files"][$sqlData["file_index"]]["path"]));
|
||||
}else{
|
||||
$fileName = basename($quenInfo["files"][$sqlData["file_index"]]["path"]);
|
||||
}
|
||||
$generatePath = $uploadHandller->getDirName($this->policy['dirrule']);
|
||||
|
||||
if($this->policy["policy_type"] == "onedrive"){
|
||||
|
||||
$savePath = ROOT_PATH . 'public/uploads/'.$generatePath.DS.$fileName;
|
||||
$task = new Task();
|
||||
$task->taskName = "Upload RemoteDownload File " . $quenInfo["files"][$sqlData["file_index"]]["path"] . " to Onedrive";
|
||||
$task->taskType = $quenInfo["files"][$sqlData["file_index"]]["length"]<=4*1024*1024 ? "UploadRegularRemoteDownloadFileToOnedrive" :"UploadLargeRemoteDownloadFileToOnedrive";
|
||||
@list($width, $height, $type, $attr) = getimagesize($quenInfo["files"][$sqlData["file_index"]]["path"]);
|
||||
$picInfo = empty($width)?"":$width.",".$height;
|
||||
$task->taskContent = json_encode([
|
||||
"path" => ltrim(str_replace("/", ",", $sqlData["save_dir"]),","),
|
||||
"fname" => basename($quenInfo["files"][$sqlData["file_index"]]["path"]),
|
||||
"originPath" => $quenInfo["files"][$sqlData["file_index"]]["path"],
|
||||
"objname" => $fileName,
|
||||
"savePath" => $generatePath,
|
||||
"fsize" => (int)$quenInfo["files"][$sqlData["file_index"]]["length"],
|
||||
"picInfo" => $picInfo,
|
||||
"policyId" => $this->policy["id"],
|
||||
]);
|
||||
$task->userId = $this->uid;
|
||||
$task->saveTask();
|
||||
|
||||
}else{
|
||||
|
||||
$savePath = ROOT_PATH . 'public/uploads/'.$generatePath.DS.$fileName;
|
||||
is_dir(dirname($savePath))? :mkdir(dirname($savePath),0777,true);
|
||||
rename($quenInfo["files"][$sqlData["file_index"]]["path"],$savePath);
|
||||
@unlink(dirname($quenInfo["files"][$sqlData["file_index"]]["path"]));
|
||||
$jsonData = array(
|
||||
"path" => ltrim(str_replace("/", ",", $sqlData["save_dir"]),","),
|
||||
"fname" => basename($quenInfo["files"][$sqlData["file_index"]]["path"]),
|
||||
"objname" => $generatePath.DS.$fileName,
|
||||
"fsize" => $quenInfo["files"][$sqlData["file_index"]]["length"],
|
||||
);
|
||||
@list($width, $height, $type, $attr) = getimagesize($savePath);
|
||||
$picInfo = empty($width)?" ":$width.",".$height;
|
||||
$addAction = FileManage::addFile($jsonData,$this->policy,$this->uid,$picInfo);
|
||||
if(!$addAction[0]){
|
||||
//取消任务
|
||||
$this->setError($quenInfo,$sqlData,$addAction[1]);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
FileManage::storageCheckOut($this->uid,$quenInfo["files"][$sqlData["file_index"]]["length"]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置任务为失败状态
|
||||
*
|
||||
* @param array $quenInfo
|
||||
* @param array $sqlData
|
||||
* @param string $msg 失败消息
|
||||
* @param string $status 状态
|
||||
* @param boolean $delete 是否删除下载文件
|
||||
* @return void
|
||||
*/
|
||||
private function setError($quenInfo,$sqlData,$msg,$status="error",$delete=true){
|
||||
$this->Remove($sqlData["pid"],$sqlData);
|
||||
$this->removeDownloadResult($sqlData["pid"],$sqlData);
|
||||
if($delete){
|
||||
if(isset($quenInfo["files"][$sqlData["file_index"]]["path"]) && file_exists($quenInfo["files"][$sqlData["file_index"]]["path"])){
|
||||
$deleteAction = @unlink($quenInfo["files"][$sqlData["file_index"]]["path"]);
|
||||
@self::remove_directory(dirname($quenInfo["files"][$sqlData["file_index"]]["path"]));
|
||||
if(file_exists(dirname($quenInfo["files"][$sqlData["file_index"]]["path"]))){
|
||||
$task = new Task();
|
||||
$task->taskName = "Delete remote download temp file";
|
||||
$task->taskType = "deleteFolder";
|
||||
$task->taskContent = json_encode([
|
||||
"folder" => dirname($quenInfo["files"][$sqlData["file_index"]]["path"]),
|
||||
]);
|
||||
$task->userId = $this->uid;
|
||||
$task->saveTask();
|
||||
}
|
||||
}
|
||||
}
|
||||
Db::name("download")->where("id",$sqlData["id"])->update([
|
||||
"msg" => $msg,
|
||||
"status" => $status,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除任务
|
||||
*
|
||||
* @param int $gid
|
||||
* @param array $sqlData
|
||||
* @return void
|
||||
*/
|
||||
public function Remove($gid,$sqlData){
|
||||
$reqFileds = [
|
||||
"params" => ["token:".$this->authToken,$gid],
|
||||
"jsonrpc" => "2.0",
|
||||
"id" => uniqid(),
|
||||
"method" => "aria2.remove"
|
||||
];
|
||||
$reqFileds = json_encode($reqFileds,JSON_OBJECT_AS_ARRAY);
|
||||
$respondData = $this->sendReq($reqFileds);
|
||||
if(isset($respondData["result"])){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除下载结果
|
||||
*
|
||||
* @param int $gid
|
||||
* @param array $sqlData
|
||||
* @return void
|
||||
*/
|
||||
public function removeDownloadResult($gid,$sqlData){
|
||||
$reqFileds = [
|
||||
"params" => ["token:".$this->authToken,$gid],
|
||||
"jsonrpc" => "2.0",
|
||||
"id" => uniqid(),
|
||||
"method" => "aria2.removeDownloadResult"
|
||||
];
|
||||
$reqFileds = json_encode($reqFileds,JSON_OBJECT_AS_ARRAY);
|
||||
$respondData = $this->sendReq($reqFileds);
|
||||
if(isset($respondData["result"])){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 强制移除任务
|
||||
*
|
||||
* @param int $gid
|
||||
* @return void
|
||||
*/
|
||||
public function forceRemove($gid){
|
||||
$reqFileds = [
|
||||
"params" => ["token:".$this->authToken,$gid],
|
||||
"jsonrpc" => "2.0",
|
||||
"id" => uniqid(),
|
||||
"method" => "aria2.forceRemove"
|
||||
];
|
||||
$reqFileds = json_encode($reqFileds,JSON_OBJECT_AS_ARRAY);
|
||||
$respondData = $this->sendReq($reqFileds);
|
||||
if(isset($respondData["result"])){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查容量
|
||||
*
|
||||
* @param array $quenInfo
|
||||
* @param array $sqlData
|
||||
* @return void
|
||||
*/
|
||||
private function storageCheck($quenInfo,$sqlData){
|
||||
if(!FileManage::sotrageCheck($this->uid,$quenInfo["totalLength"])){
|
||||
return false;
|
||||
}
|
||||
if(!FileManage::sotrageCheck($this->uid,$quenInfo["completedLength"])){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送请求
|
||||
*
|
||||
* @param string $data
|
||||
* @return array
|
||||
*/
|
||||
private function sendReq($data){
|
||||
$curl = curl_init();
|
||||
curl_setopt($curl, CURLOPT_URL, $this->apiUrl."jsonrpc");
|
||||
curl_setopt($curl, CURLOPT_POST, 1);
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
|
||||
curl_setopt($curl, CURLOPT_TIMEOUT, 15);
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||||
$tmpInfo = curl_exec($curl);
|
||||
if (curl_errno($curl)) {
|
||||
$this->reqStatus = 0;
|
||||
$this->reqMsg = "请求失败,".curl_error($curl);
|
||||
}
|
||||
curl_close($curl);
|
||||
return json_decode($tmpInfo,true);
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
@@ -4,7 +4,7 @@ namespace app\index\model;
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
use \app\index\model\Option;
|
||||
use \app\index\model\FileManage;
|
||||
use \app\index\model\LocalAdapter;
|
||||
|
||||
class Avatar extends Model{
|
||||
|
||||
@@ -20,7 +20,7 @@ class Avatar extends Model{
|
||||
if(!$new){
|
||||
$userData = Db::name("users")->where('id',$obj)->find();
|
||||
$this->userData = $userData;
|
||||
if($userData["avatar"] == "default"){
|
||||
if(empty($userData)||$userData["avatar"] == "default"){
|
||||
$this->avatarType = "default";
|
||||
}else{
|
||||
$avatarPrarm = explode(".",$userData["avatar"]);
|
||||
@@ -90,7 +90,7 @@ class Avatar extends Model{
|
||||
$filePath = ROOT_PATH . 'public/avatars/' . $this->fileName.$siezSuffix;
|
||||
if(file_exists($filePath)){
|
||||
ob_end_clean();
|
||||
header('Content-Type: '.FileManage::getMimetype($filePath));
|
||||
header('Content-Type: '.LocalAdapter::getMimetype($filePath));
|
||||
$fileObj = fopen($filePath,"r");
|
||||
while(!feof($fileObj)){
|
||||
echo fread($fileObj,2097152);
|
||||
@@ -131,7 +131,7 @@ class Avatar extends Model{
|
||||
}
|
||||
ob_end_clean();
|
||||
$filePath = ROOT_PATH . 'static/img/default.png' .$siezSuffix;
|
||||
header('Content-Type: '.FileManage::getMimetype($filePath));
|
||||
header('Content-Type: '.LocalAdapter::getMimetype($filePath));
|
||||
$fileObj = fopen($filePath,"r");
|
||||
while(!feof($fileObj)){
|
||||
echo fread($fileObj,2097152);
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
namespace app\index\model;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
use \app\index\model\Option;
|
||||
|
||||
class B2 extends Model{
|
||||
|
||||
public $policy;
|
||||
private $ak;
|
||||
|
||||
public function __construct($policy){
|
||||
$this->policy = $policy;
|
||||
$akInfo = explode(":",$this->policy["ak"]);
|
||||
$this->ak = $akInfo[0];
|
||||
if(time()-$akInfo[1]>=86000){
|
||||
$this->updateAuth();
|
||||
}
|
||||
}
|
||||
|
||||
private function updateAuth(){
|
||||
$credentials = base64_encode($this->ak . ":" . $this->policy["sk"]);
|
||||
$url = "https://api.backblazeb2.com/b2api/v1/b2_authorize_account";
|
||||
$session = curl_init($url);
|
||||
$headers = array();
|
||||
$headers[] = "Accept: application/json";
|
||||
$headers[] = "Authorization: Basic " . $credentials;
|
||||
curl_setopt($session, CURLOPT_HTTPHEADER, $headers);
|
||||
curl_setopt($session, CURLOPT_HTTPGET, true);
|
||||
curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($session, CURLOPT_SSL_VERIFYPEER, false); //不验证证书
|
||||
curl_setopt($session, CURLOPT_SSL_VERIFYHOST, false); //不验证证书
|
||||
$server_output = curl_exec($session);
|
||||
curl_close ($session);
|
||||
$authInfo = json_decode($server_output,true);
|
||||
Db::name("policy")->where("id",$this->policy["id"])
|
||||
->update([
|
||||
"ak" => $this->ak . ":" . time(),
|
||||
"op_name" => $authInfo["apiUrl"],
|
||||
"url" => $authInfo["downloadUrl"],
|
||||
"op_pwd" => $authInfo["authorizationToken"],
|
||||
]);
|
||||
$this->policy = Db::name("policy")->where("id",$this->policy["id"])->find();
|
||||
$this->updateUploadAuth();
|
||||
}
|
||||
|
||||
private function updateUploadAuth(){
|
||||
$session = curl_init($this->policy["op_name"] . "/b2api/v1/b2_get_upload_url");
|
||||
$data = array("bucketId" => $this->policy["bucketname"]);
|
||||
$post_fields = json_encode($data);
|
||||
curl_setopt($session, CURLOPT_POSTFIELDS, $post_fields);
|
||||
$headers = array();
|
||||
$headers[] = "Authorization: " . $this->policy["op_pwd"];
|
||||
curl_setopt($session, CURLOPT_HTTPHEADER, $headers);
|
||||
curl_setopt($session, CURLOPT_SSL_VERIFYPEER, false); //不验证证书
|
||||
curl_setopt($session, CURLOPT_SSL_VERIFYHOST, false); //不验证证书
|
||||
curl_setopt($session, CURLOPT_POST, true);
|
||||
curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
|
||||
$server_output = curl_exec($session);
|
||||
curl_close ($session);
|
||||
$authInfo = json_decode($server_output,true);
|
||||
Db::name("policy")->where("id",$this->policy["id"])
|
||||
->update([
|
||||
"server" => $authInfo["uploadUrl"] . "|" . $authInfo["authorizationToken"],
|
||||
]);
|
||||
$this->policy = Db::name("policy")->where("id",$this->policy["id"])->find();
|
||||
die("");
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
@@ -20,6 +20,28 @@ class CallbackHandler extends Model{
|
||||
$this->CallbackData = $data;
|
||||
}
|
||||
|
||||
public function remoteHandler($header){
|
||||
$jsonData = json_decode(base64_decode($this->CallbackData),true);
|
||||
$CallbackSqlData = Db::name('callback')->where('callback_key',$jsonData['callbackkey'])->find();
|
||||
$this->policyData = Db::name('policy')->where('id',$CallbackSqlData['pid'])->find();
|
||||
if(!$this->IsRemoteCallback($header)){
|
||||
$this->setError("Undelegated Request");
|
||||
}
|
||||
if($this->policyData == null){
|
||||
$this->setError("CallbackKey Not Exist.");
|
||||
}
|
||||
if(!FileManage::sotrageCheck($CallbackSqlData["uid"],$jsonData["fsize"])){
|
||||
$this->setError("空间容量不足",true);
|
||||
}
|
||||
$picInfo = $jsonData["picinfo"];
|
||||
$addAction = FileManage::addFile($jsonData,$this->policyData,$CallbackSqlData["uid"],$picInfo);
|
||||
if(!$addAction[0]){
|
||||
$this->setError($addAction[1],true);
|
||||
}
|
||||
FileManage::storageCheckOut($CallbackSqlData["uid"],$jsonData["fsize"]);
|
||||
$this->setSuccess($jsonData['fname']);
|
||||
}
|
||||
|
||||
public function qiniuHandler($header){
|
||||
$jsonData = json_decode($this->CallbackData,true);
|
||||
$CallbackSqlData = Db::name('callback')->where('callback_key',$jsonData['callbackkey'])->find();
|
||||
@@ -35,6 +57,7 @@ class CallbackHandler extends Model{
|
||||
$this->setError("空间容量不足",true);
|
||||
}
|
||||
$picInfo = $jsonData["picinfo"];
|
||||
$picInfo = $picInfo==="null,null"?"":$picInfo;
|
||||
$addAction = FileManage::addFile($jsonData,$this->policyData,$CallbackSqlData["uid"],$picInfo);
|
||||
if(!$addAction[0]){
|
||||
$this->setError($addAction[1],true);
|
||||
@@ -98,6 +121,7 @@ class CallbackHandler extends Model{
|
||||
if(empty($CallbackSqlData)){
|
||||
$this->setError("Undelegated Request",false,true);
|
||||
}
|
||||
Db::name('callback')->where('callback_key',$key)->delete();
|
||||
$this->policyData = Db::name('policy')->where('id',$CallbackSqlData['pid'])->find();
|
||||
$this->userData = Db::name('users')->where('id',$CallbackSqlData['uid'])->find();
|
||||
$paths = explode("/",$this->CallbackData["key"]);
|
||||
@@ -113,7 +137,7 @@ class CallbackHandler extends Model{
|
||||
if(!$jsonData["fsize"]){
|
||||
$this->setError("File not exist",false,true);
|
||||
}
|
||||
$jsonData["fsize"] = $jsonData["fsize"]["size"];
|
||||
$jsonData["fsize"] = $jsonData["fsize"];
|
||||
$picInfo = "";
|
||||
$addAction = FileManage::addFile($jsonData,$this->policyData,$this->userData["id"],"");
|
||||
if(!$addAction[0]){
|
||||
@@ -125,14 +149,25 @@ class CallbackHandler extends Model{
|
||||
}
|
||||
|
||||
private function getS3FileInfo(){
|
||||
$s3 = new \S3\S3($this->policyData["ak"], $this->policyData["sk"],false,$this->policyData["op_pwd"]);
|
||||
$s3->setSignatureVersion('v4');
|
||||
$s3 = new \Aws\S3\S3Client([
|
||||
'version' => 'latest',
|
||||
'region' => $this->policyData["op_name"],
|
||||
'endpoint' => $this->policyData["op_pwd"],
|
||||
'use_path_style_endpoint' => true,
|
||||
'credentials' => [
|
||||
'key' => $this->policyData["ak"],
|
||||
'secret' => $this->policyData["sk"],
|
||||
],
|
||||
]);
|
||||
try {
|
||||
$returnVal = $s3->getObjectInfo($this->policyData["bucketname"],$this->CallbackData["key"]);
|
||||
$returnVal = $s3->headObject([
|
||||
'Bucket'=>$this->policyData["bucketname"],
|
||||
'Key'=>$this->CallbackData["key"]
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
return $returnVal;
|
||||
return $returnVal["ContentLength"];
|
||||
}
|
||||
|
||||
public function setSuccess($fname){
|
||||
@@ -172,6 +207,11 @@ class CallbackHandler extends Model{
|
||||
}
|
||||
}
|
||||
|
||||
private function IsRemoteCallback($header){
|
||||
$signKey = hash_hmac("sha256",$this->CallbackData,$this->policyData["sk"]);
|
||||
return ($signKey == $header);
|
||||
}
|
||||
|
||||
public function IsOssCallback($auth,$pubKey){
|
||||
if (empty($auth) || empty($pubKey)){
|
||||
header("http/1.1 403 Forbidden");
|
||||
|
||||
@@ -7,6 +7,8 @@ use \think\Session;
|
||||
use \app\index\model\FileManage;
|
||||
use \app\index\model\Option;
|
||||
use \app\index\model\Mail;
|
||||
use \app\index\model\Aria2;
|
||||
use think\Exception;
|
||||
|
||||
class CronHandler extends Model{
|
||||
|
||||
@@ -40,6 +42,21 @@ class CronHandler extends Model{
|
||||
$this->deleteCallbackData($value["interval_s"]);
|
||||
}
|
||||
break;
|
||||
case 'flush_aria2':
|
||||
if($this->checkInterval($value["interval_s"],$value["last_excute"])){
|
||||
$this->flushAria2($value["interval_s"]);
|
||||
}
|
||||
break;
|
||||
case 'flush_onedrive_token':
|
||||
if($this->checkInterval($value["interval_s"],$value["last_excute"])){
|
||||
$this->flushOnedriveToken($value["interval_s"]);
|
||||
}
|
||||
break;
|
||||
case 'delete_remote_downloader_failed_folder':
|
||||
if($this->checkInterval($value["interval_s"],$value["last_excute"])){
|
||||
$this->deleteRemoteDownloaderFailedFolder($value["interval_s"]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
# code...
|
||||
break;
|
||||
@@ -69,5 +86,92 @@ class CronHandler extends Model{
|
||||
$this->setComplete("delete_callback_data");
|
||||
}
|
||||
|
||||
public function flushAria2($interval){
|
||||
echo("flushingAria2Status...");
|
||||
$aria2Options = Option::getValues(["aria2"]);
|
||||
$aria2 = new Aria2($aria2Options);
|
||||
$toBeFlushed = Db::name("download")
|
||||
->where("status","<>","complete")
|
||||
->where("status","<>","error")
|
||||
->where("status","<>","canceled")
|
||||
->select();
|
||||
foreach ($toBeFlushed as $key => $value) {
|
||||
$aria2->flushStatus($value["id"],$value["owner"],null);
|
||||
}
|
||||
echo("Complete<br>");
|
||||
$this->setComplete("flush_aria2");
|
||||
}
|
||||
|
||||
public function deleteRemoteDownloaderFailedFolder($interval){
|
||||
echo("flushOnedriveToken...");
|
||||
$toBeDeleted = Db::name("task")
|
||||
->where("type","deleteFolder")
|
||||
->where("status","todo")
|
||||
->select();
|
||||
$success=[];
|
||||
$todo = [];
|
||||
foreach ($toBeDeleted as $key => $value) {
|
||||
$attr = json_decode($value["attr"],true);
|
||||
if(file_exists($attr["folder"])){
|
||||
self::remove_directory($attr["folder"]);
|
||||
}
|
||||
if(file_exists($attr["folder"])){
|
||||
$todo[] = $value["id"];
|
||||
}else{
|
||||
$success[] = $value["id"];
|
||||
}
|
||||
}
|
||||
|
||||
Db::name("task")->where("id","in",$success)->update(["status"=>"success"]);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除整个目录
|
||||
*
|
||||
* @param string $dir
|
||||
* @return void
|
||||
*/
|
||||
static function remove_directory($dir){
|
||||
if($handle=opendir("$dir")){
|
||||
while(false!==($item=readdir($handle))){
|
||||
if($item!="."&&$item!=".."){
|
||||
if(is_dir("$dir/$item")){
|
||||
self::remove_directory("$dir/$item");
|
||||
}else{
|
||||
unlink("$dir/$item");
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir($handle);
|
||||
rmdir($dir);
|
||||
}
|
||||
}
|
||||
|
||||
public function flushOnedriveToken($interval){
|
||||
echo("flushOnedriveToken...");
|
||||
$toBeFlushedPolicy = Db::name("policy")->where("policy_type","onedrive")->select();
|
||||
foreach ($toBeFlushedPolicy as $key => $value) {
|
||||
$onedrive = new \Krizalys\Onedrive\Client([
|
||||
'stream_back_end' => \Krizalys\Onedrive\StreamBackEnd::TEMP,
|
||||
'client_id' => $value["bucketname"],
|
||||
|
||||
// Restore the previous state while instantiating this client to proceed in
|
||||
// obtaining an access token.
|
||||
'state' => json_decode($value["sk"]),
|
||||
]);
|
||||
try{
|
||||
$onedrive->renewAccessToken($value["ak"]);
|
||||
}catch(\Exception $e){
|
||||
|
||||
}
|
||||
Db::name("policy")->where("id",$value["id"])->update([
|
||||
"sk" => json_encode($onedrive->getState()),
|
||||
]);
|
||||
}
|
||||
echo("Complete<br>");
|
||||
$this->setComplete("flush_onedrive_token");
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
@@ -30,6 +30,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota{
|
||||
}
|
||||
|
||||
function createFile($name, $data = NULL){
|
||||
$name = str_replace(" ","",$name);
|
||||
$userData = Db::name("users")->where("id",$this->uid)->find();
|
||||
$groupData = Db::name("groups")->where("id",$userData["user_group"])->find();
|
||||
$policyData = Db::name("policy")->where("id",$groupData["policy_name"])->find();
|
||||
@@ -47,7 +48,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota{
|
||||
}
|
||||
$fileSize = fstat($data)["size"];
|
||||
if(empty($fileSize)){
|
||||
$fileSize = 0;
|
||||
$fileSize = -1;
|
||||
}
|
||||
if($fileSize>$policyData["max_size"]){
|
||||
throw new DAV\Exception\InsufficientStorage('File is to large');
|
||||
@@ -66,6 +67,9 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota{
|
||||
mkdir($savePath,0777,true);
|
||||
}
|
||||
file_put_contents($savePath."/".$fileName, $data);
|
||||
if($fileSize<=0){
|
||||
$fileSize = filesize($savePath."/".$fileName);
|
||||
}
|
||||
$jsonData = array(
|
||||
"path" => str_replace("/",",",ltrim($this->myPath,"/")),
|
||||
"fname" => $name,
|
||||
@@ -120,7 +124,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota{
|
||||
|
||||
function getChildFile($name){
|
||||
$path = $this->uid.rtrim($this->myPath,"/") . '/' . $name["orign_name"];
|
||||
return new Object($path);
|
||||
return new Objects($path);
|
||||
}
|
||||
|
||||
function getChildDir($name){
|
||||
@@ -134,6 +138,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota{
|
||||
}
|
||||
|
||||
function getChild($name) {
|
||||
$name = str_replace(" ","",$name);
|
||||
if(!$this->childExists($name)){
|
||||
throw new DAV\Exception\NotFound('File with name ' . $name . ' could not be located');
|
||||
}
|
||||
@@ -142,12 +147,13 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota{
|
||||
$returnObj = new Directory($path);
|
||||
return $returnObj;
|
||||
}else{
|
||||
return new Object($path);
|
||||
return new Objects($path);
|
||||
}
|
||||
}
|
||||
|
||||
function childExists($name) {
|
||||
$fileObj = new Object($this->uid.rtrim($this->myPath,"/") . '/' . $name);
|
||||
$name = str_replace(" ","",$name);
|
||||
$fileObj = new Objects($this->uid.rtrim($this->myPath,"/") . '/' . $name);
|
||||
if($this->findDir(rtrim($this->myPath,"/") . '/' . $name) || $fileObj->isExist){
|
||||
return true;
|
||||
}
|
||||
@@ -162,7 +168,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota{
|
||||
$dirName = end($explode);
|
||||
$rootPath = rtrim($path,"/".$dirName);
|
||||
$rootPath = empty($rootPath) ? "/" : $rootPath;
|
||||
$dirData = Db::name('folders')->where('owner',$this->uid)->where('position',dirname($path) == "\\" ?"/":dirname($path))->where("folder_name",basename($path))->find();
|
||||
$dirData = Db::name('folders')->where('owner',$this->uid)->where('position',dirname($path) == "\\" ?"/":dirname($path))->where("folder_name",getDirName($path))->find();
|
||||
if(empty($dirData)){
|
||||
return false;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,392 @@
|
||||
<?php
|
||||
namespace app\index\model;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
|
||||
use \app\index\model\Option;
|
||||
|
||||
/**
|
||||
* 本地策略文件管理适配器
|
||||
*/
|
||||
class LocalAdapter extends Model{
|
||||
|
||||
private $fileModel;
|
||||
private $policyModel;
|
||||
private $userModel;
|
||||
|
||||
public function __construct($file,$policy,$user){
|
||||
$this->fileModel = $file;
|
||||
$this->policyModel = $policy;
|
||||
$this->userModel = $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文本文件内容
|
||||
*
|
||||
* @return string 内容
|
||||
*/
|
||||
public function getFileContent(){
|
||||
$filePath = ROOT_PATH . 'public/uploads/' . $this->fileModel["pre_name"];
|
||||
$fileObj = fopen($filePath,"r");
|
||||
$fileContent = fread($fileObj,filesize($filePath)+1);
|
||||
return $fileContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存可编辑文件
|
||||
*
|
||||
* @param string $content 要保存的文件内容
|
||||
* @return void
|
||||
*/
|
||||
public function saveContent($content){
|
||||
$filePath = ROOT_PATH . 'public/uploads/' . $this->fileModel["pre_name"];
|
||||
file_put_contents($filePath, "");
|
||||
file_put_contents($filePath, $content);
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出预览文件
|
||||
*
|
||||
* @param boolean $isAdmin 是否为管理员请求
|
||||
* @return mixed 文件数据
|
||||
*/
|
||||
public function Preview($isAdmin = false){
|
||||
$speedLimit = Db::name('groups')->where('id',$this->userModel["user_group"])->find();
|
||||
$rangeTransfer = $speedLimit["range_transfer"];
|
||||
$speedLimit = $speedLimit["speed"];
|
||||
$sendFileOptions = Option::getValues(["download"]);
|
||||
if($sendFileOptions["sendfile"] == "1" && !empty($sendFileOptions)){
|
||||
$this->sendFile($speedLimit,$rangeTransfer,false,$sendFileOptions["header"]);
|
||||
}else{
|
||||
if($isAdmin){
|
||||
$speedLimit="";
|
||||
}
|
||||
if($speedLimit == "0"){
|
||||
exit();
|
||||
}else if(empty($speedLimit)){
|
||||
header("Cache-Control: max-age=10800");
|
||||
$this->outputWithoutLimit(false,$rangeTransfer);
|
||||
exit();
|
||||
}else if((int)$speedLimit > 0){
|
||||
header("Cache-Control: max-age=10800");
|
||||
$this->outputWithLimit($speedLimit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用Sendfile模式发送文件数据
|
||||
*
|
||||
* @param int $speed 下载限速
|
||||
* @param boolean $range 是否支持断点续传
|
||||
* @param boolean $download 是否为下载请求
|
||||
* @param string $header Sendfile Header
|
||||
* @return void
|
||||
*/
|
||||
private function sendFile($speed,$range,$download=false,$header="X-Sendfile"){
|
||||
$filePath = ROOT_PATH . 'public/uploads/' . $this->fileModel["pre_name"];
|
||||
$realPath = ROOT_PATH . 'public/uploads/' . $this->fileModel["pre_name"];
|
||||
if($header == "X-Accel-Redirect"){
|
||||
$filePath = '/public/uploads/' . $this->fileModel["pre_name"];
|
||||
}
|
||||
if($download){
|
||||
$filePath = str_replace("\\","/",$filePath);
|
||||
if($header == "X-Accel-Redirect"){
|
||||
ob_flush();
|
||||
flush();
|
||||
echo "s";
|
||||
}
|
||||
//保证如下顺序,否则最终浏览器中得到的content-type为'text/html'
|
||||
//1,写入 X-Sendfile 头信息
|
||||
$pathToFile = str_replace('%2F', '/', rawurlencode($filePath));
|
||||
header($header.": ".$pathToFile);
|
||||
//2,写入Content-Type头信息
|
||||
$mime_type = self::getMimetypeOnly($realPath);
|
||||
header('Content-Type: '.$mime_type);
|
||||
//3,写入正确的附件文件名头信息
|
||||
$orign_fname = $this->fileModel["orign_name"];
|
||||
$ua = $_SERVER["HTTP_USER_AGENT"]; // 处理不同浏览器的兼容性
|
||||
if (preg_match("/Firefox/", $ua)) {
|
||||
$encoded_filename = rawurlencode($orign_fname);
|
||||
header("Content-Disposition: attachment; filename*=\"utf8''" . $encoded_filename . '"');
|
||||
} else if (preg_match("/MSIE/", $ua) || preg_match("/Edge/", $ua) || preg_match("/rv:/", $ua)) {
|
||||
$encoded_filename = rawurlencode($orign_fname);
|
||||
header('Content-Disposition: attachment; filename="' . $encoded_filename . '"');
|
||||
} else {
|
||||
// for Chrome,Safari etc.
|
||||
header('Content-Disposition: attachment;filename="'. $orign_fname .'";filename*=utf-8'."''". $orign_fname);
|
||||
}
|
||||
exit;
|
||||
}else{
|
||||
$filePath = str_replace("\\","/",$filePath);
|
||||
header('Content-Type: '.self::getMimetype($realPath));
|
||||
if($header == "X-Accel-Redirect"){
|
||||
ob_flush();
|
||||
flush();
|
||||
echo "s";
|
||||
}
|
||||
header($header.": ".str_replace('%2F', '/', rawurlencode($filePath)));
|
||||
ob_flush();
|
||||
flush();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 无限速发送文件数据
|
||||
*
|
||||
* @param boolean $download 是否为下载
|
||||
* @param boolean $reload 是否支持断点续传
|
||||
* @return void
|
||||
*/
|
||||
public function outputWithoutLimit($download = false,$reload = false){
|
||||
ignore_user_abort(false);
|
||||
$filePath = ROOT_PATH . 'public/uploads/' . $this->fileModel["pre_name"];
|
||||
set_time_limit(0);
|
||||
session_write_close();
|
||||
$file_size = filesize($filePath);
|
||||
$ranges = $this->getRange($file_size);
|
||||
if($reload == 1 && $ranges!=null){
|
||||
header('HTTP/1.1 206 Partial Content');
|
||||
header('Accept-Ranges:bytes');
|
||||
header(sprintf('content-length:%u',$ranges['end']-$ranges['start']));
|
||||
header(sprintf('content-range:bytes %s-%s/%s', $ranges['start'], $ranges['end']-1, $file_size));
|
||||
}
|
||||
if($download){
|
||||
header('Cache-control: private');
|
||||
header('Content-Type: application/octet-stream');
|
||||
header('Content-Length: '.filesize($filePath));
|
||||
$encoded_fname = rawurlencode($this->fileModel["orign_name"]);
|
||||
header('Content-Disposition: attachment;filename="'.$encoded_fname.'";filename*=utf-8'."''".$encoded_fname);
|
||||
ob_flush();
|
||||
flush();
|
||||
}
|
||||
if(file_exists($filePath)){
|
||||
if(!$download){
|
||||
header('Content-Type: '.self::getMimetype($filePath));
|
||||
ob_flush();
|
||||
flush();
|
||||
}
|
||||
$fileObj = fopen($filePath,"rb");
|
||||
if($reload == 1){
|
||||
fseek($fileObj, sprintf('%u', $ranges['start']));
|
||||
}
|
||||
while(!feof($fileObj)){
|
||||
echo fread($fileObj,10240);
|
||||
ob_flush();
|
||||
flush();
|
||||
}
|
||||
fclose($fileObj);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 有限速发送文件数据
|
||||
*
|
||||
* @param int $speed 最大速度
|
||||
* @param boolean $download 是否为下载请求
|
||||
* @return void
|
||||
*/
|
||||
public function outputWithLimit($speed,$download = false){
|
||||
ignore_user_abort(false);
|
||||
$filePath = ROOT_PATH . 'public/uploads/' . $this->fileModel["pre_name"];
|
||||
set_time_limit(0);
|
||||
session_write_close();
|
||||
if($download){
|
||||
header('Cache-control: private');
|
||||
header('Content-Type: application/octet-stream');
|
||||
header('Content-Length: '.filesize($filePath));
|
||||
$encoded_fname = rawurlencode($this->fileModel["orign_name"]);
|
||||
header('Content-Disposition: attachment;filename="'.$encoded_fname.'";filename*=utf-8'."''".$encoded_fname);
|
||||
ob_flush();
|
||||
flush();
|
||||
}else{
|
||||
header('Content-Type: '.self::getMimetype($filePath));
|
||||
ob_flush();
|
||||
flush();
|
||||
}
|
||||
if(file_exists($filePath)){
|
||||
$fileObj = fopen($filePath,"r");
|
||||
while (!feof($fileObj)){
|
||||
echo fread($fileObj,round($speed*1024));
|
||||
ob_flush();
|
||||
flush();
|
||||
sleep(1);
|
||||
}
|
||||
fclose($fileObj);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件MIME Type
|
||||
*
|
||||
* @param string $path 文件路径
|
||||
* @return void
|
||||
*/
|
||||
static function getMimetype($path){
|
||||
//FILEINFO_MIME will output something like "image/jpeg; charset=binary"
|
||||
$finfoObj = finfo_open(FILEINFO_MIME);
|
||||
$mimetype = finfo_file($finfoObj, $path);
|
||||
finfo_close($finfoObj);
|
||||
return $mimetype;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文件MIME Type
|
||||
*
|
||||
* @param string $path 文件路径
|
||||
* @return void
|
||||
*/
|
||||
static function getMimetypeOnly($path){
|
||||
//FILEINFO_MIME_TYPE will output something like "image/jpeg"
|
||||
$finfoObj = finfo_open(FILEINFO_MIME_TYPE);
|
||||
$mimetype = finfo_file($finfoObj, $path);
|
||||
finfo_close($finfoObj);
|
||||
return $mimetype;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取断点续传时HTTP_RANGE头
|
||||
*
|
||||
* @param int $file_size 文件大小
|
||||
* @return void
|
||||
*/
|
||||
private function getRange($file_size){
|
||||
if(isset($_SERVER['HTTP_RANGE']) && !empty($_SERVER['HTTP_RANGE'])){
|
||||
$range = $_SERVER['HTTP_RANGE'];
|
||||
$range = preg_replace('/[\s|,].*/', '', $range);
|
||||
$range = explode('-', substr($range, 6));
|
||||
if(count($range)<2){
|
||||
$range[1] = $file_size;
|
||||
}
|
||||
$range = array_combine(array('start','end'), $range);
|
||||
if(empty($range['start'])){
|
||||
$range['start'] = 0;
|
||||
}
|
||||
if(empty($range['end'])){
|
||||
$range['end'] = $file_size;
|
||||
}
|
||||
return $range;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成/返回 文件缩略图
|
||||
*
|
||||
* @return array 重定向信息
|
||||
*/
|
||||
public function getThumb(){
|
||||
$picInfo = explode(",",$this->fileModel["pic_info"]);
|
||||
$picInfo = self::getThumbSize($picInfo[0],$picInfo[1]);
|
||||
if(file_exists(ROOT_PATH . "public/thumb/".$this->fileModel["pre_name"]."_thumb")){
|
||||
self::outputThumb(ROOT_PATH . "public/thumb/".$this->fileModel["pre_name"]."_thumb");
|
||||
return [0,0];
|
||||
}
|
||||
$thumbImg = new Thumb(ROOT_PATH . "public/uploads/".$this->fileModel["pre_name"]);
|
||||
$thumbImg->thumb($picInfo[1], $picInfo[0]);
|
||||
if(!is_dir(dirname(ROOT_PATH . "public/thumb/".$this->fileModel["pre_name"]))){
|
||||
mkdir(dirname(ROOT_PATH . "public/thumb/".$this->fileModel["pre_name"]),0777,true);
|
||||
}
|
||||
$thumbImg->out(ROOT_PATH . "public/thumb/".$this->fileModel["pre_name"]."_thumb");
|
||||
self::outputThumb(ROOT_PATH . "public/thumb/".$this->fileModel["pre_name"]."_thumb");
|
||||
return [0,0];
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算缩略图大小
|
||||
*
|
||||
* @param int $width 原始宽
|
||||
* @param int $height 原始高
|
||||
* @return array
|
||||
*/
|
||||
static function getThumbSize($width,$height){
|
||||
// $rate = $width/$height;
|
||||
// $maxWidth = 280;
|
||||
// $maxHeight = 150;
|
||||
// $changeWidth = 150*$rate;
|
||||
// $changeHeight = 280/$rate;
|
||||
// if($changeWidth>=$maxWidth){
|
||||
// return [(int)$changeHeight,280];
|
||||
// }
|
||||
return [230,200];
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出缩略图
|
||||
*
|
||||
* @param string $path 缩略图文件路径
|
||||
* @return void
|
||||
*/
|
||||
static function outputThumb($path){
|
||||
ob_end_clean();
|
||||
if(!input("get.cache")=="no"){
|
||||
header("Cache-Control: max-age=10800");
|
||||
}
|
||||
header('Content-Type: '.self::getMimetype($path));
|
||||
$fileObj = fopen($path,"r");
|
||||
echo fread($fileObj,filesize($path));
|
||||
fclose($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理下载请求
|
||||
*
|
||||
* @param boolean $isAdmin 是否为管理员请求
|
||||
* @return void
|
||||
*/
|
||||
public function Download($isAdmin=false){
|
||||
$speedLimit = Db::name('groups')->where('id',$this->userModel["user_group"])->find();
|
||||
$rangeTransfer = $speedLimit["range_transfer"];
|
||||
$speedLimit = $speedLimit["speed"];
|
||||
$sendFileOptions = Option::getValues(["download"]);
|
||||
if($sendFileOptions["sendfile"] == "1"){
|
||||
$this->sendFile($speedLimit,$rangeTransfer,true,$sendFileOptions["header"]);
|
||||
}else{
|
||||
if($isAdmin){
|
||||
$speedLimit = "";
|
||||
}
|
||||
if($speedLimit == "0"){
|
||||
exit();
|
||||
}else if(empty($speedLimit)){
|
||||
$this->outputWithoutLimit(true,$rangeTransfer);
|
||||
exit();
|
||||
}else if((int)$speedLimit > 0){
|
||||
$this->outputWithLimit($speedLimit,true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除指定本地文件
|
||||
*
|
||||
* @param array $fileList 待删除文件的数据库记录
|
||||
* @param array $policyData 待删除文件的上传策略信息
|
||||
* @return void
|
||||
*/
|
||||
static function DeleteFile($fileList,$policyData){
|
||||
$fileListTemp = array_column($fileList, 'pre_name');
|
||||
foreach ($fileListTemp as $key => $value) {
|
||||
@unlink(ROOT_PATH . 'public/uploads/'.$value);
|
||||
if(file_exists(ROOT_PATH . 'public/thumb/'.$value."_thumb")){
|
||||
@unlink(ROOT_PATH . 'public/thumb/'.$value."_thumb");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 签名临时直链,用于Office365预览
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function signTmpUrl(){
|
||||
$options = Option::getValues(["oss","basic"]);
|
||||
$timeOut = $options["timeout"];
|
||||
$delayTime = time()+$timeOut;
|
||||
$key=$this->fileModel["id"].":".$delayTime.":".md5($this->userModel["user_pass"].$this->fileModel["id"].$delayTime.config("salt"));
|
||||
return [1,$options['siteURL']."Callback/TmpPreview/key/".$key];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -45,13 +45,16 @@ class Mail extends Model{
|
||||
$mail->Username =$this->smtpUser;
|
||||
$mail->Password = $this->smtpPass;
|
||||
$mail->From = $this->fromAdress;
|
||||
$mail->SMTPDebug = 1;
|
||||
$mail->Debugoutput = function($str, $level) {
|
||||
$this->errorMsg .= $str;
|
||||
};
|
||||
$mail->isHTML(true);
|
||||
$mail->addAddress($to,$name);
|
||||
$mail->Subject = $title;
|
||||
$mail->Body = $content;
|
||||
$status = $mail->send();
|
||||
if(!$status){
|
||||
$this->errorMsg = $mail->ErrorInfo;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -6,7 +6,7 @@ use think\Db;
|
||||
use Sabre\DAV;
|
||||
use \app\index\model\FileManage;
|
||||
|
||||
class Object extends DAV\File{
|
||||
class Objects extends DAV\File{
|
||||
|
||||
private $myPath;
|
||||
public $id;
|
||||
@@ -0,0 +1,140 @@
|
||||
<?php
|
||||
namespace app\index\model;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
|
||||
use \Krizalys\Onedrive\Client;
|
||||
|
||||
use \app\index\model\Option;
|
||||
|
||||
/**
|
||||
* Onedrive策略文件管理适配器
|
||||
*/
|
||||
class OnedriveAdapter extends Model{
|
||||
|
||||
private $fileModel;
|
||||
private $policyModel;
|
||||
private $userModel;
|
||||
private $clinet;
|
||||
|
||||
public function __construct($file,$policy,$user){
|
||||
$this->fileModel = $file;
|
||||
$this->policyModel = $policy;
|
||||
$this->userModel = $user;
|
||||
$this->clinet = new Client([
|
||||
'stream_back_end' => \Krizalys\Onedrive\StreamBackEnd::TEMP,
|
||||
'client_id' => $this->policyModel["bucketname"],
|
||||
|
||||
// Restore the previous state while instantiating this client to proceed in
|
||||
// obtaining an access token.
|
||||
'state' => json_decode($this->policyModel["sk"]),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文本文件内容
|
||||
*
|
||||
* @return string 文件内容
|
||||
*/
|
||||
public function getFileContent(){
|
||||
$file = new \Krizalys\Onedrive\File($this->clinet,"/me/drive/root:/".$this->fileModel["pre_name"].":");
|
||||
return $file->fetchContent();
|
||||
}
|
||||
|
||||
/**
|
||||
* 签名预览URL
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function Preview($base=null,$name=null){
|
||||
$preview = json_decode(json_encode($this->clinet->apiGet("/me/drive/root:/".rawurlencode($this->fileModel["pre_name"]).":")),true);
|
||||
return [1,$preview["@microsoft.graph.downloadUrl"]];
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存文件内容
|
||||
*
|
||||
* @param string $content 文件内容
|
||||
* @return void
|
||||
*/
|
||||
public function saveContent($content){
|
||||
$this->clinet->createFile(rawurldecode($this->fileModel["pre_name"]),"/me/drive/root:/",$content);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算缩略图大小
|
||||
*
|
||||
* @param int $width 原始宽
|
||||
* @param int $height 原始高
|
||||
* @return array
|
||||
*/
|
||||
static function getThumbSize($width,$height){
|
||||
$rate = $width/$height;
|
||||
$maxWidth = 90;
|
||||
$maxHeight = 39;
|
||||
$changeWidth = 39*$rate;
|
||||
$changeHeight = 90/$rate;
|
||||
if($changeWidth>=$maxWidth){
|
||||
return [(int)$changeHeight,90];
|
||||
}
|
||||
return [39,(int)$changeWidth];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取缩略图地址
|
||||
*
|
||||
* @return string 缩略图地址
|
||||
*/
|
||||
public function getThumb(){
|
||||
$picInfo = explode(",",$this->fileModel["pic_info"]);
|
||||
$thumbSize = self::getThumbSize($picInfo[0],$picInfo[1]);
|
||||
$thumb = json_decode(json_encode($this->clinet->apiGet("/me/drive/root:/".rawurlencode($this->fileModel["pre_name"]).":/thumbnails")),true);
|
||||
return [1,$thumb["value"][0]["small"]["url"]];
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除某一策略下的指定upyun文件
|
||||
*
|
||||
* @param array $fileList 待删除文件的数据库记录
|
||||
* @param array $policyData 待删除文件的上传策略信息
|
||||
* @return void
|
||||
*/
|
||||
static function DeleteFile($fileList,$policyData){
|
||||
$clinet = new Client([
|
||||
'stream_back_end' => \Krizalys\Onedrive\StreamBackEnd::TEMP,
|
||||
'client_id' => $policyData["bucketname"],
|
||||
|
||||
// Restore the previous state while instantiating this client to proceed in
|
||||
// obtaining an access token.
|
||||
'state' => json_decode($policyData["sk"]),
|
||||
]);
|
||||
foreach (array_column($fileList, 'pre_name') as $key => $value) {
|
||||
$clinet->deleteObject("/me/drive/root:/".rawurlencode($value).":");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成文件下载URL
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function Download(){
|
||||
$preview = json_decode(json_encode($this->clinet->apiGet("/me/drive/root:/".rawurlencode($this->fileModel["pre_name"]).":")),true);
|
||||
return [1,$preview["@microsoft.graph.downloadUrl"]];
|
||||
}
|
||||
|
||||
/**
|
||||
* 签名临时URL用于Office预览
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function signTmpUrl(){
|
||||
return $this->Preview();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -5,10 +5,28 @@ use think\Model;
|
||||
use think\Db;
|
||||
|
||||
class Option extends Model{
|
||||
static function getValues($groups = ['basic']){
|
||||
|
||||
static function getValues($groups = ['basic'],$userInfo=null){
|
||||
$t = Db::name('options')->where('option_type','in',$groups)->column('option_value','option_name');
|
||||
if(in_array("basic",$groups)){
|
||||
return array_merge($t,self::getThemeOptions($t,$userInfo));
|
||||
}
|
||||
return $t;
|
||||
}
|
||||
|
||||
static function getThemeOptions($basicOptions,$userInfo){
|
||||
$themes = json_decode($basicOptions["themes"],true);
|
||||
if($userInfo==null){
|
||||
return ["themeColor"=>$basicOptions["defaultTheme"],"themeConfig"=>$themes[$basicOptions["defaultTheme"]]];
|
||||
}else{
|
||||
$userOptions = json_decode($userInfo["options"],true);
|
||||
if(empty($userOptions)||!array_key_exists("preferTheme",$userOptions)||!array_key_exists($userOptions["preferTheme"],$themes)){
|
||||
return ["themeColor"=>$basicOptions["defaultTheme"],"themeConfig"=>$themes[$basicOptions["defaultTheme"]]];
|
||||
}
|
||||
return ["themeColor"=>$userOptions["preferTheme"],"themeConfig"=>$themes[$userOptions["preferTheme"]]];
|
||||
}
|
||||
}
|
||||
|
||||
static function getValue($optionName){
|
||||
return Db::name('options')->where('option_name',$optionName)->value('option_value');
|
||||
}
|
||||
|
||||
@@ -0,0 +1,199 @@
|
||||
<?php
|
||||
namespace app\index\model;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
|
||||
use OSS\OssClient;
|
||||
use OSS\Core\OssException;
|
||||
|
||||
use \app\index\model\Option;
|
||||
|
||||
/**
|
||||
* 阿里云OSS策略文件管理适配器
|
||||
*/
|
||||
class OssAdapter extends Model{
|
||||
|
||||
private $fileModel;
|
||||
private $policyModel;
|
||||
private $userModel;
|
||||
|
||||
public function __construct($file,$policy,$user){
|
||||
$this->fileModel = $file;
|
||||
$this->policyModel = $policy;
|
||||
$this->userModel = $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取OSS策略文本文件内容
|
||||
*
|
||||
* @return string 文件内容
|
||||
*/
|
||||
public function getFileContent(){
|
||||
return file_get_contents($this->Preview()[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 签名OSS预览URL
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function Preview(){
|
||||
if(!$this->policyModel['bucket_private']){
|
||||
$fileUrl = $this->policyModel["url"].$this->fileModel["pre_name"];
|
||||
return[true,$fileUrl];
|
||||
}else{
|
||||
$accessKeyId = $this->policyModel["ak"];
|
||||
$accessKeySecret = $this->policyModel["sk"];
|
||||
$endpoint = $this->policyModel["url"];
|
||||
try {
|
||||
$ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, true);
|
||||
} catch (OssException $e) {
|
||||
return [false,0];
|
||||
}
|
||||
$baseUrl = $this->policyModel["url"].$this->fileModel["pre_name"];
|
||||
try{
|
||||
$signedUrl = $ossClient->signUrl($this->policyModel["bucketname"], $this->fileModel["pre_name"], Option::getValue("timeout"));
|
||||
} catch(OssException $e) {
|
||||
return [false,0];
|
||||
}
|
||||
return[true,$signedUrl];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存OSS文件内容
|
||||
*
|
||||
* @param string $content 文件内容
|
||||
* @return void
|
||||
*/
|
||||
public function saveContent($content){
|
||||
$accessKeyId = $this->policyModel["ak"];
|
||||
$accessKeySecret = $this->policyModel["sk"];
|
||||
$endpoint = "http".ltrim(ltrim($this->policyModel["server"],"https"),"http");
|
||||
try {
|
||||
$ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, true);
|
||||
} catch (OssException $e) {
|
||||
die('{ "result": { "success": false, "error": "鉴权失败" } }');
|
||||
}
|
||||
try{
|
||||
$ossClient->putObject($this->policyModel["bucketname"], $this->fileModel["pre_name"], $content);
|
||||
} catch(OssException $e) {
|
||||
die('{ "result": { "success": false, "error": "编辑失败" } }');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取缩略图地址
|
||||
*
|
||||
* @return string 缩略图地址
|
||||
*/
|
||||
public function getThumb(){
|
||||
if(!$this->policyModel['bucket_private']){
|
||||
$fileUrl = $this->policyModel["url"].$this->fileModel["pre_name"]."?x-oss-process=image/resize,m_lfit,h_39,w_90";
|
||||
return[true,$fileUrl];
|
||||
}else{
|
||||
$accessKeyId = $this->policyModel["ak"];
|
||||
$accessKeySecret = $this->policyModel["sk"];
|
||||
$endpoint = $this->policyModel["url"];
|
||||
try {
|
||||
$ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, true);
|
||||
} catch (OssException $e) {
|
||||
return [false,0];
|
||||
}
|
||||
$baseUrl = $this->policyModel["url"].$this->fileModel["pre_name"];
|
||||
try{
|
||||
$signedUrl = $ossClient->signUrl($this->policyModel["bucketname"], $this->fileModel["pre_name"], Option::getValue("timeout"),'GET', array("x-oss-process" => 'image/resize,m_lfit,h_39,w_90'));
|
||||
} catch(OssException $e) {
|
||||
return [false,0];
|
||||
}
|
||||
return[true,$signedUrl];
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 删除某一策略下的指定OSS文件
|
||||
*
|
||||
* @param array $fileList 待删除文件的数据库记录
|
||||
* @param array $policyData 待删除文件的上传策略信息
|
||||
* @return void
|
||||
*/
|
||||
static function DeleteFile($fileList,$policyData){
|
||||
$accessKeyId = $policyData["ak"];
|
||||
$accessKeySecret = $policyData["sk"];
|
||||
$endpoint = "http".ltrim(ltrim($policyData["server"],"https"),"http");
|
||||
try {
|
||||
$ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, true);
|
||||
} catch (OssException $e) {
|
||||
return false;
|
||||
}
|
||||
try{
|
||||
$ossClient->deleteObjects($policyData["bucketname"], array_column($fileList, 'pre_name'));
|
||||
} catch(OssException $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成文件下载URL
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function Download(){
|
||||
if(!$this->policyModel['bucket_private']){
|
||||
return[true,"/File/OssDownload?url=".urlencode($this->policyModel["url"].$this->fileModel["pre_name"])."&name=".urlencode($this->fileModel["orign_name"])];
|
||||
}else{
|
||||
$accessKeyId = $this->policyModel["ak"];
|
||||
$accessKeySecret = $this->policyModel["sk"];
|
||||
$endpoint = $this->policyModel["url"];
|
||||
try {
|
||||
$ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, true);
|
||||
} catch (OssException $e) {
|
||||
return [false,0];
|
||||
}
|
||||
$baseUrl = $this->policyModel["url"].$this->fileModel["pre_name"];
|
||||
try{
|
||||
$signedUrl = $ossClient->signUrl($this->policyModel["bucketname"], $this->fileModel["pre_name"], Option::getValue("timeout"),'GET', array("response-content-disposition" => 'attachment; filename='.$this->fileModel["orign_name"]));
|
||||
} catch(OssException $e) {
|
||||
return [false,0];
|
||||
}
|
||||
return[true,$signedUrl];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除临时文件
|
||||
*
|
||||
* @param string $fname 文件名
|
||||
* @param array $policy 上传策略信息
|
||||
* @return boolean
|
||||
*/
|
||||
static function deleteOssFile($fname,$policy){
|
||||
$accessKeyId = $policy["ak"];
|
||||
$accessKeySecret = $policy["sk"];
|
||||
$endpoint = "http".ltrim(ltrim($policy["server"],"https"),"http");
|
||||
try {
|
||||
$ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, true);
|
||||
} catch (OssException $e) {
|
||||
return false;
|
||||
}
|
||||
try{
|
||||
$ossClient->deleteObject($policy["bucketname"], $fname);
|
||||
} catch(OssException $e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 签名临时URL用于Office预览
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function signTmpUrl(){
|
||||
return $this->Preview();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,149 @@
|
||||
<?php
|
||||
namespace app\index\model;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
|
||||
require_once 'extend/Qiniu/functions.php';
|
||||
use Qiniu\Auth;
|
||||
|
||||
use \app\index\model\Option;
|
||||
|
||||
/**
|
||||
* 七牛策略文件管理适配器
|
||||
*/
|
||||
class QiniuAdapter extends Model{
|
||||
|
||||
private $fileModel;
|
||||
private $policyModel;
|
||||
private $userModel;
|
||||
|
||||
public function __construct($file,$policy,$user){
|
||||
$this->fileModel = $file;
|
||||
$this->policyModel = $policy;
|
||||
$this->userModel = $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文本文件内容
|
||||
*
|
||||
* @return string 文件内容
|
||||
*/
|
||||
public function getFileContent(){
|
||||
return file_get_contents($this->Preview()[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 签名七牛文件预览URL
|
||||
*
|
||||
* @param string $thumb 缩略图参数
|
||||
* @return void
|
||||
*/
|
||||
public function Preview($thumb=null){
|
||||
if($thumb===true || $thumb===false){
|
||||
$thumb =null;
|
||||
}
|
||||
if(!$this->policyModel['bucket_private']){
|
||||
$fileUrl = $this->policyModel["url"].$this->fileModel["pre_name"].$thumb;
|
||||
return[true,$fileUrl];
|
||||
}else{
|
||||
$auth = new Auth($this->policyModel["ak"], $this->policyModel["sk"]);
|
||||
$baseUrl = $this->policyModel["url"].$this->fileModel["pre_name"].$thumb;
|
||||
$signedUrl = $auth->privateDownloadUrl($baseUrl);
|
||||
return[true,$signedUrl];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存七牛文件内容
|
||||
*
|
||||
* @param string $content 文件内容
|
||||
* @return bool
|
||||
*/
|
||||
public function saveContent($content){
|
||||
$auth = new Auth($this->policyModel["ak"], $this->policyModel["sk"]);
|
||||
$expires = 3600;
|
||||
$keyToOverwrite = $this->fileModel["pre_name"];
|
||||
$upToken = $auth->uploadToken($this->policyModel["bucketname"], $keyToOverwrite, $expires, null, true);
|
||||
$uploadMgr = new \Qiniu\Storage\UploadManager();
|
||||
list($ret, $err) = $uploadMgr->put($upToken, $keyToOverwrite, $content);
|
||||
if ($err !== null) {
|
||||
die('{ "result": { "success": false, "error": "编辑失败" } }');
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取缩略图地址
|
||||
*
|
||||
* @return string 缩略图地址
|
||||
*/
|
||||
public function getThumb(){
|
||||
return $this->Preview("?imageView2/1/w/230/h/200");
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除某一策略下的指定七牛文件
|
||||
*
|
||||
* @param array $fileList 待删除文件的数据库记录
|
||||
* @param array $policyData 待删除文件的上传策略信息
|
||||
* @return void
|
||||
*/
|
||||
static function deleteFile($fileList,$policyData){
|
||||
$auth = new Auth($policyData["ak"], $policyData["sk"]);
|
||||
$config = new \Qiniu\Config();
|
||||
$bucketManager = new \Qiniu\Storage\BucketManager($auth);
|
||||
$fileListTemp = array_column($fileList, 'pre_name');
|
||||
$ops = $bucketManager->buildBatchDelete($policyData["bucketname"], $fileListTemp);
|
||||
list($ret, $err) = $bucketManager->batch($ops);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成文件下载URL
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function Download(){
|
||||
if(!$this->policyModel['bucket_private']){
|
||||
$fileUrl = $this->policyModel["url"].$this->fileModel["pre_name"]."?attname=".urlencode($this->fileModel["orign_name"]);
|
||||
return[true,$fileUrl];
|
||||
}else{
|
||||
$auth = new Auth($this->policyModel["ak"], $this->policyModel["sk"]);
|
||||
$baseUrl = $this->policyModel["url"].$this->fileModel["pre_name"]."?attname=".urlencode($this->fileModel["orign_name"]);
|
||||
$signedUrl = $auth->privateDownloadUrl($baseUrl);
|
||||
return[true,$signedUrl];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除临时文件
|
||||
*
|
||||
* @param string $fname 文件名
|
||||
* @param array $policy 上传策略信息
|
||||
* @return void
|
||||
*/
|
||||
static function deleteSingle($fname,$policy){
|
||||
$auth = new Auth($policy["ak"], $policy["sk"]);
|
||||
$config = new \Qiniu\Config();
|
||||
$bucketManager = new \Qiniu\Storage\BucketManager($auth);
|
||||
$err = $bucketManager->delete($policy["bucketname"], $fname);
|
||||
if ($err) {
|
||||
return false;
|
||||
}else{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 签名临时URL用于Office预览
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function signTmpUrl(){
|
||||
return $this->Preview();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
namespace app\index\model;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
use \app\index\model\Option;
|
||||
|
||||
class Remote extends Model{
|
||||
|
||||
public $sk;
|
||||
private $policy;
|
||||
private $serverOutput;
|
||||
private $httpCode;
|
||||
|
||||
public function __construct($policy){
|
||||
$this->policy = $policy;
|
||||
}
|
||||
|
||||
public function remove($fileList){
|
||||
$signKey = $this->sign($fileList,"DELETE");
|
||||
$this->send("manager.php",$signKey,"DELETE",base64_encode(json_encode($fileList)));
|
||||
}
|
||||
|
||||
public function preview($fname){
|
||||
return $this->signUrl($this->policy["url"]."object.php?action=preview&name=".urlencode($fname)."&expires=".(time()+(int)Option::getValue("timeout")));
|
||||
}
|
||||
|
||||
public function clean(){
|
||||
return $this->signUrl($this->policy["url"]."object.php?action=clean&expires=".(time()+(int)Option::getValue("timeout")));
|
||||
}
|
||||
|
||||
public function download($fname,$attnanme){
|
||||
return $this->signUrl($this->policy["url"]."object.php?action=download&name=".urlencode($fname)."&attaname=".urlencode($attnanme)."&expires=".(time()+(int)Option::getValue("timeout")));
|
||||
}
|
||||
|
||||
public function thumb($fname,$picInfo){
|
||||
return $this->signUrl($this->policy["url"]."object.php?action=thumb&name=".urlencode($fname)."&expires=".(time()+(int)Option::getValue("timeout"))."&w=".$picInfo[0]."&h=".$picInfo[1]);
|
||||
}
|
||||
|
||||
public function signUrl($url){
|
||||
$signKey = hash_hmac("sha256",$url,"GET".$this->policy["sk"]);
|
||||
return $url."&auth=".$signKey;
|
||||
}
|
||||
|
||||
public function updateContent($fname,$content){
|
||||
$object = ["fname"=>$fname,"content"=>$content];
|
||||
$signKey = $this->sign($object,"UPDATE");
|
||||
$this->send("manager.php",$signKey,"UPDATE",base64_encode(json_encode($object)));
|
||||
}
|
||||
|
||||
public function send($target,$auth,$action,$object){
|
||||
$session = curl_init($this->policy["server"].$target);
|
||||
$postData = array(
|
||||
"action" => $action,
|
||||
"auth" => $auth,
|
||||
"object" => $object,
|
||||
);
|
||||
curl_setopt($session, CURLOPT_POST, 1);
|
||||
curl_setopt($session, CURLOPT_POSTFIELDS, $postData);
|
||||
curl_setopt($session, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($session, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($session, CURLOPT_SSL_VERIFYHOST, false);
|
||||
$this->serverOutput = curl_exec($session);
|
||||
$this->httpCode = curl_getinfo($session,CURLINFO_HTTP_CODE);
|
||||
echo $this->serverOutput;
|
||||
}
|
||||
|
||||
public function sign($content,$method = null){
|
||||
return hash_hmac("sha256",base64_encode(json_encode($content)),$method.$this->policy["sk"]);
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
namespace app\index\model;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
|
||||
use \app\index\model\Option;
|
||||
|
||||
/**
|
||||
* 远程策略文件管理适配器
|
||||
*/
|
||||
class RemoteAdapter extends Model{
|
||||
|
||||
private $fileModel;
|
||||
private $policyModel;
|
||||
private $userModel;
|
||||
|
||||
public function __construct($file,$policy,$user){
|
||||
$this->fileModel = $file;
|
||||
$this->policyModel = $policy;
|
||||
$this->userModel = $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取文本文件内容
|
||||
*
|
||||
* @return string 文件内容
|
||||
*/
|
||||
public function getFileContent(){
|
||||
return file_get_contents($this->Preview()[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 签名文件预览URL
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function Preview(){
|
||||
$remote = new Remote($this->policyModel);
|
||||
return [1,$remote->preview($this->fileModel["pre_name"])];
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存文件内容
|
||||
*
|
||||
* @param string $content 文件内容
|
||||
* @return bool
|
||||
*/
|
||||
public function saveContent($content){
|
||||
$remote = new Remote($this->policyModel);
|
||||
$remote->updateContent($this->fileModel["pre_name"],$content);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取缩略图地址
|
||||
*
|
||||
* @return string 缩略图地址
|
||||
*/
|
||||
public function getThumb(){
|
||||
$remote = new Remote($this->policyModel);
|
||||
return [1,$remote->thumb($this->fileModel["pre_name"],explode(",",$this->fileModel["pic_info"]))];
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除某一策略下的指定文件
|
||||
*
|
||||
* @param array $fileList 待删除文件的数据库记录
|
||||
* @param array $policyData 待删除文件的上传策略信息
|
||||
* @return void
|
||||
*/
|
||||
static function deleteFile($fileList,$policyData){
|
||||
$remoteObj = new Remote($policyData);
|
||||
$remoteObj->remove(array_column($fileList, 'pre_name'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成文件下载URL
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function Download(){
|
||||
$remote = new Remote($this->policyModel);
|
||||
return [1,$remote->download($this->fileModel["pre_name"],$this->fileModel["orign_name"])];
|
||||
}
|
||||
|
||||
/**
|
||||
* 签名临时URL用于Office预览
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function signTmpUrl(){
|
||||
return $this->Preview();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,166 @@
|
||||
<?php
|
||||
namespace app\index\model;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
|
||||
use \app\index\model\Option;
|
||||
|
||||
/**
|
||||
* AWS S3策略文件管理适配器
|
||||
*/
|
||||
class S3Adapter extends Model{
|
||||
|
||||
private $fileModel;
|
||||
private $policyModel;
|
||||
private $userModel;
|
||||
|
||||
public function __construct($file,$policy,$user){
|
||||
$this->fileModel = $file;
|
||||
$this->policyModel = $policy;
|
||||
$this->userModel = $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取又拍云策略文本文件内容
|
||||
*
|
||||
* @return string 文件内容
|
||||
*/
|
||||
public function getFileContent(){
|
||||
return file_get_contents($this->Preview()[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 签名S3预览URL
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function Preview($base=null,$name=null){
|
||||
if($base===true || $base ===false){
|
||||
$base = null;
|
||||
}
|
||||
$s3 = new \Aws\S3\S3Client([
|
||||
'version' => 'latest',
|
||||
'region' => $this->policyModel["op_name"],
|
||||
'endpoint' => $this->policyModel["op_pwd"],
|
||||
'use_path_style_endpoint' => true,
|
||||
'credentials' => [
|
||||
'key' => $this->policyModel["ak"],
|
||||
'secret' => $this->policyModel["sk"],
|
||||
],
|
||||
]);
|
||||
$cmd = $s3->getCommand('GetObject', [
|
||||
'Bucket' => $this->policyModel["bucketname"],
|
||||
'Key' => $this->fileModel["pre_name"],
|
||||
]);
|
||||
$timeOut = Option::getValue("timeout");
|
||||
$req = $s3->createPresignedRequest($cmd, '+'.($timeOut/60).' minutes');
|
||||
$url = (string)$req->getUri();
|
||||
|
||||
return [1,$url];
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存文件内容
|
||||
*
|
||||
* @param string $content 文件内容
|
||||
* @return void
|
||||
*/
|
||||
public function saveContent($content){
|
||||
$s3 = new \Aws\S3\S3Client([
|
||||
'version' => 'latest',
|
||||
'region' => $this->policyModel["op_name"],
|
||||
'endpoint' => $this->policyModel["op_pwd"],
|
||||
'use_path_style_endpoint' => true,
|
||||
'credentials' => [
|
||||
'key' => $this->policyModel["ak"],
|
||||
'secret' => $this->policyModel["sk"],
|
||||
],
|
||||
]);
|
||||
$s3->putObject([
|
||||
'Bucket' => $this->policyModel["bucketname"],
|
||||
'Key' => $this->fileModel["pre_name"],
|
||||
'Body' => $content,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除某一策略下的指定文件
|
||||
*
|
||||
* @param array $fileList 待删除文件的数据库记录
|
||||
* @param array $policyData 待删除文件的上传策略信息
|
||||
* @return void
|
||||
*/
|
||||
static function DeleteFile($fileList,$policyData){
|
||||
foreach (array_column($fileList, 'pre_name') as $key => $value) {
|
||||
self::deleteS3File($value,$policyData);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成文件下载URL
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function Download(){
|
||||
$timeOut = Option::getValue("timeout");
|
||||
$s3 = new \Aws\S3\S3Client([
|
||||
'version' => 'latest',
|
||||
'region' => $this->policyModel["op_name"],
|
||||
'endpoint' => $this->policyModel["op_pwd"],
|
||||
'use_path_style_endpoint' => true,
|
||||
'credentials' => [
|
||||
'key' => $this->policyModel["ak"],
|
||||
'secret' => $this->policyModel["sk"],
|
||||
],
|
||||
]);
|
||||
$cmd = $s3->getCommand('GetObject', [
|
||||
'Bucket' => $this->policyModel["bucketname"],
|
||||
'Key' => $this->fileModel["pre_name"],
|
||||
'ResponseContentDisposition' => 'attachment; filename='.$this->fileModel["orign_name"],
|
||||
]);
|
||||
$timeOut = Option::getValue("timeout");
|
||||
$req = $s3->createPresignedRequest($cmd, '+'.($timeOut/60).' minutes');
|
||||
$url = (string)$req->getUri();
|
||||
|
||||
return [1,$url];
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除临时文件
|
||||
*
|
||||
* @param string $fname 文件名
|
||||
* @param array $policy 上传策略信息
|
||||
* @return boolean
|
||||
*/
|
||||
static function deleteS3File($fname,$policy){
|
||||
$s3 = new \Aws\S3\S3Client([
|
||||
'version' => 'latest',
|
||||
'region' => $policy["op_name"],
|
||||
'endpoint' => $policy["op_pwd"],
|
||||
'use_path_style_endpoint' => true,
|
||||
'credentials' => [
|
||||
'key' => $policy["ak"],
|
||||
'secret' => $policy["sk"],
|
||||
],
|
||||
]);
|
||||
$result = $s3->deleteObject([
|
||||
'Bucket' => $policy["bucketname"],
|
||||
'Key' => $fname,
|
||||
]);
|
||||
return $result["DeleteMarker"];
|
||||
}
|
||||
|
||||
/**
|
||||
* 签名临时URL用于Office预览
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function signTmpUrl(){
|
||||
return $this->Preview();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -57,13 +57,15 @@ class ShareHandler extends Model{
|
||||
"msg" => "无权操作"
|
||||
);
|
||||
}
|
||||
$newPwd = self::getRandomKey(6);
|
||||
Db::name('shares')->where('share_key',$this->shareData["share_key"])->update([
|
||||
'type' => $this->shareData["type"] == "public"?"private":"public",
|
||||
'share_pwd' => self::getRandomKey(6)
|
||||
'share_pwd' => $newPwd
|
||||
]);
|
||||
return array(
|
||||
"error" =>0,
|
||||
"msg" => "更改成功"
|
||||
"msg" => "更改成功",
|
||||
"newPwd" => $newPwd,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -81,6 +83,62 @@ class ShareHandler extends Model{
|
||||
}
|
||||
}
|
||||
|
||||
public function getThumb($user,$path,$folder=false){
|
||||
$checkStatus = $this->checkSession($user);
|
||||
if(!$checkStatus[0]){
|
||||
return [$checkStatus[0],$checkStatus[1]];
|
||||
}
|
||||
$reqPath = Db::name('folders')->where('position_absolute',$this->shareData["source_name"])->find();
|
||||
if($folder){
|
||||
$fileObj = new FileManage($path,$this->shareData["owner"]);
|
||||
}else{
|
||||
$fileObj = new FileManage($reqPath["position_absolute"].$path,$this->shareData["owner"]);
|
||||
}
|
||||
return $fileObj->getThumb();
|
||||
}
|
||||
|
||||
public function getDocPreview($user,$path,$inFolder){
|
||||
$checkStatus = $this->checkSession($user);
|
||||
if(!$checkStatus[0]){
|
||||
return [$checkStatus[0],$checkStatus[1]];
|
||||
}
|
||||
if($inFolder){
|
||||
$reqPath = Db::name('folders')->where('position_absolute',$this->shareData["source_name"])->find();
|
||||
$fileObj = new FileManage($reqPath["position_absolute"].$path,$this->shareData["owner"]);
|
||||
}else{
|
||||
$reqPath = Db::name('files')->where('id',$this->shareData["source_name"])->find();
|
||||
if($reqPath["dir"] == "/"){
|
||||
$reqPath["dir"] = $reqPath["dir"].$reqPath["orign_name"];
|
||||
}else{
|
||||
$reqPath["dir"] = $reqPath["dir"]."/".$reqPath["orign_name"];
|
||||
}
|
||||
$fileObj = new FileManage($reqPath["dir"],$this->shareData["owner"]);
|
||||
}
|
||||
$tmpUrl = $fileObj->signTmpUrl();
|
||||
return[true,"http://view.officeapps.live.com/op/view.aspx?src=".urlencode($tmpUrl)];
|
||||
}
|
||||
|
||||
public function getContent($user,$path=null,$inFolder){
|
||||
$checkStatus = $this->checkSession($user);
|
||||
if(!$checkStatus[0]){
|
||||
return [$checkStatus[0],$checkStatus[1]];
|
||||
}
|
||||
if($inFolder){
|
||||
$reqPath = Db::name('folders')->where('position_absolute',$this->shareData["source_name"])->find();
|
||||
$fileObj = new FileManage($reqPath["position_absolute"].$path,$this->shareData["owner"]);
|
||||
}else{
|
||||
$reqPath = Db::name('files')->where('id',$this->shareData["source_name"])->find();
|
||||
if($reqPath["dir"] == "/"){
|
||||
$reqPath["dir"] = $reqPath["dir"].$reqPath["orign_name"];
|
||||
}else{
|
||||
$reqPath["dir"] = $reqPath["dir"]."/".$reqPath["orign_name"];
|
||||
}
|
||||
$fileObj = new FileManage($reqPath["dir"],$this->shareData["owner"]);
|
||||
}
|
||||
$fileObj->getContent();
|
||||
exit();
|
||||
}
|
||||
|
||||
public function checkSession($user){
|
||||
if($this->lockStatus){
|
||||
return [false,"会话过期,请刷新页面"];
|
||||
@@ -132,7 +190,7 @@ class ShareHandler extends Model{
|
||||
}
|
||||
$reqPath = Db::name('folders')->where('position_absolute',$this->shareData["source_name"])->find();
|
||||
$path = $path == "/"?"":$path;
|
||||
return FileManage::ListFile($this->shareData["source_name"].$path,$this->shareData["owner"]);
|
||||
return FileManage::ListFile($this->shareData["source_name"].$path,$this->shareData["owner"],true,$this->shareData["source_name"]);
|
||||
}
|
||||
|
||||
public function Preview($user){
|
||||
@@ -221,7 +279,7 @@ class ShareHandler extends Model{
|
||||
}
|
||||
}
|
||||
|
||||
static function createShare($fname,$type,$user,$group){
|
||||
static function createShare($fname,$type,$pwd,$user,$group){
|
||||
if(!$group["allow_share"]){
|
||||
self::setError("您当前的用户组无权分享文件");
|
||||
}
|
||||
@@ -229,9 +287,9 @@ class ShareHandler extends Model{
|
||||
$fnameTmp = FileManage::getFileName($fname)[0];
|
||||
$fileRecord = Db::name('files')->where('upload_user',$user["id"])->where('orign_name',$fnameTmp)->where('dir',$path)->find();
|
||||
if(empty($fileRecord)){
|
||||
self::createDirShare($fname,$type,$user,$group);
|
||||
self::createDirShare($fname,$type,$pwd,$user,$group);
|
||||
}else{
|
||||
self::createFileShare($fileRecord,$type,$user,$group);
|
||||
self::createFileShare($fileRecord,$type,$pwd,$user,$group);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,13 +301,13 @@ class ShareHandler extends Model{
|
||||
die('{ "result": "'.$text.'" }');
|
||||
}
|
||||
|
||||
static function createDirShare($fname,$type,$user,$group){
|
||||
static function createDirShare($fname,$type,$pwd,$user,$group){
|
||||
$dirRecord = Db::name('folders')->where('owner',$user["id"])->where('position_absolute',$fname)->find();
|
||||
if(empty($dirRecord)){
|
||||
self::setError("目录不存在");
|
||||
}
|
||||
$shareKey = self::getRandomKey(8);
|
||||
$sharePwd = $type=="public" ? "0" : self::getRandomKey(6);
|
||||
$sharePwd = $type=="public" ? "0" : $pwd;
|
||||
$SQLData = [
|
||||
'type' => $type=="public" ? "public" : "private",
|
||||
'share_time' => date("Y-m-d H:i:s"),
|
||||
@@ -271,9 +329,9 @@ class ShareHandler extends Model{
|
||||
}
|
||||
}
|
||||
|
||||
static function createFileShare($file,$type,$user,$group){
|
||||
static function createFileShare($file,$type,$pwd,$user,$group){
|
||||
$shareKey = self::getRandomKey(8);
|
||||
$sharePwd = $type=="public" ? "0" : self::getRandomKey(6);
|
||||
$sharePwd = $type=="public" ? "0" : $pwd;
|
||||
$SQLData = [
|
||||
'type' => $type=="public" ? "public" : "private",
|
||||
'share_time' => date("Y-m-d H:i:s"),
|
||||
|
||||
@@ -0,0 +1,412 @@
|
||||
<?php
|
||||
namespace app\index\model;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
use \app\index\model\Option;
|
||||
use \app\index\model\FileManage;
|
||||
|
||||
use think\console\Input;
|
||||
use think\console\Output;
|
||||
|
||||
use \Krizalys\Onedrive\Client;
|
||||
use Sabre\DAV\Mock\File;
|
||||
|
||||
class Task extends Model{
|
||||
|
||||
public $taskModel;
|
||||
public $taskName;
|
||||
public $taskType;
|
||||
public $taskContent;
|
||||
public $input;
|
||||
public $output;
|
||||
public $userId;
|
||||
|
||||
public $status = "success";
|
||||
public $errorMsg;
|
||||
public $policyModel;
|
||||
|
||||
|
||||
public function __construct($id=null){
|
||||
if($id!==null){
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存任务至数据库
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function saveTask(){
|
||||
Db::name("task")->insert([
|
||||
"task_name" => $this->taskName,
|
||||
"attr" => $this->taskContent,
|
||||
"type" => $this->taskType,
|
||||
"status" => "todo",
|
||||
"uid" => $this->userId,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始执行任务
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function Doit(){
|
||||
switch ($this->taskModel["type"]){
|
||||
case "uploadSingleToOnedrive":
|
||||
$this->uploadSingleToOnedrive();
|
||||
break;
|
||||
case "UploadRegularRemoteDownloadFileToOnedrive":
|
||||
$this->uploadSingleToOnedrive();
|
||||
break;
|
||||
case "uploadChunksToOnedrive":
|
||||
$this->uploadChunksToOnedrive();
|
||||
break;
|
||||
case "UploadLargeRemoteDownloadFileToOnedrive":
|
||||
$this->uploadUnchunkedFile();
|
||||
break;
|
||||
default:
|
||||
$this->output->writeln("Unknown task type (".$this->taskModel["type"].")");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传未分片的大文件至Onedrive
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function uploadUnchunkedFile(){
|
||||
$this->taskContent = json_decode($this->taskModel["attr"],true);
|
||||
$policyData = Db::name("policy")->where("id",$this->taskContent["policyId"])->find();
|
||||
$this->policyModel = $policyData;
|
||||
$onedrive = new Client([
|
||||
'stream_back_end' => \Krizalys\Onedrive\StreamBackEnd::TEMP,
|
||||
'client_id' => $policyData["bucketname"],
|
||||
|
||||
// Restore the previous state while instantiating this client to proceed in
|
||||
// obtaining an access token.
|
||||
'state' => json_decode($policyData["sk"]),
|
||||
]);
|
||||
|
||||
//创建分片上传Session,获取上传URL
|
||||
try{
|
||||
$uploadUrl = $onedrive->apiPost("/me/drive/root:/".rawurlencode($this->taskContent["savePath"] . "/" . $this->taskContent["objname"]).":/createUploadSession",[])->uploadUrl;
|
||||
}catch(\Exception $e){
|
||||
$this->status="error";
|
||||
$this->errorMsg = $e->getMessage();
|
||||
$this->cleanTmpChunk();
|
||||
return;
|
||||
}
|
||||
//创建分片上传Session,获取上传URL
|
||||
try{
|
||||
$uploadUrl = $onedrive->apiPost("/me/drive/root:/".rawurlencode($this->taskContent["savePath"] . "/" . $this->taskContent["objname"]).":/createUploadSession",[])->uploadUrl;
|
||||
}catch(\Exception $e){
|
||||
$this->status="error";
|
||||
$this->errorMsg = $e->getMessage();
|
||||
$this->cleanTmpChunk();
|
||||
return;
|
||||
}
|
||||
|
||||
//每次4MB上传文件
|
||||
|
||||
if(!$file = @fopen($this->taskContent["originPath"],"r")){
|
||||
$this->status="error";
|
||||
$this->errorMsg = "File not exist.";
|
||||
$this->cleanTmpChunk();
|
||||
return;
|
||||
}
|
||||
$offset = 0;
|
||||
$totalSize = filesize($this->taskContent["originPath"]);
|
||||
while (1) {
|
||||
//移动文件指针
|
||||
fseek($file, $offset);
|
||||
|
||||
$chunksize = (($offset+4*1024*1024)>$totalSize)?($totalSize-$offset):1024*4*1024;
|
||||
$headers = [];
|
||||
$headers[] = "Content-Length: ".$chunksize;
|
||||
$headers[] = "Content-Range: bytes ".$offset."-".($offset+$chunksize-1)."/".$this->taskContent["fsize"];
|
||||
|
||||
//发送单个分片数据
|
||||
try{
|
||||
$onedrive->sendFileChunk($uploadUrl,$headers,fread($file,$chunksize));
|
||||
}catch(\Exception $e){
|
||||
$this->status="error";
|
||||
$this->errorMsg = $e->getMessage();
|
||||
$this->cleanTmpChunk();
|
||||
return;
|
||||
}
|
||||
$this->output->writeln("[Info] Chunk Uploaded. Offset:".$offset);
|
||||
$offset+=$chunksize;
|
||||
if($offset+1 >=$totalSize){
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
fclose($file);
|
||||
$jsonData = array(
|
||||
"path" => $this->taskContent["path"],
|
||||
"fname" => $this->taskContent["fname"],
|
||||
"objname" => $this->taskContent["savePath"]."/".$this->taskContent["objname"],
|
||||
"fsize" => $this->taskContent["fsize"],
|
||||
);
|
||||
|
||||
$addAction = FileManage::addFile($jsonData,$policyData,$this->taskModel["uid"],$this->taskContent["picInfo"]);
|
||||
if(!$addAction[0]){
|
||||
$this->setError($addAction[1],true,"/me/drive/root:/".rawurlencode($this->taskContent["savePath"] . "/" . $this->taskContent["objname"]),$onedrive);
|
||||
$this->cleanTmpChunk();
|
||||
return;
|
||||
}
|
||||
|
||||
$this->cleanTmpChunk();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传已分片的大文件至Onedrive
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function uploadChunksToOnedrive(){
|
||||
$this->taskContent = json_decode($this->taskModel["attr"],true);
|
||||
$policyData = Db::name("policy")->where("id",$this->taskContent["policyId"])->find();
|
||||
$this->policyModel = $policyData;
|
||||
$onedrive = new Client([
|
||||
'stream_back_end' => \Krizalys\Onedrive\StreamBackEnd::TEMP,
|
||||
'client_id' => $policyData["bucketname"],
|
||||
|
||||
// Restore the previous state while instantiating this client to proceed in
|
||||
// obtaining an access token.
|
||||
'state' => json_decode($policyData["sk"]),
|
||||
]);
|
||||
|
||||
//创建分片上传Session,获取上传URL
|
||||
try{
|
||||
$uploadUrl = $onedrive->apiPost("/me/drive/root:/".rawurlencode($this->taskContent["savePath"] . "/" . $this->taskContent["objname"]).":/createUploadSession",[])->uploadUrl;
|
||||
}catch(\Exception $e){
|
||||
$this->status="error";
|
||||
$this->errorMsg = $e->getMessage();
|
||||
$this->cleanTmpChunk();
|
||||
return;
|
||||
}
|
||||
|
||||
//逐个上传文件分片
|
||||
$offset = 0;
|
||||
foreach ($this->taskContent["chunks"] as $key => $value) {
|
||||
$chunkPath = ROOT_PATH . 'public/uploads/chunks/'.$value["obj_name"].".chunk";
|
||||
if(!$file = @fopen($chunkPath,"r")){
|
||||
$this->status="error";
|
||||
$this->errorMsg = "File chunk not exist.";
|
||||
$this->cleanTmpChunk();
|
||||
return;
|
||||
}
|
||||
$headers = [];
|
||||
$chunksize = filesize($chunkPath);
|
||||
$headers[] = "Content-Length: ".$chunksize;
|
||||
$headers[] = "Content-Range: bytes ".$offset."-".($offset+$chunksize-1)."/".$this->taskContent["fsize"];
|
||||
|
||||
//发送单个分片数据
|
||||
try{
|
||||
$onedrive->sendFileChunk($uploadUrl,$headers,$file);
|
||||
}catch(\Exception $e){
|
||||
$this->status="error";
|
||||
$this->errorMsg = $e->getMessage();
|
||||
$this->cleanTmpChunk();
|
||||
return;
|
||||
}
|
||||
$this->output->writeln("[Info] Chunk Uploaded. Offset:".$offset);
|
||||
$offset += $chunksize;
|
||||
fclose($file);
|
||||
|
||||
}
|
||||
|
||||
$jsonData = array(
|
||||
"path" => $this->taskContent["path"],
|
||||
"fname" => $this->taskContent["fname"],
|
||||
"objname" => $this->taskContent["savePath"]."/".$this->taskContent["objname"],
|
||||
"fsize" => $this->taskContent["fsize"],
|
||||
);
|
||||
|
||||
$addAction = FileManage::addFile($jsonData,$policyData,$this->taskModel["uid"],$this->taskContent["picInfo"]);
|
||||
if(!$addAction[0]){
|
||||
$this->setError($addAction[1],true,"/me/drive/root:/".rawurlencode($this->taskContent["savePath"] . "/" . $this->taskContent["objname"]),$onedrive);
|
||||
$this->cleanTmpChunk();
|
||||
return;
|
||||
}
|
||||
|
||||
$this->cleanTmpChunk();
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传单文件(<=4mb)至Onedrive
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function uploadSingleToOnedrive(){
|
||||
$this->taskContent = json_decode($this->taskModel["attr"],true);
|
||||
$policyData = Db::name("policy")->where("id",$this->taskContent["policyId"])->find();
|
||||
$this->policyModel = $policyData;
|
||||
$onedrive = new Client([
|
||||
'stream_back_end' => \Krizalys\Onedrive\StreamBackEnd::TEMP,
|
||||
'client_id' => $policyData["bucketname"],
|
||||
|
||||
// Restore the previous state while instantiating this client to proceed in
|
||||
// obtaining an access token.
|
||||
'state' => json_decode($policyData["sk"]),
|
||||
]);
|
||||
|
||||
$filePath = $this->taskModel["type"] == "UploadRegularRemoteDownloadFileToOnedrive"?$this->taskContent["originPath"]:ROOT_PATH . 'public/uploads/'.$this->taskContent["savePath"] . "/" . $this->taskContent["objname"];
|
||||
if($file = @fopen($filePath,"r")){
|
||||
try{
|
||||
$onedrive->createFile(rawurlencode($this->taskContent["objname"]),"/me/drive/root:/".$this->taskContent["savePath"],$file);
|
||||
}catch(\Exception $e){
|
||||
$this->status="error";
|
||||
$this->errorMsg = $e->getMessage();
|
||||
$this->cleanTmpFile();
|
||||
return;
|
||||
}
|
||||
|
||||
$jsonData = array(
|
||||
"path" => $this->taskContent["path"],
|
||||
"fname" => $this->taskContent["fname"],
|
||||
"objname" => $this->taskContent["savePath"]."/".$this->taskContent["objname"],
|
||||
"fsize" => $this->taskContent["fsize"],
|
||||
);
|
||||
|
||||
$addAction = FileManage::addFile($jsonData,$policyData,$this->taskModel["uid"],$this->taskContent["picInfo"]);
|
||||
if(!$addAction[0]){
|
||||
$this->setError($addAction[1],true,"/me/drive/root:/".$this->taskContent["savePath"]."/".rawurlencode($this->taskContent["objname"]),$onedrive);
|
||||
$this->cleanTmpFile();
|
||||
return;
|
||||
}
|
||||
|
||||
fclose($file);
|
||||
$this->cleanTmpFile();
|
||||
}else{
|
||||
$this->status = "error";
|
||||
$this->errorMsg = "Failed to open file [".$filePath."]";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除本地临时文件
|
||||
*
|
||||
* @return bool 是否成功
|
||||
*/
|
||||
private function cleanTmpFile(){
|
||||
if($this->taskModel["type"] == "UploadRegularRemoteDownloadFileToOnedrive"){
|
||||
return @unlink($this->taskContent["originPath"]);
|
||||
}else{
|
||||
return @unlink(ROOT_PATH . 'public/uploads/'.$this->taskContent["savePath"] . "/" . $this->taskContent["objname"]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除本地临时分片
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function cleanTmpChunk(){
|
||||
if($this->taskModel["type"] == "UploadLargeRemoteDownloadFileToOnedrive"){
|
||||
@unlink($this->taskContent["originPath"]);
|
||||
}else{
|
||||
foreach ($this->taskContent["chunks"] as $key => $value) {
|
||||
@unlink( ROOT_PATH . 'public/uploads/chunks/'.$value["obj_name"].".chunk");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置为出错状态并清理远程文件
|
||||
*
|
||||
* @param string $msg 错误消息
|
||||
* @param bool $delete 是否删除文件
|
||||
* @param string $path 文件路径
|
||||
* @param mixed $adapter 远程操作适配器
|
||||
* @return void
|
||||
*/
|
||||
private function setError($msg,$delete,$path,$adapter){
|
||||
$this->status="error";
|
||||
$this->errorMsg = $msg;
|
||||
if($delete){
|
||||
switch($this->taskModel["type"]){
|
||||
case "uploadSingleToOnedrive":
|
||||
$adapter->deleteObject($path);
|
||||
break;
|
||||
case "uploadChunksToOnedrive":
|
||||
$adapter->deleteObject($path);
|
||||
break;
|
||||
default:
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
FileManage::storageGiveBack($this->taskModel["uid"],$this->taskContent["fsize"]);
|
||||
}
|
||||
|
||||
public function setSuccess(){
|
||||
$this->taskContent = json_decode($this->taskModel["attr"],true);
|
||||
$policyData = Db::name("policy")->where("id",$this->taskContent["policyId"])->find();
|
||||
$this->policyModel = $policyData;
|
||||
$onedrive = new Client([
|
||||
'stream_back_end' => \Krizalys\Onedrive\StreamBackEnd::TEMP,
|
||||
'client_id' => $policyData["bucketname"],
|
||||
|
||||
// Restore the previous state while instantiating this client to proceed in
|
||||
// obtaining an access token.
|
||||
'state' => json_decode($policyData["sk"]),
|
||||
]);
|
||||
|
||||
$jsonData = array(
|
||||
"path" => $this->taskContent["path"],
|
||||
"fname" => $this->taskContent["fname"],
|
||||
"objname" => $this->taskContent["savePath"]."/".$this->taskContent["objname"],
|
||||
"fsize" => $this->taskContent["fsize"],
|
||||
);
|
||||
|
||||
$addAction = FileManage::addFile($jsonData,$policyData,$this->taskModel["uid"],$this->taskContent["picInfo"]);
|
||||
if(!$addAction[0]){
|
||||
$this->setError($addAction[1],true,"/me/drive/root:/".$this->taskContent["savePath"]."/".rawurlencode($this->taskContent["objname"]),$onedrive);
|
||||
$this->cleanTmpFile();
|
||||
|
||||
Db::name("task")->where("id",$this->taskModel["id"])->update(["status"=>"error|".$this->errorMsg]);
|
||||
|
||||
return ["error"=>true,"msg"=>$this->errorMsg];
|
||||
}
|
||||
$this->cleanTmpFile();
|
||||
if($this->taskModel["type"] == "UploadLargeRemoteDownloadFileToOnedrive" || $this->taskModel["type"] == "uploadChunksToOnedrive"){
|
||||
$this->cleanTmpChunk();
|
||||
}
|
||||
Db::name("task")->where("id",$this->taskModel["id"])->update(["status"=>"complete"]);
|
||||
return ["error"=>false,"msg"=>null];
|
||||
}
|
||||
|
||||
public function Error(){
|
||||
$this->taskContent = json_decode($this->taskModel["attr"],true);
|
||||
$policyData = Db::name("policy")->where("id",$this->taskContent["policyId"])->find();
|
||||
$this->policyModel = $policyData;
|
||||
$onedrive = new Client([
|
||||
'stream_back_end' => \Krizalys\Onedrive\StreamBackEnd::TEMP,
|
||||
'client_id' => $policyData["bucketname"],
|
||||
|
||||
// Restore the previous state while instantiating this client to proceed in
|
||||
// obtaining an access token.
|
||||
'state' => json_decode($policyData["sk"]),
|
||||
]);
|
||||
$this->setError("",false,"/me/drive/root:/".$this->taskContent["savePath"]."/".rawurlencode($this->taskContent["objname"]),$onedrive);
|
||||
$this->cleanTmpFile();
|
||||
if($this->taskModel["type"] == "UploadLargeRemoteDownloadFileToOnedrive" || $this->taskModel["type"] == "uploadChunksToOnedrive"){
|
||||
$this->cleanTmpChunk();
|
||||
}
|
||||
Db::name("task")->where("id",$this->taskModel["id"])->update(["status"=>"error"]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -20,15 +20,16 @@ class TwoFactor extends Model{
|
||||
|
||||
public function qrcodeRender(){
|
||||
ob_end_clean();
|
||||
header("content-type: image/png");
|
||||
$this->secretKey = $this->ga->createSecret();
|
||||
$qrCode = new QrCode();
|
||||
session("two_factor_enable",$this->secretKey);
|
||||
$qrCode->setText(urldecode($this->ga->getQRCodeGoogleUrl(Option::getValue("siteName"), $this->secretKey)))
|
||||
->setPadding(5)
|
||||
->render();
|
||||
$qrCode = new QrCode(urldecode(str_replace("https://chart.googleapis.com/chart?chs=200x200&chld=M|0&cht=qr&chl=","",$this->ga->getQRCodeGoogleUrl(Option::getValue("siteName"), $this->secretKey))));
|
||||
$qrCode->setSize(165);
|
||||
$qrCode->setMargin(0);
|
||||
header('Content-Type: '.$qrCode->getContentType());
|
||||
echo $qrCode->writeString();
|
||||
}
|
||||
|
||||
|
||||
public function confirmCode($key,$code){
|
||||
$this->secretKey = $key;
|
||||
if(empty($code)){
|
||||
@@ -50,4 +51,4 @@ class TwoFactor extends Model{
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
||||
?>
|
||||
|
||||
@@ -8,6 +8,7 @@ use think\Db;
|
||||
use Qiniu\Auth;
|
||||
use \app\index\model\Option;
|
||||
use \app\index\model\FileManage;
|
||||
use \app\index\model\Task;
|
||||
|
||||
class UploadHandler extends Model{
|
||||
|
||||
@@ -57,7 +58,7 @@ class UploadHandler extends Model{
|
||||
$this->setError("空间容量不足",false);
|
||||
}
|
||||
FileManage::storageCheckOut($this->userId,$chunkSize);
|
||||
if($chunkSize >=4195304){
|
||||
if($chunkSize >config('upload.chunk_size')){
|
||||
$this->setError("分片错误",false);
|
||||
}
|
||||
$chunkObj=fopen (ROOT_PATH . 'public/uploads/chunks/'.$this->chunkData["obj_name"].".chunk","w+");
|
||||
@@ -75,13 +76,25 @@ class UploadHandler extends Model{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 组合分片并生成最终文件
|
||||
*
|
||||
* @param array $ctx 文件片校验码
|
||||
* @param string $fname 最终文件名
|
||||
* @param string $path 储存目录
|
||||
* @return void
|
||||
*/
|
||||
public function generateFile($ctx,$fname,$path){
|
||||
$ctxTmp = explode(",",$ctx);
|
||||
$chunks = Db::name('chunks')->where([
|
||||
'ctx' => ["in",$ctxTmp],
|
||||
])->order('id asc')->select();
|
||||
$file = $this->combineChunks($chunks);
|
||||
$this->filterCheck($file,$fname);
|
||||
$file = null;
|
||||
if($this->policyContent["policy_type"] != "onedrive"){
|
||||
$file = $this->combineChunks($chunks);
|
||||
}
|
||||
|
||||
$this->filterCheck($file,$fname,$chunks);
|
||||
$suffixTmp = explode('.', $fname);
|
||||
$fileSuffix = array_pop($suffixTmp);
|
||||
if($this->policyContent['autoname']){
|
||||
@@ -95,28 +108,67 @@ class UploadHandler extends Model{
|
||||
if(file_exists($savePath.DS.$fileName)){
|
||||
$this->setError("文件重名",true,$file,ROOT_PATH . 'public/uploads/chunks/');
|
||||
}
|
||||
if(!@rename(ROOT_PATH . 'public/uploads/chunks/'.$file,$savePath.DS.$fileName)){
|
||||
$this->setError("文件创建失败",true,$file,ROOT_PATH . 'public/uploads/chunks/');
|
||||
}else{
|
||||
if($this->policyContent["policy_type"] == "onedrive"){
|
||||
if($path == "ROOTDIR"){
|
||||
$path = "";
|
||||
}
|
||||
$jsonData = array(
|
||||
$task = new Task();
|
||||
$task->taskName = "Upload Big File " . $fname . " to Onedrive";
|
||||
$task->taskType = "uploadChunksToOnedrive";
|
||||
$task->taskContent = json_encode([
|
||||
"path" => $path,
|
||||
"fname" => $fname,
|
||||
"objname" => $generatePath."/".$fileName,
|
||||
"objname" => $fileName,
|
||||
"savePath" => $generatePath,
|
||||
"fsize" => $this->fileSizeTmp,
|
||||
);
|
||||
$addAction = FileManage::addFile($jsonData,$this->policyContent,$this->userId);
|
||||
"picInfo" => "",
|
||||
"chunks" => $chunks,
|
||||
"policyId" => $this->policyContent['id']
|
||||
]);
|
||||
$task->userId = $this->userId;
|
||||
$task->saveTask();
|
||||
echo json_encode(array("key" => $fname));
|
||||
}else{
|
||||
if(!@rename(ROOT_PATH . 'public/uploads/chunks/'.$file,$savePath.DS.$fileName)){
|
||||
$this->setError("文件创建失败",true,$file,ROOT_PATH . 'public/uploads/chunks/');
|
||||
}else{
|
||||
if($path == "ROOTDIR"){
|
||||
$path = "";
|
||||
}
|
||||
$jsonData = array(
|
||||
"path" => $path,
|
||||
"fname" => $fname,
|
||||
"objname" => $generatePath."/".$fileName,
|
||||
"fsize" => $this->fileSizeTmp,
|
||||
);
|
||||
@list($width, $height, $type, $attr) = getimagesize($savePath.DS.$fileName);
|
||||
$picInfo = empty($width)?" ":$width.",".$height;
|
||||
$addAction = FileManage::addFile($jsonData,$this->policyContent,$this->userId,$picInfo);
|
||||
if(!$addAction[0]){
|
||||
$this->setError($addAction[1],true,$fileName,$savePath);
|
||||
}
|
||||
echo json_encode(array("key" => $fname));
|
||||
echo json_encode(array("key" => $fname));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function filterCheck($file,$fname){
|
||||
$fileSize = filesize(ROOT_PATH . 'public/uploads/chunks/'.$file);
|
||||
protected function countTotalChunkSize($chunks){
|
||||
$size = 0;
|
||||
foreach ($chunks as $key => $value) {
|
||||
$size += @filesize(ROOT_PATH . 'public/uploads/chunks/'.$value["obj_name"].".chunk");
|
||||
}
|
||||
|
||||
return $size;
|
||||
}
|
||||
|
||||
public function filterCheck($file,$fname,$chunks){
|
||||
if($file !=null){
|
||||
$fileSize = filesize(ROOT_PATH . 'public/uploads/chunks/'.$file);
|
||||
}else{
|
||||
$fileSize = $this->countTotalChunkSize($chunks);
|
||||
}
|
||||
|
||||
$suffixTmp = explode('.', $fname);
|
||||
$fileSuffix = array_pop($suffixTmp);
|
||||
$allowedSuffix = explode(',', self::getAllowedExt(json_decode($this->policyContent["filetype"],true)));
|
||||
@@ -131,6 +183,12 @@ class UploadHandler extends Model{
|
||||
$this->fileSizeTmp = $fileSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* 组合文件分片
|
||||
*
|
||||
* @param array $fname 文件分片数据库记录
|
||||
* @return void
|
||||
*/
|
||||
public function combineChunks($fname){
|
||||
$fileName = "file_".self::getRandomKey(8);
|
||||
$fileObj=fopen (ROOT_PATH . 'public/uploads/chunks/'.$fileName,"a+");
|
||||
@@ -140,8 +198,8 @@ class UploadHandler extends Model{
|
||||
if(!$fileObj || !$chunkObj){
|
||||
$this->setError("文件创建失败",false);
|
||||
}
|
||||
$content = fread($chunkObj, 4195304);
|
||||
fwrite($fileObj, $content, 4195304);
|
||||
$content = fread($chunkObj, config('upload.chunk_size'));
|
||||
fwrite($fileObj, $content, config('upload.chunk_size'));
|
||||
unset($content);
|
||||
fclose($chunkObj);
|
||||
unlink(ROOT_PATH . 'public/uploads/chunks/'.$value["obj_name"].".chunk");
|
||||
@@ -181,12 +239,39 @@ class UploadHandler extends Model{
|
||||
);
|
||||
@list($width, $height, $type, $attr) = getimagesize(rtrim($savePath, DS).DS.$Uploadinfo->getSaveName());
|
||||
$picInfo = empty($width)?" ":$width.",".$height;
|
||||
|
||||
//处理Onedrive等非直传
|
||||
if($this->policyContent['policy_type'] == "onedrive"){
|
||||
$task = new Task();
|
||||
$task->taskName = "Upload" . $info["name"] . " to Onedrive";
|
||||
$task->taskType = "uploadSingleToOnedrive";
|
||||
$task->taskContent = json_encode([
|
||||
"path" => $info["path"],
|
||||
"fname" => $info["name"],
|
||||
"objname" => $Uploadinfo->getSaveName(),
|
||||
"savePath" => $generatePath,
|
||||
"fsize" => $Uploadinfo->getSize(),
|
||||
"picInfo" => $picInfo,
|
||||
"policyId" => $this->policyContent['id']
|
||||
]);
|
||||
$task->userId = $this->userId;
|
||||
|
||||
$task->saveTask();
|
||||
|
||||
echo json_encode(array("key" => $info["name"]));
|
||||
FileManage::storageCheckOut($this->userId,$jsonData["fsize"],$Uploadinfo->getInfo('size'));
|
||||
return;
|
||||
}
|
||||
|
||||
//向数据库中添加文件记录
|
||||
$addAction = FileManage::addFile($jsonData,$this->policyContent,$this->userId,$picInfo);
|
||||
if(!$addAction[0]){
|
||||
$tmpFileName = $Uploadinfo->getSaveName();
|
||||
unset($Uploadinfo);
|
||||
$this->setError($addAction[1],true,$tmpFileName,$savePath);
|
||||
}
|
||||
|
||||
//扣除容量
|
||||
FileManage::storageCheckOut($this->userId,$jsonData["fsize"],$Uploadinfo->getInfo('size'));
|
||||
echo json_encode(array("key" => $info["name"]));
|
||||
}else{
|
||||
@@ -219,6 +304,9 @@ class UploadHandler extends Model{
|
||||
case 'local':
|
||||
return $this->getLocalToken();
|
||||
break;
|
||||
case 'onedrive':
|
||||
return 'nazGTT91tboaLWBC549$:tHSsNyTBxoV4HDfELJeKH1EUmEY=:eyJjYWxsYmFja0JvZHkiOiJ7XCJwYXRoXCI6XCJcIn0iLCJjYWxsYmFja0JvZHlUeXBlIjoiYXBwbGljYXRpb25cL2pzb24iLCJzY29wZSI6ImMxNjMyMTc3LTQ4NGEtNGU1OS1hZDBhLWUwNDc4ZjZhY2NjZSIsImRlYWRsaW5lIjoxNTM2ODMxOTEwfQ==';
|
||||
break;
|
||||
case 'oss':
|
||||
return $this->getOssToken();
|
||||
break;
|
||||
@@ -228,6 +316,9 @@ class UploadHandler extends Model{
|
||||
case 's3':
|
||||
return $this->getS3Token();
|
||||
break;
|
||||
case 'remote':
|
||||
return $this->getRemoteToken();
|
||||
break;
|
||||
default:
|
||||
# code...
|
||||
break;
|
||||
@@ -295,6 +386,35 @@ class UploadHandler extends Model{
|
||||
return $token;
|
||||
}
|
||||
|
||||
private function getRemoteToken(){
|
||||
$callbackKey = $this->getRandomKey();
|
||||
$sqlData = [
|
||||
'callback_key' => $callbackKey,
|
||||
'pid' => $this->policyId,
|
||||
'uid' => $this->userId
|
||||
];
|
||||
Db::name('callback')->insert($sqlData);
|
||||
$policy = array(
|
||||
'callbackUrl' =>Option::getValue("siteURL").'Callback/Remote',
|
||||
'callbackKey' => $callbackKey,
|
||||
'callbackBodyType' => 'application/json',
|
||||
'fsizeLimit' => (int)$this->policyContent['max_size'],
|
||||
'uid' => $this->userId,
|
||||
);
|
||||
$dirName = $this->getObjName($this->policyContent['dirrule']);
|
||||
if($this->policyContent["autoname"]){
|
||||
$policy = array_merge($policy,array("saveKey" => $dirName.(empty($dirName)?"":"/").$this->getObjName($this->policyContent['namerule'])));
|
||||
}else{
|
||||
$policy = array_merge($policy,array("saveKey" => $dirName.(empty($dirName)?"":"/")."$(fname)"));
|
||||
}
|
||||
if(!empty($this->policyContent['mimetype'])){
|
||||
$policy = array_merge($policy,array("mimeLimit" => $this->policyContent['mimetype']));
|
||||
}
|
||||
$signingKey = hash_hmac("sha256",json_encode($policy),"UPLOAD".$this->policyContent['sk']);
|
||||
$token = $signingKey. ":" .base64_encode(json_encode($policy));
|
||||
return $token;
|
||||
}
|
||||
|
||||
static function upyunSign($key, $secret, $method, $uri, $date, $policy=null, $md5=null){
|
||||
$elems = array();
|
||||
foreach (array($method, $uri, $date, $policy, $md5) as $v){
|
||||
|
||||
@@ -0,0 +1,162 @@
|
||||
<?php
|
||||
namespace app\index\model;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
|
||||
use Upyun\Upyun;
|
||||
use Upyun\Config;
|
||||
|
||||
use \app\index\model\Option;
|
||||
|
||||
/**
|
||||
* 又拍云策略文件管理适配器
|
||||
*/
|
||||
class UpyunAdapter extends Model{
|
||||
|
||||
private $fileModel;
|
||||
private $policyModel;
|
||||
private $userModel;
|
||||
|
||||
public function __construct($file,$policy,$user){
|
||||
$this->fileModel = $file;
|
||||
$this->policyModel = $policy;
|
||||
$this->userModel = $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取又拍云策略文本文件内容
|
||||
*
|
||||
* @return string 文件内容
|
||||
*/
|
||||
public function getFileContent(){
|
||||
return file_get_contents($this->Preview()[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 签名又拍云预览URL
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function Preview($base=null,$name=null){
|
||||
if($base===true || $base===false){
|
||||
$base =null;
|
||||
}
|
||||
if(!$this->policyModel['bucket_private']){
|
||||
$fileUrl = $this->policyModel["url"].$this->fileModel["pre_name"]."?auth=0";
|
||||
if(!empty($base)){
|
||||
$fileUrl = $base;
|
||||
}
|
||||
return[true,$fileUrl];
|
||||
}else{
|
||||
$baseUrl = $this->policyModel["url"].$this->fileModel["pre_name"];
|
||||
if(!empty($base)){
|
||||
$baseUrl = $base;
|
||||
}
|
||||
$etime = time() + Option::getValue("timeout");
|
||||
$key = $this->policyModel["sk"];
|
||||
$path = "/".$this->fileModel["pre_name"];
|
||||
if(!empty($name)){
|
||||
$path = "/".$name;
|
||||
}
|
||||
$sign = substr(md5($key.'&'.$etime.'&'.$path), 12, 8).$etime;
|
||||
$signedUrl = $baseUrl."?_upt=".$sign;
|
||||
return[true,$signedUrl];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存文件内容
|
||||
*
|
||||
* @param string $content 文件内容
|
||||
* @return void
|
||||
*/
|
||||
public function saveContent($content){
|
||||
$bucketConfig = new Config($this->policyModel["bucketname"], $this->policyModel["op_name"], $this->policyModel["op_pwd"]);
|
||||
$client = new Upyun($bucketConfig);
|
||||
if(empty($content)){
|
||||
$content = " ";
|
||||
}
|
||||
$res=$client->write($this->fileModel["pre_name"],$content);
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算缩略图大小
|
||||
*
|
||||
* @param int $width 原始宽
|
||||
* @param int $height 原始高
|
||||
* @return array
|
||||
*/
|
||||
static function getThumbSize($width,$height){
|
||||
$rate = $width/$height;
|
||||
$maxWidth = 90;
|
||||
$maxHeight = 39;
|
||||
$changeWidth = 39*$rate;
|
||||
$changeHeight = 90/$rate;
|
||||
if($changeWidth>=$maxWidth){
|
||||
return [(int)$changeHeight,90];
|
||||
}
|
||||
return [39,(int)$changeWidth];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取缩略图地址
|
||||
*
|
||||
* @return string 缩略图地址
|
||||
*/
|
||||
public function getThumb(){
|
||||
$picInfo = explode(",",$this->fileModel["pic_info"]);
|
||||
$thumbSize = self::getThumbSize($picInfo[0],$picInfo[1]);
|
||||
$baseUrl =$this->policyModel["url"].$this->fileModel["pre_name"]."!/fwfh/90x39";
|
||||
return [1,$this->Preview($baseUrl,$this->fileModel["pre_name"]."!/fwfh/90x39")[1]];
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除某一策略下的指定upyun文件
|
||||
*
|
||||
* @param array $fileList 待删除文件的数据库记录
|
||||
* @param array $policyData 待删除文件的上传策略信息
|
||||
* @return void
|
||||
*/
|
||||
static function DeleteFile($fileList,$policyData){
|
||||
foreach (array_column($fileList, 'pre_name') as $key => $value) {
|
||||
self::deleteUpyunFile($value,$policyData);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成文件下载URL
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function Download(){
|
||||
return [true,$this->Preview()[1]."&_upd=".urlencode($this->fileModel["orign_name"])];
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除临时文件
|
||||
*
|
||||
* @param string $fname 文件名
|
||||
* @param array $policy 上传策略信息
|
||||
* @return boolean
|
||||
*/
|
||||
static function deleteUpyunFile($fname,$policy){
|
||||
$bucketConfig = new Config($policy["bucketname"], $policy["op_name"], $policy["op_pwd"]);
|
||||
$client = new Upyun($bucketConfig);
|
||||
$res=$client->delete($fname,true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 签名临时URL用于Office预览
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function signTmpUrl(){
|
||||
return $this->Preview();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -3,8 +3,6 @@ namespace app\index\model;
|
||||
|
||||
use think\Model;
|
||||
use think\Db;
|
||||
use \think\Session;
|
||||
use \think\Cookie;
|
||||
use \app\index\model\Option;
|
||||
use \app\index\model\Mail;
|
||||
use think\Validate;
|
||||
@@ -87,7 +85,7 @@ class User extends Model{
|
||||
* @return [type] [description]
|
||||
*/
|
||||
static function register($userEmail,$userPass,$captchaCode){
|
||||
if(Option::getValue("login_captcha")=="1"){
|
||||
if(Option::getValue("reg_captcha")=="1"){
|
||||
if(!self::checkCaptcha($captchaCode)){
|
||||
return [false,"验证码错误"];
|
||||
}
|
||||
@@ -97,7 +95,7 @@ class User extends Model{
|
||||
}
|
||||
$userName = str_replace(" ", "", $userEmail);
|
||||
$passWord = $userPass;
|
||||
if ( !filter_var($userName,FILTER_VALIDATE_EMAIL) || (mb_strlen($userName,'UTF8')>22) || (mb_strlen($userName,'UTF8')<4) || (mb_strlen($passWord,'UTF8')>64) || (mb_strlen($passWord,'UTF8')<4)){
|
||||
if ( !filter_var($userName,FILTER_VALIDATE_EMAIL) || (mb_strlen($userName,'UTF8')>32) || (mb_strlen($userName,'UTF8')<4) || (mb_strlen($passWord,'UTF8')>64) || (mb_strlen($passWord,'UTF8')<4)){
|
||||
return [false,"邮箱或密码不符合规范"];
|
||||
}
|
||||
if(Db::name('users')->where('user_email',$userName)->find() !=null){
|
||||
@@ -127,6 +125,7 @@ class User extends Model{
|
||||
'delay_time' =>0,
|
||||
'avatar' => "default",
|
||||
'profile' => true,
|
||||
'options' => "{}",
|
||||
];
|
||||
if(Db::name('users')->insert($sqlData)){
|
||||
$userId = Db::name('users')->getLastInsID();
|
||||
@@ -193,7 +192,7 @@ class User extends Model{
|
||||
}
|
||||
|
||||
static function findPwd($email,$captchaCode){
|
||||
if(Option::getValue("login_captcha")=="1"){
|
||||
if(Option::getValue("forget_captcha")=="1"){
|
||||
if(!self::checkCaptcha($captchaCode)){
|
||||
return [false,"验证码错误"];
|
||||
}
|
||||
@@ -308,23 +307,23 @@ class User extends Model{
|
||||
|
||||
public function getMemory($notEcho = false){
|
||||
$usedMemory = $this->userSQLData["used_storage"];
|
||||
$groupStorage = (int)$this->groupData["max_storage"];
|
||||
$packetStorage = (int)Db::name('storage_pack')
|
||||
$groupStorage = $this->groupData["max_storage"];
|
||||
$packetStorage = Db::name('storage_pack')
|
||||
->where('uid',$this->uid)
|
||||
->where('dlay_time',">",time())
|
||||
->sum('pack_size');
|
||||
$returnData["used"] = self::countSize((int)$usedMemory);
|
||||
$returnData["used"] = self::countSize($usedMemory);
|
||||
$returnData["total"] = self::countSize($groupStorage+$packetStorage);
|
||||
$returnData["rate"] = floor((int)$usedMemory/($groupStorage+$packetStorage)*100);
|
||||
$returnData["basic"] = self::countSize((int)$groupStorage);
|
||||
$returnData["pack"] = self::countSize((int)$packetStorage);
|
||||
$returnData["rate"] = floor($usedMemory/($groupStorage+$packetStorage)*100);
|
||||
$returnData["basic"] = self::countSize($groupStorage);
|
||||
$returnData["pack"] = self::countSize($packetStorage);
|
||||
if($usedMemory > $groupStorage){
|
||||
$returnData["r1"] = floor((int)$usedMemory/($groupStorage+$packetStorage)*100);
|
||||
$returnData["r1"] = floor($usedMemory/($groupStorage+$packetStorage)*100);
|
||||
$returnData["r2"] = 0;
|
||||
$returnData["r3"] = 100-$returnData["r1"];
|
||||
}else{
|
||||
$returnData["r1"] = floor((int)$usedMemory/($groupStorage+$packetStorage)*100);
|
||||
$returnData["r2"] = floor(((int)$groupStorage-$usedMemory)/($groupStorage+$packetStorage)*100);;
|
||||
$returnData["r1"] = floor($usedMemory/($groupStorage+$packetStorage)*100);
|
||||
$returnData["r2"] = floor(($groupStorage-$usedMemory)/($groupStorage+$packetStorage)*100);;
|
||||
$returnData["r3"] = 100-$returnData["r1"]-$returnData["r2"];
|
||||
}
|
||||
if($notEcho){
|
||||
@@ -355,6 +354,13 @@ class User extends Model{
|
||||
}
|
||||
}
|
||||
|
||||
public function changeOption($optionKey,$optionValue){
|
||||
$options = json_decode($this->userSQLData["options"],true);
|
||||
$options[$optionKey] = $optionValue;
|
||||
Db::name("users")->where("id",$this->uid)->update(["options" => json_encode($options)]);
|
||||
return [1,1];
|
||||
}
|
||||
|
||||
public function changePwd($origin,$new){
|
||||
if(md5(config('salt').$origin) != $this->userSQLData["user_pass"]){
|
||||
return [0,"原密码错误"];
|
||||
|
||||
@@ -113,6 +113,18 @@
|
||||
<div class="col-md-4 option-des"> 是否允许用户使用WebDAV协议同步文件。目前此功能仅支持本地上传方案</div>
|
||||
</div>
|
||||
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="colFormLabelSm" class="col-form-label col-form-label-sm">离线下载</label>
|
||||
</div>
|
||||
<div class="col-md-4"> <input class="" type="radio" name="aria2" value="1" id="webdav1" >
|
||||
<label class="" for="webdav1" >允许</label>
|
||||
|
||||
<input class="" type="radio" name="aria2" id="webdav0" value="0" checked>
|
||||
<label class="" for="webdav0">禁止</label></div>
|
||||
<div class="col-md-4 option-des"> 是否允许用户使用离线下载。此功能仅支持本地存储策略,开启前需要到离线下载管理页面设置Aria2接口</div>
|
||||
</div>
|
||||
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="colFormLabelSm" class="col-form-label col-form-label-sm">用户组标志色</label>
|
||||
|
||||
@@ -67,11 +67,31 @@
|
||||
<img class="card-img-top" src="/static/img/s3.png" alt="Card image cap">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Amazon S3</h5>
|
||||
<p class="card-text"><a href="https://aws.amazon.com/cn/s3/?nc1=h_ls" target="_blank">Amazon S3</a>专为从任意位置存储和检索任意数量的数据而构建的对象存储</p>
|
||||
<p class="card-text"><a href="https://aws.amazon.com/cn/s3/?nc1=h_ls" target="_blank">Amazon S3</a>专为数据而构建的对象存储</p>
|
||||
<a href="/Admin/PolicyAddS3" class="btn btn-primary">添加</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 mt-2 md-2">
|
||||
<div class="card cloud">
|
||||
<img class="card-img-top" src="/static/img/remote.png" alt="Card image cap">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">远程服务器</h5>
|
||||
<p class="card-text">你可以将文件存放在不同于主程序的服务器上。<a href="https://github.com/HFO4/Cloudreve/wiki/%E8%BF%9C%E7%A8%8B%E5%AD%98%E5%82%A8%E6%9C%8D%E5%8A%A1%E7%AB%AF%E6%90%AD%E5%BB%BA">配置说明</a></p>
|
||||
<a href="/Admin/PolicyAddRemote" class="btn btn-primary">添加</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3 mt-2 md-2">
|
||||
<div class="card cloud">
|
||||
<img class="card-img-top" src="/static/img/onedrive.png" alt="Card image cap">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">Onedrive <span class="badge badge-warning">中转</span></h5>
|
||||
<p class="card-text">支持 Onedrive Bussiness 和个人版。<a href="https://github.com/HFO4/Cloudreve/wiki/Onedrive%E5%AF%B9%E6%8E%A5%E8%AF%B4%E6%98%8E">配置说明</a></p>
|
||||
<a href="/Admin/PolicyAddOnedrive" class="btn btn-primary">添加</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -430,7 +450,7 @@
|
||||
<label for="url" class="col-form-label col-form-label-sm">空间域名</label>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<input type="text" class="form-control" name="url" required>
|
||||
<input type="text" class="form-control" name="url" value="http(s)://" required>
|
||||
</div>
|
||||
<div class="col-md-4 option-des"> OSS空间绑定的域名,用于文件下载、访问,结尾要加"/"(推荐配合阿里云CDN使用,此处填写CDN域名)</div>
|
||||
</div>
|
||||
@@ -440,7 +460,7 @@
|
||||
<label for="server" class="col-form-label col-form-label-sm">上传域名</label>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<input type="text" class="form-control" name="server" required>
|
||||
<input type="text" class="form-control" name="server" value="http(s)://" required>
|
||||
</div>
|
||||
<div class="col-md-4 option-des"> OSS空间的域名,一般与上一项保持一致。(如果上一项填写的是CDN域名,则此处与上一项不应相同)</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
{extend name="header_admin" /}
|
||||
{block name="title"}添加上传策略- {$options.siteName}{/block}
|
||||
{block name="content"}
|
||||
<div class="content-wrapper">
|
||||
<div class="container-fluid">
|
||||
<!-- Breadcrumbs-->
|
||||
<ol class="breadcrumb">
|
||||
<li class="breadcrumb-item">
|
||||
<a href="/Admin">管理面板</a>
|
||||
</li>
|
||||
<li class="breadcrumb-item">
|
||||
<a href="/Admin/PolicyAdd">上传策略</a>
|
||||
</li>
|
||||
<li class="breadcrumb-item active">添加</li>
|
||||
</ol>
|
||||
|
||||
<!-- Area Chart Example-->
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h2>添加上传策略</h2>
|
||||
<br>
|
||||
|
||||
<div class="alert alert-warning" role="alert">
|
||||
<strong>添加Onedrive上传策略前请确保阅读完下面内容!</strong>
|
||||
<ul>
|
||||
<li>Onedrive策略无法直传,上传文件时,Cloudreve会先将文件暂存在服务器,之后再由任务队列上传至Onedrive;</li>
|
||||
<li>使用本策略前,请先配置并运行<a href="https://github.com/HFO4/Cloudreve/wiki/Onedrive%E5%AF%B9%E6%8E%A5%E8%AF%B4%E6%98%8E">Cloudreve任务队列</a>,否则正常无法使用;</li>
|
||||
<li>用户上传文件后不能立马看到所上传的文件,需要等待任务队列处理完毕;</li>
|
||||
<li>请确保已经正确配置好Cloudreve的Cron定时任务,以便用于刷新AccessToken信息。</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="card" id="s3" >
|
||||
<div class="card-header">
|
||||
添加Onedrive上传策略
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form id="onedrivePolicy">
|
||||
<input type="text" class="form-control" name="policy_type" value="onedrive" style="display: none">
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="policy_name" class="col-form-label col-form-label-sm">上传策略名称</label>
|
||||
</div>
|
||||
<div class="col-md-4"> <input type="text" class="form-control" name="policy_name" required></div>
|
||||
<div class="col-md-4 option-des"> 上传策略的名称,用于区别不同策略</div>
|
||||
</div>
|
||||
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="bucketname" class="col-form-label col-form-label-sm">应用 ID(Client ID) </label>
|
||||
</div>
|
||||
<div class="col-md-4"> <input type="text" class="form-control" name="bucketname" required></div>
|
||||
<div class="col-md-4 option-des"> 请<a href="https://apps.dev.microsoft.com/?referrer=https%3a%2f%2fdeveloper.microsoft.com%2fzh-CN%2fgraph%2fquick-start#/quickstart/graphIO?publicClientSupport=false&appName=Cloudreve&redirectUrl={:urlencode($options.siteURL)}Admin%2FoneDriveCalllback&allowImplicitFlow=false&ru=https:%2F%2Fdeveloper.microsoft.com%2Fzh-CN%2Fgraph%2Fquick-start%3FappID%3D_appId_%26appName%3D_appName_%26redirectUrl%3D{$options.siteURL}Admin/oneDriveCalllback%26platform%3Doption-php" target="_blank">点击这里</a>获取下一步要用到的应用机密和此处的应用ID</div>
|
||||
</div>
|
||||
|
||||
<input type="text" class="form-control" name="sk" value="0" style="display: none" required>
|
||||
|
||||
<input type="text" name="bucket_private" value="1" style="display: none">
|
||||
<input type="text" name="origin_link" value="0" style="display: none">
|
||||
<input type="text" name="url" value="0" style="display: none">
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="url" class="col-form-label col-form-label-sm">应用机密(密码/公钥)</label>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<input type="text" class="form-control" name="ak" required>
|
||||
</div>
|
||||
<div class="col-md-4 option-des"> 同上一项一起获取</div>
|
||||
</div>
|
||||
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="filetype" class="col-form-label col-form-label-sm">单文件最大大小</label>
|
||||
</div>
|
||||
<div class="col-md-4 input-group mb-3">
|
||||
<input type="number" class="form-control" name="max_size" spellcheck="false" min="0" value="10" required>
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text" id="basic-addon2">
|
||||
<select name="sizeTimes" class="selectIn">
|
||||
<option value="1">B</option>
|
||||
<option value="1024">KB</option>
|
||||
<option value="1048576" selected>MB</option>
|
||||
<option value="1073741824">GB</option>
|
||||
</select>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4 option-des"> 允许上传的单个文件的最大尺寸</div>
|
||||
</div>
|
||||
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="filetype" class="col-form-label col-form-label-sm">文件重命名</label>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<input class="" type="radio" name="autoname" id="autoname1" value="1" checked>
|
||||
<label class="" for="autoname1" >开启</label>
|
||||
|
||||
<input class="" type="radio" name="autoname" id="autoname2" value="0" >
|
||||
<label class="" for="autoname2">关闭</label>
|
||||
</div>
|
||||
<div class="col-md-4 option-des"> 是否对存储的文件自动重命名。推荐开启,重命名不会影响用户端文件名展示,开启后可以避免文件重名</div>
|
||||
</div>
|
||||
<div class="row form-setting" id="autoname_form" >
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="url" class="col-form-label col-form-label-sm">重命名规则</label>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<input type="text" class="form-control" name="namerule" value="{uid}_{randomkey8}_{originname}" spellcheck="false" required>
|
||||
</div>
|
||||
<div class="col-md-4 option-des"> 你可以使用变量对照表中的字段填写</div>
|
||||
</div>
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="filetype" class="col-form-label col-form-label-sm">存储目录</label>
|
||||
</div>
|
||||
<div class="col-md-4 input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text" id="basic-addon2">
|
||||
Onedrive根目录
|
||||
</span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="dirrule" spellcheck="false" value="{date}/{uid}" required>
|
||||
</div>
|
||||
<div class="col-md-4 option-des"> 文件存放的目录,你可以使用目录变量对照表中的字段填写</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
</div>
|
||||
<div class="col-md-4"> <button type="submit" class="btn btn-primary" id="saveQiniu">保存并继续</button></div>
|
||||
<div class="col-md-4 option-des"> </div>
|
||||
<br> <br>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<bn>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Example DataTables Card-->
|
||||
</div>
|
||||
<!-- /.container-fluid-->
|
||||
</div>
|
||||
|
||||
{/block}
|
||||
{block name="js"}
|
||||
<script src="/static/js/admin/add_policy.js"></script>
|
||||
{/block}
|
||||
@@ -0,0 +1,170 @@
|
||||
{extend name="header_admin" /}
|
||||
{block name="title"}添加上传策略- {$options.siteName}{/block}
|
||||
{block name="content"}
|
||||
<div class="content-wrapper">
|
||||
<div class="container-fluid">
|
||||
<!-- Breadcrumbs-->
|
||||
<ol class="breadcrumb">
|
||||
<li class="breadcrumb-item">
|
||||
<a href="/Admin">管理面板</a>
|
||||
</li>
|
||||
<li class="breadcrumb-item">
|
||||
<a href="/Admin/PolicyAdd">上传策略</a>
|
||||
</li>
|
||||
<li class="breadcrumb-item active">添加</li>
|
||||
</ol>
|
||||
|
||||
<!-- Area Chart Example-->
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h2>添加上传策略</h2>
|
||||
<br>
|
||||
|
||||
|
||||
<div class="card" id="s3" >
|
||||
<div class="card-header">
|
||||
添加远程上传策略
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form id="qiniuPolicy">
|
||||
<input type="text" class="form-control" name="policy_type" value="remote" style="display: none">
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="policy_name" class="col-form-label col-form-label-sm">上传策略名称</label>
|
||||
</div>
|
||||
<div class="col-md-4"> <input type="text" class="form-control" name="policy_name" required></div>
|
||||
<div class="col-md-4 option-des"> 上传策略的名称,用于区别不同策略</div>
|
||||
</div>
|
||||
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="ak" class="col-form-label col-form-label-sm">AccessToken </label>
|
||||
</div>
|
||||
<div class="col-md-4"> <input type="text" class="form-control" name="sk" required></div>
|
||||
<div class="col-md-4 option-des"> 默认随机生成,请与远程服务端配置文件中保持一致</div>
|
||||
</div>
|
||||
|
||||
<input type="text" class="form-control" name="ak" value="0" style="display: none" required>
|
||||
|
||||
<input type="text" name="bucket_private" value="1" style="display: none">
|
||||
<input type="text" name="origin_link" value="0" style="display: none">
|
||||
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="url" class="col-form-label col-form-label-sm">服务端URL</label>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<input type="text" class="form-control" name="server" required>
|
||||
</div>
|
||||
<div class="col-md-4 option-des"> 结尾要加"/"</div>
|
||||
</div>
|
||||
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="url" class="col-form-label col-form-label-sm">下载根URL</label>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<input type="text" class="form-control" name="url" required>
|
||||
</div>
|
||||
<div class="col-md-4 option-des"> 一般与上一步保持一致,结尾要加"/"</div>
|
||||
</div>
|
||||
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="filetype" class="col-form-label col-form-label-sm">单文件最大大小</label>
|
||||
</div>
|
||||
<div class="col-md-4 input-group mb-3">
|
||||
<input type="number" class="form-control" name="max_size" spellcheck="false" min="0" value="10" required>
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text" id="basic-addon2">
|
||||
<select name="sizeTimes" class="selectIn">
|
||||
<option value="1">B</option>
|
||||
<option value="1024">KB</option>
|
||||
<option value="1048576" selected>MB</option>
|
||||
<option value="1073741824">GB</option>
|
||||
</select>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4 option-des"> 允许上传的单个文件的最大尺寸</div>
|
||||
</div>
|
||||
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="filetype" class="col-form-label col-form-label-sm">文件重命名</label>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<input class="" type="radio" name="autoname" id="autoname1" value="1" checked>
|
||||
<label class="" for="autoname1" >开启</label>
|
||||
|
||||
<input class="" type="radio" name="autoname" id="autoname2" value="0" >
|
||||
<label class="" for="autoname2">关闭</label>
|
||||
</div>
|
||||
<div class="col-md-4 option-des"> 是否对存储的文件自动重命名。推荐开启,重命名不会影响用户端文件名展示,开启后可以避免文件重名</div>
|
||||
</div>
|
||||
<div class="row form-setting" id="autoname_form" >
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="url" class="col-form-label col-form-label-sm">重命名规则</label>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<input type="text" class="form-control" name="namerule" value="{uid}_{randomkey8}_{originname}" spellcheck="false" required>
|
||||
</div>
|
||||
<div class="col-md-4 option-des"> 你可以使用变量对照表中的字段填写</div>
|
||||
</div>
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="filetype" class="col-form-label col-form-label-sm">存储目录</label>
|
||||
</div>
|
||||
<div class="col-md-4 input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text" id="basic-addon2">
|
||||
/public/uploads/
|
||||
</span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="dirrule" spellcheck="false" value="{date}/{uid}" required>
|
||||
</div>
|
||||
<div class="col-md-4 option-des"> 文件存放的目录,你可以使用目录变量对照表中的字段填写</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
</div>
|
||||
<div class="col-md-4"> <button type="submit" class="btn btn-primary" id="saveQiniu">保存设置</button></div>
|
||||
<div class="col-md-4 option-des"> </div>
|
||||
<br> <br>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<bn>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<br>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Example DataTables Card-->
|
||||
</div>
|
||||
<!-- /.container-fluid-->
|
||||
</div>
|
||||
|
||||
{/block}
|
||||
{block name="js"}
|
||||
<script src="/static/js/admin/add_policy.js"></script>
|
||||
<script type="text/javascript">
|
||||
function randomString(len) {
|
||||
len = len || 32;
|
||||
var $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
|
||||
var maxPos = $chars.length;
|
||||
var pwd = '';
|
||||
for (i = 0; i < len; i++) {
|
||||
pwd += $chars.charAt(Math.floor(Math.random() * maxPos));
|
||||
}
|
||||
return pwd;
|
||||
}
|
||||
$("[name='sk']").val(randomString(32));
|
||||
</script>
|
||||
{/block}
|
||||
@@ -11,7 +11,14 @@
|
||||
<li class="breadcrumb-item active">数据概况</li>
|
||||
</ol>
|
||||
<!-- Icon Cards-->
|
||||
{eq name="isCronOk" value="true"}
|
||||
{else/}
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<strong>警告!Cron定时任务疑似未执行</strong><p>检测到<a href="/Admin/Cron">定时任务</a>未正常执行,请检查您的定时任务配置。您可以通过Crontab或者其他网站监控服务,让 “您的域名/Cron” 此地址每隔一段时间被访问一次。</p>
|
||||
</div>
|
||||
{/eq}
|
||||
<div class="row">
|
||||
|
||||
<div class="col-xl-3 col-sm-6 mb-3">
|
||||
<div class="card text-white bg-primary o-hidden h-100">
|
||||
<div class="card-body">
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
{extend name="header_admin" /}
|
||||
{block name="title"}基础设置- {$options.siteName}{/block}
|
||||
{block name="content"}
|
||||
<div class="content-wrapper">
|
||||
<div class="container-fluid">
|
||||
<!-- Breadcrumbs-->
|
||||
<ol class="breadcrumb">
|
||||
<li class="breadcrumb-item">
|
||||
<a href="/Admin">管理面板</a>
|
||||
</li>
|
||||
<li class="breadcrumb-item active">配色方案</li>
|
||||
</ol>
|
||||
|
||||
<!-- Area Chart Example-->
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h2>配色方案</h2>
|
||||
<div class="alert alert-primary" role="alert">
|
||||
<ul>
|
||||
<li>你可以使用<a href="https://theme.cloudreve.org">Cloudreve配色工具</a>创建配色,并将生成的配置信息填写在下方;</li>
|
||||
<li>主色调为不同配色的区分标识,请不要创建主色调相同的配色方案。</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-9">
|
||||
<form id="colorForm">
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="colFormLabelSm" class="col-form-label col-form-label-sm">默认配色方案</label>
|
||||
</div>
|
||||
<div class="col-md-4"><select class="form-control" name="header">
|
||||
{volist name="colors" id="theme"}
|
||||
<option value="{$key}" {eq name="optionsForSet.defaultTheme" value="$key"}selected{/eq}>{$key}</option>
|
||||
{/volist}
|
||||
|
||||
</select></div>
|
||||
</div>
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="colFormLabelSm" class="col-form-label col-form-label-sm">可选配色方案</label>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<table class="table" id="colorTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">主色调</th>
|
||||
<th scope="col">颜色配置</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{volist name="colors" id="theme"}
|
||||
<tr>
|
||||
<th scope="row" style="color:{$key}">{$key}
|
||||
<br><button id="removeRow" type="button" data-action="removeRow" class="btn btn-default">删除</button>
|
||||
</th>
|
||||
<td><textarea class="form-control" rows="4" name="color[]">{:json_encode($theme)}</textarea></td>
|
||||
</tr>
|
||||
{/volist}
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
<div style="text-align:right;"><button id="addRow" type="button" class="btn btn-default">增加一行</button></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
</div>
|
||||
<div class="col-md-4"> <button type="button" class="btn btn-primary" id="saveColor">保存设置</button></div>
|
||||
<div class="col-md-4 option-des"> </div>
|
||||
<br> <br>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
<br><br>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="file_side">
|
||||
<div class="nav flex-column nav-pills" id="v-pills-tab" role="tablist" aria-orientation="vertical">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Example DataTables Card-->
|
||||
</div>
|
||||
<!-- /.container-fluid-->
|
||||
</div>
|
||||
{/block}
|
||||
{block name="js"}
|
||||
<script src="/static/js/admin/color.js"></script>
|
||||
<script type="text/javascript">
|
||||
</script>
|
||||
{/block}
|
||||
@@ -0,0 +1,122 @@
|
||||
{extend name="header_admin" /}
|
||||
{block name="title"}离线下载 - {$options.siteName}{/block}
|
||||
{block name="content"}
|
||||
<div class="content-wrapper">
|
||||
<div class="container-fluid">
|
||||
<!-- Breadcrumbs-->
|
||||
<ol class="breadcrumb">
|
||||
<li class="breadcrumb-item">
|
||||
<a href="/Admin">管理面板</a>
|
||||
</li>
|
||||
<li class="breadcrumb-item active">离线下载</li>
|
||||
<li class="breadcrumb-item active">配置</li>
|
||||
</ol>
|
||||
|
||||
<!-- Area Chart Example-->
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h2>离线下载</h2>
|
||||
<br>
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<ul class="nav nav-tabs card-header-tabs">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" data-toggle="tab" href="#options"><i class="fa fa-cog" aria-hidden="true"></i> Aria2配置</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-toggle="tab" href="#list"><i class="fa fa-list" aria-hidden="true"></i> 任务列表</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="tab-content" >
|
||||
<div class="tab-pane fade show active" id="options" role="tabpanel" aria-labelledby="pills-home-tab">
|
||||
<form id="aria2Options">
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="fromName" class="col-form-label col-form-label-sm">RPC Server</label>
|
||||
</div>
|
||||
<div class="col-md-4"> <input type="text" class="form-control" name="aria2_rpcurl" value="{$optionsForSet.aria2_rpcurl}" spellcheck="false"></div>
|
||||
<div class="col-md-4 option-des"> aria2的RPC服务器地址,请在aria2的配置文件中启用RPC服务。例如:http://127.0.0.1:6800/</div>
|
||||
</div>
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="fromName" class="col-form-label col-form-label-sm">RPC Token</label>
|
||||
</div>
|
||||
<div class="col-md-4"> <input type="text" class="form-control" name="aria2_token" value="{$optionsForSet.aria2_token}" spellcheck="false"></div>
|
||||
<div class="col-md-4 option-des"> 在配置文件中设置的RPC服务的Token</div>
|
||||
</div>
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="fromName" class="col-form-label col-form-label-sm">下载临时目录</label>
|
||||
</div>
|
||||
<div class="col-md-4"> <input type="text" class="form-control" name="aria2_tmppath" value="{$optionsForSet.aria2_tmppath}" spellcheck="false"></div>
|
||||
<div class="col-md-4 option-des"> 下载文件数据的临时存放目录,请确保PHP对该目录拥有读写权限</div>
|
||||
</div>
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="aria2_options" class="col-form-label col-form-label-sm">其他下载参数</label>
|
||||
</div>
|
||||
<div class="col-md-4"> <textarea class="form-control" name="aria2_options" spellcheck="false">{$optionsForSet.aria2_options}</textarea></div>
|
||||
<div class="col-md-4 option-des"> aria2启动下载的其他附带参数,请以json格式书写。你可也可以将这些设置写在aria2配置文件里。可用参数请查阅<a href="https://aria2.github.io/manual/en/html/aria2c.html#options" target="_blank">官方文档</a></div>
|
||||
</div>
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
</div>
|
||||
<div class="col-md-4"> <button type="button" class="btn btn-primary" id="saveAria2">保存设置</button></div>
|
||||
<div class="col-md-4 option-des"> </div>
|
||||
<br><br><br>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade" id="list" role="tabpanel" aria-labelledby="pills-profile-tab">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" class="textCenter">#</th>
|
||||
<th scope="col" width="50%">文件名</th>
|
||||
<th scope="col" class="textCenter">创建者</th>
|
||||
<th scope="col" class="textCenter">文件大小</th>
|
||||
<th scope="col" class="textCenter">状态</th>
|
||||
<th scope="col" class="textCenter">进度</th>
|
||||
<th scope="col" class="textCenter">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="listContent">
|
||||
{volist name='list' id='download'}
|
||||
<tr id="i-{$download.id}" data-pid="{$download.pid}">
|
||||
<th scope="row" class="textCenter">{$download.id}</th>
|
||||
<td>{:is_array($originList[$key]['fileName'])?"未知":$originList[$key]['fileName']}</td>
|
||||
<td class="textCenter">{:$originList[$key]['user']["user_nick"]}</td>
|
||||
<td class="textCenter">{:countSize($download.total_size)}</td>
|
||||
<td class="textCenter">{$download.status}</td>
|
||||
<td class="textCenter">{eq name="$originList[$key]['totalLength']" value="0"}-{else/}{:floor($originList[$key]['completedLength']/$originList[$key]['totalLength']*10000)/100}%{/eq}</td>
|
||||
<td class="textCenter">{eq name="download.status" value="active"}<a href="javascript:" onclick="cancel('{$download.id}')">取消任务</a>{else/} - {/eq}</td>
|
||||
</tr>
|
||||
{/volist}
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
{$list->render()}
|
||||
</div>
|
||||
<div class="tab-pane fade" id="tools" role="tabpanel" aria-labelledby="pills-profile-tab">
|
||||
ddd
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><br>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Example DataTables Card-->
|
||||
</div>
|
||||
<!-- /.container-fluid-->
|
||||
</div>
|
||||
{/block}
|
||||
{block name="js"}
|
||||
<script src="/static/js/admin/summernote.min.js"></script>
|
||||
<script src="/static/js/admin/summernote-zh-CN.min.js"></script>
|
||||
<script src="/static/js/admin/aria2.js"></script>
|
||||
{/block}
|
||||
@@ -114,6 +114,18 @@
|
||||
<div class="col-md-4 option-des"> 是否允许用户使用WebDAV协议同步文件。目前此功能仅支持本地上传方案</div>
|
||||
</div>
|
||||
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="colFormLabelSm" class="col-form-label col-form-label-sm">离线下载</label>
|
||||
</div>
|
||||
<div class="col-md-4"> <input class="" type="radio" name="aria2" value="1" id="webdav1" >
|
||||
<label class="" for="webdav1" >允许</label>
|
||||
|
||||
<input class="" type="radio" name="aria2" id="webdav0" value="0">
|
||||
<label class="" for="webdav0">禁止</label></div>
|
||||
<div class="col-md-4 option-des"> 是否允许用户使用离线下载。此功能仅支持本地存储策略,开启前需要到离线下载管理页面设置Aria2接口</div>
|
||||
</div>
|
||||
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="colFormLabelSm" class="col-form-label col-form-label-sm">用户组标志色</label>
|
||||
@@ -162,10 +174,15 @@
|
||||
<script src="/static/js/admin/add_group.js"></script>
|
||||
<script type="text/javascript">
|
||||
$("option[value='{$group.policy_name}']").attr("selected",true);
|
||||
$("option[value='{$group.max_storage}']").attr("selected",true);
|
||||
$("option[value='{:countSize($group.max_storage,true)[1]}']").attr("selected",true);
|
||||
$("input[name='range_transfer'][value='{$group.range_transfer}']").attr("checked",true);
|
||||
$("input[name='allow_share'][value='{$group.allow_share}']").attr("checked",true);
|
||||
$("input[name='color'][value='{$group.color}']").attr("checked",true);
|
||||
$("input[name='webdav'][value='{$group.webdav}']").attr("checked",true);
|
||||
if('{$group.aria2}'=="1,1,1"){
|
||||
$("input[name='aria2'][value='1']").attr("checked",true);
|
||||
}else{
|
||||
$("input[name='aria2'][value='0']").attr("checked",true);
|
||||
}
|
||||
</script>
|
||||
{/block}
|
||||
@@ -684,7 +684,7 @@
|
||||
{case value="s3"}
|
||||
<div class="card" id="s3" >
|
||||
<div class="card-header">
|
||||
添加S3上传策略
|
||||
编辑S3上传策略
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form id="Policy">
|
||||
@@ -804,6 +804,252 @@
|
||||
</div>
|
||||
|
||||
{/case}
|
||||
{case value="remote"}
|
||||
<div class="card" id="remote" >
|
||||
<div class="card-header">
|
||||
编辑远程上传策略
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form id="Policy">
|
||||
<input type="text" value="{$policy.id}" name="id" style="display: none">
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="policy_name" class="col-form-label col-form-label-sm">上传策略名称</label>
|
||||
</div>
|
||||
<div class="col-md-4"> <input type="text" class="form-control" value="{$policy.policy_name}" name="policy_name" required></div>
|
||||
<div class="col-md-4 option-des"> 上传策略的名称,用于区别不同策略</div>
|
||||
</div>
|
||||
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="ak" class="col-form-label col-form-label-sm">AccessToken </label>
|
||||
</div>
|
||||
<div class="col-md-4"> <input type="text" class="form-control" name="sk" value="{$policy.sk}" required></div>
|
||||
<div class="col-md-4 option-des"> 默认随机生成,请与远程服务端配置文件中保持一致</div>
|
||||
</div>
|
||||
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="url" class="col-form-label col-form-label-sm">服务端URL</label>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<input type="text" class="form-control" name="server" value="{$policy.server}" required>
|
||||
</div>
|
||||
<div class="col-md-4 option-des"> 结尾要加"/"</div>
|
||||
</div>
|
||||
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="url" class="col-form-label col-form-label-sm">下载根URL</label>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<input type="text" class="form-control" name="url" value="{$policy.url}" required>
|
||||
</div>
|
||||
<div class="col-md-4 option-des"> 一般与上一步保持一致,结尾要加"/"</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="filetype" class="col-form-label col-form-label-sm">单文件最大大小</label>
|
||||
</div>
|
||||
<div class="col-md-4 input-group mb-3">
|
||||
<input type="number" class="form-control" name="max_size" spellcheck="false" min="0" value="{:countSize($policy.max_size,true)[0]}" required>
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text" id="basic-addon2">
|
||||
<select name="sizeTimes" class="selectIn" data-value="{:countSize($policy.max_size,true)[1]}">
|
||||
<option value="1">B</option>
|
||||
<option value="1024">KB</option>
|
||||
<option value="1048576" >MB</option>
|
||||
<option value="1073741824">GB</option>
|
||||
</select>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4 option-des"> 允许上传的单个文件的最大尺寸</div>
|
||||
</div>
|
||||
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="filetype" class="col-form-label col-form-label-sm">文件重命名</label>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
{eq name="$policy.autoname" value="1"}
|
||||
<input class="" type="radio" name="autoname" id="autoname1" value="1" checked>
|
||||
<label class="" for="autoname1" >开启</label>
|
||||
|
||||
<input class="" type="radio" name="autoname" id="autoname2" value="0" >
|
||||
<label class="" for="autoname2">关闭</label>
|
||||
{else/}
|
||||
<input class="" type="radio" name="autoname" id="autoname1" value="1" >
|
||||
<label class="" for="autoname1" >开启</label>
|
||||
|
||||
<input class="" type="radio" name="autoname" id="autoname2" value="0" checked>
|
||||
<label class="" for="autoname2" >关闭</label>
|
||||
{/eq}
|
||||
</div>
|
||||
<div class="col-md-4 option-des"> 是否对存储的文件自动重命名。推荐开启,重命名不会影响用户端文件名展示,开启后可以避免文件重名</div>
|
||||
</div>
|
||||
<div class="row form-setting" id="autoname_form" style=" {eq name="$policy.autoname" value="0"}display:none{/eq}">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="url" class="col-form-label col-form-label-sm">重命名规则</label>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<input type="text" class="form-control" name="namerule" value="{$policy.namerule}" spellcheck="false" required>
|
||||
</div>
|
||||
<div class="col-md-4 option-des"> 你可以使用<a href="javascript:void()" data-toggle="modal" data-target="#varTable">变量对照表</a>中的字段填写</div>
|
||||
</div>
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="filetype" class="col-form-label col-form-label-sm">存储目录</label>
|
||||
</div>
|
||||
<div class="col-md-4 input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text" id="basic-addon2">
|
||||
/public/uploads/
|
||||
</span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="dirrule" spellcheck="false" value="{$policy.dirrule}" required>
|
||||
</div>
|
||||
<div class="col-md-4 option-des"> 文件存放的目录,你可以使用<a href="javascript:void()" data-toggle="modal" data-target="#varTableFolder">目录变量对照表</a>中的字段填写</div>
|
||||
</div>
|
||||
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
</div>
|
||||
<div class="col-md-4"> <button type="submit" class="btn btn-primary" id="savePolicy">保存设置</button></div>
|
||||
<div class="col-md-4 option-des"> </div>
|
||||
<br> <br>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<bn>
|
||||
</div>
|
||||
|
||||
{/case}
|
||||
{case value="onedrive"}
|
||||
<div class="alert alert-warning" role="alert">
|
||||
<strong>添加Onedrive上传策略前请确保阅读完下面内容!</strong>
|
||||
<ul>
|
||||
<li>Onedrive策略无法直传,上传文件时,Cloudreve会先将文件暂存在服务器,之后再由任务队列上传至Onedrive;</li>
|
||||
<li>使用本策略前,请先配置并运行<a href="https://github.com/HFO4/Cloudreve/wiki/Onedrive%E5%AF%B9%E6%8E%A5%E8%AF%B4%E6%98%8E">Cloudreve任务队列</a>,否则正常无法使用;</li>
|
||||
<li>用户上传文件后不能立马看到所上传的文件,需要等待任务队列处理完毕;</li>
|
||||
<li>请确保已经正确配置好Cloudreve的Cron定时任务,以便用于刷新AccessToken信息。</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="card" id="s3" >
|
||||
<div class="card-header">
|
||||
添加Onedrive上传策略
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form id="Policy">
|
||||
<input type="text" value="{$policy.id}" name="id" style="display: none">
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="policy_name" class="col-form-label col-form-label-sm">上传策略名称</label>
|
||||
</div>
|
||||
<div class="col-md-4"> <input type="text" class="form-control" value="{$policy.policy_name}" name="policy_name" required></div>
|
||||
<div class="col-md-4 option-des"> 上传策略的名称,用于区别不同策略</div>
|
||||
</div>
|
||||
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="bucketname" class="col-form-label col-form-label-sm">应用 ID(Client ID) </label>
|
||||
</div>
|
||||
<div class="col-md-4"> <input type="text" class="form-control" name="bucketname" value="{$policy.bucketname}" required></div>
|
||||
<div class="col-md-4 option-des"> 请<a href="https://apps.dev.microsoft.com/?referrer=https%3a%2f%2fdeveloper.microsoft.com%2fzh-CN%2fgraph%2fquick-start#/quickstart/graphIO?publicClientSupport=false&appName=Cloudreve&redirectUrl={:urlencode($options.siteURL)}Admin%2FoneDriveCalllback&allowImplicitFlow=false&ru=https:%2F%2Fdeveloper.microsoft.com%2Fzh-CN%2Fgraph%2Fquick-start%3FappID%3D_appId_%26appName%3D_appName_%26redirectUrl%3D{$options.siteURL}Admin/oneDriveCalllback%26platform%3Doption-php" target="_blank">点击这里</a>获取下一步要用到的应用机密和此处的应用ID</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="url" class="col-form-label col-form-label-sm">应用机密(密码/公钥)</label>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<input type="text" class="form-control" name="ak" value="{$policy.ak}" required>
|
||||
</div>
|
||||
<div class="col-md-4 option-des"> 同上一项一起获取</div>
|
||||
</div>
|
||||
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="filetype" class="col-form-label col-form-label-sm">单文件最大大小</label>
|
||||
</div>
|
||||
<div class="col-md-4 input-group mb-3">
|
||||
<input type="number" class="form-control" name="max_size" spellcheck="false" min="0" value="{:countSize($policy.max_size,true)[0]}" required>
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text" id="basic-addon2">
|
||||
<select name="sizeTimes" class="selectIn" data-value="{:countSize($policy.max_size,true)[1]}">
|
||||
<option value="1">B</option>
|
||||
<option value="1024">KB</option>
|
||||
<option value="1048576" >MB</option>
|
||||
<option value="1073741824">GB</option>
|
||||
</select>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4 option-des"> 允许上传的单个文件的最大尺寸</div>
|
||||
</div>
|
||||
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="filetype" class="col-form-label col-form-label-sm">文件重命名</label>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
{eq name="$policy.autoname" value="1"}
|
||||
<input class="" type="radio" name="autoname" id="autoname1" value="1" checked>
|
||||
<label class="" for="autoname1" >开启</label>
|
||||
|
||||
<input class="" type="radio" name="autoname" id="autoname2" value="0" >
|
||||
<label class="" for="autoname2">关闭</label>
|
||||
{else/}
|
||||
<input class="" type="radio" name="autoname" id="autoname1" value="1" >
|
||||
<label class="" for="autoname1" >开启</label>
|
||||
|
||||
<input class="" type="radio" name="autoname" id="autoname2" value="0" checked>
|
||||
<label class="" for="autoname2" >关闭</label>
|
||||
{/eq}
|
||||
</div>
|
||||
<div class="col-md-4 option-des"> 是否对存储的文件自动重命名。推荐开启,重命名不会影响用户端文件名展示,开启后可以避免文件重名</div>
|
||||
</div>
|
||||
<div class="row form-setting" id="autoname_form" style=" {eq name="$policy.autoname" value="0"}display:none{/eq}">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="url" class="col-form-label col-form-label-sm">重命名规则</label>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<input type="text" class="form-control" name="namerule" value="{$policy.namerule}" spellcheck="false" required>
|
||||
</div>
|
||||
<div class="col-md-4 option-des"> 你可以使用<a href="javascript:void()" data-toggle="modal" data-target="#varTable">变量对照表</a>中的字段填写</div>
|
||||
</div>
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="filetype" class="col-form-label col-form-label-sm">存储目录</label>
|
||||
</div>
|
||||
<div class="col-md-4 input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text" id="basic-addon2">
|
||||
Onedrive根目录/
|
||||
</span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="dirrule" spellcheck="false" value="{$policy.dirrule}" required>
|
||||
</div>
|
||||
<div class="col-md-4 option-des"> 文件存放的目录,你可以使用<a href="javascript:void()" data-toggle="modal" data-target="#varTableFolder">目录变量对照表</a>中的字段填写</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
</div>
|
||||
<div class="col-md-4"> <button type="submit" class="btn btn-primary" id="saveQiniu">保存</button> <a class="btn btn-danger" href="/Admin/UpdateOnedriveToken?id={$policy.id}" id="saveQiniu">重新授权账号(请先保存)</a></div>
|
||||
<div class="col-md-4 option-des"> </div>
|
||||
<br> <br>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<bn>
|
||||
</div>
|
||||
{/case}
|
||||
{/switch}
|
||||
<br>
|
||||
</div>
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="tab-pane fade" id="test" role="tabpanel" aria-labelledby="pills-profile-tab">
|
||||
<form id="testMail">
|
||||
<div class="row form-setting">
|
||||
@@ -145,7 +145,7 @@
|
||||
<div class="tab-pane fade" id="template" role="tabpanel" aria-labelledby="pills-profile-tab">
|
||||
<form id="mailTemplate">
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
|
||||
@@ -66,6 +66,37 @@
|
||||
<div class="col-md-4 option-des"> 用于展示用户头像的Gravatar服务器地址</div>
|
||||
</div>
|
||||
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="gravatar_server" class="col-form-label col-form-label-sm">文件数据发送模式</label>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<select class="form-control" name="sendfile">
|
||||
<option value="0">传统</option>
|
||||
<option value="1" {eq name="optionsForSet.sendfile" value="1"}selected{/eq}>X-Sendfile</option>
|
||||
|
||||
</select>
|
||||
|
||||
</div>
|
||||
<div class="col-md-4 option-des"> 推荐使用X-Sendfile以获得高效的文件传输,启用前请确保服务器安装X-Sendfile模块并在站点配置文件中启用。</div>
|
||||
</div>
|
||||
|
||||
<div class="row form-setting" style="{eq name="optionsForSet.sendfile" value="0"}display:none{/eq}" id="sendfile_header">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="gravatar_server" class="col-form-label col-form-label-sm">Sendfile Header</label>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<select class="form-control" name="header">
|
||||
<option value="X-Sendfile" {eq name="optionsForSet.header" value="X-Sendfile"}selected{/eq}>X-Sendfile [Apache,Lighttpd v1.5,Cherokee]</option>
|
||||
<option value="X-LIGHTTPD-send-file" {eq name="optionsForSet.header" value="X-LIGHTTPD-send-file"}selected{/eq}>X-LIGHTTPD-send-file [Lighttpd v1.4]</option>
|
||||
<option value="X-Accel-Redirect" {eq name="optionsForSet.header" value="X-Accel-Redirect"}selected{/eq}>X-Accel-Redirect [Nginx,Cherokee]</option>
|
||||
|
||||
</select>
|
||||
|
||||
</div>
|
||||
<div class="col-md-4 option-des"> 请根据你所使用的服务器软件选择合适的header</div>
|
||||
</div>
|
||||
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
</div>
|
||||
|
||||
@@ -42,6 +42,12 @@
|
||||
<li class="nav-item">
|
||||
<a class="nav-link selectLab" href="javascript:void()" data-policy="s3">S3</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link selectLab" href="javascript:void()" data-policy="remote">远程</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link selectLab" href="javascript:void()" data-policy="onedrive">Onedrive</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@@ -78,6 +84,8 @@
|
||||
{case value="oss"}OSS{/case}
|
||||
{case value="upyun"}又拍云{/case}
|
||||
{case value="s3"}Amazon S3{/case}
|
||||
{case value="remote"}远程{/case}
|
||||
{case value="onedrive"}Onedrive{/case}
|
||||
{default /}其他
|
||||
{/switch}
|
||||
</td>
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
{extend name="header_admin" /}
|
||||
{block name="title"}任务队列 - {$options.siteName}{/block}
|
||||
{block name="content"}
|
||||
<div class="content-wrapper">
|
||||
<div class="container-fluid">
|
||||
<!-- Breadcrumbs-->
|
||||
<ol class="breadcrumb">
|
||||
<li class="breadcrumb-item">
|
||||
<a href="/Admin">管理面板</a>
|
||||
</li>
|
||||
<li class="breadcrumb-item active">任务队列</li>
|
||||
<li class="breadcrumb-item active">配置</li>
|
||||
</ol>
|
||||
|
||||
<!-- Area Chart Example-->
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<h2>任务队列</h2>
|
||||
<br>
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<ul class="nav nav-tabs card-header-tabs">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" data-toggle="tab" href="#options"><i class="fa fa-cog" aria-hidden="true"></i> 配置</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-toggle="tab" href="#list"><i class="fa fa-list" aria-hidden="true"></i> 任务列表</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="tab-content" >
|
||||
<div class="tab-pane fade show active" id="options" role="tabpanel" aria-labelledby="pills-home-tab">
|
||||
<form id="taskOptions">
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
<label for="fromName" class="col-form-label col-form-label-sm">Token</label>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<input type="text" class="form-control" name="task_queue_token" id="task_queue_token" value="{$taskOption}" spellcheck="false">
|
||||
|
||||
</div>
|
||||
<div class="col-md-4 option-des"> 任务队列鉴权Token,应该与任务队列配置文件conf.yaml中的token保持一致,留空表示禁止任务队列请求</div>
|
||||
</div>
|
||||
<div class="row form-setting">
|
||||
<div class="col-md-1 form-label ">
|
||||
</div>
|
||||
<div class="col-md-4"> <button type="button" class="btn btn-outline-secondary" id="generateToken">随机生成Token</button> <button type="button" class="btn btn-primary" id="saveTask">保存设置</button></div>
|
||||
<div class="col-md-4 option-des"> </div>
|
||||
<br><br><br>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade" id="list" role="tabpanel" aria-labelledby="pills-profile-tab">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" class="textCenter">#</th>
|
||||
<th scope="col" width="50%">任务名</th>
|
||||
<th scope="col" class="textCenter">状态</th>
|
||||
<th scope="col" class="textCenter">创建日期</th>
|
||||
<th scope="col" class="textCenter">创建者UID</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="listContent">
|
||||
{volist name='task' id='t'}
|
||||
<tr id="i-{$t.id}" >
|
||||
<th scope="row" class="textCenter">{$t.id}</th>
|
||||
<td>{$t.task_name}</td>
|
||||
<td class="textCenter">{$t.status}</td>
|
||||
<td class="textCenter">{$t.addtime}</td>
|
||||
<td class="textCenter">{$t.uid}</td>
|
||||
</tr>
|
||||
{/volist}
|
||||
</tbody>
|
||||
</table>
|
||||
{$task->render()}
|
||||
</div>
|
||||
<div class="tab-pane fade" id="tools" role="tabpanel" aria-labelledby="pills-profile-tab">
|
||||
ddd
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><br>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Example DataTables Card-->
|
||||
</div>
|
||||
<!-- /.container-fluid-->
|
||||
</div>
|
||||
{/block}
|
||||
{block name="js"}
|
||||
<script src="/static/js/admin/summernote.min.js"></script>
|
||||
<script src="/static/js/admin/summernote-zh-CN.min.js"></script>
|
||||
<script src="/static/js/admin/task.js"></script>
|
||||
{/block}
|
||||
@@ -1,6 +1,3 @@
|
||||
{extend name="header_public" /}
|
||||
{block name="title"}错误提示 - {$options.siteName}{/block}
|
||||
{block name="content"}
|
||||
<link rel="stylesheet" href="/static/css/error.css" />
|
||||
</head>
|
||||
<body data-ma-header="teal">
|
||||
@@ -19,6 +16,4 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{$options.js_code}
|
||||
</body>
|
||||
{/block}
|
||||
@@ -1,76 +1,23 @@
|
||||
{extend name="header_public" /}
|
||||
{block name="title"}“{$keyWords}”搜索结果 - {$options.siteName}{/block}
|
||||
{block name="content"}
|
||||
<link rel="stylesheet" href="/static/css/search.css" />
|
||||
</head>
|
||||
<body data-ma-header="teal">
|
||||
<nav class="navbar navbar-inverse" >
|
||||
<div class="container-fluid">
|
||||
<div class="container" >
|
||||
{include file="navbar_public" /}
|
||||
<div class="header-panel shadow-z-2">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container main-h">
|
||||
|
||||
<div class="col-md-12">
|
||||
<h1>搜索分享</h1>
|
||||
<input type="text" placeholder="请输入关键词,回车键发起搜索" value="{$keyWords}" autofocus="true"><br><br>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="50%">文件名 </th>
|
||||
<th class="cent">分享日期</th>
|
||||
<th class="cent">下载次数</th>
|
||||
<th class="cent">浏览次数</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>{volist name='list' id='shares'}
|
||||
<tr>
|
||||
<td >{switch $shares.source_type}
|
||||
{case file}<i class="fa fa-file" aria-hidden="true"></i> {/case}
|
||||
{case dir}<i class="fa fa-folder-open blue" aria-hidden="true"></i> {/case}
|
||||
|
||||
{/switch} <a href="/s/{$shares.share_key}" class="notWave" target="_blank">{$shares.fileData|htmlspecialchars=ENT_NOQUOTES}</a></td>
|
||||
<td class="cent">{$shares.share_time}</td>
|
||||
<td align="center">{$shares.download_num}</td>
|
||||
<td align="center">{$shares.view_num}</td>
|
||||
</tr>
|
||||
|
||||
{/volist}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
{$listOrigin->render()}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
<script type="text/javascript">
|
||||
</script>
|
||||
<script src="/static/js/material.js"></script>
|
||||
<script >
|
||||
$.material.init();
|
||||
document.onkeydown=function(){
|
||||
if (event.keyCode == 13){
|
||||
keyWords = $("input").val();
|
||||
if(keyWords ==""){
|
||||
toastr["warning"]("关键字不能为空");
|
||||
}else{
|
||||
window.location="/Explore/S/"+keyWords;
|
||||
}
|
||||
}
|
||||
else{
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
{$options.js_code}
|
||||
{/block}
|
||||
<!doctype html><html lang="zh-cn"><head><meta charset="utf-8"><link rel="shortcut icon" href="/favicon.ico"><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"><meta name="theme-color" content="{$options.themeColor}"/><link rel="manifest" href="/manifest.json"><title>“{$keyWords}”搜索结果 - {$options.siteName}</title><script type="text/javascript">colorTheme = {:json_encode($options["themeConfig"])};
|
||||
isHomePage = false;
|
||||
isSharePage = false;
|
||||
pageId="shareLock";
|
||||
list = {$list};
|
||||
userInfo = {
|
||||
uid: {$userData.uid},
|
||||
nick: "{$userData.userNick}",
|
||||
email: "{$userData.userMail}",
|
||||
group: "{$userData.groupData.group_name}",
|
||||
groupId: {$userData.groupData.id},
|
||||
groupColor: "{$userData.groupData.color}",
|
||||
};
|
||||
siteInfo = {
|
||||
mainTitle: "{$options.siteName}",
|
||||
};
|
||||
uploadConfig = {
|
||||
allowSource: false,
|
||||
allowShare: false,
|
||||
allowRemoteDownload: "0",
|
||||
allowTorrentDownload: "0",
|
||||
};
|
||||
isMobile = window.innerWidth < 600;</script></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(l){function e(e){for(var r,t,n=e[0],o=e[1],u=e[2],f=0,i=[];f<n.length;f++)t=n[f],p[t]&&i.push(p[t][0]),p[t]=0;for(r in o)Object.prototype.hasOwnProperty.call(o,r)&&(l[r]=o[r]);for(s&&s(e);i.length;)i.shift()();return c.push.apply(c,u||[]),a()}function a(){for(var e,r=0;r<c.length;r++){for(var t=c[r],n=!0,o=1;o<t.length;o++){var u=t[o];0!==p[u]&&(n=!1)}n&&(c.splice(r--,1),e=f(f.s=t[0]))}return e}var t={},p={21:0},c=[];function f(e){if(t[e])return t[e].exports;var r=t[e]={i:e,l:!1,exports:{}};return l[e].call(r.exports,r,r.exports,f),r.l=!0,r.exports}f.m=l,f.c=t,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(r,e){if(1&e&&(r=f(r)),8&e)return r;if(4&e&&"object"==typeof r&&r&&r.__esModule)return r;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:r}),2&e&&"string"!=typeof r)for(var n in r)f.d(t,n,function(e){return r[e]}.bind(null,n));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="/";var r=window.webpackJsonp=window.webpackJsonp||[],n=r.push.bind(r);r.push=e,r=r.slice();for(var o=0;o<r.length;o++)e(r[o]);var s=n;a()}([])</script><script src="/static/js/0.chunk.js"></script><script src="/static/js/2.chunk.js"></script><script src="/static/js/search.chunk.js"></script></body></html>
|
||||
@@ -1,47 +0,0 @@
|
||||
{extend name="header_public" /}
|
||||
{block name="title"}用户主页 - {$options.siteName}{/block}
|
||||
{block name="content"}
|
||||
<link rel="stylesheet" href="/static/css/search.css" />
|
||||
</head>
|
||||
<body data-ma-header="teal">
|
||||
<nav class="navbar navbar-inverse" >
|
||||
<div class="container-fluid">
|
||||
<div class="container" >
|
||||
{include file="navbar_public" /}
|
||||
<div class="header-panel shadow-z-2">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container main-h">
|
||||
|
||||
<div class="col-md-12">
|
||||
<h1>搜索分享</h1>
|
||||
<input type="text" placeholder="请输入关键词,回车键发起搜索" autofocus="true">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
<script type="text/javascript">
|
||||
</script>
|
||||
<script src="/static/js/material.js"></script>
|
||||
<script >
|
||||
document.onkeydown=function(){
|
||||
if (event.keyCode == 13){
|
||||
keyWords = $("input").val();
|
||||
if(keyWords ==""){
|
||||
toastr["warning"]("关键字不能为空");
|
||||
}else{
|
||||
window.location="/Explore/S/"+keyWords;
|
||||
}
|
||||
}
|
||||
else{
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
{$options.js_code}
|
||||
{/block}
|
||||
@@ -6,6 +6,7 @@
|
||||
<meta http-equiv="x-ua-compatible" content="ie=edge">
|
||||
<meta name="keywords" content="{$options.siteKeywords}"/>
|
||||
<meta name="description" content="{$options.siteDes}"/>
|
||||
<meta name="theme-color" content="#4e64d9"/>
|
||||
<title>{$options.siteName} - {$options.siteTitle}</title>
|
||||
|
||||
<!-- Font Awesome -->
|
||||
|
||||
@@ -58,11 +58,19 @@
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-item" data-toggle="tooltip" data-placement="right" title="模板">
|
||||
<a class="nav-link" href="/Admin/Theme">
|
||||
<li class="nav-item" data-toggle="tooltip" data-placement="right" title="模板">
|
||||
<a class="nav-link nav-link-collapse collapsed" data-toggle="collapse" href="#theme">
|
||||
<i class="fa fa-fw fa-paint-brush"></i>
|
||||
<span class="nav-link-text">模板</span>
|
||||
</a>
|
||||
<ul class="sidenav-second-level collapse" id="theme">
|
||||
<li>
|
||||
<a href="/Admin/Theme">模板</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/Admin/Color">配色方案</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="nav-item" data-toggle="tooltip" data-placement="right" title="文件">
|
||||
<a class="nav-link" href="/Admin/Files">
|
||||
@@ -76,6 +84,12 @@
|
||||
<span class="nav-link-text">分享</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item" data-toggle="tooltip" data-placement="right" title="离线下载">
|
||||
<a class="nav-link" href="/Admin/RemoteDownload">
|
||||
<i class="fa fa-fw fa-cloud-download"></i>
|
||||
<span class="nav-link-text">离线下载</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item" data-toggle="tooltip" data-placement="right" title="用户">
|
||||
<a class="nav-link" href="/Admin/Users" data-parent="#user">
|
||||
<i class="fa fa-fw fa-user"></i>
|
||||
@@ -116,6 +130,9 @@
|
||||
<span class="nav-link-text">其他</span>
|
||||
</a>
|
||||
<ul class="sidenav-second-level collapse" id="else">
|
||||
<li>
|
||||
<a href="/Admin/Queue">任务队列</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/Admin/Cron">定时任务</a>
|
||||
</li>
|
||||
|
||||
@@ -1,27 +1,18 @@
|
||||
<!doctype html>
|
||||
<html lang="zh-cn" data-ng-app="FileManagerApp">
|
||||
<head>
|
||||
<!--
|
||||
* Angular FileManager v1.5.1 (https://github.com/joni2back/angular-filemanager)
|
||||
* Jonas Sciangula Street <joni2back@gmail.com>
|
||||
* Licensed under MIT (https://github.com/joni2back/angular-filemanager/blob/master/LICENSE)
|
||||
-->
|
||||
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
|
||||
<meta charset="utf-8">
|
||||
<title>{block name="title"}{/block}</title>
|
||||
<!-- third party -->
|
||||
|
||||
<meta name="theme-color" content="#4e64d9"/>
|
||||
<title>{block name="title"}{/block}</title>
|
||||
<script src="/static/js/jquery.min.js"></script>
|
||||
<link rel="stylesheet" href="/static/css/bootstrap.min.css" />
|
||||
<link rel="stylesheet" href="/static/css/material.css" />
|
||||
<script src="/static/js/bootstrap.min.js"></script>
|
||||
<link rel="stylesheet" href="/static/css/font-awesome.min.css">
|
||||
<!-- /third party -->
|
||||
<!-- Comment if you need to use raw source code -->
|
||||
<link href="/static/css/angular-filemanager.min.css" rel="stylesheet">
|
||||
<link href="/static/css/toastr.min.css" rel="stylesheet">
|
||||
<script type="text/javascript" src="/static/js/toastr.min.js"></script>
|
||||
<!-- /Comment if you need to use raw source code -->
|
||||
<script type="text/javascript">
|
||||
</script>
|
||||
{block name="content"}{/block}
|
||||
@@ -2,6 +2,7 @@
|
||||
<head>
|
||||
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
|
||||
<meta charset="utf-8">
|
||||
<meta name="theme-color" content="#4e64d9"/>
|
||||
<title>{block name="title"}{/block}</title>
|
||||
<!-- third party -->
|
||||
<script src="/static/js/jquery.min.js"></script>
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<!--
|
||||
Multiverse by HTML5 UP
|
||||
html5up.net | @ajlkn
|
||||
Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>图片集 - {$options.siteName}</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
|
||||
<!--[if lte IE 8]><script src="https://file.aoaoao.me/content/themes/material/pages/js/ie/html5shiv.js"></script><![endif]-->
|
||||
<link rel="stylesheet" href="/static/css/main.css" />
|
||||
<link href="/static/css/font-awesome.min.css" rel="stylesheet">
|
||||
<!--[if lte IE 9]><link rel="stylesheet" href="https://file.aoaoao.me/content/themes/material/pages/css/ie9.css" /><![endif]-->
|
||||
<!--[if lte IE 8]><link rel="stylesheet" href="https://file.aoaoao.me/content/themes/material/pages/css/ie8.css" /><![endif]-->
|
||||
<style type="text/css">
|
||||
body{
|
||||
font-family: "微软雅黑","黑体";
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<!-- Wrapper -->
|
||||
<div id="wrapper">
|
||||
<!-- Header -->
|
||||
|
||||
<div id="main">
|
||||
{volist name='list' id='pic'}
|
||||
<article class="thumb">
|
||||
<a href="/File/Preview?action=preview&path={$pic.dir|urlencode}/{$pic.orign_name|urlencode}" class="image"><img src="/File/Preview?action=preview&path={$pic.dir|urlencode}/{$pic.orign_name|urlencode}" alt="" /></a>
|
||||
<h2>{$pic.orign_name}</h2>
|
||||
|
||||
</article>
|
||||
{/volist}
|
||||
</div>
|
||||
<header id="header">
|
||||
<h1><a href="/Home"><strong>图片集</strong> {$options.siteName}</a></h1>
|
||||
<nav>
|
||||
<ul>
|
||||
<li><a href="javascript:previous();" class="icon fa-arrow-circle-left">上一页</a></li>
|
||||
{$page}/{$pageCount} <li><a href="javascript:next();" class="icon fa-arrow-circle-right">下一页</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<!-- Main -->
|
||||
<!-- Footer -->
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Scripts -->
|
||||
<script src = "/static/js/jquery.min.js"></script>
|
||||
<script src="/static/js/jquery.poptrox.min.js"></script>
|
||||
<script src="/static/js/skel.min.js"></script>
|
||||
<script src="/static/js/util.js"></script>
|
||||
<!--[if lte IE 8]><script src="assets/js/ie/respond.min.js"></script><![endif]-->
|
||||
<script src="/static/js/album.js"></script>
|
||||
<script type="text/javascript">
|
||||
pageNow = {$page};
|
||||
pageTotal = {$pageCount};
|
||||
function next(){
|
||||
if(pageNow == pageTotal){
|
||||
|
||||
}else{
|
||||
window.location.href="/Home/Album?page="+(pageNow+1);
|
||||
}
|
||||
}
|
||||
function previous(){
|
||||
if(pageNow == 1){
|
||||
|
||||
}else{
|
||||
window.location.href="/Home/Album?page="+(pageNow-1);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
{$options.js_code}
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,22 @@
|
||||
<!doctype html><html lang="zh-cn"><head><meta charset="utf-8"><link rel="shortcut icon" href="/favicon.ico"><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"><meta name="theme-color" content="{$options.themeColor}"/><link rel="manifest" href="/manifest.json"><title>离线下载管理- {$options.siteName}</title><script type="text/javascript">colorTheme = {:json_encode($options["themeConfig"])};
|
||||
isHomePage = false;
|
||||
isSharePage = false;
|
||||
pageId="shareLock";
|
||||
userInfo = {
|
||||
uid: {$userInfo.uid},
|
||||
nick: "{$userInfo.userNick}",
|
||||
email: "{$userInfo.userMail}",
|
||||
group: "{$userInfo.groupData.group_name}",
|
||||
groupId: {$userInfo.groupData.id},
|
||||
groupColor: "{$userInfo.groupData.color}",
|
||||
};
|
||||
siteInfo = {
|
||||
mainTitle: "离线下载",
|
||||
};
|
||||
uploadConfig = {
|
||||
allowSource: false,
|
||||
allowShare: false,
|
||||
allowRemoteDownload: "0",
|
||||
allowTorrentDownload: "0",
|
||||
};
|
||||
isMobile = window.innerWidth < 600;</script></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(l){function e(e){for(var r,t,n=e[0],o=e[1],u=e[2],f=0,i=[];f<n.length;f++)t=n[f],p[t]&&i.push(p[t][0]),p[t]=0;for(r in o)Object.prototype.hasOwnProperty.call(o,r)&&(l[r]=o[r]);for(s&&s(e);i.length;)i.shift()();return c.push.apply(c,u||[]),a()}function a(){for(var e,r=0;r<c.length;r++){for(var t=c[r],n=!0,o=1;o<t.length;o++){var u=t[o];0!==p[u]&&(n=!1)}n&&(c.splice(r--,1),e=f(f.s=t[0]))}return e}var t={},p={20:0},c=[];function f(e){if(t[e])return t[e].exports;var r=t[e]={i:e,l:!1,exports:{}};return l[e].call(r.exports,r,r.exports,f),r.l=!0,r.exports}f.m=l,f.c=t,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(r,e){if(1&e&&(r=f(r)),8&e)return r;if(4&e&&"object"==typeof r&&r&&r.__esModule)return r;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:r}),2&e&&"string"!=typeof r)for(var n in r)f.d(t,n,function(e){return r[e]}.bind(null,n));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="/";var r=window.webpackJsonp=window.webpackJsonp||[],n=r.push.bind(r);r.push=e,r=r.slice();for(var o=0;o<r.length;o++)e(r[o]);var s=n;a()}([])</script><script src="/static/js/0.chunk.js"></script><script src="/static/js/2.chunk.js"></script><script src="/static/js/download.chunk.js"></script></body></html>
|
||||
@@ -1,97 +1,43 @@
|
||||
<!doctype html>
|
||||
<html lang="zh_cn" data-ng-app="FileManagerApp">
|
||||
<head>
|
||||
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
|
||||
<meta charset="utf-8">
|
||||
<title>我的文件 - {$options.siteName}</title>
|
||||
<script src="/static/js/angular.min.js"></script>
|
||||
<script src="/static/js/angular-translate.min.js"></script>
|
||||
<script src="/static/js/jquery.min.js"></script>
|
||||
<link rel="stylesheet" href="/static/css/bootstrap.min.css" />
|
||||
<link rel="stylesheet" href="/static/css/material.css" />
|
||||
<script src="/static/js/bootstrap.min.js"></script>
|
||||
<link rel="stylesheet" href="/static/css/font-awesome.min.css">
|
||||
<link href="/static/css/angular-filemanager.min.css" rel="stylesheet">
|
||||
<link href="/static/css/toastr.min.css" rel="stylesheet">
|
||||
<script type="text/javascript" src="/static/js/toastr.min.js"></script>
|
||||
<script src="/static/js/angular-filemanager.min.js"></script>
|
||||
<link rel="stylesheet" href="/static/css/photoswipe.css">
|
||||
<link rel="stylesheet" href="/static/css/default-skin/default-skin.css">
|
||||
<script type="text/javascript">
|
||||
uploadConfig={
|
||||
saveType : "{$policyData.policy_type}",
|
||||
maxSize : "{$policyData.max_size}mb",
|
||||
allowedType: [
|
||||
{$extLimit}
|
||||
],
|
||||
allowSource : "{$policyData.origin_link}",
|
||||
upUrl : "{$policyData.server}",
|
||||
allowShare:"{$groupData.allow_share}",
|
||||
};
|
||||
</script>
|
||||
<script src="/static/js/home.js"></script>
|
||||
</head>
|
||||
<body class="ng-cloak">
|
||||
<div id="container">
|
||||
{include file="navbar_home" /}
|
||||
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
|
||||
|
||||
<!-- Background of PhotoSwipe.
|
||||
It's a separate element, as animating opacity is faster than rgba(). -->
|
||||
<div class="pswp__bg"></div>
|
||||
<!-- Slides wrapper with overflow:hidden. -->
|
||||
<div class="pswp__scroll-wrap">
|
||||
<!-- Container that holds slides. PhotoSwipe keeps only 3 slides in DOM to save memory. -->
|
||||
<div class="pswp__container">
|
||||
<!-- don't modify these 3 pswp__item elements, data is added later on -->
|
||||
<div class="pswp__item"></div>
|
||||
<div class="pswp__item"></div>
|
||||
<div class="pswp__item"></div>
|
||||
</div>
|
||||
<!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->
|
||||
<div class="pswp__ui pswp__ui--hidden">
|
||||
<div class="pswp__top-bar">
|
||||
<!-- Controls are self-explanatory. Order can be changed. -->
|
||||
<div class="pswp__counter"></div>
|
||||
|
||||
<button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
|
||||
<button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
|
||||
<button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>
|
||||
<!-- Preloader demo https://codepen.io/dimsemenov/pen/yyBWoR -->
|
||||
<!-- element will get class pswp__preloader--active when preloader is running -->
|
||||
<div class="pswp__preloader">
|
||||
<div class="pswp__preloader__icn">
|
||||
<div class="pswp__preloader__cut">
|
||||
<div class="pswp__preloader__donut"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
|
||||
<div class="pswp__share-tooltip"></div>
|
||||
</div>
|
||||
<button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
|
||||
</button>
|
||||
<button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
|
||||
</button>
|
||||
<div class="pswp__caption">
|
||||
<div class="pswp__caption__center"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-10 max_height">
|
||||
<angular-filemanager></angular-filemanager>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<script src="/static/js/material.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
upload_load=0;
|
||||
|
||||
</script>
|
||||
{$options.js_code}
|
||||
</html>
|
||||
<!doctype html><html lang="zh-cn"><head><meta charset="utf-8"><link rel="shortcut icon" href="/favicon.ico"><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"><meta name="theme-color" content="{$options.themeColor}"/><link rel="manifest" href="/manifest.json"><title>我的文件 - {$options.siteName}</title><script type="text/javascript">colorTheme = {:json_encode($options["themeConfig"])};
|
||||
isHomePage = true;
|
||||
pageId="";
|
||||
isSharePage = false;
|
||||
uploadConfig = {
|
||||
saveType: "{$policyData.policy_type}",
|
||||
maxSize: "{$policyData.max_size}mb",
|
||||
allowedType: [{$extLimit}],
|
||||
allowSource: "{$policyData.origin_link}",
|
||||
upUrl: "{$policyData.server}",
|
||||
allowShare: "{$groupData.allow_share}",
|
||||
allowRemoteDownload: "{:explode(",",$groupData.aria2)[0]}",
|
||||
allowTorrentDownload: "{:explode(",",$groupData.aria2)[1]}",
|
||||
};
|
||||
if(uploadConfig.saveType == "oss" || uploadConfig.saveType == "upyun" || uploadConfig.saveType == "s3"){
|
||||
ChunkSize = "0";
|
||||
}else if(uploadConfig.saveType == "qiniu" ){
|
||||
ChunkSize = 4*1024*1024;
|
||||
}else{
|
||||
ChunkSize = {$chunkSize};
|
||||
}
|
||||
apiURL = {
|
||||
imgThumb: "/File/Thumb",
|
||||
preview: "/File/Preview",
|
||||
download: "/File/Download",
|
||||
docPreiview: '/File/DocPreview',
|
||||
listFile:"/File/ListFile"
|
||||
};
|
||||
userInfo = {
|
||||
uid: {$userInfo.uid},
|
||||
nick: "{$userInfo.userNick}",
|
||||
email: "{$userInfo.userMail}",
|
||||
group: "{$userInfo.groupData.group_name}",
|
||||
groupId: {$userInfo.groupData.id},
|
||||
groupColor: "{$userInfo.groupData.color}",
|
||||
};
|
||||
siteInfo = {
|
||||
mainTitle: "{$options.siteName}",
|
||||
};
|
||||
pathCache = {};
|
||||
path = "{$path}";
|
||||
mediaType = {},
|
||||
isMobile = window.innerWidth < 600;</script></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(c){function e(e){for(var t,r,n=e[0],o=e[1],a=e[2],u=0,i=[];u<n.length;u++)r=n[u],f[r]&&i.push(f[r][0]),f[r]=0;for(t in o)Object.prototype.hasOwnProperty.call(o,t)&&(c[t]=o[t]);for(d&&d(e);i.length;)i.shift()();return s.push.apply(s,a||[]),l()}function l(){for(var e,t=0;t<s.length;t++){for(var r=s[t],n=!0,o=1;o<r.length;o++){var a=r[o];0!==f[a]&&(n=!1)}n&&(s.splice(t--,1),e=p(p.s=r[0]))}return e}var r={},i={19:0},f={19:0},s=[];function p(e){if(r[e])return r[e].exports;var t=r[e]={i:e,l:!1,exports:{}};return c[e].call(t.exports,t,t.exports,p),t.l=!0,t.exports}p.e=function(s){var e=[];i[s]?e.push(i[s]):0!==i[s]&&{15:1}[s]&&e.push(i[s]=new Promise(function(e,n){for(var t="static/css/"+({}[s]||s)+".chunk.css",o=p.p+t,r=document.getElementsByTagName("link"),a=0;a<r.length;a++){var u=(c=r[a]).getAttribute("data-href")||c.getAttribute("href");if("stylesheet"===c.rel&&(u===t||u===o))return e()}var i=document.getElementsByTagName("style");for(a=0;a<i.length;a++){var c;if((u=(c=i[a]).getAttribute("data-href"))===t||u===o)return e()}var l=document.createElement("link");l.rel="stylesheet",l.type="text/css",l.onload=e,l.onerror=function(e){var t=e&&e.target&&e.target.src||o,r=new Error("Loading CSS chunk "+s+" failed.\n("+t+")");r.request=t,n(r)},l.href=o,document.getElementsByTagName("head")[0].appendChild(l)}).then(function(){i[s]=0}));var r=f[s];if(0!==r)if(r)e.push(r[2]);else{var t=new Promise(function(e,t){r=f[s]=[e,t]});e.push(r[2]=t);var n,o=document.getElementsByTagName("head")[0],a=document.createElement("script");a.charset="utf-8",a.timeout=120,p.nc&&a.setAttribute("nonce",p.nc),a.src=p.p+"static/js/"+({}[s]||s)+".chunk.js",n=function(e){a.onerror=a.onload=null,clearTimeout(u);var t=f[s];if(0!==t){if(t){var r=e&&("load"===e.type?"missing":e.type),n=e&&e.target&&e.target.src,o=new Error("Loading chunk "+s+" failed.\n("+r+": "+n+")");o.type=r,o.request=n,t[1](o)}f[s]=void 0}};var u=setTimeout(function(){n({type:"timeout",target:a})},12e4);a.onerror=a.onload=n,o.appendChild(a)}return Promise.all(e)},p.m=c,p.c=r,p.d=function(e,t,r){p.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},p.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},p.t=function(t,e){if(1&e&&(t=p(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var r=Object.create(null);if(p.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var n in t)p.d(r,n,function(e){return t[e]}.bind(null,n));return r},p.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return p.d(t,"a",t),t},p.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},p.p="/",p.oe=function(e){throw console.error(e),e};var t=window.webpackJsonp=window.webpackJsonp||[],n=t.push.bind(t);t.push=e,t=t.slice();for(var o=0;o<t.length;o++)e(t[o]);var d=n;l()}([])</script><script src="/static/js/0.chunk.js"></script><script src="/static/js/1.chunk.js"></script><script src="/static/js/index.chunk.js"></script></body></html>
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
<!--Video-->
|
||||
<div class="intro-video view" id="home">
|
||||
<img src="static/img/output.jpg">
|
||||
|
||||
|
||||
|
||||
<div class="hm-gradient">
|
||||
@@ -16,7 +16,8 @@
|
||||
<hr class="hr-light">
|
||||
<h4 class="subtext-header mt-2 mb-2">只需十秒钟,注册后即可开始使用免费高速的云存储服务</h4>
|
||||
</div>
|
||||
<a href="/Login" class="btn btn-rounded btn-light-green-2" ><i class="fa fa-paper-plane-o"></i> 立即注册</a>
|
||||
<a href="/Login" class="btn btn-rounded btn-light-green-2" ><i class="fa fa-paper-plane-o"></i> 注册</a>
|
||||
<a href="/Home" class="btn btn-rounded btn-light-green-2" ><i class="fa fa-sign-in"></i> 登录</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
{extend name="header_public" /}
|
||||
{block name="title"}注册成功- {$options.siteName}{/block}
|
||||
{block name="content"}
|
||||
<link rel="stylesheet" href="/static/css/login.css" />
|
||||
<link rel="stylesheet" href="/static/css/photoswipe.css">
|
||||
<link rel="stylesheet" href="/static/css/default-skin/default-skin.css">
|
||||
<script src="/static/js/jquery.color.js"></script>
|
||||
</head>
|
||||
<body data-ma-header="teal">
|
||||
|
||||
|
||||
<nav class="navbar navbar-inverse" >
|
||||
<div class="container-fluid">
|
||||
<div class="container" >
|
||||
{include file="navbar_public" loginStatus=$loginStatus userData=$userData /}
|
||||
<div class="header-panel shadow-z-2">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container main" >
|
||||
<div class="col-md-4"></div>
|
||||
<div class="col-md-4">
|
||||
<div class="jumbotron" >
|
||||
<div class="card_top">
|
||||
<div class="row top-color">
|
||||
<div class="card-top-row">
|
||||
<div class="login-icon"><i class="fa fa-check" aria-hidden="true"></i></div>
|
||||
<div class="login-text">注册成功</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card_botom">
|
||||
<div class="row bottom-width">
|
||||
<br>
|
||||
您已成功激活账号。<br><br>
|
||||
<a class="btn btn-raised btn-primary" href="/Login">立即登录</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div></div>
|
||||
<div class="col-md-4"></div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
|
||||
</script>
|
||||
<script src="/static/js/two_step.js"> </script>
|
||||
{$options.js_code}
|
||||
{/block}
|
||||
@@ -1,185 +1,23 @@
|
||||
{extend name="header_public" /}
|
||||
{block name="title"}登录- {$options.siteName}{/block}
|
||||
{block name="content"}
|
||||
<link rel="stylesheet" href="/static/css/login.css" />
|
||||
<link rel="stylesheet" href="/static/css/photoswipe.css">
|
||||
<link rel="stylesheet" href="/static/css/default-skin/default-skin.css">
|
||||
<script src="/static/js/jquery.color.js"></script>
|
||||
</head>
|
||||
<body data-ma-header="teal">
|
||||
|
||||
|
||||
<nav class="navbar navbar-inverse" >
|
||||
<div class="container-fluid">
|
||||
<div class="container" >
|
||||
{include file="navbar_public" loginStatus=$loginStatus userData=$userData /}
|
||||
<div class="header-panel shadow-z-2">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container main" >
|
||||
<div class="col-md-4"></div>
|
||||
<div class="col-md-4">
|
||||
<div class="jumbotron" id="logForm">
|
||||
<div class="card_top">
|
||||
<div class="row top-color">
|
||||
<div class="card-top-row">
|
||||
<div class="login-icon"><i class="fa fa-user-circle-o" aria-hidden="true"></i></div>
|
||||
<div class="login-text">登录后方可享用精彩内容</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card_botom">
|
||||
<div class="row bottom-width">
|
||||
<form id="loginForm">
|
||||
<div class="form-group label-floating">
|
||||
<label class="control-label" for="inputEmail">Email 电子邮箱</label>
|
||||
<input type="text" class="form-control" id="inputEmail" name="userMail">
|
||||
</div>
|
||||
<div class="form-group label-floating">
|
||||
<label class="control-label" for="inputPwd">密码</label>
|
||||
<input type="password" class="form-control" id="inputPwd" name="userPass">
|
||||
</div>
|
||||
{eq name="$RegOptions.login_captcha" value="1"}
|
||||
|
||||
<div class="input-group form-group label-floating">
|
||||
<label class="control-label" for="captcha">验证码</label>
|
||||
<input type="text" id="captcha" class="form-control" name="captchaCode">
|
||||
<span class="input-group-btn">
|
||||
<div class="captcha_img">{:captcha_img()}</div>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{else/}
|
||||
{/eq}
|
||||
|
||||
</form> <button class="btn btn-raised btn-primary" id="loginButton">登录</button>
|
||||
<div class="link-group">
|
||||
<a href="javascript:void" class="noWave" id="create" data-change="true">创建一个账户</a><br>
|
||||
<a href="javascript:void" class="noWave" id="forgetSwitch2" data-change="true">忘记密码?</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="jumbotron" id="regForm" style="display: none;">
|
||||
<div class="card_top">
|
||||
<div class="row top-color">
|
||||
<div class="card-top-row">
|
||||
<div class="login-icon"><i class="fa fa-sign-in" aria-hidden="true"></i></div>
|
||||
<div class="login-text">注册账户</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card_botom">
|
||||
<div class="row bottom-width">
|
||||
<form id="registerForm">
|
||||
<div class="form-group label-floating">
|
||||
<label class="control-label" for="inputEmail">Email 电子邮箱</label>
|
||||
<input type="text" class="form-control" id="inputEmail" name="username-reg">
|
||||
</div>
|
||||
<div class="form-group label-floating">
|
||||
<label class="control-label" for="inputPwd">密码</label>
|
||||
<input type="password" class="form-control" id="inputPwd" name="password-reg">
|
||||
</div>
|
||||
<div class="form-group label-floating">
|
||||
<label class="control-label" for="inputPwd">重复密码</label>
|
||||
<input type="password" class="form-control" id="inputPwd" name="password-check">
|
||||
</div>
|
||||
{eq name="$RegOptions.reg_captcha" value="1"}
|
||||
|
||||
<div class="input-group form-group label-floating">
|
||||
<label class="control-label" for="captcha">验证码</label>
|
||||
<input type="text" id="captcha" class="form-control" name="captchaCode">
|
||||
<span class="input-group-btn">
|
||||
<div class="captcha_img">{:captcha_img()}</div>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{else/}
|
||||
{/eq}
|
||||
|
||||
</form> <button class="btn btn-raised btn-primary" id="regButton">注册</button> <div class="link-group">
|
||||
<a href="javascript:void" class="noWave" id="loginSwitch3" data-change="true">已有账号?立即登录</a><br>
|
||||
<a href="javascript:void" class="noWave" id="forgetSwitch" data-change="true">忘记密码?</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="jumbotron" id="emailCheck" style="display: none;">
|
||||
<div class="card_top">
|
||||
<div class="row top-color">
|
||||
<div class="card-top-row">
|
||||
<div class="login-icon"><i class="fa fa-envelope" aria-hidden="true"></i></div>
|
||||
<div class="login-text">激活账户</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card_botom">
|
||||
<div class="row bottom-width"><br>
|
||||
我们已经向您的注册邮箱发送了一封确认邮件,请访问邮件中的激活链接以完成注册。如果未收到邮件,请检查您的垃圾邮件。<br><br>如果还仍无法接受邮件,请尝试更换注册邮箱或联系站点管理员。
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="jumbotron" id="forgetForm" style="display: none;">
|
||||
<div class="card_top">
|
||||
<div class="row top-color">
|
||||
<div class="card-top-row">
|
||||
<div class="login-icon"><i class="fa fa-question-circle-o" aria-hidden="true"></i></div>
|
||||
<div class="login-text">找回密码</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card_botom">
|
||||
<div class="row bottom-width">
|
||||
<form id="forgetPwdForm">
|
||||
|
||||
<div class="form-group label-floating">
|
||||
<label class="control-label" for="inputEmail">请填写注册时绑定的邮箱</label>
|
||||
<input type="text" class="form-control" id="regEmail" name="regEmail">
|
||||
</div>
|
||||
{eq name="$RegOptions.forget_captcha" value="1"}
|
||||
|
||||
<div class="input-group form-group label-floating">
|
||||
<label class="control-label" for="captcha">验证码</label>
|
||||
<input type="text" id="captcha" class="form-control" name="captchaCode">
|
||||
<span class="input-group-btn">
|
||||
<div class="captcha_img">{:captcha_img()}</div>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{else/}
|
||||
{/eq}
|
||||
|
||||
</form> <button class="btn btn-raised btn-primary" id="findMyFuckingPwd">找回密码</button> <div class="link-group">
|
||||
<a href="javascript:void" class="noWave" id="loginSwitch2" data-change="true">返回登录</a><br>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div></div>
|
||||
<div class="col-md-4"></div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
|
||||
</script>
|
||||
<script src="/static/js/login.js"> </script>
|
||||
{$options.js_code}
|
||||
{/block}
|
||||
<!doctype html><html lang="zh-cn"><head><meta charset="utf-8"><link rel="shortcut icon" href="/favicon.ico"><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"><meta name="theme-color" content="{$options.themeColor}"/><link rel="manifest" href="/manifest.json"><title>{eq name="pageId" value="resetPwdForm"}找回密码{/eq}{eq name="pageId" value="resetPwd"}找回密码{/eq}{eq name="pageId" value="emailActivate"}激活成功{/eq}{eq name="pageId" value="login"}登录{/eq}{eq name="pageId" value="register"}注册{/eq}{eq name="pageId" value="TwoStep"}二步验证{/eq} - {$options.siteName}</title><script type="text/javascript">colorTheme = {:json_encode($options["themeConfig"])};
|
||||
isHomePage = false;
|
||||
isSharePage = false;
|
||||
captcha = "{$RegOptions.login_captcha}";
|
||||
regCaptcha = "{$RegOptions.reg_captcha}";
|
||||
findPwdCaptcha = "{$RegOptions.forget_captcha}";
|
||||
{if isset($key)}
|
||||
resetKey = '{$key}';
|
||||
{/if}
|
||||
pageId="{$pageId}";
|
||||
userInfo = {
|
||||
uid: -1,
|
||||
};
|
||||
siteInfo = {
|
||||
mainTitle: "{$options.siteName}",
|
||||
};
|
||||
uploadConfig = {
|
||||
allowSource: false,
|
||||
allowShare: false,
|
||||
allowRemoteDownload: "0",
|
||||
allowTorrentDownload: "0",
|
||||
};
|
||||
isMobile = window.innerWidth < 600;</script></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(l){function e(e){for(var r,t,n=e[0],o=e[1],u=e[2],f=0,i=[];f<n.length;f++)t=n[f],p[t]&&i.push(p[t][0]),p[t]=0;for(r in o)Object.prototype.hasOwnProperty.call(o,r)&&(l[r]=o[r]);for(s&&s(e);i.length;)i.shift()();return c.push.apply(c,u||[]),a()}function a(){for(var e,r=0;r<c.length;r++){for(var t=c[r],n=!0,o=1;o<t.length;o++){var u=t[o];0!==p[u]&&(n=!1)}n&&(c.splice(r--,1),e=f(f.s=t[0]))}return e}var t={},p={22:0},c=[];function f(e){if(t[e])return t[e].exports;var r=t[e]={i:e,l:!1,exports:{}};return l[e].call(r.exports,r,r.exports,f),r.l=!0,r.exports}f.m=l,f.c=t,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(r,e){if(1&e&&(r=f(r)),8&e)return r;if(4&e&&"object"==typeof r&&r&&r.__esModule)return r;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:r}),2&e&&"string"!=typeof r)for(var n in r)f.d(t,n,function(e){return r[e]}.bind(null,n));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="/";var r=window.webpackJsonp=window.webpackJsonp||[],n=r.push.bind(r);r.push=e,r=r.slice();for(var o=0;o<r.length;o++)e(r[o]);var s=n;a()}([])</script><script src="/static/js/0.chunk.js"></script><script src="/static/js/1.chunk.js"></script><script src="/static/js/login.chunk.js"></script></body></html>
|
||||
@@ -1,122 +0,0 @@
|
||||
{extend name="header_public" /}
|
||||
{block name="title"}登录- {$options.siteName}{/block}
|
||||
{block name="content"}
|
||||
<link rel="stylesheet" href="/static/css/login.css" />
|
||||
<link rel="stylesheet" href="/static/css/photoswipe.css">
|
||||
<link rel="stylesheet" href="/static/css/default-skin/default-skin.css">
|
||||
<script src="/static/js/jquery.color.js"></script>
|
||||
</head>
|
||||
<body data-ma-header="teal">
|
||||
|
||||
|
||||
<nav class="navbar navbar-inverse" >
|
||||
<div class="container-fluid">
|
||||
<div class="container" >
|
||||
{include file="navbar_public" loginStatus=$loginStatus userData=$userData /}
|
||||
<div class="header-panel shadow-z-2">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container main" >
|
||||
<div class="col-md-4"></div>
|
||||
<div class="col-md-4">
|
||||
<div class="jumbotron" id="logForm">
|
||||
<div class="card_top">
|
||||
<div class="row top-color">
|
||||
<div class="card-top-row">
|
||||
<div class="login-icon"><i class="fa fa-user-circle-o" aria-hidden="true"></i></div>
|
||||
<div class="login-text">登录后方可享用精彩内容</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card_botom">
|
||||
<div class="row bottom-width">
|
||||
<form id="loginForm">
|
||||
<div class="form-group label-floating">
|
||||
<label class="control-label" for="inputEmail">Email 电子邮箱</label>
|
||||
<input type="text" class="form-control" id="inputEmail" name="userMail">
|
||||
</div>
|
||||
<div class="form-group label-floating">
|
||||
<label class="control-label" for="inputPwd">密码</label>
|
||||
<input type="password" class="form-control" id="inputPwd" name="userPass">
|
||||
</div>
|
||||
{eq name="$RegOptions.login_captcha" value="1"}
|
||||
|
||||
<div class="input-group form-group label-floating">
|
||||
<label class="control-label" for="captcha">验证码</label>
|
||||
<input type="text" id="captcha" class="form-control" name="captchaCode">
|
||||
<span class="input-group-btn">
|
||||
<div class="captcha_img">{:captcha_img()}</div>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{else/}
|
||||
{/eq}
|
||||
|
||||
</form> <button class="btn btn-raised btn-primary" id="loginButton">登录</button> <button class="btn btn-raised btn-info" ><i class="fa fa-qq" aria-hidden="true"></i> 使用QQ账号登录</button><div class="link-group">
|
||||
<a href="#" class="noWave">创建一个账户</a><br>
|
||||
<a href="#" class="noWave">忘记密码?</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="jumbotron" id="regForm">
|
||||
<div class="card_top">
|
||||
<div class="row top-color">
|
||||
<div class="card-top-row">
|
||||
<div class="login-icon"><i class="fa fa-user-circle-o" aria-hidden="true"></i></div>
|
||||
<div class="login-text">登录后方可享用精彩内容</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card_botom">
|
||||
<div class="row bottom-width">
|
||||
<form id="loginForm">
|
||||
<div class="form-group label-floating">
|
||||
<label class="control-label" for="inputEmail">Email 电子邮箱</label>
|
||||
<input type="text" class="form-control" id="inputEmail" name="userMail">
|
||||
</div>
|
||||
<div class="form-group label-floating">
|
||||
<label class="control-label" for="inputPwd">密码</label>
|
||||
<input type="password" class="form-control" id="inputPwd" name="userPass">
|
||||
</div>
|
||||
{eq name="$RegOptions.login_captcha" value="1"}
|
||||
|
||||
<div class="input-group form-group label-floating">
|
||||
<label class="control-label" for="captcha">验证码</label>
|
||||
<input type="text" id="captcha" class="form-control" name="captchaCode">
|
||||
<span class="input-group-btn">
|
||||
<div class="captcha_img">{:captcha_img()}</div>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{else/}
|
||||
{/eq}
|
||||
|
||||
</form> <button class="btn btn-raised btn-primary" id="loginButton">登录</button> <button class="btn btn-raised btn-info" ><i class="fa fa-qq" aria-hidden="true"></i> 使用QQ账号登录</button><div class="link-group">
|
||||
<a href="#" class="noWave">创建一个账户</a><br>
|
||||
<a href="#" class="noWave">忘记密码?</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div></div>
|
||||
<div class="col-md-4"></div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
|
||||
</script>
|
||||
<script src="/static/js/login_bind.js"> </script>
|
||||
{$options.js_code}
|
||||
{/block}
|
||||
@@ -1,70 +0,0 @@
|
||||
{extend name="header_public" /}
|
||||
{block name="title"}密码重置- {$options.siteName}{/block}
|
||||
{block name="content"}
|
||||
<link rel="stylesheet" href="/static/css/login.css" />
|
||||
<link rel="stylesheet" href="/static/css/photoswipe.css">
|
||||
<link rel="stylesheet" href="/static/css/default-skin/default-skin.css">
|
||||
<script src="/static/js/jquery.color.js"></script>
|
||||
</head>
|
||||
<body data-ma-header="teal">
|
||||
|
||||
|
||||
<nav class="navbar navbar-inverse" >
|
||||
<div class="container-fluid">
|
||||
<div class="container" >
|
||||
{include file="navbar_public" loginStatus=$loginStatus userData=$userData /}
|
||||
<div class="header-panel shadow-z-2">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container main" >
|
||||
<div class="col-md-4"></div>
|
||||
<div class="col-md-4">
|
||||
<div class="jumbotron" >
|
||||
<div class="card_top">
|
||||
<div class="row top-color">
|
||||
<div class="card-top-row">
|
||||
<div class="login-icon"><i class="fa fa-id-card-o" aria-hidden="true"></i></div>
|
||||
<div class="login-text">密码重置</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card_botom">
|
||||
<div class="row bottom-width">
|
||||
<form id="resetForm">
|
||||
<div class="form-group label-floating">
|
||||
<label class="control-label" for="inputPwd">请输入新密码</label>
|
||||
<input type="password" class="form-control" id="inputPwd" name="password-reg">
|
||||
</div>
|
||||
<div class="form-group label-floating">
|
||||
<label class="control-label" for="inputPwd">重复密码</label>
|
||||
<input type="password" class="form-control" id="inputPwd" name="password-check">
|
||||
</div>
|
||||
<input type="text" style="display:none" class="form-control" id="resetKey" name="key" value="{$key}">
|
||||
|
||||
|
||||
</form> <button class="btn btn-raised btn-primary" id="regButton">重设密码</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div></div>
|
||||
<div class="col-md-4"></div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
|
||||
</script>
|
||||
<script src="/static/js/reset.js"> </script>
|
||||
{$options.js_code}
|
||||
{/block}
|
||||
@@ -1,265 +1,28 @@
|
||||
{extend name="header_home" /}
|
||||
{block name="title"}用户设置- {$options.siteName}{/block}
|
||||
{block name="content"}
|
||||
<link rel="stylesheet" href="/static/css/setting.css" />
|
||||
<style type="text/css">
|
||||
.col-md-3{
|
||||
padding-right: 15px;
|
||||
padding-left: 15px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body >
|
||||
<div id="container">
|
||||
{include file="navbar_home" /}
|
||||
|
||||
<div class="col-md-10 quota_content">
|
||||
<h1>用户设置</h1>
|
||||
<br>
|
||||
<div class="fix_side">
|
||||
<div class="fix">
|
||||
<div class="col-md-9">
|
||||
<ul class="nav nav-tabs" >
|
||||
<li class="active"><a href="#home" data-toggle="tab" aria-expanded="true">基本信息<div class="ripple-container"></div></a></li>
|
||||
<li class=""><a href="#security" data-toggle="tab" aria-expanded="false">安全隐私<div class="ripple-container"></div></a></li>
|
||||
<li class=""><a href="#password" data-toggle="tab" aria-expanded="false">修改密码<div class="ripple-container"></div></a></li>
|
||||
<li class=""><a href="#webdav" data-toggle="tab" aria-expanded="false">WebDAV<div class="ripple-container"></div></a></li>
|
||||
</ul>
|
||||
<div id="myTabContent" class="tab-content">
|
||||
<div class="tab-pane fade active in" id="home">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body" id="packs">
|
||||
<div class="col-md-8">
|
||||
<div class="row fix">
|
||||
<div class="col-md-3 option_name"><label for="uid">UID:</label></div>
|
||||
<div class="col-md-9">
|
||||
<div class="non_input">{$userInfo.uid}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row fix">
|
||||
<div class="col-md-3 option_name"><label for="nick">昵称:</label></div>
|
||||
<div class="col-md-6">
|
||||
<input type="text" class="form-control" id="nick" value="{$userInfo.userNick}" >
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row fix">
|
||||
<div class="col-md-3 option_name"><label for="email">Email:</label></div>
|
||||
<div class="col-md-9">
|
||||
<input type="email" class="form-control" id="email" value="{$userInfo.userMail}" disabled>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row fix">
|
||||
<div class="col-md-3 option_name"><label for="inputEmail">用户组:</label></div>
|
||||
<div class="col-md-9">
|
||||
<div class="non_input group">{$groupData.group_name} </div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row fix">
|
||||
<div class="col-md-3 option_name"><label for="inputEmail">注册日期:</label></div>
|
||||
<div class="col-md-9">
|
||||
<div class="non_input ">{$userInfo.regDate}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row fix">
|
||||
<div class="col-md-3 option_name"><label for="inputEmail"></label></div>
|
||||
<div class="col-md-9">
|
||||
<div class="non_input "><button class="btn btn-raised btn-primary" id="saveNick">保存更改</button></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="avatar">
|
||||
<img src="/Member/Avatar/{$userInfo.uid}/l?cache=no" class="img-circle avatar-img"><br>
|
||||
<button class="btn btn-primary" data-toggle="modal" data-target="#avatar_modal"><i class="fa fa-pencil-square-o" aria-hidden="true"></i> 修改头像</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="security">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body" >
|
||||
<div class="row fix">
|
||||
<div class="col-md-3 option_name"><label for="inputEmail">个人主页:</label></div>
|
||||
<div class="col-md-9">
|
||||
<div ><div class="togglebutton">
|
||||
<label>
|
||||
|
||||
<input type="checkbox" id="homePage" {eq name="$userSQL.profile" value="1"}checked{else}{/eq}>
|
||||
</label>
|
||||
</div></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row fix">
|
||||
<div class="col-md-3 option_name" style="margin-top: 10px;"><label for="inputEmail">二步验证:</label></div>
|
||||
<div class="col-md-9">
|
||||
{eq name="$userSQL.two_step" value="0"}
|
||||
<button class="btn btn-primary btn-raised" id="twoStep"><i class="fa fa-lock" aria-hidden="true"></i> 开启二步验证</button>
|
||||
{else}
|
||||
<button class="btn btn-primary btn-raised"><i class="fa fa-check" aria-hidden="true"></i> 已开启</button>
|
||||
{/eq}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="password">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body" >
|
||||
<div class="row fix">
|
||||
<div class="col-md-3 option_name"><label for="inputEmail">原密码:</label></div>
|
||||
<div class="col-md-6">
|
||||
<input type="password" class="form-control" id="passOrigin" >
|
||||
</div>
|
||||
</div>
|
||||
<div class="row fix">
|
||||
<div class="col-md-3 option_name"><label for="inputEmail">新密码:</label></div>
|
||||
<div class="col-md-6">
|
||||
<input type="password" class="form-control" id="passNew" >
|
||||
</div>
|
||||
</div>
|
||||
<div class="row fix">
|
||||
<div class="col-md-3 option_name"><label for="inputEmail">确认新密码:</label></div>
|
||||
<div class="col-md-6">
|
||||
<input type="password" class="form-control" id="passNewRepet" >
|
||||
</div>
|
||||
</div>
|
||||
<div class="row fix">
|
||||
<div class="col-md-3 option_name"><label for="inputEmail"></label></div>
|
||||
<div class="col-md-9">
|
||||
<div class="non_input "><button class="btn btn-raised btn-primary waves-effect" id="savePwd">保存更改</button></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade" id="webdav">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body" >
|
||||
{eq name="groupData.webdav" value="0"}
|
||||
<div class="alert alert-warning" role="alert">
|
||||
您当前的用户组不支持WebDAV
|
||||
</div>
|
||||
{else/}
|
||||
<div class="row fix">
|
||||
<div class="col-md-3 option_name"><label for="inputEmail">连接地址:</label></div>
|
||||
<div class="col-md-6">
|
||||
<input type="text" class="form-control" id="webdavUrl" value="{$options.siteURL}WebDav/Api/uid/{$userInfo.uid}" spellcheck="false" readonly>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row fix">
|
||||
<div class="col-md-3 option_name"><label for="inputEmail">用户名:</label></div>
|
||||
<div class="col-md-6">
|
||||
<input type="text" class="form-control" id="webdavUsername" value="{$userInfo.userMail}" spellcheck="false" readonly>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row fix">
|
||||
<div class="col-md-3 option_name" style="margin-top: 10px;"><label for="inputEmail">登录密码:</label></div>
|
||||
<div class="col-md-9">
|
||||
<button class="btn btn-primary btn-raised" id="setWebdavPwd"><i class="fa fa-lock" aria-hidden="true"></i> 设置/更改密码</button>
|
||||
</div>
|
||||
</div>
|
||||
{/eq}<br>
|
||||
<p>你可以使用任何支持WebDAV协议的文件管理工具或操作系统将网盘映射到本地,方便多端同步管理。初次使用请先设置WebDAV登录密码,此密码默认与登录密码不相同。</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3"><div class="panel panel-default">
|
||||
<div class="panel-heading">公告</div>
|
||||
<div class="panel-body">
|
||||
公告内容
|
||||
</div>
|
||||
</div></div>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<div class="fix_side">
|
||||
<div class="fix">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal fade" tabindex="-1" role="dialog" id="avatar_modal">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title">修改头像</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row fix">
|
||||
<div class="col-md-4"><div class="avatar"><img src="/Member/Avatar/{$userInfo.uid}/l?cache=no" class="img-circle avatar-img"><br></div></div>
|
||||
<div class="col-md-8">
|
||||
<span class="btn btn-raised btn-info fileinput-button" id="uploadAvatar">
|
||||
<span id="upload-text">上传头像</span>
|
||||
<input type="file" accept="image/*" id="avatar_file" name="avatar">
|
||||
</span>
|
||||
<br><button class="btn btn-raised btn-info" id="useGravatar">使用Gravatar头像</button>
|
||||
<br>修改头像后请清理浏览器缓存
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-primary " data-dismiss="modal">取消</button>
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div><!-- /.modal -->
|
||||
<div class="modal fade" tabindex="-1" role="dialog" id="two_step_modal">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title">开启二步验证</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row fix">
|
||||
<div class="col-md-4"><img id="qrcode"></div>
|
||||
<div class="col-md-8">
|
||||
<div class="alert alert-success" role="alert">请使用任意二步验证APP或者支持二步验证的密码管理软件扫描左侧二维码添加本站。扫描完成后请填写二步验证APP给出的6位验证码以开启二步验证。</div>
|
||||
<input type="number" class="form-control" placeholder="请输入6位验证码" id="vCode">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-info " id="confirm">确认开启</button>
|
||||
<button class="btn btn-primary " data-dismiss="modal">取消</button>
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div><!-- /.modal -->
|
||||
<div class="modal fade" tabindex="-1" role="dialog" id="set_webdav_pwd">
|
||||
<div class="modal-dialog modal-sm" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title">设置WebDAV认证密码</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="row fix">
|
||||
<label>请输入密码:</label>
|
||||
<input type="password" id="webdav_pwd" class="form-control" autocomplete="false">
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-info " id="confirmWebdav">保存</button>
|
||||
<button class="btn btn-primary " data-dismiss="modal">取消</button>
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div><!-- /.modal -->
|
||||
</body>
|
||||
<script src="/static/js/material.js"></script>
|
||||
<script src="/static/js/uploader.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
upload_load=0;
|
||||
</script>
|
||||
<script src="/static/js/setting.js"></script>
|
||||
{$options.js_code}
|
||||
</html>
|
||||
{/block}
|
||||
<!doctype html><html lang="zh-cn"><head><meta charset="utf-8"><link rel="shortcut icon" href="/favicon.ico"><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"><meta name="theme-color" content="{$options.themeColor}"/><link rel="manifest" href="/manifest.json"><title>用户设置- {$options.siteName}</title><script type="text/javascript">colorTheme = {:json_encode($options["themeConfig"])};
|
||||
colorThemeOptions = {$options["themes"]};
|
||||
isHomePage = false;
|
||||
isSharePage = false;
|
||||
pageId="userSetting";
|
||||
siteUrl = "{$options.siteURL}";
|
||||
userInfo = {
|
||||
uid: {$userInfo.uid},
|
||||
nick: "{$userInfo.userNick}",
|
||||
email: "{$userInfo.userMail}",
|
||||
group: "{$userInfo.groupData.group_name}",
|
||||
groupId: {$userInfo.groupData.id},
|
||||
groupColor: "{$userInfo.groupData.color}",
|
||||
regTime: "{$userSQL.user_date}",
|
||||
homePage: "{$userSQL.profile}",
|
||||
twoFactor: "{$userSQL.two_step}",
|
||||
webdav:"{$userInfo.groupData.webdav}",
|
||||
};
|
||||
siteInfo = {
|
||||
mainTitle: "{$options.siteName}",
|
||||
};
|
||||
uploadConfig = {
|
||||
allowSource: false,
|
||||
allowShare: false,
|
||||
allowRemoteDownload: "0",
|
||||
allowTorrentDownload: "0",
|
||||
};
|
||||
isMobile = window.innerWidth < 600;</script></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(l){function e(e){for(var r,t,n=e[0],o=e[1],u=e[2],f=0,i=[];f<n.length;f++)t=n[f],p[t]&&i.push(p[t][0]),p[t]=0;for(r in o)Object.prototype.hasOwnProperty.call(o,r)&&(l[r]=o[r]);for(s&&s(e);i.length;)i.shift()();return c.push.apply(c,u||[]),a()}function a(){for(var e,r=0;r<c.length;r++){for(var t=c[r],n=!0,o=1;o<t.length;o++){var u=t[o];0!==p[u]&&(n=!1)}n&&(c.splice(r--,1),e=f(f.s=t[0]))}return e}var t={},p={26:0},c=[];function f(e){if(t[e])return t[e].exports;var r=t[e]={i:e,l:!1,exports:{}};return l[e].call(r.exports,r,r.exports,f),r.l=!0,r.exports}f.m=l,f.c=t,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(r,e){if(1&e&&(r=f(r)),8&e)return r;if(4&e&&"object"==typeof r&&r&&r.__esModule)return r;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:r}),2&e&&"string"!=typeof r)for(var n in r)f.d(t,n,function(e){return r[e]}.bind(null,n));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="/";var r=window.webpackJsonp=window.webpackJsonp||[],n=r.push.bind(r);r.push=e,r=r.slice();for(var o=0;o<r.length;o++)e(r[o]);var s=n;a()}([])</script><script src="/static/js/0.chunk.js"></script><script src="/static/js/1.chunk.js"></script><script src="/static/js/setting.chunk.js"></script></body></html>
|
||||
@@ -1,66 +0,0 @@
|
||||
{extend name="header_public" /}
|
||||
{block name="title"}两步验证- {$options.siteName}{/block}
|
||||
{block name="content"}
|
||||
<link rel="stylesheet" href="/static/css/login.css" />
|
||||
<link rel="stylesheet" href="/static/css/photoswipe.css">
|
||||
<link rel="stylesheet" href="/static/css/default-skin/default-skin.css">
|
||||
<script src="/static/js/jquery.color.js"></script>
|
||||
</head>
|
||||
<body data-ma-header="teal">
|
||||
|
||||
|
||||
<nav class="navbar navbar-inverse" >
|
||||
<div class="container-fluid">
|
||||
<div class="container" >
|
||||
{include file="navbar_public" loginStatus=$loginStatus userData=$userData /}
|
||||
<div class="header-panel shadow-z-2">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container main" >
|
||||
<div class="col-md-4"></div>
|
||||
<div class="col-md-4">
|
||||
<div class="jumbotron" >
|
||||
<div class="card_top">
|
||||
<div class="row top-color">
|
||||
<div class="card-top-row">
|
||||
<div class="login-icon"><i class="fa fa-lock" aria-hidden="true"></i></div>
|
||||
<div class="login-text">由于您开启了两步验证,请输入您的两步验证APP上显示的验证码</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card_botom">
|
||||
<div class="row bottom-width">
|
||||
<form id="loginForm">
|
||||
<div class="form-group label-floating">
|
||||
<label class="control-label" for="inputEmail">验证码</label>
|
||||
<input type="text" class="form-control" id="inputEmail" name="code">
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</form> <button class="btn btn-raised btn-primary" id="loginButton">继续登录</button>
|
||||
<br>如果您丢失了两步验证秘钥,请联系站点管理员核验身份后取消二步验证。
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div></div>
|
||||
<div class="col-md-4"></div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
|
||||
</script>
|
||||
<script src="/static/js/two_step.js"> </script>
|
||||
{$options.js_code}
|
||||
{/block}
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="container-fluid">
|
||||
<!-- Brand and toggle get grouped for better mobile display -->
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="/">
|
||||
<a class="navbar-brand waves-light" href="/">
|
||||
|
||||
</a>
|
||||
|
||||
@@ -19,14 +19,26 @@
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle avatar-a" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><img src="/Member/Avatar/{$userInfo.uid}/s" class="img-circle avatar-s"> {$userInfo.userNick} <span class="caret"></span></a>
|
||||
<a href="#" class="dropdown-toggle avatar-a waves-light" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><img src="/Member/Avatar/{$userInfo.uid}/s" class="img-circle avatar-s"> {$userInfo.userNick} <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="/Profile/{$userInfo.uid}">个人主页</a></li>
|
||||
<li><a href="/Member/Setting">设置</a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
{eq name="$userInfo.groupId" value="1"}
|
||||
<li><a href="/Admin">管理面板</a></li>
|
||||
{/eq}
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a href="/Member/LogOut">退出登录</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="mobile-addition">
|
||||
<a href="/Share/My" role="button" aria-haspopup="true" ><i class="fa fa-share-alt" aria-hidden="true"></i> 我的分享</a>
|
||||
</li>
|
||||
<li class="mobile-addition">
|
||||
<a href="/Explore/Search" role="button" aria-haspopup="true" ><i class="fa fa-search" aria-hidden="true"></i> 搜索分享</a>
|
||||
</li>
|
||||
<li class="mobile-addition">
|
||||
<a href="/Home/Album" role="button" aria-haspopup="true" ><i class="fa fa-picture-o" aria-hidden="true"></i> 图片集</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div><!-- /.navbar-collapse -->
|
||||
</div><!-- /.container-fluid -->
|
||||
@@ -51,7 +63,7 @@
|
||||
|
||||
<div id="container">
|
||||
|
||||
<button class="btn btn-raised btn-info btn-lg upload_button" id="pickfiles" >
|
||||
<button class="btn btn-raised btn-info btn-lg upload_button waves-light" id="pickfiles" >
|
||||
<i class="glyphicon glyphicon-plus"></i>
|
||||
<span id="up_text"></span>
|
||||
</button>
|
||||
@@ -117,6 +129,11 @@
|
||||
<a href="/Home/Album" class="list-group-item">
|
||||
<i class="fa fa-picture-o" aria-hidden="true"></i> 图片集
|
||||
</a>
|
||||
{eq name=':(explode(",",$groupData.aria2)[0] OR explode(",",$groupData.aria2)[1])' value="1"}
|
||||
<a href="/Home/Download" class="list-group-item">
|
||||
<i class="fa fa-cloud-download" aria-hidden="true"></i> 离线下载
|
||||
</a>
|
||||
{/eq}
|
||||
</div>
|
||||
<div clss="usage" style=" visibility: visible;
|
||||
position: absolute;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<div class="navbar-header">
|
||||
<div >
|
||||
<a class="navbar-brand" href="/">
|
||||
<a class="navbar-brand waves-light" href="/">
|
||||
|
||||
</a>
|
||||
</div>
|
||||
@@ -19,7 +19,7 @@
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
{eq name="$loginStatus" value="1"}
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle avatar-a" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><img src="/Member/Avatar/{$userData.id}/s" class="img-circle avatar-s"> {$userData.user_nick} <span class="caret"></span></a>
|
||||
<a href="#" class="dropdown-toggle avatar-a waves-light" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><img src="/Member/Avatar/{$userData.id}/s" class="img-circle avatar-s"> {$userData.user_nick} <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="/Home">我的文件</a></li>
|
||||
<li><a href="/Profile/{$userData.id}">个人主页</a></li>
|
||||
@@ -30,7 +30,7 @@
|
||||
</li>
|
||||
{else/}
|
||||
<li >
|
||||
<a href="/Login" class="dropdown-toggle" role="button" aria-haspopup="true" aria-expanded="false"><i class="fa fa-user mr-1"></i> 登录/注册 </a>
|
||||
<a href="/Login" class="dropdown-toggle waves-light" role="button" aria-haspopup="true" aria-expanded="false"><i class="fa fa-user mr-1"></i> 登录/注册 </a>
|
||||
|
||||
</li>
|
||||
{/eq}
|
||||
|
||||
@@ -1,115 +1,33 @@
|
||||
{extend name="header_public" /}
|
||||
{block name="title"}用户主页 - {$options.siteName}{/block}
|
||||
{block name="content"}
|
||||
<link rel="stylesheet" href="/static/css/profile.css" />
|
||||
</head>
|
||||
<body data-ma-header="teal">
|
||||
<nav class="navbar navbar-inverse" >
|
||||
<div class="container-fluid">
|
||||
<div class="container" >
|
||||
{include file="navbar_public" /}
|
||||
<div class="header-panel shadow-z-2">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container main-h">
|
||||
<div class="col-md-3">
|
||||
<div class="card type--profile">
|
||||
<header class="card-heading card-background" id="card_img_02">
|
||||
<img src="/Member/Avatar/{$userInfo.id}/l" alt="" class="img-circle">
|
||||
<ul class="card-actions icons right-top">
|
||||
<li class="dropdown" style="display: none;">
|
||||
<a href="javascript:void(0)" data-toggle="dropdown" aria-expanded="false">
|
||||
<i class="zmdi zmdi-more-vert text-white"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-menu-right">
|
||||
<li>
|
||||
<a href="javascript:void(0)">Option One</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="javascript:void(0)">Option Two</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="javascript:void(0)">Option Three</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</header>
|
||||
<div class="card-body">
|
||||
<h3 class="name">{$userInfo.user_nick|htmlspecialchars=ENT_NOQUOTES}</h3>
|
||||
<span class="title span-fix"><span class="label span-fix label-{$groupData.color}">{$groupData.group_name}</span></span>
|
||||
|
||||
</div>
|
||||
<footer class="card-footer border-top">
|
||||
<div class="row row p-t-10 p-b-10">
|
||||
<div class="col-xs-4"><span class="count">{$shareCount}</span><span>公开分享</span></div>
|
||||
<div class="col-xs-4"><span class="count">{$regDays}</span><span>注册天数</span></div>
|
||||
<div class="col-xs-4"><span class="count">{$userInfo.id}</span><span>用户编号</span></div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
<div class="jumbotron">
|
||||
<div class="card_botom">
|
||||
<div class="row bottom-width">
|
||||
<ul class="nav nav-tabs" >
|
||||
<li id="all"><a href="?page=1" aria-expanded="true">全部分享<div class="ripple-container"></div></a></li>
|
||||
<li id="hot"><a href="?type=hot" aria-expanded="false">热门分享<div class="ripple-container"></div></a></li>
|
||||
|
||||
</ul>
|
||||
<div id="myTabContent" class="tab-content">
|
||||
<div class="tab-pane fade active in">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body" >
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="50%">文件名 </th>
|
||||
<th class="cent">分享日期</th>
|
||||
<th class="cent">下载次数</th>
|
||||
<th class="cent">浏览次数</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>{volist name='list' id='shares'}
|
||||
<tr>
|
||||
<td >{switch $shares.source_type}
|
||||
{case file}<i class="fa fa-file" aria-hidden="true"></i> {/case}
|
||||
{case dir}<i class="fa fa-folder-open blue" aria-hidden="true"></i> {/case}
|
||||
|
||||
{/switch} <a href="/s/{$shares.share_key}" class="fname" target="_blank">{$shares.fileData|htmlspecialchars=ENT_NOQUOTES}</a></td>
|
||||
<td class="cent">{$shares.share_time}</td>
|
||||
<td align="center">{$shares.download_num}</td>
|
||||
<td align="center">{$shares.view_num}</td>
|
||||
</tr>
|
||||
|
||||
{/volist}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
<div class="navi">
|
||||
{eq name="$type" value="hot"}
|
||||
{else/}
|
||||
{$listOrigin->render()}
|
||||
{/eq}
|
||||
</div>
|
||||
</div></div></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div></div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
<script type="text/javascript">
|
||||
</script>
|
||||
<script src="/static/js/material.js"></script>
|
||||
<script src="/static/js/profile.js"> </script>
|
||||
{$options.js_code}
|
||||
{/block}
|
||||
<!doctype html><html lang="zh-cn"><head><meta charset="utf-8"><link rel="shortcut icon" href="/favicon.ico"><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"><meta name="theme-color" content="{$options.themeColor}"/><link rel="manifest" href="/manifest.json"><title>用户主页 - {$options.siteName}</title><script type="text/javascript">colorTheme = {:json_encode($options["themeConfig"])};
|
||||
isHomePage = false;
|
||||
isSharePage = false;
|
||||
pageId="profile";
|
||||
taegetUserInfo = {
|
||||
uid:{$targetUserInfo.id},
|
||||
nickname:"{$targetUserInfo.user_nick}",
|
||||
regDate:"{$targetUserInfo.user_date}",
|
||||
shareCount:"{$shareCount}",
|
||||
group:"{$groupData.group_name}",
|
||||
};
|
||||
userInfo = {
|
||||
uid: {$userInfo.uid},
|
||||
nick: "{$userInfo.userNick}",
|
||||
email: "{$userInfo.userMail}",
|
||||
group: "{$userInfo.groupData.group_name}",
|
||||
groupId: {$userInfo.groupData.id},
|
||||
groupColor: "{$userInfo.groupData.color}",
|
||||
regTime: "{$userSQL.user_date}",
|
||||
homePage: "{$userSQL.profile}",
|
||||
twoFactor: "{$userSQL.two_step}",
|
||||
webdav:"{$userInfo.groupData.webdav}",
|
||||
};
|
||||
siteInfo = {
|
||||
mainTitle: "{$options.siteName}",
|
||||
};
|
||||
uploadConfig = {
|
||||
allowSource: false,
|
||||
allowShare: false,
|
||||
allowRemoteDownload: "0",
|
||||
allowTorrentDownload: "0",
|
||||
};
|
||||
isMobile = window.innerWidth < 600;</script></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(l){function e(e){for(var r,t,n=e[0],o=e[1],u=e[2],f=0,i=[];f<n.length;f++)t=n[f],p[t]&&i.push(p[t][0]),p[t]=0;for(r in o)Object.prototype.hasOwnProperty.call(o,r)&&(l[r]=o[r]);for(s&&s(e);i.length;)i.shift()();return c.push.apply(c,u||[]),a()}function a(){for(var e,r=0;r<c.length;r++){for(var t=c[r],n=!0,o=1;o<t.length;o++){var u=t[o];0!==p[u]&&(n=!1)}n&&(c.splice(r--,1),e=f(f.s=t[0]))}return e}var t={},p={25:0},c=[];function f(e){if(t[e])return t[e].exports;var r=t[e]={i:e,l:!1,exports:{}};return l[e].call(r.exports,r,r.exports,f),r.l=!0,r.exports}f.m=l,f.c=t,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(r,e){if(1&e&&(r=f(r)),8&e)return r;if(4&e&&"object"==typeof r&&r&&r.__esModule)return r;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:r}),2&e&&"string"!=typeof r)for(var n in r)f.d(t,n,function(e){return r[e]}.bind(null,n));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="/";var r=window.webpackJsonp=window.webpackJsonp||[],n=r.push.bind(r);r.push=e,r=r.slice();for(var o=0;o<r.length;o++)e(r[o]);var s=n;a()}([])</script><script src="/static/js/0.chunk.js"></script><script src="/static/js/16.chunk.js"></script><script src="/static/js/profile.chunk.js"></script></body></html>
|
||||
@@ -1,83 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="zh_cn" data-ng-app="FileManagerApp">
|
||||
<head>
|
||||
<!--
|
||||
* Angular FileManager v1.5.1 (https://github.com/joni2back/angular-filemanager)
|
||||
* Jonas Sciangula Street <joni2back@gmail.com>
|
||||
* Licensed under MIT (https://github.com/joni2back/angular-filemanager/blob/master/LICENSE)
|
||||
-->
|
||||
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
|
||||
<meta charset="utf-8">
|
||||
<title>我的文件 - {$options.siteName}</title>
|
||||
<!-- third party -->
|
||||
<script src="/static/js/angular.min.js"></script>
|
||||
<script src="/static/js/angular-translate.min.js"></script>
|
||||
|
||||
<script src="/static/js/jquery.min.js"></script>
|
||||
<link rel="stylesheet" href="/static/css/bootstrap.min.css" />
|
||||
<link rel="stylesheet" href="/static/css/material.css" />
|
||||
|
||||
<script src="/static/js/bootstrap.min.js"></script>
|
||||
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.0/css/font-awesome.min.css">
|
||||
<!-- /third party -->
|
||||
<!-- Comment if you need to use raw source code -->
|
||||
<link href="/static/css/angular-filemanager.min.css" rel="stylesheet">
|
||||
<link href="/static/css/toastr.min.css" rel="stylesheet">
|
||||
<script type="text/javascript" src="/static/js/toastr.min.js"></script>
|
||||
<script src="/static/js/angular-filemanager.min.js"></script>
|
||||
<!-- /Comment if you need to use raw source code -->
|
||||
<script type="text/javascript">
|
||||
uploadConfig={
|
||||
saveType : "{$policyData.policy_type}",
|
||||
maxSize : "{$policyData.max_size}mb",
|
||||
allowedType: [
|
||||
{$extLimit}
|
||||
],
|
||||
allowSource : "{$policyData.origin_link}",
|
||||
upUrl : "{$policyData.server}",
|
||||
allowShare:"{$groupData.allow_share}",
|
||||
};
|
||||
</script>
|
||||
<script src="/static/js/home.js"></script>
|
||||
</head>
|
||||
<body class="ng-cloak">
|
||||
<div id="container">
|
||||
{include file="navbar_home" /}
|
||||
<div class="col-md-2 s" id="side">
|
||||
<div class="list-group" id="b">
|
||||
<a href="/Home" class="list-group-item active">
|
||||
<i class="fa fa-file" aria-hidden="true"></i> 我的文件
|
||||
</a>
|
||||
<a href="/Share" class="list-group-item"> <i class="fa fa-share-alt" aria-hidden="true"></i> 我的分享
|
||||
</a>
|
||||
<a href="#" class="list-group-item"><i class="fa fa-database" aria-hidden="true"></i> 容量配额
|
||||
</a>
|
||||
</div>
|
||||
<div clss="usage" style=" visibility: visible;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100px;
|
||||
top: auto;
|
||||
bottom: 0px;
|
||||
background-color: #f3f3f3;padding: 15px">
|
||||
<div class="usage-title">容量使用:</div>
|
||||
<div class="usage-bar">
|
||||
<div class="progress progress-striped active">
|
||||
<div class="progress-bar" id="memory_bar"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="usage-text"><span id="used">--</span>/<span id="total">--</span></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-10">
|
||||
<angular-filemanager></angular-filemanager>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
<script src="/static/js/material.js"></script>
|
||||
<script type="text/javascript">
|
||||
upload_load=0;
|
||||
|
||||
</script>
|
||||
{$options.js_code}
|
||||
</html>
|
||||
@@ -1,105 +1,32 @@
|
||||
{extend name="header_dir_share" /}
|
||||
{block name="title"}{$dirData.folder_name} - {$options.siteName}{/block}
|
||||
{block name="content"}
|
||||
<link rel="stylesheet" href="/static/css/share_dir.css" />
|
||||
<link rel="stylesheet" href="/static/css/photoswipe.css">
|
||||
<link rel="stylesheet" href="/static/css/default-skin/default-skin.css">
|
||||
</head>
|
||||
<body data-ma-header="teal">
|
||||
<div class="modal fade" id="previewModal" role="dialog">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" onclick="audioPause()" data-dismiss="modal">
|
||||
<span aria-hidden="true">×</span>
|
||||
<span class="sr-only ng-binding">关闭</span>
|
||||
</button>
|
||||
<h4 class="modal-title">视频预览</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="text-center previewContent">
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
|
||||
<!-- Background of PhotoSwipe.
|
||||
It's a separate element, as animating opacity is faster than rgba(). -->
|
||||
<div class="pswp__bg"></div>
|
||||
<!-- Slides wrapper with overflow:hidden. -->
|
||||
<div class="pswp__scroll-wrap">
|
||||
<!-- Container that holds slides. PhotoSwipe keeps only 3 slides in DOM to save memory. -->
|
||||
<div class="pswp__container">
|
||||
<!-- don't modify these 3 pswp__item elements, data is added later on -->
|
||||
<div class="pswp__item"></div>
|
||||
<div class="pswp__item"></div>
|
||||
<div class="pswp__item"></div>
|
||||
</div>
|
||||
<!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->
|
||||
<div class="pswp__ui pswp__ui--hidden">
|
||||
<div class="pswp__top-bar">
|
||||
<!-- Controls are self-explanatory. Order can be changed. -->
|
||||
<div class="pswp__counter"></div>
|
||||
<button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
|
||||
<button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
|
||||
<button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>
|
||||
<!-- Preloader demo https://codepen.io/dimsemenov/pen/yyBWoR -->
|
||||
<!-- element will get class pswp__preloader--active when preloader is running -->
|
||||
<div class="pswp__preloader">
|
||||
<div class="pswp__preloader__icn">
|
||||
<div class="pswp__preloader__cut">
|
||||
<div class="pswp__preloader__donut"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
|
||||
<div class="pswp__share-tooltip"></div>
|
||||
</div>
|
||||
<button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
|
||||
</button>
|
||||
<button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
|
||||
</button>
|
||||
<div class="pswp__caption">
|
||||
<div class="pswp__caption__center"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<nav class="navbar navbar-inverse" >
|
||||
<div class="container-fluid">
|
||||
<div class="container" >
|
||||
{include file="navbar_public" loginStatus=$loginStatus userData=$userInfo /}
|
||||
<div class="header-panel shadow-z-2">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container main-h">
|
||||
|
||||
<div class="">
|
||||
<div class="jumbotron">
|
||||
|
||||
|
||||
<div class="card_botom">
|
||||
<div class="row bottom-width">
|
||||
|
||||
<div class="manager"><angular-filemanager></angular-filemanager>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
<script type="text/javascript">
|
||||
<!doctype html><html lang="zh-cn"><head><meta charset="utf-8"><link rel="shortcut icon" href="/favicon.ico"><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"><meta name="theme-color" content="{$options.themeColor}"/><link rel="manifest" href="/manifest.json"><title>{$dirData.folder_name} - {$options.siteName}</title><script type="text/javascript">colorTheme = {:json_encode($options["themeConfig"])};
|
||||
isHomePage = false;
|
||||
isSharePage = true;
|
||||
pageId="";
|
||||
apiURL = {
|
||||
imgThumb: "/Share/Thumb/{$shareData.share_key}",
|
||||
preview: "/Share/Preview/{$shareData.share_key}",
|
||||
download: "/Share/Download/{$shareData.share_key}",
|
||||
docPreiview: '/Share/DocPreview/{$shareData.share_key}',
|
||||
listFile:'/Share/ListFile/{$shareData.share_key}'
|
||||
};
|
||||
userInfo = {
|
||||
uid: {$userData.uid},
|
||||
nick: "{$userData.userNick}",
|
||||
email: "{$userData.userMail}",
|
||||
group: "{$userData.groupData.group_name}",
|
||||
groupId: {$userData.groupData.id},
|
||||
groupColor: "{$userData.groupData.color}",
|
||||
};
|
||||
siteInfo = {
|
||||
mainTitle: "{$dirData.folder_name}",
|
||||
};
|
||||
path = "{$path}";
|
||||
uploadConfig = {
|
||||
allowSource: false,
|
||||
allowShare: false,
|
||||
allowRemoteDownload: "0",
|
||||
allowTorrentDownload: "0",
|
||||
};
|
||||
shareInfo={
|
||||
shareDate : "{$shareData.share_time}",
|
||||
ownerUid:"{$userInfo.id}",
|
||||
@@ -116,15 +43,5 @@
|
||||
allowPreview:{$allowPreview},
|
||||
{/eq}
|
||||
};
|
||||
</script>
|
||||
<script src="/static/js/angular.min.js"></script>
|
||||
<script src="/static/js/angular-translate.min.js"></script>
|
||||
<script src="/static/js/jquery.min.js"></script>
|
||||
<script src="/static/js/jquery.min.js"></script>
|
||||
<script src="/static/js/material.js"></script>
|
||||
<script src="/static/js/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="/static/js/toastr.min.js"></script>
|
||||
<script src="/static/js/filemanager_share.js"></script>
|
||||
<script src="/static/js/share_dir.js"> </script>
|
||||
{$options.js_code}
|
||||
{/block}
|
||||
mediaType = {},
|
||||
isMobile = window.innerWidth < 600;</script></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(c){function e(e){for(var t,r,n=e[0],o=e[1],a=e[2],u=0,i=[];u<n.length;u++)r=n[u],f[r]&&i.push(f[r][0]),f[r]=0;for(t in o)Object.prototype.hasOwnProperty.call(o,t)&&(c[t]=o[t]);for(d&&d(e);i.length;)i.shift()();return s.push.apply(s,a||[]),l()}function l(){for(var e,t=0;t<s.length;t++){for(var r=s[t],n=!0,o=1;o<r.length;o++){var a=r[o];0!==f[a]&&(n=!1)}n&&(s.splice(t--,1),e=p(p.s=r[0]))}return e}var r={},i={27:0},f={27:0},s=[];function p(e){if(r[e])return r[e].exports;var t=r[e]={i:e,l:!1,exports:{}};return c[e].call(t.exports,t,t.exports,p),t.l=!0,t.exports}p.e=function(s){var e=[];i[s]?e.push(i[s]):0!==i[s]&&{15:1}[s]&&e.push(i[s]=new Promise(function(e,n){for(var t="static/css/"+({}[s]||s)+".chunk.css",o=p.p+t,r=document.getElementsByTagName("link"),a=0;a<r.length;a++){var u=(c=r[a]).getAttribute("data-href")||c.getAttribute("href");if("stylesheet"===c.rel&&(u===t||u===o))return e()}var i=document.getElementsByTagName("style");for(a=0;a<i.length;a++){var c;if((u=(c=i[a]).getAttribute("data-href"))===t||u===o)return e()}var l=document.createElement("link");l.rel="stylesheet",l.type="text/css",l.onload=e,l.onerror=function(e){var t=e&&e.target&&e.target.src||o,r=new Error("Loading CSS chunk "+s+" failed.\n("+t+")");r.request=t,n(r)},l.href=o,document.getElementsByTagName("head")[0].appendChild(l)}).then(function(){i[s]=0}));var r=f[s];if(0!==r)if(r)e.push(r[2]);else{var t=new Promise(function(e,t){r=f[s]=[e,t]});e.push(r[2]=t);var n,o=document.getElementsByTagName("head")[0],a=document.createElement("script");a.charset="utf-8",a.timeout=120,p.nc&&a.setAttribute("nonce",p.nc),a.src=p.p+"static/js/"+({}[s]||s)+".chunk.js",n=function(e){a.onerror=a.onload=null,clearTimeout(u);var t=f[s];if(0!==t){if(t){var r=e&&("load"===e.type?"missing":e.type),n=e&&e.target&&e.target.src,o=new Error("Loading chunk "+s+" failed.\n("+r+": "+n+")");o.type=r,o.request=n,t[1](o)}f[s]=void 0}};var u=setTimeout(function(){n({type:"timeout",target:a})},12e4);a.onerror=a.onload=n,o.appendChild(a)}return Promise.all(e)},p.m=c,p.c=r,p.d=function(e,t,r){p.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},p.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},p.t=function(t,e){if(1&e&&(t=p(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var r=Object.create(null);if(p.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var n in t)p.d(r,n,function(e){return t[e]}.bind(null,n));return r},p.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return p.d(t,"a",t),t},p.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},p.p="/",p.oe=function(e){throw console.error(e),e};var t=window.webpackJsonp=window.webpackJsonp||[],n=t.push.bind(t);t.push=e,t=t.slice();for(var o=0;o<t.length;o++)e(t[o]);var d=n;l()}([])</script><script src="/static/js/0.chunk.js"></script><script src="/static/js/1.chunk.js"></script><script src="/static/js/folderShare.chunk.js"></script></body></html>
|
||||
@@ -1,98 +1,22 @@
|
||||
{extend name="header_home" /}
|
||||
{block name="title"}我的分享- {$options.siteName}{/block}
|
||||
{block name="content"}
|
||||
<script src="/static/js/share_home.js"></script>
|
||||
</head>
|
||||
<body >
|
||||
|
||||
|
||||
<div class="modal fade bs-example-modal-sm" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" id="deleteConfirm">
|
||||
<div class="modal-dialog modal-sm" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title" id="myModalLabel">确认</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
您确定要取消此分享吗?
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn pro-btn" data-dismiss="modal">取消</button>
|
||||
<button type="button" class="btn btn-primary pro-btn" onclick="deleteConfirm();">确定</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal fade bs-example-modal-sm" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" id="changeConfirm">
|
||||
<div class="modal-dialog modal-sm" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title" id="myModalLabel">确认</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
您确定要将此分享改为<span id="shareType"></span>?
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn pro-btn" data-dismiss="modal">取消</button>
|
||||
<button type="button" class="btn btn-primary pro-btn" onclick="changeConfirm();">确定</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div id="container">
|
||||
{include file="navbar_home" /}
|
||||
|
||||
|
||||
<div class="col-md-10 share-content">
|
||||
<h1>我的分享</h1>
|
||||
<br>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered table-hover">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="50%">文件名</th>
|
||||
<th class="table_center">分享日期</th>
|
||||
<th class="table_center">分享类型</th>
|
||||
<th class="table_center">下载次数</th>
|
||||
<th class="table_center">浏览次数</th>
|
||||
<th class="table_center">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
{volist name='list' id='shares'}
|
||||
<tr id="{$shares.share_key}">
|
||||
|
||||
<td >{switch $shares.source_type}
|
||||
{case file}<i class="fa fa-file" aria-hidden="true"></i> {/case}
|
||||
{case dir}<i class="fa fa-folder-open blue" aria-hidden="true"></i> {/case}
|
||||
{/switch} {$shares.fileData}</td>
|
||||
<td align="center">{$shares.share_time}</td>
|
||||
<td align="center">{switch $shares.type}
|
||||
{case private}<button class="btn btn-default small-btn" data-toggle="tooltip" data-placement="top" title="密码:{$shares.share_pwd},点击变更公开类型" onclick="changeType('{$shares.share_key}','private')"><i class="fa fa-lock" aria-hidden="true"></i></button> {/case}
|
||||
{case public}<button class="btn btn-default small-btn" data-toggle="tooltip" data-placement="top" title="变更公开类型" onclick="changeType('{$shares.share_key}','public')"><i class="fa fa-eye" aria-hidden="true"></i></button> {/case}
|
||||
{/switch} </td>
|
||||
<td align="center">{$shares.download_num}</td>
|
||||
<td align="center">{$shares.view_num}</td>
|
||||
<td align="center"><button class="btn btn-info small-btn-border" data-toggle="tooltip" data-placement="top" title="查看分享" onclick="openShare('{$shares.share_key}')"><i class="fa fa-share-square" aria-hidden="true"></i></button>
|
||||
<button class="btn btn-danger small-btn-border" data-toggle="tooltip" data-placement="top" title="删除分享" onclick="deleteShare('{$shares.share_key}')"><i class="fa fa-times" aria-hidden="true"></i></button>
|
||||
<button class="btn btn-success small-btn-border" data-toggle="tooltip" data-placement="top" title="变更公开类型" onclick="changeType('{$shares.share_key}','{$shares.type}')"><i class="fa fa-unlock-alt" aria-hidden="true"></i></button>
|
||||
</td>
|
||||
</tr>
|
||||
{/volist}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{$listOrigin->render()}
|
||||
</body>
|
||||
<script src="/static/js/material.js"></script>
|
||||
<script type="text/javascript">
|
||||
upload_load=0;
|
||||
|
||||
</script>
|
||||
{$options.js_code}
|
||||
</html>
|
||||
{/block}
|
||||
<!doctype html><html lang="zh-cn"><head><meta charset="utf-8"><link rel="shortcut icon" href="/favicon.ico"><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"><meta name="theme-color" content="{$options.themeColor}"/><link rel="manifest" href="/manifest.json"><title>我的分享- {$options.siteName}</title><script type="text/javascript">colorTheme = {:json_encode($options["themeConfig"])};
|
||||
isHomePage = false;
|
||||
isSharePage = false;
|
||||
pageId="shareLock";
|
||||
userInfo = {
|
||||
uid: {$userData.uid},
|
||||
nick: "{$userData.userNick}",
|
||||
email: "{$userData.userMail}",
|
||||
group: "{$userData.groupData.group_name}",
|
||||
groupId: {$userData.groupData.id},
|
||||
groupColor: "{$userData.groupData.color}",
|
||||
};
|
||||
siteInfo = {
|
||||
mainTitle: "{$options.siteName}",
|
||||
};
|
||||
uploadConfig = {
|
||||
allowSource: false,
|
||||
allowShare: false,
|
||||
allowRemoteDownload: "0",
|
||||
allowTorrentDownload: "0",
|
||||
};
|
||||
isMobile = window.innerWidth < 600;</script></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(l){function e(e){for(var r,t,n=e[0],o=e[1],u=e[2],f=0,i=[];f<n.length;f++)t=n[f],p[t]&&i.push(p[t][0]),p[t]=0;for(r in o)Object.prototype.hasOwnProperty.call(o,r)&&(l[r]=o[r]);for(s&&s(e);i.length;)i.shift()();return c.push.apply(c,u||[]),a()}function a(){for(var e,r=0;r<c.length;r++){for(var t=c[r],n=!0,o=1;o<t.length;o++){var u=t[o];0!==p[u]&&(n=!1)}n&&(c.splice(r--,1),e=f(f.s=t[0]))}return e}var t={},p={30:0},c=[];function f(e){if(t[e])return t[e].exports;var r=t[e]={i:e,l:!1,exports:{}};return l[e].call(r.exports,r,r.exports,f),r.l=!0,r.exports}f.m=l,f.c=t,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(r,e){if(1&e&&(r=f(r)),8&e)return r;if(4&e&&"object"==typeof r&&r&&r.__esModule)return r;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:r}),2&e&&"string"!=typeof r)for(var n in r)f.d(t,n,function(e){return r[e]}.bind(null,n));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="/";var r=window.webpackJsonp=window.webpackJsonp||[],n=r.push.bind(r);r.push=e,r=r.slice();for(var o=0;o<r.length;o++)e(r[o]);var s=n;a()}([])</script><script src="/static/js/0.chunk.js"></script><script src="/static/js/1.chunk.js"></script><script src="/static/js/myShare.chunk.js"></script></body></html>
|
||||
@@ -1,53 +1,28 @@
|
||||
{extend name="header_public" /}
|
||||
{block name="title"}私密分享 - {$options.siteName}{/block}
|
||||
{block name="content"}
|
||||
<link rel="stylesheet" href="/static/css/share.css" />
|
||||
<link rel="stylesheet" href="/static/css/lock.css" />
|
||||
<script src="/static/js/jquery.color.js"></script>
|
||||
</head>
|
||||
<body data-ma-header="teal">
|
||||
<nav class="navbar navbar-inverse" >
|
||||
<div class="container-fluid">
|
||||
<div class="container" >
|
||||
{include file="navbar_public" loginStatus=$loginStatus userData=$userData /}
|
||||
<div class="header-panel shadow-z-2">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container main" >
|
||||
<div class="col-md-4"></div>
|
||||
<div class="col-md-4">
|
||||
<div class="jumbotron" >
|
||||
<div class="card_top">
|
||||
<div class="row top-color">
|
||||
<div class="card-top-row">
|
||||
加密分享
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="card_botom">
|
||||
<div class="row bottom-width" align="right">
|
||||
<input type="password" class="form-control" id="inputPassword" placeholder="请输入分享密码" value="{$pwd}">
|
||||
<button href="javascript:void(0)" id="submit_pwd" class="btn btn-raised active"><i class="fa fa-arrow-right" aria-hidden="true"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4"></div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
<script src="/static/js/jquery.liMarquee.js"></script>
|
||||
<script type="text/javascript">
|
||||
shareInfo={
|
||||
shareId : "{$shareData.share_key}",
|
||||
};
|
||||
|
||||
</script>
|
||||
<script src="/static/js/lock.js"> </script>
|
||||
{$options.js_code}
|
||||
{/block}
|
||||
<!doctype html><html lang="zh-cn"><head><meta charset="utf-8"><link rel="shortcut icon" href="/favicon.ico"><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"><meta name="theme-color" content="{$options.themeColor}"/><link rel="manifest" href="/manifest.json"><title>私密分享 - {$options.siteName}</title><script type="text/javascript">colorTheme = {:json_encode($options["themeConfig"])};
|
||||
isHomePage = false;
|
||||
isSharePage = false;
|
||||
pageId="shareLock";
|
||||
userInfo = {
|
||||
uid: {$userData.uid},
|
||||
nick: "{$userData.userNick}",
|
||||
email: "{$userData.userMail}",
|
||||
group: "{$userData.groupData.group_name}",
|
||||
groupId: {$userData.groupData.id},
|
||||
groupColor: "{$userData.groupData.color}",
|
||||
};
|
||||
siteInfo = {
|
||||
mainTitle: "{$options.siteName}",
|
||||
};
|
||||
uploadConfig = {
|
||||
allowSource: false,
|
||||
allowShare: false,
|
||||
allowRemoteDownload: "0",
|
||||
allowTorrentDownload: "0",
|
||||
};
|
||||
shareInfo={
|
||||
shareDate : "{$shareData.share_time}",
|
||||
shareId : "{$shareData.share_key}",
|
||||
ownerUid:"{$userInfo.id}",
|
||||
ownerNick:"{$userInfo.user_nick}",
|
||||
};
|
||||
isMobile = window.innerWidth < 600;</script></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(l){function e(e){for(var r,t,n=e[0],o=e[1],u=e[2],f=0,i=[];f<n.length;f++)t=n[f],p[t]&&i.push(p[t][0]),p[t]=0;for(r in o)Object.prototype.hasOwnProperty.call(o,r)&&(l[r]=o[r]);for(s&&s(e);i.length;)i.shift()();return c.push.apply(c,u||[]),a()}function a(){for(var e,r=0;r<c.length;r++){for(var t=c[r],n=!0,o=1;o<t.length;o++){var u=t[o];0!==p[u]&&(n=!1)}n&&(c.splice(r--,1),e=f(f.s=t[0]))}return e}var t={},p={28:0},c=[];function f(e){if(t[e])return t[e].exports;var r=t[e]={i:e,l:!1,exports:{}};return l[e].call(r.exports,r,r.exports,f),r.l=!0,r.exports}f.m=l,f.c=t,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(r,e){if(1&e&&(r=f(r)),8&e)return r;if(4&e&&"object"==typeof r&&r&&r.__esModule)return r;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:r}),2&e&&"string"!=typeof r)for(var n in r)f.d(t,n,function(e){return r[e]}.bind(null,n));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="/";var r=window.webpackJsonp=window.webpackJsonp||[],n=r.push.bind(r);r.push=e,r=r.slice();for(var o=0;o<r.length;o++)e(r[o]);var s=n;a()}([])</script><script src="/static/js/0.chunk.js"></script><script src="/static/js/1.chunk.js"></script><script src="/static/js/lock.chunk.js"></script></body></html>
|
||||
@@ -1,154 +1,47 @@
|
||||
{extend name="header_public" /}
|
||||
{block name="title"}{$fileData.orign_name} - {$options.siteName}{/block}
|
||||
{block name="content"}
|
||||
<link rel="stylesheet" href="/static/css/share.css" />
|
||||
<link rel="stylesheet" href="/static/css/photoswipe.css">
|
||||
<link rel="stylesheet" href="/static/css/default-skin/default-skin.css">
|
||||
<script src="/static/js/jquery.color.js"></script>
|
||||
</head>
|
||||
<body data-ma-header="teal">
|
||||
<div class="modal fade" id="previewModal" role="dialog">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" onclick="audioPause()" data-dismiss="modal">
|
||||
<span aria-hidden="true">×</span>
|
||||
<span class="sr-only ng-binding">关闭</span>
|
||||
</button>
|
||||
<h4 class="modal-title">视频预览</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="text-center previewContent">
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
|
||||
|
||||
<!-- Background of PhotoSwipe.
|
||||
It's a separate element, as animating opacity is faster than rgba(). -->
|
||||
<div class="pswp__bg"></div>
|
||||
<!-- Slides wrapper with overflow:hidden. -->
|
||||
<div class="pswp__scroll-wrap">
|
||||
<!-- Container that holds slides. PhotoSwipe keeps only 3 slides in DOM to save memory. -->
|
||||
<div class="pswp__container">
|
||||
<!-- don't modify these 3 pswp__item elements, data is added later on -->
|
||||
<div class="pswp__item"></div>
|
||||
<div class="pswp__item"></div>
|
||||
<div class="pswp__item"></div>
|
||||
</div>
|
||||
<!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->
|
||||
<div class="pswp__ui pswp__ui--hidden">
|
||||
<div class="pswp__top-bar">
|
||||
<!-- Controls are self-explanatory. Order can be changed. -->
|
||||
<div class="pswp__counter"></div>
|
||||
|
||||
<button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
|
||||
<button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
|
||||
<button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>
|
||||
<!-- Preloader demo https://codepen.io/dimsemenov/pen/yyBWoR -->
|
||||
<!-- element will get class pswp__preloader--active when preloader is running -->
|
||||
<div class="pswp__preloader">
|
||||
<div class="pswp__preloader__icn">
|
||||
<div class="pswp__preloader__cut">
|
||||
<div class="pswp__preloader__donut"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
|
||||
<div class="pswp__share-tooltip"></div>
|
||||
</div>
|
||||
<button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
|
||||
</button>
|
||||
<button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
|
||||
</button>
|
||||
<div class="pswp__caption">
|
||||
<div class="pswp__caption__center"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<nav class="navbar navbar-inverse" >
|
||||
<div class="container-fluid">
|
||||
<div class="container" >
|
||||
{include file="navbar_public" /}
|
||||
<div class="header-panel shadow-z-2">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container main" >
|
||||
<div class="col-md-3"></div>
|
||||
<div class="col-md-6">
|
||||
<div class="jumbotron" >
|
||||
<div class="card_top">
|
||||
<div class="row top-color">
|
||||
<div class="card-top-row">
|
||||
<div class="file-sign col-xs-2">
|
||||
<i class="fa fa-file-image-o" aria-hidden="true"></i>
|
||||
</div>
|
||||
<div class="file_title col-xs-10">
|
||||
<div class="file_title_inside str_wrap">
|
||||
{$fileData.orign_name|htmlspecialchars=ENT_NOQUOTES}
|
||||
</div>
|
||||
<div class="file_info"><span id="size"></span> <span><i class="fa fa-cloud-download" aria-hidden="true"></i> <span id="down_num"></span></span> <span><i class="fa fa-eye" aria-hidden="true"></i> <span id="view_num"></span></span></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-middle">
|
||||
<button class="btn btn-info btn-fab" id="previewButton"><i class="material-icons fa fa-eye"></i><div class="ripple-container"></div></button>
|
||||
<button class="btn btn-primary btn-fab" id="download"><i class="material-icons fa fa-download"></i><div class="ripple-container"></div></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card_botom">
|
||||
<div class="row bottom-width">
|
||||
<div class="avatar ">
|
||||
<img src="/Member/Avatar/{$userInfo.id}/s" class="img-circle animated rotateIn">
|
||||
<div class="nick">
|
||||
<span class="nickname"><a class="notWave" href="/Profile/{$userInfo.id}">{$userInfo.user_nick}</a></span>
|
||||
<br>
|
||||
<span class="share_time">分享于<span id="share_time"></span></span>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div></div>
|
||||
<div class="col-md-3"></div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
<script src="/static/js/jquery.liMarquee.js"></script>
|
||||
<script type="text/javascript">
|
||||
shareInfo={
|
||||
fileSize : "{$fileData.size}",
|
||||
shareDate : "{$shareData.share_time}",
|
||||
ownerUid:"{$userInfo.id}",
|
||||
ownerNick:"{$userInfo.user_nick}",
|
||||
downloadNum:"{$shareData.download_num}",
|
||||
ViewNum:"{$shareData.view_num}",
|
||||
shareId:"{$shareData.share_key}",
|
||||
fileName:"{$fileData.orign_name}",
|
||||
picSize:"{$fileData.pic_info}",
|
||||
{eq name="$loginStatus" value="1"}
|
||||
allowPreview:true,
|
||||
{else/}
|
||||
allowPreview:{$allowPreview},
|
||||
{/eq}
|
||||
};
|
||||
|
||||
</script>
|
||||
<script src="/static/js/share_single.js"> </script>
|
||||
{$options.js_code}
|
||||
{/block}
|
||||
<!doctype html><html lang="zh-cn"><head><meta charset="utf-8"><link rel="shortcut icon" href="/favicon.ico"><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"><meta name="theme-color" content="{$options.themeColor}"/><link rel="manifest" href="/manifest.json"><title>{$fileData.orign_name} - {$options.siteName}</title><script type="text/javascript">colorTheme = {:json_encode($options["themeConfig"])};
|
||||
isHomePage = false;
|
||||
isSharePage = true;
|
||||
pageId="fileShare";
|
||||
apiURL = {
|
||||
imgThumb: "/Share/Thumb/{$shareData.share_key}",
|
||||
preview: "/Share/Preview/{$shareData.share_key}",
|
||||
download: "/Share/Download/{$shareData.share_key}",
|
||||
docPreiview: '/Share/DocPreview/{$shareData.share_key}',
|
||||
listFile:'/Share/ListFile/{$shareData.share_key}'
|
||||
};
|
||||
userInfo = {
|
||||
uid: {$userData.uid},
|
||||
nick: "{$userData.userNick}",
|
||||
email: "{$userData.userMail}",
|
||||
group: "{$userData.groupData.group_name}",
|
||||
groupId: {$userData.groupData.id},
|
||||
groupColor: "{$userData.groupData.color}",
|
||||
};
|
||||
siteInfo = {
|
||||
mainTitle: "{$fileData.orign_name}",
|
||||
};
|
||||
path = "{$path}";
|
||||
uploadConfig = {
|
||||
allowSource: false,
|
||||
allowShare: false,
|
||||
allowRemoteDownload: "0",
|
||||
allowTorrentDownload: "0",
|
||||
};
|
||||
shareInfo={
|
||||
fileSize : "{$fileData.size}",
|
||||
shareDate : "{$shareData.share_time}",
|
||||
ownerUid:"{$userInfo.id}",
|
||||
ownerNick:"{$userInfo.user_nick}",
|
||||
downloadNum:"{$shareData.download_num}",
|
||||
ViewNum:"{$shareData.view_num}",
|
||||
shareId:"{$shareData.share_key}",
|
||||
fileName:"{$fileData.orign_name}",
|
||||
picSize:"{$fileData.pic_info}",
|
||||
{eq name="$loginStatus" value="1"}
|
||||
allowPreview:true,
|
||||
{else/}
|
||||
allowPreview:{$allowPreview},
|
||||
{/eq}
|
||||
};
|
||||
mediaType = {},
|
||||
isMobile = window.innerWidth < 600;</script></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(l){function e(e){for(var r,t,n=e[0],o=e[1],u=e[2],f=0,i=[];f<n.length;f++)t=n[f],p[t]&&i.push(p[t][0]),p[t]=0;for(r in o)Object.prototype.hasOwnProperty.call(o,r)&&(l[r]=o[r]);for(s&&s(e);i.length;)i.shift()();return c.push.apply(c,u||[]),a()}function a(){for(var e,r=0;r<c.length;r++){for(var t=c[r],n=!0,o=1;o<t.length;o++){var u=t[o];0!==p[u]&&(n=!1)}n&&(c.splice(r--,1),e=f(f.s=t[0]))}return e}var t={},p={29:0},c=[];function f(e){if(t[e])return t[e].exports;var r=t[e]={i:e,l:!1,exports:{}};return l[e].call(r.exports,r,r.exports,f),r.l=!0,r.exports}f.m=l,f.c=t,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(r,e){if(1&e&&(r=f(r)),8&e)return r;if(4&e&&"object"==typeof r&&r&&r.__esModule)return r;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:r}),2&e&&"string"!=typeof r)for(var n in r)f.d(t,n,function(e){return r[e]}.bind(null,n));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="/";var r=window.webpackJsonp=window.webpackJsonp||[],n=r.push.bind(r);r.push=e,r=r.slice();for(var o=0;o<r.length;o++)e(r[o]);var s=n;a()}([])</script><script src="/static/js/0.chunk.js"></script><script src="/static/js/18.chunk.js"></script><script src="/static/js/fileShare.chunk.js"></script></body></html>
|
||||
@@ -0,0 +1,28 @@
|
||||
<!doctype html><html lang="zh-cn"><head><meta charset="utf-8"><link rel="shortcut icon" href="/favicon.ico"><link rel="stylesheet" href="/static/css/mdeditor/editormd.min.css"/><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"><meta name="theme-color" content="{$options.themeColor}"/><link rel="manifest" href="/manifest.json"><title>{$fileName} - {$options.siteName}</title><script type="text/javascript">colorTheme = {:json_encode($options["themeConfig"])};
|
||||
isHomePage = false;
|
||||
isSharePage = false;
|
||||
pageId="";
|
||||
apiURL={
|
||||
imgThumb:"/File/Thumb",
|
||||
preview:"/File/Preview",
|
||||
download:"/File/Download",
|
||||
docPreiview:'/File/DocPreview',
|
||||
};
|
||||
userInfo={
|
||||
uid:{$userInfo.uid},
|
||||
nick:"{$userInfo.userNick}",
|
||||
email:"{$userInfo.userMail}",
|
||||
group:"{$userInfo.groupData.group_name}",
|
||||
groupId:{$userInfo.groupData.id},
|
||||
groupColor:"{$userInfo.groupData.color}",
|
||||
};
|
||||
siteInfo = {
|
||||
mainTitle:"{$fileName}",
|
||||
};
|
||||
fileInfo={
|
||||
url:"{$url}",
|
||||
name:"{$fileName}",
|
||||
path:"{$path}",
|
||||
};
|
||||
mediaType = {},
|
||||
isMobile = window.innerWidth<600;</script></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(l){function e(e){for(var r,t,n=e[0],o=e[1],u=e[2],f=0,i=[];f<n.length;f++)t=n[f],p[t]&&i.push(p[t][0]),p[t]=0;for(r in o)Object.prototype.hasOwnProperty.call(o,r)&&(l[r]=o[r]);for(s&&s(e);i.length;)i.shift()();return c.push.apply(c,u||[]),a()}function a(){for(var e,r=0;r<c.length;r++){for(var t=c[r],n=!0,o=1;o<t.length;o++){var u=t[o];0!==p[u]&&(n=!1)}n&&(c.splice(r--,1),e=f(f.s=t[0]))}return e}var t={},p={24:0},c=[];function f(e){if(t[e])return t[e].exports;var r=t[e]={i:e,l:!1,exports:{}};return l[e].call(r.exports,r,r.exports,f),r.l=!0,r.exports}f.m=l,f.c=t,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(r,e){if(1&e&&(r=f(r)),8&e)return r;if(4&e&&"object"==typeof r&&r&&r.__esModule)return r;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:r}),2&e&&"string"!=typeof r)for(var n in r)f.d(t,n,function(e){return r[e]}.bind(null,n));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="/";var r=window.webpackJsonp=window.webpackJsonp||[],n=r.push.bind(r);r.push=e,r=r.slice();for(var o=0;o<r.length;o++)e(r[o]);var s=n;a()}([])</script><script src="/static/js/jquery.min.js"></script><script src="/static/js/mdeditor/editormd.min.js"></script><script src="/static/js/0.chunk.js"></script><script src="/static/js/2.chunk.js"></script><script src="/static/js/markdown.chunk.js"></script></body></html>
|
||||
@@ -0,0 +1,27 @@
|
||||
<!doctype html><html lang="zh-cn"><head><meta charset="utf-8"><link rel="shortcut icon" href="/favicon.ico"><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"><meta name="theme-color" content="{$options.themeColor}"/><link rel="manifest" href="/manifest.json"><title>{$fileName} - {$options.siteName}</title><script type="text/javascript">colorTheme = {:json_encode($options["themeConfig"])};
|
||||
isHomePage = false;
|
||||
isSharePage = false;
|
||||
pageId="";
|
||||
apiURL={
|
||||
imgThumb:"/File/Thumb",
|
||||
preview:"/File/Preview",
|
||||
download:"/File/Download",
|
||||
docPreiview:'/File/DocPreview',
|
||||
};
|
||||
userInfo={
|
||||
uid:{$userInfo.uid},
|
||||
nick:"{$userInfo.userNick}",
|
||||
email:"{$userInfo.userMail}",
|
||||
group:"{$userInfo.groupData.group_name}",
|
||||
groupId:{$userInfo.groupData.id},
|
||||
groupColor:"{$userInfo.groupData.color}",
|
||||
};
|
||||
siteInfo = {
|
||||
mainTitle:"{$fileName}",
|
||||
};
|
||||
videoInfo={
|
||||
url:"{$url}",
|
||||
name:"{$fileName}"
|
||||
};
|
||||
mediaType = {},
|
||||
isMobile = window.innerWidth<600;</script><link href="/static/css/17.chunk.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div><script>!function(l){function e(e){for(var r,t,n=e[0],o=e[1],u=e[2],f=0,i=[];f<n.length;f++)t=n[f],p[t]&&i.push(p[t][0]),p[t]=0;for(r in o)Object.prototype.hasOwnProperty.call(o,r)&&(l[r]=o[r]);for(s&&s(e);i.length;)i.shift()();return c.push.apply(c,u||[]),a()}function a(){for(var e,r=0;r<c.length;r++){for(var t=c[r],n=!0,o=1;o<t.length;o++){var u=t[o];0!==p[u]&&(n=!1)}n&&(c.splice(r--,1),e=f(f.s=t[0]))}return e}var t={},p={23:0},c=[];function f(e){if(t[e])return t[e].exports;var r=t[e]={i:e,l:!1,exports:{}};return l[e].call(r.exports,r,r.exports,f),r.l=!0,r.exports}f.m=l,f.c=t,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(r,e){if(1&e&&(r=f(r)),8&e)return r;if(4&e&&"object"==typeof r&&r&&r.__esModule)return r;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:r}),2&e&&"string"!=typeof r)for(var n in r)f.d(t,n,function(e){return r[e]}.bind(null,n));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="/";var r=window.webpackJsonp=window.webpackJsonp||[],n=r.push.bind(r);r.push=e,r=r.slice();for(var o=0;o<r.length;o++)e(r[o]);var s=n;a()}([])</script><script src="/static/js/0.chunk.js"></script><script src="/static/js/17.chunk.js"></script><script src="/static/js/video.chunk.js"></script></body></html>
|
||||
@@ -15,13 +15,17 @@ Route::rule([
|
||||
's/:key'=>'index/Share/index',
|
||||
'Share/Download/:key'=>'index/Share/Download',
|
||||
'Share/Preview/:key'=>'index/Share/Preview',
|
||||
'Share/List/:key'=>'index/Share/List',
|
||||
'Share/ListFile/:key'=>'index/Share/ListFile',
|
||||
'Login'=>'index/Member/LoginForm',
|
||||
'SignUp'=>'index/Member/SignUp',
|
||||
'Member/emailActivate/:key'=>'index/Member/emailActivate',
|
||||
'Member/resetPwd/:key'=>'index/Member/resetPwd',
|
||||
'Callback/Payment/Jinshajiang' => 'index/Callback/Jinshajiang',
|
||||
'Explore/S/:key' => 'index/Explore/S',
|
||||
'Explore/Search/:key' => 'index/Explore/Search',
|
||||
'Member/Avatar/:uid/:size' => ['Member/Avatar',[],['uid'=>'\d+']],
|
||||
'Profile/:uid' => ['Profile/index',[],['uid'=>'\d+']],
|
||||
'Callback/Payment/Jinshajiang' => 'index/Callback/Jinshajiang',
|
||||
'Share/Thumb/:key' => 'index/Share/Thumb',
|
||||
'Share/DocPreview/:key' => 'index/Share/DocPreview',
|
||||
'Share/Content/:key' => 'index/Share/Content',
|
||||
]);
|
||||
@@ -1 +1 @@
|
||||
{"type":"","version":"1.0 Beta","version_id":1}
|
||||
{"type":"","version":"2.0.0-Alpha1","version_id":7,"db_version":5}
|
||||
+3
-2
@@ -4,7 +4,7 @@
|
||||
"keywords": ["php", "cloud", "ThinkPHP", "file-sharing"],
|
||||
"homepage": "https://cloudreve.org",
|
||||
"type": "project",
|
||||
"license": "GPL-3.0-only",
|
||||
"license": "GPL-3.0-only",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Aaron",
|
||||
@@ -32,7 +32,8 @@
|
||||
"topthink/think-captcha":"1.*",
|
||||
"aliyuncs/oss-sdk-php": "~2.0",
|
||||
"sabre/dav":"~3.2.0",
|
||||
"upyun/sdk": "^3.3"
|
||||
"upyun/sdk": "^3.3",
|
||||
"aws/aws-sdk-php": "^3.90"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
zip -r -q -o pack.zip ./
|
||||
curl -F "token=$TOKEN" -F "commit=$TRAVIS_COMMIT" -F "filename=@pack.zip" -H "Expect:" http://cloudreve.org/deploy.php
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,298 @@
|
||||
<?php
|
||||
|
||||
namespace Krizalys\Onedrive;
|
||||
|
||||
/**
|
||||
* @class DriveItem
|
||||
*
|
||||
* A DriveItem instance is an entity that may be stored in a OneDrive account.
|
||||
* There are two types of drive items: file or a folder, each of which being a
|
||||
* subclass of the DriveItem class.
|
||||
*
|
||||
* Note that DriveItem instances are only "proxy" to actual OneDrive drive items
|
||||
* (eg. destroying a DriveItem instance will not delete the actual OneDrive
|
||||
* drive item it is referencing to).
|
||||
*/
|
||||
abstract class DriveItem
|
||||
{
|
||||
/**
|
||||
* @var Client The owning Client instance.
|
||||
*/
|
||||
protected $_client;
|
||||
|
||||
/**
|
||||
* @var string The unique ID assigned by OneDrive to this drive item.
|
||||
*/
|
||||
protected $_id;
|
||||
|
||||
/**
|
||||
* @var string The unique ID assigned by OneDrive to the parent folder of
|
||||
* this drive item.
|
||||
*/
|
||||
private $_parentId;
|
||||
|
||||
/**
|
||||
* @var string The name of this drive item.
|
||||
*/
|
||||
private $_name;
|
||||
|
||||
/**
|
||||
* @var string The description of this drive item.
|
||||
*/
|
||||
private $_description;
|
||||
|
||||
/**
|
||||
* @var int The size of this drive item, in bytes.
|
||||
*/
|
||||
private $_size;
|
||||
|
||||
/**
|
||||
* @var string The source link of this drive item.
|
||||
*/
|
||||
private $_source;
|
||||
|
||||
/**
|
||||
* @var int The creation time, in seconds since UNIX epoch.
|
||||
*/
|
||||
private $_createdTime;
|
||||
|
||||
/**
|
||||
* @var int The last modification time, in seconds since UNIX epoch.
|
||||
*/
|
||||
private $_updatedTime;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Client $client The Client instance owning this DriveItem
|
||||
* instance.
|
||||
* @param null|string $id The unique ID of the OneDrive drive item
|
||||
* referenced by this DriveItem instance.
|
||||
* @param array|object $options An array/object with one or more of the
|
||||
* following keys/properties:
|
||||
* - 'parent_id' (string) The unique ID of
|
||||
* the parent OneDrive folder of this drive
|
||||
* item.
|
||||
* - 'name' (string) The name of this drive
|
||||
* item.
|
||||
* - 'description' (string) The description of
|
||||
* this drive item. May be empty.
|
||||
* - 'size' (int) The size of this drive item,
|
||||
* in bytes.
|
||||
* - 'source' (string) The source link of this
|
||||
* drive item.
|
||||
* - 'created_time' (string) The creation time,
|
||||
* as a RFC date/time.
|
||||
* - 'updated_time' (string) The last
|
||||
* modification time, as a RFC date/time.
|
||||
*/
|
||||
public function __construct(Client $client, $id, $options = [])
|
||||
{
|
||||
$options = (object) $options;
|
||||
$this->_client = $client;
|
||||
$this->_id = null !== $id ? (string) $id : null;
|
||||
|
||||
$this->_parentId = property_exists($options, 'parent_id') ?
|
||||
(string) $options->parent_id : null;
|
||||
|
||||
$this->_name = property_exists($options, 'name') ?
|
||||
(string) $options->name : null;
|
||||
|
||||
$this->_description = property_exists($options, 'description') ?
|
||||
(string) $options->description : null;
|
||||
|
||||
$this->_size = property_exists($options, 'size') ?
|
||||
(int) $options->size : null;
|
||||
|
||||
$this->_source = property_exists($options, 'source') ?
|
||||
(string) $options->source : null;
|
||||
|
||||
$this->_createdTime = property_exists($options, 'created_time') ?
|
||||
strtotime($options->created_time) : null;
|
||||
|
||||
$this->_updatedTime = property_exists($options, 'updated_time') ?
|
||||
strtotime($options->updated_time) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the OneDrive drive item referenced by this DriveItem
|
||||
* instance is a folder.
|
||||
*
|
||||
* @return bool true if the OneDrive drive item referenced by this DriveItem
|
||||
* instance is a folder, false otherwise.
|
||||
*/
|
||||
public function isFolder()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the properties of the OneDrive drive item referenced by this
|
||||
* DriveItem instance. Some properties are cached for faster subsequent
|
||||
* access.
|
||||
*
|
||||
* @return array The properties of the OneDrive drive item referenced by
|
||||
* this DriveItem instance.
|
||||
*/
|
||||
public function fetchProperties()
|
||||
{
|
||||
$result = $this->_client->fetchProperties($this->_id);
|
||||
|
||||
$this->_parentId = '' != $result->parent_id ?
|
||||
(string) $result->parent_id : null;
|
||||
|
||||
$this->_name = $result->name;
|
||||
|
||||
$this->_description = '' != $result->description ?
|
||||
(string) $result->description : null;
|
||||
|
||||
$this->_size = (int) $result->size;
|
||||
|
||||
/** @todo Handle volatile existence (eg. present only for files). */
|
||||
$this->_source = (string) $result->source;
|
||||
|
||||
$this->_createdTime = strtotime($result->created_time);
|
||||
$this->_updatedTime = strtotime($result->updated_time);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the unique ID of the OneDrive drive item referenced by this
|
||||
* DriveItem instance.
|
||||
*
|
||||
* @return string The unique ID of the OneDrive drive item referenced by
|
||||
* this DriveItem instance.
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the unique ID of the parent folder of the OneDrive drive item
|
||||
* referenced by this DriveItem instance.
|
||||
*
|
||||
* @return string The unique ID of the OneDrive folder containing the drive
|
||||
* item referenced by this DriveItem instance.
|
||||
*/
|
||||
public function getParentId()
|
||||
{
|
||||
if (null === $this->_parentId) {
|
||||
$this->fetchProperties();
|
||||
}
|
||||
|
||||
return $this->_parentId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the OneDrive drive item referenced by this DriveItem
|
||||
* instance.
|
||||
*
|
||||
* @return string The name of the OneDrive drive item referenced by this
|
||||
* DriveItem instance.
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
if (null === $this->_name) {
|
||||
$this->fetchProperties();
|
||||
}
|
||||
|
||||
return $this->_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the description of the OneDrive drive item referenced by this
|
||||
* DriveItem instance.
|
||||
*
|
||||
* @return string The description of the OneDrive drive item referenced by
|
||||
* this DriveItem instance.
|
||||
*/
|
||||
public function getDescription()
|
||||
{
|
||||
if (null === $this->_description) {
|
||||
$this->fetchProperties();
|
||||
}
|
||||
|
||||
return $this->_description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the size of the OneDrive drive item referenced by this DriveItem
|
||||
* instance.
|
||||
*
|
||||
* @return int The size of the OneDrive drive item referenced by this
|
||||
* DriveItem instance.
|
||||
*/
|
||||
public function getSize()
|
||||
{
|
||||
if (null === $this->_size) {
|
||||
$this->fetchProperties();
|
||||
}
|
||||
|
||||
return $this->_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the source link of the OneDrive drive item referenced by this
|
||||
* DriveItem instance.
|
||||
*
|
||||
* @return string The source link of the OneDrive drive item referenced by
|
||||
* this DriveItem instance.
|
||||
*/
|
||||
public function getSource()
|
||||
{
|
||||
if (null === $this->_source) {
|
||||
$this->fetchProperties();
|
||||
}
|
||||
|
||||
return $this->_source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the creation time of the OneDrive drive item referenced by this
|
||||
* DriveItem instance.
|
||||
*
|
||||
* @return int The creation time of the drive item referenced by this
|
||||
* DriveItem instance, in seconds since UNIX epoch.
|
||||
*/
|
||||
public function getCreatedTime()
|
||||
{
|
||||
if (null === $this->_createdTime) {
|
||||
$this->fetchProperties();
|
||||
}
|
||||
|
||||
return $this->_createdTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the last modification time of the OneDrive drive item referenced by
|
||||
* this DriveItem instance.
|
||||
*
|
||||
* @return int The last modification time of the drive item referenced by
|
||||
* this DriveItem instance, in seconds since UNIX epoch.
|
||||
*/
|
||||
public function getUpdatedTime()
|
||||
{
|
||||
if (null === $this->_updatedTime) {
|
||||
$this->fetchProperties();
|
||||
}
|
||||
|
||||
return $this->_updatedTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the OneDrive drive item referenced by this DriveItem instance into
|
||||
* another OneDrive folder.
|
||||
*
|
||||
* @param null|string $destinationId The unique ID of the OneDrive folder
|
||||
* into which to move the OneDrive drive
|
||||
* item referenced by this DriveItem
|
||||
* instance, or null to move it to the
|
||||
* OneDrive root folder. Default: null.
|
||||
*/
|
||||
public function move($destinationId = null)
|
||||
{
|
||||
$this->_client->moveObject($this->_id, $destinationId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
namespace Krizalys\Onedrive;
|
||||
|
||||
/**
|
||||
* @class File
|
||||
*
|
||||
* A File instance is a DriveItem instance referencing a OneDrive file. It may
|
||||
* have content but may not contain other OneDrive drive items.
|
||||
*/
|
||||
class File extends DriveItem
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Client $client The Client instance owning this DriveItem
|
||||
* instance.
|
||||
* @param null|string $id The unique ID of the OneDrive drive item
|
||||
* referenced by this DriveItem instance.
|
||||
* @param array|object $options An array/object with one or more of the
|
||||
* following keys/properties:
|
||||
* - 'parent_id' (string) The unique ID of the
|
||||
* parent OneDrive folder of this drive item.
|
||||
* - 'name' (string) The name of this drive
|
||||
* item.
|
||||
* - 'description' (string) The description of
|
||||
* this drive item. May be empty.
|
||||
* - 'size' (int) The size of this drive item,
|
||||
* in bytes.
|
||||
* - 'created_time' (string) The creation time,
|
||||
* as a RFC date/time.
|
||||
* - 'updated_time' (string) The last
|
||||
* modification time, as a RFC date/time.
|
||||
*/
|
||||
public function __construct(Client $client, $id, $options = [])
|
||||
{
|
||||
parent::__construct($client, $id, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the content of the OneDrive file referenced by this File
|
||||
* instance.
|
||||
*
|
||||
* @param array $options Extra cURL options to apply.
|
||||
*
|
||||
* @return string The content of the OneDrive file referenced by this File
|
||||
* instance.
|
||||
*
|
||||
* @todo Should somewhat return the content-type as well; this information
|
||||
* is not disclosed by OneDrive.
|
||||
*/
|
||||
public function fetchContent($options = [])
|
||||
{
|
||||
return $this->_client->apiGet($this->_id . '/content', $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies the OneDrive file referenced by this File instance into another
|
||||
* OneDrive folder.
|
||||
*
|
||||
* @param null|string $destinationId The unique ID of the OneDrive folder
|
||||
* into which to copy the OneDrive file
|
||||
* referenced by this File instance, or
|
||||
* null to copy it in the OneDrive root
|
||||
* folder. Default: null.
|
||||
*/
|
||||
public function copy($destinationId = null)
|
||||
{
|
||||
$this->_client->copyFile($this->_id, $destinationId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
<?php
|
||||
|
||||
namespace Krizalys\Onedrive;
|
||||
|
||||
/**
|
||||
* @class Folder
|
||||
*
|
||||
* A Folder instance is a DriveItem instance referencing to a OneDrive folder.
|
||||
* It may contain other OneDrive drive items but may not have content.
|
||||
*/
|
||||
class Folder extends DriveItem
|
||||
{
|
||||
/**
|
||||
* Determines whether the OneDrive drive item referenced by this DriveItem
|
||||
* instance is a folder.
|
||||
*
|
||||
* @return bool true if the OneDrive drive item referenced by this DriveItem
|
||||
* instance is a folder, false otherwise.
|
||||
*/
|
||||
public function isFolder()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Client $client The Client instance owning this DriveItem
|
||||
* instance.
|
||||
* @param null|string $id The unique ID of the OneDrive drive item
|
||||
* referenced by this DriveItem instance, or
|
||||
* null to reference the OneDrive root folder.
|
||||
* Default: null.
|
||||
* @param array|object $options Options to pass to the DriveItem
|
||||
* constructor.
|
||||
*/
|
||||
public function __construct(Client $client, $id = null, $options = [])
|
||||
{
|
||||
parent::__construct($client, $id, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the drive items in the OneDrive folder referenced by this Folder
|
||||
* instance.
|
||||
*
|
||||
* @return array The drive items in the OneDrive folder referenced by this
|
||||
* Folder instance, as DriveItem instances.
|
||||
*
|
||||
* @deprecated Use Folder::fetchChildObjects() instead.
|
||||
*/
|
||||
public function fetchObjects()
|
||||
{
|
||||
/** @todo Log deprecation notice. */
|
||||
return $this->fetchChildObjects();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the child drive items in the OneDrive folder referenced by this
|
||||
* Folder instance.
|
||||
*
|
||||
* @return array The drive items in the OneDrive folder referenced by this
|
||||
* Folder instance, as DriveItem instances.
|
||||
*/
|
||||
public function fetchChildObjects()
|
||||
{
|
||||
return $this->_client->fetchObjects($this->_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the descendant drive items under the OneDrive folder referenced by
|
||||
* this Folder instance.
|
||||
*
|
||||
* @return array The files in the OneDrive folder referenced by this Folder
|
||||
* instance, as DriveItem instances.
|
||||
*/
|
||||
public function fetchDescendantObjects()
|
||||
{
|
||||
$driveItems = [];
|
||||
|
||||
foreach ($this->fetchChildObjects() as $driveItem) {
|
||||
if ($driveItem->isFolder()) {
|
||||
$driveItems = array_merge(
|
||||
$driveItem->fetchDescendantObjects(),
|
||||
$driveItems
|
||||
);
|
||||
} else {
|
||||
array_push($driveItems, $driveItem);
|
||||
}
|
||||
}
|
||||
|
||||
return $driveItems;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a folder in the OneDrive folder referenced by this Folder
|
||||
* instance.
|
||||
*
|
||||
* @param string $name The name of the OneDrive folder to be
|
||||
* created.
|
||||
* @param null|string $description The description of the OneDrive folder
|
||||
* to be created, or null to create it
|
||||
* without a description. Default: null.
|
||||
*
|
||||
* @return Folder The folder created, as a Folder instance.
|
||||
*/
|
||||
public function createFolder($name, $description = null)
|
||||
{
|
||||
return $this->_client->createFolder($name, $this->_id, $description);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a file in the OneDrive folder referenced by this Folder instance.
|
||||
*
|
||||
* @param string $name The name of the OneDrive file to be
|
||||
* created.
|
||||
* @param string|resource $content The content of the OneDrive file to be
|
||||
* created, as a string or handle to an
|
||||
* already opened file. In the latter case,
|
||||
* the responsibility to close the handle is
|
||||
* is left to the calling function. Default:
|
||||
* ''.
|
||||
* @param array $options The options.
|
||||
*
|
||||
* @return File The file created, as a File instance.
|
||||
*
|
||||
* @throws \Exception Thrown on I/O errors.
|
||||
*/
|
||||
public function createFile($name, $content = '', array $options = [])
|
||||
{
|
||||
$client = $this->_client;
|
||||
|
||||
$options = array_merge([
|
||||
'name_conflict_behavior' => $client->getNameConflictBehavior(),
|
||||
'stream_back_end' => $client->getStreamBackEnd(),
|
||||
], $options);
|
||||
|
||||
return $this->_client->createFile(
|
||||
$name, $this->_id,
|
||||
$content,
|
||||
$options
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace Krizalys\Onedrive;
|
||||
|
||||
class NameConflictBehavior
|
||||
{
|
||||
// Fail behavior: fail the operation if the drive item exists.
|
||||
const FAIL = 1;
|
||||
|
||||
// Rename behavior: rename the drive item if it already exists. The drive
|
||||
// item is renamed as "<original name> 1", incrementing the trailing number
|
||||
// until an available file name is discovered.
|
||||
const RENAME = 2;
|
||||
|
||||
// Replace behavior: replace the drive item if it already exists.
|
||||
const REPLACE = 3;
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace Krizalys\Onedrive;
|
||||
|
||||
class NameConflictBehaviorParameterizer
|
||||
{
|
||||
/**
|
||||
* Parameterizes a given name conflict behavior.
|
||||
*
|
||||
* @param array $params The parameters.
|
||||
* @param int $nameConflictBehavior The name conflict behavior.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws \Exception Thrown if the name conflict behavior given is not
|
||||
* supported.
|
||||
*/
|
||||
public function parameterize(array $params, $nameConflictBehavior)
|
||||
{
|
||||
switch ($nameConflictBehavior) {
|
||||
case NameConflictBehavior::FAIL:
|
||||
$params['overwrite'] = 'false';
|
||||
break;
|
||||
|
||||
case NameConflictBehavior::RENAME:
|
||||
$params['overwrite'] = 'ChooseNewName';
|
||||
break;
|
||||
|
||||
case NameConflictBehavior::REPLACE:
|
||||
$params['overwrite'] = 'true';
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new \Exception(
|
||||
"Unsupported name conflict behavior: $nameConflictBehavior"
|
||||
);
|
||||
}
|
||||
|
||||
return $params;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace Krizalys\Onedrive;
|
||||
|
||||
class StreamBackEnd
|
||||
{
|
||||
// Memory-backed stream.
|
||||
const MEMORY = 1;
|
||||
|
||||
// Temporary file-backed stream. A temporary file is actually used if the
|
||||
// stream contents exceeds 2 MiB.
|
||||
const TEMP = 2;
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Krizalys\Onedrive;
|
||||
|
||||
class StreamOpener
|
||||
{
|
||||
private static $uris = [
|
||||
StreamBackEnd::MEMORY => 'php://memory',
|
||||
StreamBackEnd::TEMP => 'php://temp',
|
||||
];
|
||||
|
||||
/**
|
||||
* Opens a stream given a stream back end.
|
||||
*
|
||||
* @param int $streamBackEnd The stream back end.
|
||||
*
|
||||
* @return bool|resource The open stream.
|
||||
*
|
||||
* @throws \Exception Thrown if the stream back end given is not supported.
|
||||
*/
|
||||
public function open($streamBackEnd)
|
||||
{
|
||||
if (!array_key_exists($streamBackEnd, self::$uris)) {
|
||||
throw new \Exception("Unsupported stream back end: $streamBackEnd");
|
||||
}
|
||||
|
||||
$uri = self::$uris[$streamBackEnd];
|
||||
return fopen($uri, 'rw+b');
|
||||
}
|
||||
}
|
||||
-2653
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user