pull/4/head
HFO4 8 years ago
parent a7691a1d1d
commit 3b9040028d

@ -0,0 +1,8 @@
<IfModule mod_rewrite.c>
Options +FollowSymlinks -Multiviews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]
</IfModule>

@ -1,2 +1,40 @@
# Cloudreve
A project helps you build your own cloud in minutes.
![logo_white.png](https://download.aoaoao.me/logo_white.png)
Cloudreve - Make the cloud easy for everyone
=========================
[![GitHub release](https://img.shields.io/github/release/qubyte/rubidium.svg)]()
[![GPL Licence](https://badges.frapsoft.com/os/gpl/gpl.svg?v=103)](https://opensource.org/licenses/GPL-3.0/)
基于ThinkPHP构建的网盘系统能够助您以较低成本快速搭建起公私兼备的网盘。
![TIM截图20180204124101.png](https://download.aoaoao.me/TIM截图20180204124101.png)
目前已经实现的特性:
* 快速对接多家云存储支持七牛、又拍云、阿里云OSS、AWS S3当然还有本地存储
* 可限制单文件最大大小、MMMEType、文件后缀、用户可用容量
* 图片、音频、视频、文本、Markdown、Ofiice文档 在线预览
* 移动端全站响应式布局
* 文件、目录分享系统,可创建私有分享或公开分享链接
* 用户个人主页,可查看用户所有分享
* 多用户系统、用户组支持
* 初步完善的后台,方便管理
* 拖拽上传、分片上传、断点续传、下载限速(*实验性功能)
* 多上传策略,可为不同用户组分配不同策略
* 用户组基础权限设置
* WebDAV协议支持
安装需求
------------
* LNMP/LAMP With PHP5.6+
* curl、fileinfo、gd扩展
* Composer
简要安装说明
------------
Coming Soon...
许可证
------------
GPLV3

@ -0,0 +1 @@
deny from all

@ -0,0 +1,12 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
return [];

@ -0,0 +1,41 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: 流年 <liu21st@gmail.com>
// +----------------------------------------------------------------------
// 应用公共文件
function array_column_fix($array,$key){
if(count($array) == count($array,1)){
return array(0 =>$array[$key]);
}else{
return array_column($array,$key);
}
}
function getAllowedExt($ext){
$returnValue = "";
foreach (json_decode($ext,true) as $key => $value) {
$returnValue .= $value["ext"].",";
}
return rtrim($returnValue, ",");
}
function getDirName($name){
$explode = explode("/", $name);
return end($explode);
}
function getSize($bit,$array=false){
$type = array('Bytes','KB','MB','GB','TB');
$box = array('1','1024','1048576','1073741824','TB');
for($i = 0; $bit >= 1024; $i++) {
$bit/=1024;
}
if($array){
return [(floor($bit*100)/100),$box[$i]];
}
return (floor($bit*100)/100).$type[$i];
}

@ -0,0 +1,270 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
return [
// +----------------------------------------------------------------------
// | 应用设置
// +----------------------------------------------------------------------
//密码加盐
'salt' => 'sdshare',
// 应用命名空间
'app_namespace' => 'app',
// 应用调试模式
'app_debug' => false,
// 应用Trace
'app_trace' => false,
// 应用模式状态
'app_status' => '',
// 是否支持多模块
'app_multi_module' => true,
// 入口自动绑定模块
'auto_bind_module' => false,
// 注册的根命名空间
'root_namespace' => [],
// 扩展函数文件
'extra_file_list' => [THINK_PATH . 'helper' . EXT],
// 默认输出类型
'default_return_type' => 'html',
// 默认AJAX 数据返回格式,可选json xml ...
'default_ajax_return' => 'json',
// 默认JSONP格式返回的处理方法
'default_jsonp_handler' => 'jsonpReturn',
// 默认JSONP处理方法
'var_jsonp_handler' => 'callback',
// 默认时区
'default_timezone' => 'PRC',
// 是否开启多语言
'lang_switch_on' => false,
// 默认全局过滤方法 用逗号分隔多个
'default_filter' => '',
// 默认语言
'default_lang' => 'zh-cn',
// 应用类库后缀
'class_suffix' => false,
// 控制器类后缀
'controller_suffix' => false,
// +----------------------------------------------------------------------
// | 模块设置
// +----------------------------------------------------------------------
// 默认模块名
'default_module' => 'index',
// 禁止访问模块
'deny_module_list' => ['common'],
// 默认控制器名
'default_controller' => 'Index',
// 默认操作名
'default_action' => 'index',
// 默认验证器
'default_validate' => '',
// 默认的空控制器名
'empty_controller' => 'Error',
// 操作方法后缀
'action_suffix' => '',
// 自动搜索控制器
'controller_auto_search' => false,
// +----------------------------------------------------------------------
// | URL设置
// +----------------------------------------------------------------------
// PATHINFO变量名 用于兼容模式
'var_pathinfo' => 's',
'url_convert' => false,
// 兼容PATH_INFO获取
'pathinfo_fetch' => ['ORIG_PATH_INFO', 'REDIRECT_PATH_INFO', 'REDIRECT_URL'],
// pathinfo分隔符
'pathinfo_depr' => '/',
// URL伪静态后缀
'url_html_suffix' => '',
// URL普通方式参数 用于自动生成
'url_common_param' => false,
// URL参数方式 0 按名称成对解析 1 按顺序解析
'url_param_type' => 0,
// 是否开启路由
'url_route_on' => true,
// 路由使用完整匹配
'route_complete_match' => false,
// 路由配置文件(支持配置多个)
'route_config_file' => ['route'],
// 是否强制使用路由
'url_route_must' => false,
// 域名部署
'url_domain_deploy' => false,
// 域名根如thinkphp.cn
'url_domain_root' => '',
// 是否自动转换URL中的控制器和操作名
'url_convert' => false,
// 默认的访问控制器层
'url_controller_layer' => 'controller',
// 表单请求类型伪装变量
'var_method' => '_method',
// 表单ajax伪装变量
'var_ajax' => '_ajax',
// 表单pjax伪装变量
'var_pjax' => '_pjax',
// 是否开启请求缓存 true自动缓存 支持设置请求缓存规则
'request_cache' => false,
// 请求缓存有效期
'request_cache_expire' => null,
// 全局请求缓存排除规则
'request_cache_except' => [],
// +----------------------------------------------------------------------
// | 模板设置
// +----------------------------------------------------------------------
'template' => [
// 模板引擎类型 支持 php think 支持扩展
'type' => 'Think',
// 模板路径
'view_path' => '',
// 模板后缀
'view_suffix' => 'html',
// 模板文件名分隔符
'view_depr' => DS,
// 模板引擎普通标签开始标记
'tpl_begin' => '{',
// 模板引擎普通标签结束标记
'tpl_end' => '}',
// 标签库标签开始标记
'taglib_begin' => '{',
// 标签库标签结束标记
'taglib_end' => '}',
],
// 视图输出字符串内容替换
'view_replace_str' => [],
// 默认跳转页面对应的模板文件
'dispatch_success_tmpl' => THINK_PATH . 'tpl' . DS . 'dispatch_jump.tpl',
'dispatch_error_tmpl' => "application/index/view/error.html",
// +----------------------------------------------------------------------
// | 异常及错误设置
// +----------------------------------------------------------------------
// 异常页面的模板文件
'exception_tmpl' => THINK_PATH . 'tpl' . DS . 'think_exception.tpl',
// 错误显示信息,非调试模式有效
'error_message' => '页面错误!请稍后再试~',
// 显示错误信息
'show_error_msg' => false,
// 异常处理handle类 留空使用 \think\exception\Handle
'exception_handle' => '',
// +----------------------------------------------------------------------
// | 日志设置
// +----------------------------------------------------------------------
'log' => [
// 日志记录方式,内置 file socket 支持扩展
'type' => 'File',
// 日志保存目录
'path' => LOG_PATH,
// 日志记录级别
'level' => ["error"],
],
// +----------------------------------------------------------------------
// | Trace设置 开启 app_trace 后 有效
// +----------------------------------------------------------------------
'trace' => [
// 内置Html Console 支持扩展
'type' => 'Html',
],
// +----------------------------------------------------------------------
// | 缓存设置
// +----------------------------------------------------------------------
'cache' => [
// 驱动方式
'type' => 'File',
// 缓存保存目录
'path' => CACHE_PATH,
// 缓存前缀
'prefix' => '',
// 缓存有效期 0表示永久缓存
'expire' => 0,
],
// +----------------------------------------------------------------------
// | 会话设置
// +----------------------------------------------------------------------
'session' => [
'id' => '',
// SESSION_ID的提交变量,解决flash上传跨域
'var_session_id' => '',
// SESSION 前缀
'prefix' => 'sd',
// 驱动方式 支持redis memcache memcached
'type' => '',
// 是否自动开启 SESSION
'auto_start' => true,
],
// +----------------------------------------------------------------------
// | Cookie设置
// +----------------------------------------------------------------------
'cookie' => [
// cookie 名称前缀
'prefix' => '',
// cookie 保存时间
'expire' => 0,
// cookie 保存路径
'path' => '/',
// cookie 有效域名
'domain' => '',
// cookie 启用安全传输
'secure' => false,
// httponly设置
'httponly' => '',
// 是否使用 setcookie
'setcookie' => true,
],
//分页配置
'paginate' => [
'type' => 'bootstrap',
'var_page' => 'page',
'list_rows' => 15,
],
// +----------------------------------------------------------------------
// | 验证码设置
// +----------------------------------------------------------------------
'captcha'=>[
'codeSet' => '2345678abcdefhijkmnpqrstuvwxyzABCDEFGHJKLMNPQRTUVWXY',
// 验证码字符集合
'expire' => 1800,
// 验证码过期时间s
'useZh' => false,
// 使用背景图片
'fontSize' => 25,
// 验证码字体大小(px)
'useCurve' => true,
// 是否画混淆曲线
'useNoise' => true,
// 是否添加杂点
'imageH' => 0,
// 验证码图片高度
'imageW' => 0,
// 验证码图片宽度
'length' => 4,
// 验证码位数
'fontttf' => '',
// 验证码字体,不设置随机获取
'bg' => [243, 251, 254],
// 背景颜色
'reset' => true],
];

@ -0,0 +1,53 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
return [
// 数据库类型
'type' => 'mysql',
// 服务器地址
'hostname' => '127.0.0.1',
// 数据库名
'database' => 'lite',
// 用户名
'username' => 'root',
// 密码
'password' => 'root',
// 端口
'hostport' => '3306',
// 连接dsn
'dsn' => '',
// 数据库连接参数
'params' => [],
// 数据库编码默认采用utf8
'charset' => 'utf8',
// 数据库表前缀
'prefix' => 'sd_',
// 数据库调试模式
'debug' => true,
// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
'deploy' => 0,
// 数据库读写是否分离 主从式有效
'rw_separate' => false,
// 读写分离后 主服务器数量
'master_num' => 1,
// 指定从服务器序号
'slave_no' => '',
// 是否严格检查字段是否存在
'fields_strict' => true,
// 数据集返回类型
'resultset_type' => 'array',
// 自动写入时间戳字段
'auto_timestamp' => false,
// 时间字段取出后的默认时间格式
'datetime_format' => 'Y-m-d H:i:s',
// 是否需要进行SQL性能分析
'sql_explain' => false,
];

@ -0,0 +1,53 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
return [
// 数据库类型
'type' => 'mysql',
// 服务器地址
'hostname' => '127.0.0.1',
// 数据库名
'database' => 'tp',
// 用户名
'username' => 'root',
// 密码
'password' => 'root',
// 端口
'hostport' => '3306',
// 连接dsn
'dsn' => '',
// 数据库连接参数
'params' => [],
// 数据库编码默认采用utf8
'charset' => 'utf8',
// 数据库表前缀
'prefix' => 'sd_',
// 数据库调试模式
'debug' => true,
// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
'deploy' => 0,
// 数据库读写是否分离 主从式有效
'rw_separate' => false,
// 读写分离后 主服务器数量
'master_num' => 1,
// 指定从服务器序号
'slave_no' => '',
// 是否严格检查字段是否存在
'fields_strict' => true,
// 数据集返回类型
'resultset_type' => 'array',
// 自动写入时间戳字段
'auto_timestamp' => false,
// 时间字段取出后的默认时间格式
'datetime_format' => 'Y-m-d H:i:s',
// 是否需要进行SQL性能分析
'sql_explain' => false,
];

@ -0,0 +1,14 @@
<?php
function classLoader($class)
{
$path = str_replace('\\', DIRECTORY_SEPARATOR, $class);
$file = __DIR__ . '/src/' . $path . '.php';
if (file_exists($file)) {
require_once $file;
}
}
spl_autoload_register('classLoader');
require_once __DIR__ . '/src/Qiniu/functions.php';

@ -0,0 +1,25 @@
<?php
function countSize($bit,$array=false){
$type = array('Bytes','KB','MB','GB','TB');
$box = array('1','1024','1048576','1073741824','TB');
for($i = 0; $bit >= 1024; $i++) {
$bit/=1024;
}
if($array){
return [(floor($bit*100)/100),$box[$i]];
}
return (floor($bit*100)/100).$type[$i];
}
function isPreview($fileName){
$allowedSuffix=["jpg","jpeg","gif","bmp","png","svg","mp4","mp3","ogg"];
$suffix = explode(".",$fileName);
if(in_array(end($suffix),$allowedSuffix)){
return "yes";
}
return "no";
}
function getDay($sec){
return floor($sec/86400);
}
?>

@ -0,0 +1,448 @@
<?php
namespace app\index\controller;
use think\Controller;
use app\index\model\User;
use think\Cookie;
use think\Db;
use \app\index\model\Option;
use \app\index\model\AdminHandler;
use \app\index\model\FileManage;
class Admin extends Controller{
public $userObj;
public $siteOptions;
public $adminObj;
public function _initialize(){
$this->siteOptions = Option::getValues(["basic","admin"]);
$this->userObj = new User(cookie('user_id'),cookie('login_key'));
if(!$this->userObj->loginStatus){
$this->redirect(url('/Login','',''));
exit();
}
if($this->userObj->groupData["id"] != 1){
$this->error('你无权访问此页面',403,$this->siteOptions);
}
$this->adminObj = new AdminHandler($this->siteOptions);
}
public function index(){
return view('admin_index', [
'options' => $this->siteOptions,
'statics' => $this->adminObj->getStatics(),
]);
}
public function Setting(){
return view('basic_setting', [
'options' => $this->siteOptions,
]);
}
public function Config(){
$configType=input("?param.type") ? input("param.type") : "common";
$configFile = $this->adminObj->getConfigFile($configType);
return view('config_file', [
'options' => $this->siteOptions,
'type' => $configType,
'content' => $configFile[0],
'path' => $configFile[1],
]);
}
public function SaveConfigFile(){
return $this->adminObj->saveConfigFile(input('post.'));
}
public function SettingReg(){
return view('reg_setting', [
'options' => $this->siteOptions,
'optionsForSet' => Option::getValues(["login","register"]),
'groups' => $this->adminObj->getAvaliableGroup(),
]);
}
public function Theme(){
$fileName=input("?param.name") ? input("param.name") : "error";
$dir = ROOT_PATH."application/index/view/";
if(!function_exists("scandir")){
return "scandir被禁用";
}
$fileList=[];
$fileList=$fileList+scandir($dir);
$pathList=["/"=>$fileList];
foreach (["admin","explore","file","home","index","member","profile","share"] as $key => $value) {
$childPath = scandir($dir.$value."/");
$fileList=array_merge($fileList,$childPath);
$pathList = array_merge($pathList,[$value => $childPath]);
}
foreach ($fileList as $key => $value) {
if(substr_compare($value, ".html", -strlen(".html")) != 0){
unset($fileList[$key]);
}
}
foreach($pathList as $key=>$val){
if(in_array($fileName.".html",$val)){
$parentPath = $key;
break;
}
}
$fileContent = file_get_contents($dir.rtrim($parentPath,"/")."/".$fileName.".html");
return view('theme', [
'options' => $this->siteOptions,
'list' => $fileList,
'content' => $fileContent,
'path' => $parentPath,
'name' => $fileName,
]);
}
public function SaveThemeFile(){
return $this->adminObj->saveThemeFile(input('post.'));
}
public function SettingMail(){
return view('mail_setting', [
'options' => $this->siteOptions,
'optionsForSet' => Option::getValues(["mail_template","mail"]),
]);
}
public function SettingPay(){
return view('pay_setting', [
'options' => $this->siteOptions,
'optionsForSet' => Option::getValues(["payment"]),
]);
}
public function SettingOther(){
return view('other_setting', [
'options' => $this->siteOptions,
'optionsForSet' => Option::getValues(["file_edit","share","avatar","admin","storage_policy"]),
]);
}
public function Files(){
$this->adminObj->listFile();
return view('file_list', [
'options' => $this->siteOptions,
'groups' => $this->adminObj->getAvaliableGroup(),
'list' => $this->adminObj->pageData,
'originList' => $this->adminObj->listData,
'pageNow' => $this->adminObj->pageNow,
'pageTotal' => $this->adminObj->pageTotal,
'dataTotal' => $this->adminObj->dataTotal,
'policy' => $this->adminObj->getAvaliablePolicy(),
]);
}
Public function Users(){
$this->adminObj->listUser();
$group = $this->adminObj->getAvaliableGroup();
return view('user_list', [
'options' => $this->siteOptions,
'group' => $group,
'groups' => $group,
'list' => $this->adminObj->pageData,
'originList' => $this->adminObj->listData,
'pageNow' => $this->adminObj->pageNow,
'pageTotal' => $this->adminObj->pageTotal,
'dataTotal' => $this->adminObj->dataTotal,
'policy' => $this->adminObj->getAvaliablePolicy(),
]);
}
public function Shares(){
$this->adminObj->listShare();
return view('share_list', [
'options' => $this->siteOptions,
'groups' => $this->adminObj->getAvaliableGroup(),
'list' => $this->adminObj->pageData,
'originList' => $this->adminObj->listData,
'pageNow' => $this->adminObj->pageNow,
'pageTotal' => $this->adminObj->pageTotal,
'dataTotal' => $this->adminObj->dataTotal,
]);
}
public function PolicyList(){
$this->adminObj->listPolicy();
return view('policy_list', [
'options' => $this->siteOptions,
'groups' => $this->adminObj->getAvaliableGroup(),
'list' => $this->adminObj->pageData,
'originList' => $this->adminObj->listData,
'pageNow' => $this->adminObj->pageNow,
'pageTotal' => $this->adminObj->pageTotal,
'dataTotal' => $this->adminObj->dataTotal,
]);
}
public function GroupList(){
$this->adminObj->listGroup();
return view('group_list', [
'options' => $this->siteOptions,
'list' => $this->adminObj->pageData,
'originList' => $this->adminObj->listData,
'pageNow' => $this->adminObj->pageNow,
'pageTotal' => $this->adminObj->pageTotal,
'dataTotal' => $this->adminObj->dataTotal,
]);
}
public function OrderList(){
$this->adminObj->listOrder();
return view('order_list', [
'options' => $this->siteOptions,
'list' => $this->adminObj->pageData,
'originList' => $this->adminObj->listData,
'pageNow' => $this->adminObj->pageNow,
'pageTotal' => $this->adminObj->pageTotal,
'dataTotal' => $this->adminObj->dataTotal,
]);
}
public function SaveBasicSetting(){
return $this->adminObj->saveBasicSetting(input('post.'));
}
public function SaveRegSetting(){
return $this->adminObj->saveRegSetting(input('post.'));
}
public function SaveMailSetting(){
return $this->adminObj->saveMailSetting(input('post.'));
}
public function SendTestMail(){
return $this->adminObj->sendTestMail(input('post.'));
}
public function SaveMailTemplate(){
return $this->adminObj->saveMailTemplate(input('post.'));
}
public function GetFileInfo(){
return $this->adminObj->getFileInfo(input('post.id'));
}
public function GetUserInfo(){
return $this->adminObj->getUserInfo(input('post.id'));
}
public function savePolicy(){
return $this->adminObj->addPolicy(input('post.'));
}
public function SaveEditPolicy(){
return $this->adminObj->editPolicy(input('post.'));
}
public function SaveGroup(){
return $this->adminObj->saveGroup(input('post.'));
}
public function AddPack(){
return $this->adminObj->addPack(input('post.'));
}
public function AddGroupPurchase(){
return $this->adminObj->addGroupPurchase(input('post.'));
}
public function SaveCron(){
$this->adminObj->saveCron(input('post.'));
$this->redirect("/Admin/Cron",302);
}
public function SaveUser(){
return $this->adminObj->saveUser(input('post.'));
}
public function BanUser(){
return $this->adminObj->banUser(input('post.id'),$this->userObj->uid);
}
public function AddUser(){
return $this->adminObj->addUser(input('post.'));
}
public function Preview(){
$fileId = input('param.id');
$fileRecord = Db::name("files")->where("id",$fileId)->find();
$fileObj = new FileManage(rtrim($fileRecord["dir"],"/")."/".$fileRecord["orign_name"],$fileRecord["upload_user"]);
$previewHandler = $fileObj->PreviewHandler(true);
if($previewHandler[0]){
$this->redirect($previewHandler[1],302);
}
}
public function Download(){
$fileId = input('param.id');
$fileRecord = Db::name("files")->where("id",$fileId)->find();
$fileObj = new FileManage(rtrim($fileRecord["dir"],"/")."/".$fileRecord["orign_name"],$fileRecord["upload_user"]);
$FileHandler = $fileObj->Download(true);
if($FileHandler[0]){
$this->redirect($FileHandler[1],302);
}
}
public function Delete(){
return $this->adminObj->deleteSingle(input('post.id'));
}
public function DeleteShare(){
return $this->adminObj->deleteShare([0=>input('post.id')]);
}
public function DeleteShareMultiple(){
return $this->adminObj->deleteShare(json_decode(input('post.id'),true));
}
public function DeleteMultiple(){
return $this->adminObj->deleteMultiple(input('post.id'));
}
public function DeletePolicy(){
return $this->adminObj->deletePolicy(input('post.id'));
}
public function DeleteGroup(){
return $this->adminObj->deleteGroup(input('post.id'));
}
public function DeleteOrder(){
return $this->adminObj->deleteOrder(input('post.id'));
}
public function ChangeShareType(){
return $this->adminObj->changeShareType(input('post.id'));
}
public function DeletePack(){
return $this->adminObj->deletePack(input('post.id'));
}
public function DeleteGroupPurchase(){
return $this->adminObj->deleteGroupPurchase(input('post.id'));
}
public function DeleteUser(){
return $this->adminObj->deleteUser(input('post.id'),$this->userObj->uid);
}
public function DeleteUsers(){
$uidGroup = json_decode(input('post.id'),true);
foreach ($uidGroup as $key => $value) {
$this->adminObj->deleteUser($value,$this->userObj->uid);
}
return ["error"=>false,"msg"=>"删除成功"];
}
public function SwitchColor(){
$colorNow = Option::getValues(["admin"]);
if($colorNow["admin_color_body"] == "fixed-nav sticky-footer bg-light"){
$colorNew = [
"admin_color_body" => "fixed-nav sticky-footer bg-dark",
"admin_color_nav" => "navbar navbar-expand-lg fixed-top navbar-dark bg-dark",
];
}else{
$colorNew = [
"admin_color_body" => "fixed-nav sticky-footer bg-light",
"admin_color_nav" => "navbar navbar-expand-lg fixed-top navbar-light bg-light",
];
}
foreach ($colorNew as $key => $value) {
Db::name("options")->where("option_name",$key)->update(["option_value" => $value]);
}
}
public function EditPolicy(){
$policyId = input('param.id');
$policyRecord = Db::name("policy")->where("id",$policyId)->find();
return view('edit_policy', [
'options' => $this->siteOptions,
'policy' => $policyRecord,
]);
}
public function EditGroup(){
$groupId = input('param.id');
$groupRecord = Db::name("groups")->where("id",$groupId)->find();
return view('edit_group', [
'options' => $this->siteOptions,
'group' => $groupRecord,
'policy' => $this->adminObj->getAvaliablePolicy(),
]);
}
public function AddGroup(){
return $this->adminObj->addGroup(input('post.'));
}
public function PolicyAdd(){
return view('add_policy', [
'options' => $this->siteOptions,
]);
}
public function Cron(){
$cronData = Db::name("corn")->select();
$neverExcute = true;
foreach ($cronData as $key => $value) {
if($value["last_excute"] !=0){
$neverExcute = false;
}
}
return view('cron_list', [
'options' => $this->siteOptions,
'cron' => $cronData,
'neverExcute' => $neverExcute,
]);
}
public function PolicyAddS3(){
return view('add_policy_s3', [
'options' => $this->siteOptions,
]);
}
public function About(){
$verison = json_decode(file_get_contents(ROOT_PATH . "application/version.json"),true);
return view('about', [
'options' => $this->siteOptions,
'programVersion' => $verison,
"dbsVersion" => Option::getValue("database_version"),
]);
}
public function Purchase(){
$packData = json_decode(Option::getValue("pack_data"),true);
return view('purchase', [
'options' => $this->siteOptions,
'pack' => $packData,
]);
}
public function PurchaseGroup(){
$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();
}
return view('purchase_group', [
'options' => $this->siteOptions,
'group' => $groupData,
'group_list' => $this->adminObj->getAvaliableGroup(),
]);
}
public function GroupAdd(){
return view('add_group', [
'options' => $this->siteOptions,
'policy' => $this->adminObj->getAvaliablePolicy(),
]);
}
}

@ -0,0 +1,84 @@
<?php
namespace app\index\controller;
use think\Controller;
use think\Db;
use think\Request;
use \app\index\model\CallbackHandler;
use \app\index\model\User;
use \app\index\model\Option;
use \app\index\model\FileManage;
use think\Session;
class Callback extends Controller{
public function index(){
return "";
}
public function Qiniu(){
ob_end_clean();
header('Content-Type: application/json');
$handllerObj = new CallbackHandler(file_get_contents("php://input"));
$handllerObj -> qiniuHandler(Request::instance()->header('Authorization'));
}
public function Oss(){
ob_end_clean();
header('Content-Type: application/json');
$handllerObj = new CallbackHandler(file_get_contents("php://input"));
$handllerObj -> ossHandler(Request::instance()->header('Authorization'),Request::instance()->header('x-oss-pub-key-url'));
}
public function TmpPreview(){
$basicOptions = Option::getValues(['basic']);
$params = explode(":",input("param.key"));
$fileData = Db::name("files")->where("id",$params[0])->find();
if (empty($fileData)){
abort(404);
}
$userData = Db::name("users")->where("id",$fileData["upload_user"])->find();
if(md5($userData["user_pass"].$fileData["id"].$params[1].config("salt")) != $params[2] || time()<$params[0]){
abort(403);
}
$fileObj = new FileManage(rtrim($fileData["dir"],"/")."/".$fileData["orign_name"],$userData["id"]);
$Redirect = $fileObj->PreviewHandler();
}
public function Upyun(){
$signToken = Request::instance()->header('Authorization');
$reqDate = Request::instance()->header('Date');
$contentMd5 = Request::instance()->header('Content-MD5');
ob_end_clean();
header('Content-Type: application/json');
$callbackData = [
"code" => input("post.code"),
"file_size" => input("post.file_size"),
"url" => input("post.url"),
"image-width" => input("post.image-width"),
"image-height" => input("post.image-height"),
"ext-param" => json_decode(input("post.ext-param"),true),
];
$handllerObj = new CallbackHandler($callbackData);
$handllerObj -> upyunHandler($signToken,$reqDate,$contentMd5);
}
public function S3(){
$request = Request::instance();
if($request->method() == "OPTIONS"){
ob_end_clean();
header("Access-Control-Allow-Origin: *");
exit();
}
ob_end_clean();
header("Access-Control-Allow-Origin: *");
$callbackKey = input("param.key");
$callbackData = [
"bucket" => input("get.bucket"),
"key" => input("get.key"),
];
$handllerObj = new CallbackHandler($callbackData);
$handllerObj -> s3Handler($callbackKey);
}
}

@ -0,0 +1,17 @@
<?php
namespace app\index\controller;
use think\Controller;
use think\Db;
use think\Request;
use \app\index\model\CronHandler;
use think\Session;
class Cron extends Controller{
public function index(){
$cornObj = new CronHandler();
$cornObj->Doit();
}
}

@ -0,0 +1,60 @@
<?php
namespace app\index\controller;
use think\Controller;
use app\index\model\User;
use think\Cookie;
use think\Db;
use \app\index\model\Option;
class Explore extends Controller{
public $visitorObj;
public $userObj;
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'));
$keyWords=input("param.key");
if(empty($keyWords)){
$this->redirect('/Explore/Search',302);
}
$list = Db::name('shares')
->where('type',"public")
->where('origin_name',"like","%".$keyWords."%")
->order('id DESC')
->paginate(10);
$listData = $list->all();
foreach ($listData as $key => $value) {
if($value["source_type"]=="file"){
$listData[$key]["fileData"] = $value["origin_name"];
}else{
$pathDir = explode("/",$value["source_name"]);
$listData[$key]["fileData"] = end($pathDir);
}
}
return view("result",[
"options" => $this->siteOptions,
'loginStatus' => $this->visitorObj->loginStatus,
'userData' => $this->visitorObj->userSQLData,
'list' => $listData,
'listOrigin' => $list,
'keyWords' => $keyWords,
]);
}
}

@ -0,0 +1,175 @@
<?php
namespace app\index\controller;
use think\Controller;
use think\Db;
use think\Request;
use \app\index\model\Option;
use \app\index\model\User;
use \app\index\model\FileManage;
use \app\index\model\ShareHandler;
use think\Session;
class File extends Controller{
public $userObj;
/**
* [_initialize description]
* @return [type] [description]
*/
public function _initialize(){
$this->userObj = new User(cookie('user_id'),cookie('login_key'));
if(!$this->userObj->loginStatus){
echo "Bad request";
exit();
}
}
/**
* [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);
}
public function Delete(){
$reqPath = json_decode(file_get_contents("php://input"),true)['items'];
$dirPath = json_decode(file_get_contents("php://input"),true)['dirs'];
FileManage::DirDeleteHandler($dirPath,$this->userObj->uid);
return 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'];
return FileManage::MoveHandler($reqPath,$dirPath,$newPath,$this->userObj->uid);
}
public function Rename(){
$reqPath = json_decode(file_get_contents("php://input"),true)['item'];
$newPath = json_decode(file_get_contents("php://input"),true)['newItemPath'];
return FileManage::RenameHandler($reqPath,$newPath,$this->userObj->uid);
}
public function Preview(){
$reqPath = $_GET["path"];
$fileObj = new FileManage($reqPath,$this->userObj->uid);
$Redirect = $fileObj->PreviewHandler();
if($Redirect[0]){
$this->redirect($Redirect[1],302);
}
}
public function ListPic(){
$reqPath = $_GET["path"];
return FileManage::listPic($reqPath,$this->userObj->uid);
}
public function Download(){
$reqPath = $_GET["path"];
$fileObj = new FileManage($reqPath,$this->userObj->uid);
$FileHandler = $fileObj->Download();
if($FileHandler[0]){
$this->redirect($FileHandler[1],302);
}
}
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());
}
public function gerSource(){
$reqPath = $_POST["path"];
$fileObj = new FileManage($reqPath,$this->userObj->uid);
$FileHandler = $fileObj->Source();
}
public function Content(){
$reqPath = json_decode(file_get_contents("php://input"),true)['item'];
$fileObj = new FileManage($reqPath,$this->userObj->uid);
$FileHandler = $fileObj->getContent();
}
public function Edit(){
$reqPath = json_decode(file_get_contents("php://input"),true)['item'];
$fileContent = json_decode(file_get_contents("php://input"),true)['content'];
$fileObj = new FileManage($reqPath,$this->userObj->uid);
$FileHandler = $fileObj->saveContent($fileContent);
}
public function OssDownload(){
return view('oss_download', [
'url' => urldecode(input("get.url")),
'name' => urldecode(input("get.name")),
]);
}
public function DocPreview(){
$filePath = input("get.path");
$fileObj = new FileManage($filePath,$this->userObj->uid);
$tmpUrl = $fileObj->signTmpUrl();
$this->redirect("http://view.officeapps.live.com/op/view.aspx?src=".urlencode($tmpUrl),302);
}
public function Thumb(){
$filePath = input("get.path");
if(input("get.isImg") != "true"){
return "";
}
$fileObj = new FileManage($filePath,$this->userObj->uid);
$Redirect = $fileObj->getThumb();
if($Redirect[0]){
$this->redirect($Redirect[1],302);
}
}
public function GoogleDocPreview(){
$filePath = input("get.path");
$fileObj = new FileManage($filePath,$this->userObj->uid);
$tmpUrl = $fileObj->signTmpUrl();
$this->redirect("https://docs.google.com/viewer?url=".urlencode($tmpUrl),302);
}
/**
* [createFolder description]
* @Author Aaron
* @DateTime 2017-07-03
* @return [type] [description]
*/
public function createFolder(){
$reqPath = stripslashes(json_decode(file_get_contents("php://input"),true)['newPath']);
$pathSplit = explode("/",$reqPath);
$dirName = end($pathSplit);
$dirPosition="/";
foreach ($pathSplit as $key => $value) {
if (empty($value)){
}else if($key == (count($pathSplit)-2)){
$dirPosition = $dirPosition.$value;
}else if($key == (count($pathSplit)-1)){
}else{
$dirPosition = $dirPosition.$value."/";
}
}
return FileManage::createFolder($dirName,$dirPosition,$this->userObj->uid);
}
}

@ -0,0 +1,75 @@
<?php
namespace app\index\controller;
use think\Controller;
use think\Db;
use \app\index\model\Option;
use \app\index\model\User;
use think\Session;
class Home 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();
}
}
public function index(){
$userInfo = $this->userObj->getInfo();
$policyData = $this->userObj->getPolicy();
$groupData = $this->userObj->getGroupData();
$extJson = json_decode($policyData["filetype"],true);
$extLimit="";
foreach ($extJson as $key => $value) {
$extLimit.='{ title : "'.$value["title"].'", extensions : "'.$value["ext"].'" },';
}
$policyData["max_size"] = $policyData["max_size"]/(1024*1024);
return view('home', [
'options' => Option::getValues(['basic','upload']),
'userInfo' => $userInfo,
'extLimit' => $extLimit,
'policyData' => $policyData,
'groupData' => $groupData,
]);
}
public function Album(){
$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']),
'userInfo' => $userInfo,
'list' => $listData,
'listOrigin' => $list,
'pageCount' => $pageCount,
'page' => $pageNow,
]);
}
}

@ -0,0 +1,23 @@
<?php
namespace app\index\controller;
use think\Controller;
use think\Db;
use \app\index\model\Option;
use \app\index\model\User;
class Index extends Controller{
public $userObj;
public function index(){
$this->userObj = new User(cookie('user_id'),cookie('login_key'));
$userInfo = $this->userObj->getInfo();
return view('index', [
'options' => Option::getValues(['basic']),
'userInfo' => $userInfo,
]);
}
}

@ -0,0 +1,300 @@
<?php
namespace app\index\controller;
use think\Controller;
use app\index\model\User;
use think\Cookie;
use think\Db;
use \app\index\model\Option;
use \app\index\model\Avatar;
use \PHPGangsta_GoogleAuthenticator;
use \app\index\model\TwoFactor;
class Member extends Controller{
public $userObj;
/**
* [index description]
* @return [type] [description]
*/
public function index(){
echo "hello";
}
/**
* [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'));
if ($regAction[0]){
return json(['code' => '200','message' => $regAction[1]]);
}else{
return json(['code' => '1','message' => $regAction[1]]);
}
}else{
return json(['code' => '1','message' => "信息不完整"]);
}
}
public function ForgetPwd(){
if(input('?post.regEmail') && input('?post.captchaCode') && !empty(input('post.captchaCode')) && !empty(input('post.regEmail'))){
$findAction = User::findPwd(input('post.regEmail'),input('post.captchaCode'));
if ($findAction[0]){
return json(['code' => '200','message' => $findAction[1]]);
}else{
return json(['code' => '1','message' => $findAction[1]]);
}
}else{
return json(['code' => '1','message' => "信息不完整"]);
}
}
/**
* [Login description]
*/
public function Login(){
if(input('?post.userMail') && input('?post.userPass')){
$logAction = User::login(input('post.userMail'),input('post.userPass'),input('post.captchaCode'));
if ($logAction[0]){
return json(['code' => '200','message' => '登陆成功']);
}else{
return json(['code' => '1','message' => $logAction[1]]);
}
}else{
return json(['code' => '1','message' => "信息不完整"]);
}
}
/**
* [LogOut description]
*/
public function LogOut(){
$this->userObj = new User(cookie('user_id'),cookie('login_key'));
$this->userObj->clear();
$this->redirect("/Login",302);
}
public function Memory(){
$this->userObj = new User(cookie('user_id'),cookie('login_key'));
$this->userObj->getMemory();
}
public function LoginForm(){
$this->userObj = new User(cookie('user_id'),cookie('login_key'));
$this->isLoginStatusCheck();
return view('login', [
'options' => Option::getValues(['basic']),
'RegOptions' => Option::getValues(['register','login']),
'loginStatus' => $this->userObj->loginStatus,
]);
}
public function TwoStepCheck(){
$checkCode = input("post.code");
if(empty($checkCode)){
return json(['code' => '1','message' => "验证码不能为空"]);
}
$userId = session("user_id_tmp");
$userData = Db::name('users')->where('id',$userId)->find();
$ga = new PHPGangsta_GoogleAuthenticator();
$checkResult = $ga->verifyCode($userData["two_step"], $checkCode, 2);
if($checkResult) {
cookie('user_id',session("user_id_tmp"),604800);
cookie('login_status',session("login_status_tmp"),604800);
cookie('login_key',session("login_key_tmp"),604800);
return json(['code' => '200','message' => '登陆成功']);
}else{
return json(['code' => '1','message' => "验证失败"]);
}
}
public function TwoStep(){
$this->userObj = new User(cookie('user_id'),cookie('login_key'));
$this->isLoginStatusCheck();
return view('two_step', [
'options' => Option::getValues(['basic']),
'RegOptions' => Option::getValues(['register','login']),
'loginStatus' => $this->userObj->loginStatus,
]);
}
public function setWebdavPwd(){
$this->userObj = new User(cookie('user_id'),cookie('login_key'));
$this->loginStatusCheck();
Db::name("users")->where("id",$this->userObj->uid)
->update([
"webdav_key" => md5($this->userObj->userSQLData["user_email"].":CloudreveWebDav:".input("post.pwd")),
]);
return json(['error' => '200','msg' => '设置成功']);
}
public function emailActivate(){
$activationKey = input('param.key');
$basicOptions = Option::getValues(['basic']);
$this->userObj = new User(cookie('user_id'),cookie('login_key'));
$this->isLoginStatusCheck();
$activeAction = User::activicateUser($activationKey);
if($activeAction[0]){
return view('active_user', [
'options' => $basicOptions,
'loginStatus' => $this->userObj->loginStatus,
]);
}else{
$this->error($activeAction[1],403,$basicOptions);
}
}
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'));
$this->isLoginStatusCheck();
$resetAction = User::resetUser($resetKey,$userId);
if($resetAction[0]){
return view('reset_user', [
'options' => $basicOptions,
'loginStatus' => $this->userObj->loginStatus,
'key' => $resetKey."_".$userId,
]);
}else{
$this->error($resetAction[1],403,$basicOptions);
}
}
public function Reset(){
$newPwd = input('post.pwd');
$resetKey = input('post.key');
$resetAction = User::resetPwd($resetKey,$newPwd);
if($resetAction[0]){
return json(['code' => '200','message' => '重设成功,请前往登录页登录']);
}else{
return json(['code' => '1','message' => $resetAction[1]]);
}
}
public function Setting(){
$this->userObj = new User(cookie('user_id'),cookie('login_key'));
$userInfo = $this->userObj->getInfo();
$this->loginStatusCheck();
$policyList=[];
foreach (explode(",",$this->userObj->groupData["policy_list"]) as $key => $value) {
$policyList[$key] = $value;
}
$avaliablePolicy = Db::name("policy")->where("id","in",$policyList)->select();
$basicOptions = Option::getValues(['basic']);
return view('setting', [
'options' => $basicOptions,
'userInfo' => $userInfo,
'userSQL' => $this->userObj->userSQLData,
'groupData' => $this->userObj->groupData,
'loginStatus' => $this->userObj->loginStatus,
'avaliablePolicy' => $avaliablePolicy,
]);
}
public function SaveAvatar(){
$this->userObj = new User(cookie('user_id'),cookie('login_key'));
$file = request()->file("avatar");
$avatarObj = new Avatar(true,$file);
if(!$avatarObj->SaveAvatar()){
return json_encode($avatarObj->errorMsg);
}else{
$avatarObj->bindUser($this->userObj->uid);
return json_encode(["result" => "success"]);
}
}
public function Avatar(){
if(!input("get.cache")=="no"){
header("Cache-Control: max-age=10800");
}
$userId = input("param.uid");
$avatarObj = new Avatar(false,$userId);
$avatarImg = $avatarObj->Out(input("param.size"));
$this->redirect($avatarImg,302);
}
public function SetGravatar(){
$this->userObj = new User(cookie('user_id'),cookie('login_key'));
$avatarObj = new Avatar(false,$this->userObj->uid);
$avatarObj->setGravatar();
}
public function Nick(){
$this->userObj = new User(cookie('user_id'),cookie('login_key'));
$userInfo = $this->userObj->getInfo();
$this->loginStatusCheck();
$saveAction = $this->userObj->changeNick(input("post.nick"));
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();
$this->loginStatusCheck();
$saveAction = $this->userObj->homePageToggle(input("post.status"));
if($saveAction[0]){
return json(['error' => '200','msg' => '设置成功']);
}else{
return json(['error' => '1','msg' => $saveAction[1]]);
}
}
public function EnableTwoFactor(){
$twoFactor = new TwoFactor();
$twoFactor->qrcodeRender();
}
public function TwoFactorConfirm(){
$this->userObj = new User(cookie('user_id'),cookie('login_key'));
$userInfo = $this->userObj->getInfo();
$this->loginStatusCheck();
$twoFactor = new TwoFactor();
$confirmResult = $twoFactor->confirmCode(session("two_factor_enable"),input("post.code"));
if($confirmResult[0]){
$twoFactor->bindUser($this->userObj->uid);
return json(['error' => '200','msg' => '设置成功']);
}else{
return json(['error' => '1','msg' => $confirmResult[1]]);
}
}
public function ChangePwd(){
$this->userObj = new User(cookie('user_id'),cookie('login_key'));
$userInfo = $this->userObj->getInfo();
$this->loginStatusCheck();
$changeAction = $this->userObj->changePwd(input("post.origin"),input("post.new"));
if($changeAction[0]){
return json(['error' => '200','msg' => '设置成功']);
}else{
return json(['error' => '1','msg' => $changeAction[1]]);
}
}
private function loginStatusCheck($login=true){
if(!$this->userObj->loginStatus){
if($login){
$this->redirect(url('/Login','',''));
}else{
$this->redirect(url('/Home','',''));
}
exit();
}
}
private function isLoginStatusCheck(){
if($this->userObj->loginStatus){
$this->redirect(url('/Home','',''));
exit();
}
}
}

@ -0,0 +1,80 @@
<?php
namespace app\index\controller;
use think\Controller;
use app\index\model\User;
use think\Cookie;
use think\Db;
use \app\index\model\Option;
class Profile extends Controller{
public $visitorObj;
public $userObj;
public $siteOptions;
public function _initialize(){
$this->siteOptions = Option::getValues(["basic"]);
}
public function index(){
$this->visitorObj = new User(cookie('user_id'),cookie('login_key'));
$userId = (string)input("param.uid");
$userData = Db::name("users")->where("id",$userId)->find();
if (empty($userId) || empty($userData) || $userData["profile"] == 0){
$this->error('用户主页不存或者用户关闭了个人主页',404,$this->siteOptions);
}
$groupData = Db::name("groups")->where("id",$userData["user_group"])->find();
$shareCount = Db::name('shares')
->where('owner',$userId)
->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,
'groupData' => $groupData,
'list' => $listData,
'listOrigin' => $list,
'type' => input("get.type"),
'shareCount' => $shareCount,
'regDays' => $regDays,
]);
}
}

@ -0,0 +1,185 @@
<?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\ShareHandler;
use think\Session;
use think\Request;
class Share extends Controller{
public $userObj;
public $siteOptions;
public function _initialize(){
$this->userObj = new User(cookie('user_id'),cookie('login_key'));
$this->siteOptions = Option::getValues(["basic"]);
}
public function index(){
$shareKey = input('param.key');
$shareObj = new ShareHandler($shareKey);
if(!$shareObj->querryStatus){
header('HTTP/1.1 404 Not Found');
$this->error('当前分享不存在或者已经失效',404,$this->siteOptions);
}
if(!$shareObj->lockStatus){
$shareObj->numIncrease("view_num");
if($shareObj->shareData["source_type"] == "dir"){
return view('share_dir', [
'options' => Option::getValues(['basic','share']),
'userInfo' => $shareObj->shareOwner->userSQLData,
'dirData' => $shareObj->dirData,
'shareData' => $shareObj->shareData,
'loginStatus' => $this->userObj->loginStatus,
'userData' => $this->userObj->userSQLData,
'groupData' => $shareObj->shareOwner->groupData,
'allowPreview' => Option::getValue("allowdVisitorDownload"),
]);
}else{
return view('share_single', [
'options' => Option::getValues(['basic','share']),
'userInfo' => $shareObj->shareOwner->userSQLData,
'fileData' => $shareObj->fileData,
'shareData' => $shareObj->shareData,
'loginStatus' => $this->userObj->loginStatus,
'userData' => $this->userObj->userSQLData,
'allowPreview' => Option::getValue("allowdVisitorDownload"),
]);
}
}else{
return view('share_lock', [
'options' => Option::getValues(['basic','share']),
'userInfo' => $shareObj->shareOwner->userSQLData,
'fileData' => $shareObj->fileData,
'shareData' => $shareObj->shareData,
'loginStatus' => $this->userObj->loginStatus,
'userData' => $this->userObj->userSQLData,
'pwd' => input("?get.pwd") ? input("get.pwd") : "",
]);
}
}
public function getDownloadUrl(){
$shareId = input('key');
$shareObj = new ShareHandler($shareId,false);
return $shareObj->getDownloadUrl($this->userObj);
}
public function Download(){
$shareId = input('param.key');
$filePath = input('get.path');
$shareObj = new ShareHandler($shareId,false);
if(empty($filePath)){
$DownloadHandler = $shareObj->Download($this->userObj);
}else{
$DownloadHandler = $shareObj->DownloadFolder($this->userObj,$filePath);
}
if($DownloadHandler[0]){
$this->redirect($DownloadHandler[1],302);
}else{
$this->error($DownloadHandler[1],404,$this->siteOptions);
}
}
public function chekPwd(){
$shareId = input('key');
$inputPwd = input('password');
$shareObj = new ShareHandler($shareId,false);
if(!$shareObj->querryStatus){
return array(
"error" => 1,
"msg" => "分享不存在"
);
}
return $shareObj->checkPwd($inputPwd);
}
public function Preview(){
$shareId = input('param.key');
$filePath = input('get.path');
$shareObj = new ShareHandler($shareId,false);
if(empty($filePath)){
$previewHandler = $shareObj->Preview($this->userObj);
}else{
if(!empty(input('get.folder'))){
$previewHandler = $shareObj->PreviewFolder($this->userObj,$filePath,true);
}else{
$previewHandler = $shareObj->PreviewFolder($this->userObj,$filePath);
}
}
if($previewHandler[0]){
$this->redirect($previewHandler[1],302);
}else{
$this->error($previewHandler[1],404,$this->siteOptions);
}
}
public function ListFile(){
$shareId = input('param.key');
$reqPathTo = stripslashes(json_decode(file_get_contents("php://input"),true)['path']);
$shareObj = new ShareHandler($shareId,false);
return $shareObj->ListFile($reqPathTo);
}
public function ListPic(){
$filePath = input('get.path');
$shareId = input('get.id');
$shareObj = new ShareHandler($shareId,false);
return $shareObj->listPic($shareId,$filePath);
}
public function Delete(){
$shareId = input('post.id');
$shareObj = new ShareHandler($shareId,false);
if(!$shareObj->querryStatus){
return array(
"error" => 1,
"msg" => "分享不存在"
);
}
return $shareObj->deleteShare($this->userObj->uid);
}
public function ChangePromission(){
$shareId = input('post.id');
$shareObj = new ShareHandler($shareId,false);
if(!$shareObj->querryStatus){
return array(
"error" => 1,
"msg" => "分享不存在"
);
}
return $shareObj->changePromission($this->userObj->uid);
}
public function My(){
if(!$this->userObj->loginStatus){
$this->redirect(url('/Login','',''));
exit();
}
$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,
'groupData' => $groupData,
'list' => $listData,
'listOrigin' => $list
]);
}
}

@ -0,0 +1,78 @@
<?php
namespace app\index\controller;
use think\Controller;
use think\Db;
use think\Request;
use \app\index\model\Option;
use \app\index\model\User;
use \app\index\model\UploadHandler;
use think\Session;
class Upload 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();
}
}
public function index(){
ob_end_clean();
$file = request()->file('file');
$fileInfo = Request::instance()->request();
$UploadHandler = new UploadHandler($this->userObj->groupData['policy_name'],$this->userObj->uid);
return $UploadHandler->fileReceive($file,$fileInfo);
}
public function Token(){
$uploadObj = new UploadHandler($this->userObj->groupData['policy_name'],$this->userObj->uid);
$upToken = $uploadObj->getToken();
if(!empty($uploadObj->upyunPolicy)){
return json([
"token" => $upToken,
"policy" => $uploadObj->upyunPolicy,
]);
}
if(!empty($uploadObj->s3Policy)){
return json([
"policy" => $uploadObj->s3Policy,
"sign" => $uploadObj->s3Sign,
"key" => $uploadObj->dirName,
"credential" => $uploadObj->s3Credential,
"x_amz_date" => $uploadObj->x_amz_date,
"siteUrl"=>$uploadObj->siteUrl,
"callBackKey" => $uploadObj->callBackKey,
]);
}
if(!$uploadObj->getToken()){
return json([
"uptoken" => $uploadObj->ossToken,
"sign" => $uploadObj->ossSign,
"id" => $uploadObj->ossAccessId,
"key" => $uploadObj->ossFileName,
"callback" => $uploadObj->ossCallBack,
]);
}
return json(["uptoken" => $uploadObj->getToken()]);
}
public function chunk(){
$file = file_get_contents('php://input');
$uploadObj = new UploadHandler($this->userObj->groupData['policy_name'],$this->userObj->uid);
$uploadObj->setChunk(input('param.chunk'),input('param.chunks'),$file);
}
public function mkFile(){
$ctx = file_get_contents('php://input');
$originName = UploadHandler::b64Decode(input('param.fname'));
$filePath = UploadHandler::b64Decode(input('param.path'));
$uploadObj = new UploadHandler($this->userObj->groupData['policy_name'],$this->userObj->uid);
$uploadObj->generateFile($ctx,$originName,$filePath);
}
}

@ -0,0 +1,45 @@
<?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\Directory;
use \app\index\model\Object;
use \app\index\model\DavAuth;
use \app\index\model\BasicCallBack;
use Sabre\DAV;
use Sabre\DAV\Auth;
class WebDav extends Controller{
public $userObj;
public $uid;
public function index(){
}
public function Api(){
$this->uid = input("param.uid");
$publicDir = new Directory($this->uid."/");
$server = new DAV\Server($publicDir);
$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);
$check = new DavAuth($this->uid);
$callBack = new BasicCallBack($check);
$authPlugin = new Auth\Plugin($callBack);
$server->addPlugin($authPlugin);
$server->addPlugin(new DAV\Browser\Plugin());
$server->addPlugin(new \Sabre\DAV\Browser\GuessContentType());
ob_end_clean();
$server->exec();
}
}

@ -0,0 +1,657 @@
<?php
namespace app\index\model;
use think\Model;
use think\Db;
use \app\index\model\Mail;
use \app\index\model\FileManage;
class AdminHandler extends Model{
public $siteOptions;
public $pageData;
public $listData;
public $pageNow;
public $pageTotal;
public $dataTotal;
public function __construct($options){
$this->siteOptions = $options;
}
public function getStatics(){
$statics["fileNum"] = Db::name('files')->count();
$statics["privateShareNum"] = Db::name('shares')->where("type","private")->count();
$statics["publicShareNum"] = Db::name('shares')->where("type","public")->count();
$statics["userNum"] = Db::name('users')->where("user_status",0)->count();
if($statics["fileNum"]==0){
$statics["imgRate"] = 0;
$statics["audioRate"] = 0;
$statics["videoRate"] = 0;
$statics['otherRate'] = 0;
}else{
$statics["imgRate"] =floor(Db::name('files')
->where('pic_info',"<>"," ")
->where('pic_info',"<>","0,0")
->where('pic_info',"<>","null,null")
->count()/$statics["fileNum"]*10000)/100;
$statics["audioRate"] =floor(Db::name('files')
->where(function ($query) {
$query->where('orign_name', "like","%mp3")
->whereor('orign_name', "like","%flac")
->whereor('orign_name', "like","%wma")
->whereor('orign_name', "like","%aac")
->whereor('orign_name', "like","%wav")
->whereor('orign_name', "like","%ogg");
})
->count()/$statics["fileNum"]*10000)/100;
$statics["videoRate"] =floor(Db::name('files')
->where(function ($query) {
$query->where('orign_name', "like","%mp4")
->whereor('orign_name', "like","%avi")
->whereor('orign_name', "like","%rmvb")
->whereor('orign_name', "like","%aac")
->whereor('orign_name', "like","%wav")
->whereor('orign_name', "like","%mkv");
})
->count()/$statics["fileNum"]*10000)/100;
$statics['otherRate'] = 100-($statics["videoRate"]+$statics["audioRate"]+$statics["imgRate"]);
}
$timeNow=time();
$statics["trendFile"]="";
$statics["trendUser"]="";
$statics["trendDate"]="";
for ($i=0; $i < 13; $i++) {
$statics["trendFile"].= Db::name('files')->where('upload_date','between time',[date("Y-m-d",$timeNow-(12-$i)*3600*24),date("Y-m-d",$timeNow-(11-$i)*3600*24)])->count().",";
}
for ($i=0; $i < 13; $i++) {
$statics["trendUser"].= Db::name('users')->where('user_date','between time',[date("Y-m-d",$timeNow-(12-$i)*3600*24),date("Y-m-d",$timeNow-(11-$i)*3600*24)])->count().",";
}
for ($i=0; $i < 13; $i++) {
$statics["trendDate"].='"'.date("m月d日",$timeNow-(12-$i)*3600*24).'",';
}
$statics["trendFile"] = rtrim($statics["trendFile"],",");
$statics["trendDate"] = rtrim($statics["trendDate"],",");
$statics["trendUser"] = rtrim($statics["trendUser"],",");
return $statics;
}
public function saveBasicSetting($options){
$siteUrl = rtrim($options["siteURL"],"/")."/";
$options["siteURL"]=$siteUrl;
return $this->saveOptions($options);
}
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;
}
return $this->saveOptions($options);
}
public function saveMailSetting($options){
return $this->saveOptions($options);
}
public function saveMailTemplate($options){
return $this->saveOptions($options);
}
public function AddGroup($options){
$options["max_storage"] = $options["max_storage"]*$options["sizeTimes"];
unset($options["sizeTimes"]);
$options["grade_policy"] = 0;
$options["policy_list"] = $options["policy_name"];
try {
Db::name("groups")->insert($options);
} catch (Exception $e) {
return ["error"=>1,"msg"=>$e->getMessage()];
}
return ["error"=>200,"msg"=>"设置已保存"];
}
public function addPolicy($options){
$options["max_size"] = $options["max_size"]*$options["sizeTimes"];
unset($options["sizeTimes"]);
$options["server"] = isset($options["server"]) ? $options["server"] : "/Upload";
foreach (["bucketname","bucket_private","bucketname","ak","sk","op_name","op_pwd","mimetype","namerule"] as $key => $value) {
$options[$value] = isset($options[$value]) ? $options[$value] : "0";
}
if(empty($options["filetype"])){
$options["filetype"]="[]";
}else{
$options["filetype"] = json_encode([0=>["ext"=>$options["filetype"],"title"=>"default"]]);
}
if($options["policy_type"] == "upyun"){
$options["server"] = "https://v0.api.upyun.com/".$options["bucketname"];
}
try {
Db::name("policy")->insert($options);
} catch (Exception $e) {
return ["error"=>1,"msg"=>$e->getMessage()];
}
return ["error"=>200,"msg"=>"设置已保存"];
}
public function editPolicy($options){
$policyId = $options["id"];
$options["max_size"] = $options["max_size"]*$options["sizeTimes"];
unset($options["sizeTimes"]);
unset($options["id"]);
if(empty($options["filetype"])){
$options["filetype"]="[]";
}else{
$options["filetype"] = json_encode([0=>["ext"=>$options["filetype"],"title"=>"default"]]);
}
try {
Db::name("policy")->where("id",$policyId)->update($options);
} catch (Exception $e) {
return ["error"=>1,"msg"=>$e->getMessage()];
}
return ["error"=>200,"msg"=>"设置已保存"];
}
public function saveGroup($options){
$groupId = $options["id"];
unset($options["id"]);
$options["max_storage"] = $options["max_storage"]*$options["sizeTimes"];
unset($options["sizeTimes"]);
try {
Db::name("groups")->where("id",$groupId)->update($options);
} catch (Exception $e) {
return ["error"=>1,"msg"=>$e->getMessage()];
}
return ["error"=>200,"msg"=>"设置已保存"];
}
public function saveOptions($options){
try {
foreach ($options as $key => $value) {
Db::name("options")->where("option_name",$key)->update(["option_value"=>$value]);
}
} catch (Exception $e) {
return ["error"=>1,"msg"=>$e->getMessage()];
}
return ["error"=>200,"msg"=>"设置已保存"];
}
public function getAvaliableGroup(){
$groupData = Db::name("groups")->where("id","neq",2)->select();
return $groupData;
}
public function saveCron($options){
$cronId = $options["id"];
unset($options["id"]);
Db::name("corn")->where("id",$cronId)->update($options);
}
public function getAvaliablePolicy(){
$policyData = Db::name("policy")->select();
return $policyData;
}
public function sendTestMail($options){
$mailObj = new Mail();
if(empty($options["receiveMail"])){
return ["error"=>1,"msg"=>"接收邮箱不能为空"];
}
$sendResult = $mailObj->Send($options["receiveMail"],"发信测试",$options["subject"],$options["content"]);
if($sendResult){
return ["error"=>200,"msg"=>"发送成功"];
}else{
return ["error"=>1,"msg"=>$mailObj->errorMsg];
}
}
public function deleteSingle($id){
$fileRecord = Db::name("files")->where("id",$id)->find();
return FileManage::DeleteHandler([0 => rtrim($fileRecord["dir"],"/")."/".$fileRecord["orign_name"]],$fileRecord["upload_user"]);
}
public function deletePolicy($id){
$groupData = Db::name("groups")->where("policy_name",$id)->select();
if(!empty($groupData)){
return ["error"=>true,"msg"=>"此上传策略正在被以下用户组使用:".join(",",array_column($groupData, "group_name"))];
}
Db::name("policy")->where("id",$id)->delete();
return ["error"=>false,"msg"=>"已删除"];
}
public function deleteGroup($id){
$userData = Db::name("users")->where("user_group",$id)->find();
if(!empty($userData)){
return ["error"=>true,"msg"=>"此用户组下仍有用户,请先删除这些用户"];
}
if($id == 1 || $id == 2){
return ["error"=>true,"msg"=>"系统保留用户组,无法删除"];
}
Db::name("groups")->where("id",$id)->delete();
return ["error"=>false,"msg"=>"已删除"];
}
public function getConfigFile($type){
switch ($type) {
case 'common':
$configPath = ROOT_PATH ."application/config.php";
$basicPath = "application/config.php";
break;
case 'database':
if(file_exists( ROOT_PATH ."application/database.lock")){
return ["出于安全考虑,默认禁止直接编辑数据库配置文件。如果需要开启编辑,请手动删除 application/database.lock 文件。","application/database.php"];
}
$configPath = ROOT_PATH ."application/database.php";
$basicPath = "application/database.php";
break;
case 'route':
$configPath = ROOT_PATH ."application/route.php";
$basicPath = "application/route.php";
break;
case 'tags':
$configPath = ROOT_PATH ."application/tags.php";
$basicPath = "application/tags.php";
break;
default:
die("");
break;
}
return [file_get_contents($configPath),$basicPath];
}
public function saveConfigFile($options){
switch ($options["type"]) {
case 'common':
file_put_contents(ROOT_PATH ."application/config.php",$options["content"]);
break;
case 'route':
file_put_contents(ROOT_PATH ."application/route.php",$options["content"]);
break;
case 'tags':
file_put_contents(ROOT_PATH ."application/tags.php",$options["content"]);
break;
case 'database':
if(file_exists( ROOT_PATH ."application/database.lock")){
return ["error"=>true,"msg"=>"出于安全考虑,默认禁止直接编辑数据库配置文件。如果需要开启编辑,请手动删除 application/database.lock 文件。"];
}
file_put_contents(ROOT_PATH ."application/database.php",$options["content"]);
break;
default:
# code...
break;
}
return ["error"=>false,"msg"=>""];
}
public function deleteMultiple($id){
$fileInfo = json_decode($id,true);
$pathGroup = [];
foreach ($fileInfo as $key => $value) {
$pathGroup[$value["uid"]] = isset($pathGroup[$value["uid"]]) ? $pathGroup[$value["uid"]] : [];
array_push($pathGroup[$value["uid"]], $value["path"]);
}
foreach ($pathGroup as $key => $value) {
FileManage::DeleteHandler($value,$key);
}
return ["error"=>200,"msg"=>"删除成功"];
}
public function deleteShare($ids){
Db::name("shares")->where("id","in",$ids)->delete();
return ["error"=>false,"msg"=>"删除成功"];
}
public function deleteOrder($id){
Db::name("order")->where("id",$id)->delete();
return ["error"=>false,"msg"=>"删除成功"];
}
public function deleteUser($id,$userNow){
if($userNow == $id){
return ["error"=>true,"msg"=>"我的老伙计,你可不能删除你自己"];
}
//删除用户所有文件及目录
FileManage::DirDeleteHandler([0 => "/"],$id);
//删除此用户所有分享
Db::name("shares")->where("owner",$id)->delete();
//删除此用户
Db::name("users")->where("id",$id)->delete();
return ["error"=>false,"msg"=>"删除成功"];
}
public function changeShareType($id){
$shareId = $id;
$shareObj = new ShareHandler($shareId,false);
if(!$shareObj->querryStatus){
return array(
"error" => 1,
"msg" => "分享不存在"
);
}
return $shareObj->changePromission(0,true);
}
public function getUserInfo($id){
$userData = Db::name("users")->where("id",$id)->find();
$userData["used_storage"] =getSize($userData["used_storage"]);
return $userData;
}
public function listFile(){
$pageSize = empty(cookie('pageSize')) ? 10 : cookie('pageSize');
$orderType = empty(cookie('orderMethodFile')) ? "id DESC" : cookie('orderMethodFile');
$this->pageData = Db::name("files")
->where(function ($query) {
if(!empty(cookie('fileSearch'))){
$query->where('orign_name', "like","%".cookie('fileSearch')."%");
}
})
->where(function ($query) {
if(!empty(cookie('filePolicy'))){
$query->where('policy_id', cookie('filePolicy'));
}
})
->where(function ($query) {
if(!empty(cookie('searchValue'))){
$query->where(cookie('searchCol'),"like", cookie('searchValue'));
}
})
->order($orderType)
->paginate($pageSize);
$this->dataTotal = Db::name("files")
->where(function ($query) {
if(!empty(cookie('fileSearch'))){
$query->where('orign_name', "like","%".cookie('fileSearch')."%");
}
})
->where(function ($query) {
if(!empty(cookie('filePolicy'))){
$query->where('policy_id', cookie('filePolicy'));
}
})
->where(function ($query) {
if(!empty(cookie('searchValue'))){
$query->where(cookie('searchCol'),"like", cookie('searchValue'));
}
})
->order($orderType)
->count();
$this->pageTotal = ceil($this->dataTotal/$pageSize);
$this->listData = $this->pageData->all();
$userCache=[];
$userCacheList=[];
foreach ($this->listData as $key => $value) {
if(in_array($value["upload_user"], $userCacheList)){
$this->listData[$key]["user"] = $userCache[$value["upload_user"]];
}else{
$this->listData[$key]["user"] = Db::name("users")->where("id",$value["upload_user"])->find();
array_push($userCacheList,$value["upload_user"]);
$userCache[$value["upload_user"]] = $this->listData[$key]["user"];
}
}
$this->pageNow = input("?get.page")?input("get.page"):1;
}
public function listUser(){
$pageSize = empty(cookie('pageSize')) ? 10 : cookie('pageSize');
$orderType = empty(cookie('orderMethodUser')) ? "id DESC" : cookie('orderMethodUser');
$this->pageData = Db::name("users")
->where(function ($query) {
if(!empty(cookie('userStatus'))){
$query->where('user_status', cookie('userStatus')-1);
}
})
->where(function ($query) {
if(!empty(cookie('userSearch'))){
$query->where('user_nick', "like","%".cookie('userSearch')."%")
->whereOr("id",cookie('userSearch'))
->whereOr("user_email","like","%".cookie('userSearch')."%");
}
})
->where(function ($query) {
if(!empty(cookie('userGroup'))){
$query->where('user_group', cookie('userGroup'));
}
})
->where(function ($query) {
if(!empty(cookie('searchValueUser'))){
$query->where(cookie('searchColUser'),"like", cookie('searchValueUser'));
}
})
->order($orderType)
->paginate($pageSize);
$this->dataTotal = Db::name("users")
->where(function ($query) {
if(!empty(cookie('userStatus'))){
$query->where('user_status', cookie('userStatus')-1);
}
})
->where(function ($query) {
if(!empty(cookie('userSearch'))){
$query->where('user_nick', "like","%".cookie('userSearch')."%")
->whereOr("id",cookie('userSearch'))
->whereOr("user_email","like","%".cookie('userSearch')."%");
}
})
->where(function ($query) {
if(!empty(cookie('userGroup'))){
$query->where('user_group', cookie('userGroup'));
}
})
->where(function ($query) {
if(!empty(cookie('searchValueUser'))){
$query->where(cookie('searchColUser'),"like", cookie('searchValueUser'));
}
})
->order($orderType)
->count();
$this->pageTotal = ceil($this->dataTotal/$pageSize);
$this->listData = $this->pageData->all();
$groupCache=[];
$groupCacheList=[];
foreach ($this->listData as $key => $value) {
if(in_array($value["user_group"], $groupCacheList)){
$this->listData[$key]["group"] = $groupCache[$value["user_group"]];
}else{
$this->listData[$key]["group"] = Db::name("groups")->where("id",$value["user_group"])->find();
array_push($groupCacheList,$value["user_group"]);
$groupCache[$value["user_group"]] = $this->listData[$key]["group"];
}
}
$this->pageNow = input("?get.page")?input("get.page"):1;
}
public function listShare(){
$pageSize = empty(cookie('pageSize')) ? 10 : cookie('pageSize');
$orderType = empty(cookie('orderMethodShare')) ? "id DESC" : cookie('orderMethodShare');
$this->pageData = Db::name("shares")
->where(function ($query) {
if(!empty(cookie('shareSearch'))){
$query->where('source_name', "like","%".cookie('shareSearch')."%")->whereOr('origin_name', "like","%".cookie('shareSearch')."%");
}
})
->where(function ($query) {
if(!empty(cookie('shareType'))){
$query->where('type', cookie('shareType'));
}
})
->order($orderType)
->paginate($pageSize);
$this->dataTotal = Db::name("shares")
->where(function ($query) {
if(!empty(cookie('shareSearch'))){
$query->where('source_name', "like","%".cookie('shareSearch')."%")->whereOr('origin_name', "like","%".cookie('shareSearch')."%");
}
})
->where(function ($query) {
if(!empty(cookie('shareType'))){
$query->where('type', cookie('shareType'));
}
})
->order($orderType)
->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"];
}
}
$this->pageNow = input("?get.page")?input("get.page"):1;
}
public function listPolicy(){
$pageSize = empty(cookie('pageSize')) ? 10 : cookie('pageSize');
$this->pageData = Db::name("policy")
->where(function ($query) {
if(!empty(cookie('policySearch'))){
$query->where('policy_name', "like","%".cookie('policySearch')."%");
}
})
->where(function ($query) {
if(!empty(cookie('policyType'))){
$query->where('policy_type', cookie('policyType'));
}
})
->order("id DESC")
->paginate($pageSize);
$this->dataTotal = Db::name("policy")
->where(function ($query) {
if(!empty(cookie('policySearch'))){
$query->where('policy_name', "like","%".cookie('policySearch')."%");
}
})
->where(function ($query) {
if(!empty(cookie('policyType'))){
$query->where('policy_type', cookie('policyType'));
}
})
->order("id DESC")
->count();
$this->pageTotal = ceil($this->dataTotal/$pageSize);
$this->listData = $this->pageData->all();
$this->pageNow = input("?get.page")?input("get.page"):1;
foreach ($this->listData as $key => $value) {
$this->listData[$key]["file_num"] = Db::name("files")->where("policy_id",$value["id"])->count();
$this->listData[$key]["file_size"] = Db::name("files")->where("policy_id",$value["id"])->sum("size");
}
}
public function getFileInfo($id){
$fileRecord = Db::name("files")->where("id",$id)->find();
$policyRecord = Db::name("policy")->where("id",$fileRecord["policy_id"])->find();
$fileRecord["policy"] = $policyRecord;
return $fileRecord;
}
public function saveThemeFile($options){
$fileName=$options["name"];
$dir = ROOT_PATH."application/index/view/";
$fileList=[];
$fileList=$fileList+scandir($dir);
$pathList=["/"=>$fileList];
foreach (["admin","explore","file","home","index","member","profile","share"] as $key => $value) {
$childPath = scandir($dir.$value."/");
$fileList=array_merge($fileList,$childPath);
$pathList = array_merge($pathList,[$value => $childPath]);
}
foreach ($fileList as $key => $value) {
if(substr_compare($value, ".html", -strlen(".html")) != 0){
unset($fileList[$key]);
}
}
foreach($pathList as $key=>$val){
if(in_array($fileName.".html",$val)){
$parentPath = $key;
break;
}
}
file_put_contents($dir.rtrim($parentPath,"/")."/".$fileName.".html",$options["content"]);
return ["error"=>false,"msg"=>"成功"];
}
public function saveUser($options){
if(empty($options["user_pass"])){
unset($options["user_pass"]);
}else{
$options["user_pass"] = md5(config('salt').$options["user_pass"]);
}
$userId = $options["uid"];
unset($options["uid"]);
try {
Db::name("users")->where("id",$userId)->update($options);
} catch (Exception $e) {
return ["error"=>1,"msg"=>$e->getMessage()];
}
return ["error"=>200,"msg"=>"设置已保存"];
}
public function banUser($id,$uid){
if($id == $uid){
return ["error"=>1,"msg"=>"我的老伙计,你怎么能封禁你自己?"];
}
$userData = Db::name("users")->where("id",$id)->find();
$statusNew = $userData["user_status"] == 1 ? 0 : 1;
Db::name("users")->where("id",$id)->update(["user_status" => $statusNew]);
return ["error"=>200,"msg"=>"设置已保存"];
}
public function listGroup(){
$pageSize = empty(cookie('pageSize')) ? 10 : cookie('pageSize');
$this->pageData = Db::name("groups")
->order("id DESC")
->paginate($pageSize);
$this->dataTotal = Db::name("groups")
->order("id DESC")
->count();
$this->pageTotal = ceil($this->dataTotal/$pageSize);
$this->listData = $this->pageData->all();
$this->pageNow = input("?get.page")?input("get.page"):1;
foreach ($this->listData as $key => $value) {
$this->listData[$key]["policy"] = Db::name("policy")->where("id",$value["policy_name"])->find();
$this->listData[$key]["user_num"] = Db::name("users")->where("user_group",$value["id"])->count();
}
}
public function addUser($options){
$options["user_pass"] = md5(config('salt').$options["user_pass"]);
if(Db::name('users')->where('user_email',$options["user_email"])->find() !=null){
return ["error" => true,"msg"=>"该邮箱已被注册"];
}
$sqlData = [
'user_email' => $options["user_email"],
'user_pass' => $options["user_pass"],
'user_status' => $options["user_status"],
'user_group' => $options["user_group"],
'group_primary' => $options["user_group"],
'user_date' => date("Y-m-d H:i:s"),
'user_nick' => $options["user_nick"],
'user_activation_key' => "n",
'used_storage' => 0,
'two_step'=>"0",
'webdav_key' =>$options["user_pass"],
'delay_time' =>0,
'avatar' => "default",
'profile' => true,
];
if(Db::name('users')->insert($sqlData)){
$userId = Db::name('users')->getLastInsID();
Db::name('folders')->insert( [
'folder_name' => '根目录',
'parent_folder' => 0,
'position' => '.',
'owner' => $userId,
'date' => date("Y-m-d H:i:s"),
'position_absolute' => '/',
]);
}
return ["error"=>0,"msg"=>"设置已保存"];
}
}
?>

@ -0,0 +1,146 @@
<?php
namespace app\index\model;
use think\Model;
use think\Db;
use \app\index\model\Option;
use \app\index\model\FileManage;
class Avatar extends Model{
public $avatarObj;
public $errorMsg;
public $fileName;
public $avatarKey;
public $userData;
public $avatarType;
public function __construct($new=false,$obj){
$this->avatarObj = $obj;
if(!$new){
$userData = Db::name("users")->where('id',$obj)->find();
$this->userData = $userData;
if($userData["avatar"] == "default"){
$this->avatarType = "default";
}else{
$avatarPrarm = explode(".",$userData["avatar"]);
$this->avatarType = $avatarPrarm[0];
$this->fileName = ltrim(ltrim($userData["avatar"],"g."),"f.");
}
}
}
public function SaveAvatar(){
$info = $this->avatarObj->validate(['size'=>2097152,'ext'=>'jpg,png,gif.bmp'])->rule('uniqid')->move(ROOT_PATH . 'public' . DS . 'avatars');
if($info){
$_path = ROOT_PATH.'public/avatars/'.$info->getSaveName();
$_img = new Image($_path);
$_img->thumb(200, 200);
$_img->output();
$_img = new Image($_path);
$_img->thumb(130, 130);
$_img->output("_130");
$_img = new Image($_path);
$_img->thumb(50, 50);
$_img->output("_50");
$this->fileName = $info->getSaveName();
return true;
}else{
$this->errorMsg=["result"=>"error","msg"=>$this->avatarObj->getError()];
return false;
}
}
public function bindUser($uid){
$this->avatarKey = "f.".$this->fileName;
Db::name("users")->where('id',$uid)->update(["avatar" => $this->avatarKey]);
}
public function Out($size){
switch ($this->avatarType) {
case 'f':
$this->outPutFile($size);
exit();
break;
case 'default':
$this->defaultAvatar($size);
exit();
break;
case 'g':
return $this->outGravatar($size);
break;
default:
# code...
break;
}
}
public function outPutFile($size){
switch ($size) {
case 's':
$siezSuffix = "_50";
break;
case 'm':
$siezSuffix = "_130";
break;
default:
$siezSuffix = "";
break;
}
$filePath = ROOT_PATH . 'public/avatars/' . $this->fileName.$siezSuffix;
if(file_exists($filePath)){
ob_end_clean();
header('Content-Type: '.FileManage::getMimetype($filePath));
$fileObj = fopen($filePath,"r");
while(!feof($fileObj)){
echo fread($fileObj,2097152);
}
}else{
$this->defaultAvatar($siezSuffix);
}
}
public function outGravatar($size){
switch ($size) {
case 's':
$siezSuffix = "50";
break;
case 'm':
$siezSuffix = "130";
break;
default:
$siezSuffix = "200";
break;
}
ob_end_clean();
$gravatarServer = Option::getValue("gravatar_server");
return $gravatarServer.$this->fileName."?d=mm&s=".$siezSuffix;
}
public function defaultAvatar($size){
switch ($size) {
case 's':
$siezSuffix = "_50";
break;
case 'm':
$siezSuffix = "_130";
break;
default:
$siezSuffix = "";
break;
}
ob_end_clean();
$filePath = ROOT_PATH . 'static/img/default.png' .$siezSuffix;
header('Content-Type: '.FileManage::getMimetype($filePath));
$fileObj = fopen($filePath,"r");
while(!feof($fileObj)){
echo fread($fileObj,2097152);
}
}
public function setGravatar(){
$this->avatarKey="g.".md5($this->userData["user_email"]);
Db::name("users")->where('id',$this->userData["id"])->update(["avatar" => $this->avatarKey]);
}
}

@ -0,0 +1,39 @@
<?php
namespace app\index\model;
use think\Model;
use Sabre\DAV;
use Sabre\DAV\Auth\Backend;
class BasicCallBack extends \Sabre\DAV\Auth\Backend\AbstractDigest {
/**
* Callback
*
* @var callable
*/
protected $callBack;
/**
* Creates the backend.
*
* A callback must be provided to handle checking the username and
* password.
*
* @param callable $callBack
* @return void
*/
function __construct(callable $callBack) {
$this->callBack = $callBack;
$this->realm = 'CloudreveWebDav';
}
public function getDigestHash($realm, $username){
$cb = $this->callBack;
return $cb($realm,$username);
}
}

@ -0,0 +1,206 @@
<?php
namespace app\index\model;
require_once 'extend/Qiniu/functions.php';
use think\Model;
use think\Db;
use Qiniu\Auth;
use \app\index\model\Option;
use \app\index\model\FileManage;
use \app\index\model\UploadHandler;
class CallbackHandler extends Model{
public $CallbackData;
public $policyData;
public $userData;
public function __construct($data){
$this->CallbackData = $data;
}
public function qiniuHandler($header){
$jsonData = json_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->IsQiniuCallback($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 ossHandler($auth,$pubKey){
if(!$this->IsOssCallback($auth,$pubKey)){
$this->setError("Undelegated Request");
}
$jsonData = json_decode($this->CallbackData,true);
$jsonData["fname"] = urldecode($jsonData["fname"]);
$jsonData["objname"] = urldecode($jsonData["objname"]);
$jsonData["path"] = urldecode($jsonData["path"]);
$CallbackSqlData = Db::name('callback')->where('callback_key',$jsonData['callbackkey'])->find();
$this->policyData = Db::name('policy')->where('id',$CallbackSqlData['pid'])->find();
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 upyunHandler($token,$date,$md5){
$this->policyData = Db::name("policy")->where("id",$this->CallbackData["ext-param"]["pid"])->find();
if(!$this->IsUpyunCallback($token,$date,$md5)){
$this->setError("Undelegated Request",false,true);
}
if(!FileManage::sotrageCheck($this->CallbackData["ext-param"]["uid"],$this->CallbackData["file_size"])){
FileManage::deleteFile($this->CallbackData["url"],$this->policyData);
$this->setError("空间容量不足",false,true);
}
$picInfo = empty($this->CallbackData["image-width"]) ? "" :$this->CallbackData["image-width"].",".$this->CallbackData["image-height"];
$fileNameExplode = explode("CLSUFF",$this->CallbackData["url"]);
$jsonData["fname"] = end($fileNameExplode);
$jsonData["objname"] = $this->CallbackData["url"];
$jsonData["path"] = $this->CallbackData["ext-param"]["path"];
$jsonData["fsize"] = $this->CallbackData["file_size"];
$addAction = FileManage::addFile($jsonData,$this->policyData,$this->CallbackData["ext-param"]["uid"],$picInfo);
if(!$addAction[0]){
FileManage::deleteFile($this->CallbackData["url"],$this->policyData);
$this->setError($addAction[1],false,true);
}
FileManage::storageCheckOut($this->CallbackData["ext-param"]["uid"],$jsonData["fsize"]);
$this->setSuccess($jsonData['fname']);
}
public function s3Handler($key){
$CallbackSqlData = Db::name('callback')->where('callback_key',$key)->find();
//删除callback记录
if(empty($CallbackSqlData)){
$this->setError("Undelegated Request",false,true);
}
$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"]);
$jsonData["fname"] = end($paths);
$jsonData["objname"] = $this->CallbackData["key"];
$jsonData["path"] ="";
foreach ($paths as $key => $value) {
if($key == 0 || $key == count($paths)-1) continue;
$jsonData["path"].=$value.",";
}
$jsonData["path"] = rtrim($jsonData["path"],",");
$jsonData["fsize"] = $this->getS3FileInfo();
if(!$jsonData["fsize"]){
$this->setError("File not exist",false,true);
}
$jsonData["fsize"] = $jsonData["fsize"]["size"];
$picInfo = "";
$addAction = FileManage::addFile($jsonData,$this->policyData,$this->userData["id"],"");
if(!$addAction[0]){
FileManage::deleteFile($this->CallbackData["key"],$this->policyData);
$this->setError($addAction[1],false,true);
}
FileManage::storageCheckOut($this->userData["id"],$jsonData["fsize"]);
$this->setSuccess($jsonData['fname']);
}
private function getS3FileInfo(){
$s3 = new \S3\S3($this->policyData["ak"], $this->policyData["sk"],false,$this->policyData["op_pwd"]);
$s3->setSignatureVersion('v4');
try {
$returnVal = $s3->getObjectInfo($this->policyData["bucketname"],$this->CallbackData["key"]);
} catch (Exception $e) {
return false;
}
return $returnVal;
}
public function setSuccess($fname){
die(json_encode(["key"=> $fname]));
}
public function setError($text,$delete = false,$ignore=false){
header("HTTP/1.1 401 Unauthorized");
if(!$ignore){
$deletedFile = json_decode($this->CallbackData,true);
$fileNmae = $deletedFile['objname'];
if($delete){
FileManage::deleteFile($fileNmae,$this->policyData);
}
}
die(json_encode(["error"=> $text]));
}
private function isUpyunCallback($token,$date,$md5){
if(UploadHandler::upyunSign($this->policyData["op_name"],md5($this->policyData["op_pwd"]),"POST","/Callback/Upyun",$date,$md5) != $token){
return false;
}
return true;
}
public function IsQiniuCallback($httpHeader){
$auth = new Auth($this->policyData['ak'], $this->policyData['sk']);
$callbackBody = $this->CallbackData;
$contentType = 'application/json';
$authorization = $httpHeader;
$url = Option::getValue("siteUrl")."Callback/Qiniu";
$isQiniuCallback = $auth->verifyCallback($contentType, $authorization, $url,$callbackBody);
if ($isQiniuCallback) {
return true;
} else {
return false;
}
}
public function IsOssCallback($auth,$pubKey){
if (empty($auth) || empty($pubKey)){
header("http/1.1 403 Forbidden");
exit();
}
$authorization = base64_decode($auth);
$pubKeyUrl = base64_decode($pubKey);
$pubOssKey = file_get_contents($pubKeyUrl);
if ($pubOssKey == ""){
return false;
}
$body = file_get_contents('php://input');
$authStr = '';
$path = $_SERVER['REQUEST_URI'];
$pos = strpos($path, '?');
if ($pos === false){
$authStr = urldecode($path)."\n".$body;
}else{
$authStr = urldecode(substr($path, 0, $pos)).substr($path, $pos, strlen($path) - $pos)."\n".$body;
}
$ok = openssl_verify($authStr, $authorization, $pubOssKey, OPENSSL_ALGO_MD5);
if ($ok == 1){
return true;
}else{
return false;
}
}
}
?>

@ -0,0 +1,73 @@
<?php
namespace app\index\model;
use think\Model;
use think\Db;
use \think\Session;
use \app\index\model\FileManage;
use \app\index\model\Option;
use \app\index\model\Mail;
class CronHandler extends Model{
public $cornTasks;
public $timeNow;
public $notifiedUid = [];
public function __construct(){
$this->cornTasks = Db::name('corn')->where('enable',1)->order('rank desc')->select();
$this->timeNow = time();
}
public function checkInterval($interval,$last){
return ($last+$interval)<= $this->timeNow ? true : false;
}
public function setComplete($name){
Db::name('corn')->where('name', $name)->update(['last_excute' => $this->timeNow]);
}
public function Doit(){
foreach ($this->cornTasks as $key => $value) {
switch ($value["name"]) {
case 'delete_unseful_chunks':
if($this->checkInterval($value["interval_s"],$value["last_excute"])){
$this->deleteUnsefulChunks($value["interval_s"]);
}
break;
case 'delete_callback_data':
if($this->checkInterval($value["interval_s"],$value["last_excute"])){
$this->deleteCallbackData($value["interval_s"]);
}
break;
default:
# code...
break;
}
}
}
private function deleteUnsefulChunks($interval){
echo("deleteUnsefulChunks...");
$chunkInfo = Db::name('chunks')->whereTime('time', '<', date('Y-m-d', time()-86400))->select();
$deleteList=[];
foreach ($chunkInfo as $key => $value) {
$fileSize = @filesize(ROOT_PATH . 'public/uploads/chunks/'.$value["obj_name"].".chunk");
@unlink(ROOT_PATH . 'public/uploads/chunks/'.$value["obj_name"].".chunk");
FileManage::storageGiveBack($value["user"],$fileSize?$fileSize:0);
$deleteList["$key"] = $value["id"];
}
Db::name('chunks')->where(['id' => ["in",$deleteList],])->delete();
$this->setComplete("delete_unseful_chunks");
echo("Complete<br>");
}
private function deleteCallbackData($interval){
echo("deleteCallbackData...");
Db::name("callback")->delete(true);
echo("Complete<br>");
$this->setComplete("delete_callback_data");
}
}
?>

@ -0,0 +1,30 @@
<?php
namespace app\index\model;
use think\Model;
use think\Db;
use app\index\model\User;
class DavAuth extends Model{
public $uid;
function __construct($id) {
$this->uid = $id;
}
public function __invoke($realm,$um){
$userData = Db::name("users")->where("id",$this->uid)->find();
if(empty($userData) || $userData["user_email"] != $um){
return null;
}
$userGroup = Db::name("groups")->where("id",$userData["user_group"])->find();
if(!$userGroup["webdav"]){
return null;
}
return $userData["webdav_key"];
}
}
?>

@ -0,0 +1,186 @@
<?php
namespace app\index\model;
use think\Model;
use think\Db;
use Sabre\DAV;
use \app\index\model\FileManage;
use \app\index\model\User;
use \app\index\model\UploadHandler;
class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota{
private $myPath;
public $uid;
public $userObj;
function __construct($path) {
$ex = explode("/",$path);
$this->uid = $ex[0];
if(empty($this->uid)){
return false;
}
$t = strpos($path,$this->uid);
if($t == 0){
$this->myPath = substr($path,$t+strlen($this->uid));
}else{
$this->myPath = $path;
}
$this->myPath = empty($this->myPath) ? "/" : $this->myPath;
}
function createFile($name, $data = NULL){
$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();
$uploadHandle = new UploadHandler($groupData["policy_name"],$this->uid);
$allowedExt = UploadHandler::getAllowedExt(json_decode($policyData["filetype"],true));
if(!empty($allowedExt)){
$ex = explode(".",$name);
$fileSuffix = end($ex);
if(!in_array($fileSuffix, explode(",",$allowedExt))){
throw new DAV\Exception\InvalidResourceType('File type not allowed');
}
}
if($policyData["policy_type"] !="local"){
throw new DAV\Exception\Forbidden('Poliyc not supported yet');
}
$fileSize = fstat($data)["size"];
if(empty($fileSize)){
$fileSize = 0;
}
if($fileSize>$policyData["max_size"]){
throw new DAV\Exception\InsufficientStorage('File is to large');
}
if(!FileManage::sotrageCheck($this->uid,$fileSize)){
throw new DAV\Exception\InsufficientStorage('Quota is not enough');
}
if($policyData['autoname']){
$fileName = $uploadHandle->getObjName($policyData['namerule'],"local",$name);
}else{
$fileName = $name;
}
$generatePath = $uploadHandle->getDirName($policyData['dirrule']);
$savePath = ROOT_PATH . 'public/uploads/'.$generatePath;
if(!file_exists($savePath)){
mkdir($savePath,0777,true);
}
file_put_contents($savePath."/".$fileName, $data);
$jsonData = array(
"path" => str_replace("/",",",ltrim($this->myPath,"/")),
"fname" => $name,
"objname" => $generatePath."/".$fileName,
"fsize" => $fileSize,
);
@list($width, $height, $type, $attr) = getimagesize(rtrim($savePath, DS).DS.$fileName);
$picInfo = empty($width)?" ":$width.",".$height;
$addAction = FileManage::addFile($jsonData,$policyData,$this->uid,$picInfo);
if(!$addAction[0]){
unlink($savePath."/".$fileName);
throw new DAV\Exception\Conflict($addAction[1]);
}
FileManage::storageCheckOut($this->uid,$jsonData["fsize"]);
//echo json_encode(array("key" => $info["name"]));
}
function getQuotaInfo() {
$this->userObj = new User($this->uid,"",true);
$quotaInfo = json_decode($this->userObj->getMemory(true),true);
return [
$quotaInfo["used"],
$quotaInfo["total"]
];
}
function setName($name){
$reqPath = $this->myPath;
$ex = explode("/",$reqPath);
$newPath = rtrim(dirname($reqPath) == "\\" ?"/":dirname($reqPath),"/")."/".$name;
$renameAction = json_decode(FileManage::RenameHandler($reqPath,$newPath,$this->uid,true),true);
if(!$renameAction["result"]["success"]){
throw new DAV\Exception\InvalidResourceType($renameAction["result"]["error"]);
}
}
function getChildren() {
$children = array();
$fileList = Db::name('files')->where('upload_user',$this->uid)->where('dir',$this->myPath)->select();
$dirList = Db::name('folders')->where('owner',$this->uid)->where('position',$this->myPath)->select();
foreach($fileList as $node) {
// Ignoring files staring with .
$children[] = $this->getChildFile($node,false);
}
foreach($dirList as $node) {
// Ignoring files staring with .
$children[] = $this->getChildDir($node,true);
}
return $children;
}
function getChildFile($name){
$path = $this->uid.rtrim($this->myPath,"/") . '/' . $name["orign_name"];
return new Object($path);
}
function getChildDir($name){
$path = $this->uid.rtrim($this->myPath,"/") . '/' . $name["folder_name"];
return new Directory($path);
}
function delete(){
foreach ($this->getChildren() as $child) $child->delete();
FileManage::DirDeleteHandler([0=>$this->myPath],$this->uid);
}
function getChild($name) {
if(!$this->childExists($name)){
throw new DAV\Exception\NotFound('File with name ' . $name . ' could not be located');
}
$path = $this->uid.rtrim($this->myPath,"/") . '/' . $name;
if($this->findDir(rtrim($this->myPath,"/") . '/' . $name)){
$returnObj = new Directory($path);
return $returnObj;
}else{
return new Object($path);
}
}
function childExists($name) {
$fileObj = new Object($this->uid.rtrim($this->myPath,"/") . '/' . $name);
if($this->findDir(rtrim($this->myPath,"/") . '/' . $name) || $fileObj->isExist){
return true;
}
return false;
}
public function findDir($path){
if($path == "/"){
return true;
}
$explode = explode("/",$path);
$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();
if(empty($dirData)){
return false;
}
return true;
}
function getName() {
$explode = explode("/", $this->myPath);
return end($explode);
}
function createDirectory($name) {
$createAction = FileManage::createFolder($name,$this->myPath,$this->uid);
if(!$createAction["result"]["success"]){
die($this->myPath);
throw new DAV\Exception\InvalidResourceType($createAction["result"]["error"]);
}
}
}
?>

File diff suppressed because it is too large Load Diff

@ -0,0 +1,89 @@
<?php
namespace app\index\model;
use think\Model;
class Image extends Model{
private $file; //图片地址
private $width; //图片长度
private $height; //图片长度
private $itype; //图片类型
private $img; //原图的资源句柄
private $new; //新图的资源句柄
//构造方法,初始化
public function __construct($_file) {
$this->file = $_file;
list($this->width, $this->height, $this->itype) = getimagesize($this->file);
$this->img = $this->getFromImg($this->file, $this->itype);
}
//缩略图(固定长高容器,图像等比例,扩容填充,裁剪)[固定了大小,不失真,不变形]
public function thumb($new_width = 0,$new_height = 0) {
if (empty($new_width) && empty($new_height)) {
$new_width = $this->width;
$new_height = $this->height;
}
if (!is_numeric($new_width) || !is_numeric($new_height)) {
$new_width = $this->width;
$new_height = $this->height;
}
//创建一个容器
$_n_w = $new_width;
$_n_h = $new_height;
//创建裁剪点
$_cut_width = 0;
$_cut_height = 0;
if ($this->width < $this->height) {
$new_width = ($new_height / $this->height) * $this->width;
} else {
$new_height = ($new_width / $this->width) * $this->height;
}
if ($new_width < $_n_w) { //如果新高度小于新容器高度
$r = $_n_w / $new_width; //按长度求出等比例因子
$new_width *= $r; //扩展填充后的长度
$new_height *= $r; //扩展填充后的高度
$_cut_height = ($new_height - $_n_h) / 2; //求出裁剪点的高度
}
if ($new_height < $_n_h) { //如果新高度小于容器高度
$r = $_n_h / $new_height; //按高度求出等比例因子
$new_width *= $r; //扩展填充后的长度
$new_height *= $r; //扩展填充后的高度
$_cut_width = ($new_width - $_n_w) / 2; //求出裁剪点的长度
}
$this->new = imagecreatetruecolor($_n_w,$_n_h);
imagecopyresampled($this->new,$this->img,0,0,$_cut_width,$_cut_height,$new_width,$new_height,$this->width,$this->height);
}
//加载图片,各种类型,返回图片的资源句柄
public function getFromImg($_file, $_type) {
switch ($_type) {
case 1 :
$img = imagecreatefromgif($_file);
break;
case 2 :
$img = imagecreatefromjpeg($_file);
break;
case 3 :
$img = imagecreatefrompng($_file);
break;
default:
$img = '';
}
return $img;
}
//图像输出
public function output($name = "") {
imagepng($this->new,$this->file.$name);//第二个参数为新生成的图片名
imagedestroy($this->img);
imagedestroy($this->new);
}
}
?>

@ -0,0 +1,60 @@
<?php
namespace app\index\model;
use think\Model;
use think\Db;
use \app\index\model\Option;
use \PHPMailer\PHPMailer\PHPMailer;
use \PHPMailer\PHPMailer\Exception;
class Mail extends Model{
public $fromName;
public $fromAdress;
public $smtpHost;
public $smtpPort;
public $replyTo;
public $smtpUser;
public $smtpPass;
public $encriptionType;
public $errorMsg;
public function __construct(){
$mailOptions = Option::getValues(["mail"]);
$this->fromName = $mailOptions["fromName"];
$this->fromAdress = $mailOptions["fromAdress"];
$this->smtpHost = $mailOptions["smtpHost"];
$this->smtpPort = $mailOptions["smtpPort"];
$this->replyTo = $mailOptions["replyTo"];
$this->smtpUser = $mailOptions["smtpUser"];
$this->smtpPass = $mailOptions["smtpPass"];
$this->encriptionType = $mailOptions["encriptionType"];
}
public function Send($to,$name,$title,$content){
$mail = new PHPMailer();
$mail->isSMTP();
$mail->SMTPAuth=true;
$mail->Host = $this->smtpHost;
if(!empty($this->encriptionType) && $this->encriptionType != "no"){
$mail->SMTPSecure = $this->encriptionType;
}
$mail->Port = $this->smtpPort;
$mail->CharSet = 'UTF-8';
$mail->FromName = $this->fromName;
$mail->Username =$this->smtpUser;
$mail->Password = $this->smtpPass;
$mail->From = $this->fromAdress;
$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;
}
}
?>

@ -0,0 +1,95 @@
<?php
namespace app\index\model;
use think\Model;
use think\Db;
use Sabre\DAV;
use \app\index\model\FileManage;
class Object extends DAV\File{
private $myPath;
public $id;
public $fileData;
public $uid;
public $fileName;
public $dir;
public $actualPath;
public $isExist;
function __construct($path) {
$ex = explode("/",$path);
$this->uid = $ex[0];
$t = strpos($path,$this->uid);
if($t == 0){
$this->myPath = substr($path,$t+strlen($this->uid));
}else{
$this->myPath = $path;
}
$this->fileName = end($ex);
$this->dir = dirname($this->myPath) == "\\" ? "/" :dirname($this->myPath);
$this->fileData = Db::name('files')->where('upload_user',$this->uid)->where('dir',$this->dir)->where('orign_name',$this->fileName)->find();
if(empty($this->fileData)){
$this->isExist = false;
}else{
$this->isExist = true;
}
$this->actualPath = ROOT_PATH . 'public/uploads/'.$this->fileData["pre_name"];
}
function getName() {
return $this->fileName;
}
function get() {
return fopen($this->actualPath, 'r');
}
function getSize() {
return $this->fileData["size"];
}
function setName($name){
$reqPath = $this->myPath;
$ex = explode("/",$reqPath);
$newPath = rtrim($reqPath,end($ex)).$name;
$renameAction = json_decode(FileManage::RenameHandler($reqPath,$newPath,$this->uid,true),true);
if(!$renameAction["result"]["success"]){
throw new DAV\Exception\Forbidden($renameAction["result"]["error"]);
}
}
function getContentType() {
return null;
}
function put($data){
$fileSize = (int)$_SERVER['CONTENT_LENGTH'];
if(!FileManage::sotrageCheck($this->uid,$fileSize)){
throw new DAV\Exception\InsufficientStorage("Quota is not enough");
}
$filePath = ROOT_PATH . 'public/uploads/' . $this->fileData["pre_name"];
file_put_contents($filePath, "");
file_put_contents($filePath, $data);
FileManage::storageGiveBack($this->uid,$this->fileData["size"]);
FileManage::storageCheckOut($this->uid,$fileSize);
@list($width, $height, $type, $attr) = getimagesize($filePath);
$picInfo = empty($width)?" ":$width.",".$height;
Db::name('files')->where('id', $this->fileData["id"])->update(['size' => $fileSize,'pic_info' => $picInfo]);
}
function delete(){
FileManage::DeleteHandler([0=>$this->myPath],$this->uid);
}
function getETag() {
return '"' . sha1(
fileinode($this->actualPath) .
filesize($this->actualPath) .
filemtime($this->actualPath)
) . '"';
}
}
?>

@ -0,0 +1,16 @@
<?php
namespace app\index\model;
use think\Model;
use think\Db;
class Option extends Model{
static function getValues($groups = ['basic']){
$t = Db::name('options')->where('option_type','in',$groups)->column('option_value','option_name');
return $t;
}
static function getValue($optionName){
return Db::name('options')->where('option_name',$optionName)->value('option_value');
}
}
?>

@ -0,0 +1,308 @@
<?php
namespace app\index\model;
use think\Model;
use think\Db;
use \think\Session;
use \app\index\model\FileManage;
use \app\index\model\Option;
use \app\index\model\User;
class ShareHandler extends Model{
public $shareData;
public $querryStatus = true;
public $shareOwner;
public $fileData;
public $dirData;
public $lockStatus = false;
public function __construct($key,$notExist=true){
$this->shareData = Db::name('shares')->where('share_key',$key)->find();
if(empty($this->shareData)){
$this->querryStatus = false;
}else{
if($notExist){
if($this->shareData["source_type"] == "file"){
$this->fileShareHandler();
}else{
$this->dirShareHandler();
}
}
}
if($this->shareData["type"] == "private"){
$this->lockStatus = Session::has("share".$this->shareData["id"])?false:true;
}
}
public function deleteShare($uid){
if($this->shareData["owner"] != $uid){
return array(
"error" => 1,
"msg" => "无权操作"
);
}
Db::name('shares')->where('share_key',$this->shareData["share_key"])->delete();
return array(
"error" => 0,
"msg" => "分享取消成功"
);
}
public function changePromission($uid,$ignore=false){
if($this->shareData["owner"] != $uid && $ignore == false){
return array(
"error" => 1,
"msg" => "无权操作"
);
}
Db::name('shares')->where('share_key',$this->shareData["share_key"])->update([
'type' => $this->shareData["type"] == "public"?"private":"public",
'share_pwd' => self::getRandomKey(6)
]);
return array(
"error" =>0,
"msg" => "更改成功"
);
}
public function checkPwd($pwd){
if($pwd == $this->shareData["share_pwd"]){
Session::set("share".$this->shareData["id"],"1");
return array(
"error" =>0,
);
}else{
return array(
"error" =>1,
"msg" => "密码错误"
);
}
}
public function checkSession($user){
if($this->lockStatus){
return [false,"会话过期,请刷新页面"];
}
if(Option::getValue("allowdVisitorDownload") == "false" && !$user->loginStatus){
return [false,"未登录用户禁止下载,请先登录"];
}
if(!$this->querryStatus){
return [false,"分享不存在,请检查链接是否正确"];
}
return[true,null];
}
public function Download($user){
$checkStatus = $this->checkSession($user);
if(!$checkStatus[0]){
return [$checkStatus[0],$checkStatus[1]];
}
$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"]);
$FileHandler = $fileObj->Download();
return $FileHandler;
}
public function DownloadFolder($user,$path){
$checkStatus = $this->checkSession($user);
if(!$checkStatus[0]){
return [$checkStatus[0],$checkStatus[1]];
}
$reqPath = Db::name('folders')->where('position_absolute',$this->shareData["source_name"])->find();
$path = $path == "/"?"":$path;
$fileObj = new FileManage($reqPath["position_absolute"].$path,$this->shareData["owner"]);
$this->numIncrease("download_num");
$FileHandler = $fileObj->Download();
return $FileHandler;
}
public function ListFile($path){
if($this->lockStatus){
die('{ "result": { "success": false, "error": "会话过期,请重新登陆" } }');
}
if(!$this->querryStatus){
return [false,"分享不存在,请检查链接是否正确"];
}
$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"]);
}
public function Preview($user){
$checkStatus = $this->checkSession($user);
if(!$checkStatus[0]){
return [$checkStatus[0],$checkStatus[1]];
}
$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"]);
return $fileObj->PreviewHandler();
}
public function PreviewFolder($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->PreviewHandler();
}
public function listPic($id,$path){
if($this->lockStatus){
die('{ "result": { "success": false, "error": "会话过期,请重新登陆" } }');
}
if(!$this->querryStatus){
return [false,"分享不存在,请检查链接是否正确"];
}
$reqPath = Db::name('folders')->where('position_absolute',$this->shareData["source_name"])->find();
$path = $path == "/"?"":$path;
return FileManage::listPic($this->shareData["source_name"].$path,$this->shareData["owner"],"/Share/Preview/".$this->shareData["share_key"]."?folder=true");
}
public function numIncrease($name){
Db::name('shares')->where('share_key',$this->shareData["share_key"])->setInc($name);
}
public function getDownloadUrl($user){
if(Option::getValue("allowdVisitorDownload") == "false" && !$user->loginStatus){
return array(
"error" => 1,
"msg" => "未登录用户禁止下载,请先登录",
);
}else{
$this->numIncrease("download_num");
return array(
"error" => 0,
"result" => "/Share/Download/".$this->shareData["share_key"],
);
}
}
public function fileShareHandler(){
$this->shareOwner = new User($this->shareData["owner"],null,true);
$this->fileData = Db::name('files')
->where('upload_user',$this->shareData["owner"])
->where('id',(int)$this->shareData["source_name"])
->find();
if(!$this->shareOwner->loginStatus || empty($this->fileData)){
$this->querryStatus = false;
}else{
$this->querryStatus = true;
}
}
public function dirShareHandler(){
$this->shareOwner = new User($this->shareData["owner"],null,true);
$this->dirData = Db::name('folders')
->where('owner',$this->shareData["owner"])
->where('position_absolute',$this->shareData["source_name"])
->find();
if(!$this->shareOwner->loginStatus || empty($this->dirData)){
$this->querryStatus = false;
}else{
$this->querryStatus = true;
}
}
static function createShare($fname,$type,$user,$group){
if(!$group["allow_share"]){
self::setError("您当前的用户组无权分享文件");
}
$path = FileManage::getFileName($fname)[1];
$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);
}else{
self::createFileShare($fileRecord,$type,$user,$group);
}
}
static function setError($text){
die('{ "result": { "success": false, "error": "'.$text.'" } }');
}
static function setSuccess($text){
die('{ "result": "'.$text.'" }');
}
static function createDirShare($fname,$type,$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);
$SQLData = [
'type' => $type=="public" ? "public" : "private",
'share_time' => date("Y-m-d H:i:s"),
'owner' => $user["id"],
'source_name' => $fname,
'origin_name' => $fname,
'download_num' => 0,
'view_num' => 0,
'source_type' => "dir",
'share_key' => $shareKey,
'share_pwd' => $sharePwd,
];
if(Db::name('shares')->insert($SQLData)){
if($sharePwd == "0"){
self::setSuccess(Option::getValue("siteURL")."s/".$shareKey);
}else{
self::setSuccess("链接:".Option::getValue("siteURL")."s/".$shareKey." 密码:".$sharePwd);
}
}
}
static function createFileShare($file,$type,$user,$group){
$shareKey = self::getRandomKey(8);
$sharePwd = $type=="public" ? "0" : self::getRandomKey(6);
$SQLData = [
'type' => $type=="public" ? "public" : "private",
'share_time' => date("Y-m-d H:i:s"),
'owner' => $user["id"],
'source_name' => $file["id"],
'origin_name' => $file["orign_name"],
'download_num' => 0,
'view_num' => 0,
'source_type' => "file",
'share_key' => $shareKey,
'share_pwd' => $sharePwd,
];
if(Db::name('shares')->insert($SQLData)){
if($sharePwd == "0"){
self::setSuccess(Option::getValue("siteURL")."s/".$shareKey);
}else{
self::setSuccess("链接:".Option::getValue("siteURL")."s/".$shareKey." 密码:".$sharePwd);
}
}
}
static function getRandomKey($length = 16){
$charTable = 'abcdefghijklmnopqrstuvwxyz0123456789';
$result = "";
for ( $i = 0; $i < $length; $i++ ){
$result .= $charTable[ mt_rand(0, strlen($charTable) - 1) ];
}
return $result;
}
}
?>

@ -0,0 +1,91 @@
<?php
namespace app\index\model;
use think\Model;
use think\Db;
class Thumb extends Model{
private $file; //图片地址
private $width; //图片长度
private $height; //图片长度
private $img_type; //图片类型
private $img; //原图的资源句柄
private $new; //新图的资源句柄
//构造方法,初始化
public function __construct($_file) {
$this->file = $_file;
list($this->width, $this->height, $this->img_type) = getimagesize($this->file);
$this->img = $this->getFromImg($this->file, $this->img_type);
}
//缩略图(固定长高容器,图像等比例,扩容填充,裁剪)[固定了大小,不失真,不变形]
public function thumb($new_width = 0,$new_height = 0) {
if (empty($new_width) && empty($new_height)) {
$new_width = $this->width;
$new_height = $this->height;
}
if (!is_numeric($new_width) || !is_numeric($new_height)) {
$new_width = $this->width;
$new_height = $this->height;
}
//创建一个容器
$_n_w = $new_width;
$_n_h = $new_height;
//创建裁剪点
$_cut_width = 0;
$_cut_height = 0;
if ($this->width < $this->height) {
$new_width = ($new_height / $this->height) * $this->width;
} else {
$new_height = ($new_width / $this->width) * $this->height;
}
if ($new_width < $_n_w) { //如果新高度小于新容器高度
$r = $_n_w / $new_width; //按长度求出等比例因子
$new_width *= $r; //扩展填充后的长度
$new_height *= $r; //扩展填充后的高度
$_cut_height = ($new_height - $_n_h) / 2; //求出裁剪点的高度
}
if ($new_height < $_n_h) { //如果新高度小于容器高度
$r = $_n_h / $new_height; //按高度求出等比例因子
$new_width *= $r; //扩展填充后的长度
$new_height *= $r; //扩展填充后的高度
$_cut_width = ($new_width - $_n_w) / 2; //求出裁剪点的长度
}
$this->new = imagecreatetruecolor($_n_w,$_n_h);
imagecopyresampled($this->new,$this->img,0,0,$_cut_width,$_cut_height,$new_width,$new_height,$this->width,$this->height);
}
//加载图片,各种类型,返回图片的资源句柄
private function getFromImg($_file, $_type) {
switch ($_type) {
case 1 :
$img = imagecreatefromgif($_file);
break;
case 2 :
$img = imagecreatefromjpeg($_file);
break;
case 3 :
$img = imagecreatefrompng($_file);
break;
default:
$img = '';
}
return $img;
}
//图像输出
public function out($name) {
imagepng($this->new,$name);//第二个参数为新生成的图片名
imagedestroy($this->img);
imagedestroy($this->new);
}
}
?>

@ -0,0 +1,53 @@
<?php
namespace app\index\model;
use think\Model;
use think\Db;
use \think\Session;
use \PHPGangsta_GoogleAuthenticator;
use \Endroid\QrCode\QrCode;
use \app\index\model\Option;
class TwoFactor extends Model{
public $ga;
public $secretKey;
public $checkResult;
public function __construct(){
$this->ga = new PHPGangsta_GoogleAuthenticator();
}
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();
}
public function confirmCode($key,$code){
$this->secretKey = $key;
if(empty($code)){
return [0,"验证码不能为空"];
}
if(empty($key)){
return [0,"二维码过期,请刷新页面后重新扫描"];
}
$this->checkResult = $this->ga->verifyCode($key, $code, 2);
if($this->checkResult){
return [1,"验证成功"];
}else{
return [0,"验证码错误"];
}
}
public function bindUser($uid){
Db::name("users")->where("id",$uid)->update(["two_step" => $this->secretKey]);
}
}
?>

@ -0,0 +1,452 @@
<?php
namespace app\index\model;
require_once 'extend/Qiniu/functions.php';
use think\Model;
use think\Db;
use Qiniu\Auth;
use \app\index\model\Option;
use \app\index\model\FileManage;
class UploadHandler extends Model{
public $policyId;
public $policyContent;
public $userId;
public $chunkData;
public $fileSizeTmp;
public $ossToken;
public $ossSign;
public $ossCallback;
public $ossAccessId;
public $ossFileName;
public $ossCallBack;
public $upyunPolicy;
public $s3Policy;
public $s3Sign;
public $dirName;
public $s3Credential;
public $siteUrl;
public $callBackKey;
public function __construct($id,$uid){
$this->policyId = $id;
$this->userId = $uid;
$this->policyContent = Db::name('policy')->where('id',$id)->find();
}
public function setChunk($chunkId,$chunkSum,$file){
$sqlData = [
'user' => $this->userId,
'ctx' => self::getRandomKey(),
'obj_name' => self::getRandomKey(8),
'time' => date("Y-m-d H:i:s"),
'chunk_id' => $chunkId,
'sum' => $chunkSum,
];
$this->chunkData = $sqlData;
Db::name('chunks')->insert($sqlData);
$this->saveChunk($file);
$this->chunkInfo();
}
public function saveChunk($file){
$chunkSize = strlen($file);
if(!FileManage::sotrageCheck($this->userId,$chunkSize)){
$this->setError("空间容量不足",false);
}
FileManage::storageCheckOut($this->userId,$chunkSize);
if($chunkSize >=4195304){
$this->setError("分片错误",false);
}
$chunkObj=fopen (ROOT_PATH . 'public/uploads/chunks/'.$this->chunkData["obj_name"].".chunk","w+");
$chunkObjWrite = fwrite ($chunkObj,$file);
if(!$chunkObj || !$chunkObjWrite){
$this->setError("分片创建错误",false);
}
}
public function chunkInfo(){
$returnJson = array(
"ctx" => $this->chunkData["ctx"],
);
echo json_encode($returnJson);
return 0;
}
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);
$suffixTmp = explode('.', $fname);
$fileSuffix = array_pop($suffixTmp);
if($this->policyContent['autoname']){
$fileName = $this->getObjName($this->policyContent['namerule'],"local",$fname).".".$fileSuffix;
}else{
$fileName = $fname;
}
$generatePath = $this->getDirName($this->policyContent['dirrule']);
$savePath = ROOT_PATH . 'public/uploads/'.$generatePath;
is_dir($savePath)? :mkdir($savePath,0777,true);
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($path == "ROOTDIR"){
$path = "";
}
$jsonData = array(
"path" => $path,
"fname" => $fname,
"objname" => $generatePath."/".$fileName,
"fsize" => $this->fileSizeTmp,
);
$addAction = FileManage::addFile($jsonData,$this->policyContent,$this->userId);
if(!$addAction[0]){
$this->setError($addAction[1],true,$fileName,$savePath);
}
echo json_encode(array("key" => $fname));
}
}
public function filterCheck($file,$fname){
$fileSize = filesize(ROOT_PATH . 'public/uploads/chunks/'.$file);
$suffixTmp = explode('.', $fname);
$fileSuffix = array_pop($suffixTmp);
$allowedSuffix = explode(',', self::getAllowedExt(json_decode($this->policyContent["filetype"],true)));
$sufficCheck = !in_array($fileSuffix,$allowedSuffix);
if(empty(self::getAllowedExt(json_decode($this->policyContent["filetype"],true)))){
$sufficCheck = false;
}
if(($fileSize >= (int)$this->policyContent["max_size"]) || $sufficCheck){
FileManage::storageGiveBack($this->userId,$fileSize);
$this->setError("文件效验失败",true,$file,ROOT_PATH . 'public/uploads/chunks/');
}
$this->fileSizeTmp = $fileSize;
}
public function combineChunks($fname){
$fileName = "file_".self::getRandomKey(8);
$fileObj=fopen (ROOT_PATH . 'public/uploads/chunks/'.$fileName,"a+");
$deleteList=[];
foreach ($fname as $key => $value) {
$chunkObj = fopen(ROOT_PATH . 'public/uploads/chunks/'.$value["obj_name"].".chunk", "rb");
if(!$fileObj || !$chunkObj){
$this->setError("文件创建失败",false);
}
$content = fread($chunkObj, 4195304);
fwrite($fileObj, $content, 4195304);
unset($content);
fclose($chunkObj);
unlink(ROOT_PATH . 'public/uploads/chunks/'.$value["obj_name"].".chunk");
array_push($deleteList, $value["id"]);
}
$chunks = Db::name('chunks')->where([
'id' => ["in",$deleteList],
])->delete();
return $fileName;
}
public function fileReceive($file,$info){
$allowedExt = self::getAllowedExt(json_decode($this->policyContent["filetype"],true));
$filter = array('size'=>(int)$this->policyContent["max_size"]);
if(!empty($allowedExt)){
$filter = array_merge($filter,array("ext" => $allowedExt));
}
if(!FileManage::sotrageCheck($this->userId,$file->getInfo('size'))){
$this->setError("空间容量不足",false);
}
if($this->policyContent['autoname']){
$fileName = $this->getObjName($this->policyContent['namerule'],"local",$file->getInfo('name'));
}else{
$fileName = $file->getInfo('name');
}
$generatePath = $this->getDirName($this->policyContent['dirrule']);
$savePath = ROOT_PATH . 'public/uploads/'.$generatePath;
$Uploadinfo = $file
->validate($filter)
->move($savePath,$fileName,false);
if($Uploadinfo){
$jsonData = array(
"path" => $info["path"],
"fname" => $info["name"],
"objname" => $generatePath."/".$Uploadinfo->getSaveName(),
"fsize" => $Uploadinfo->getSize(),
);
@list($width, $height, $type, $attr) = getimagesize(rtrim($savePath, DS).DS.$Uploadinfo->getSaveName());
$picInfo = empty($width)?" ":$width.",".$height;
$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{
header("HTTP/1.1 401 Unauthorized");
echo json_encode(array("error" => $file->getError()));
}
}
public function setError($text,$delete = false,$fname="",$path=""){
header("HTTP/1.1 401 Unauthorized");
if($delete){
unlink(rtrim($path, DS).DS.$fname);
}
die(json_encode(["error"=> $text]));
}
static function getAllowedExt($ext){
$returnValue = "";
foreach ($ext as $key => $value) {
$returnValue .= $value["ext"].",";
}
return rtrim($returnValue, ",");
}
public function getToken(){
switch ($this->policyContent['policy_type']) {
case 'qiniu':
return $this->getQiniuToken();
break;
case 'local':
return $this->getLocalToken();
break;
case 'oss':
return $this->getOssToken();
break;
case 'upyun':
return $this->getUpyunToken();
break;
case 's3':
return $this->getS3Token();
break;
default:
# code...
break;
}
}
public function getObjName($expression,$type = "qiniu",$origin = ""){
$policy = array(
'{date}' =>date("Ymd"),
'{datetime}' =>date("YmdHis"),
'{uid}' =>$this->userId,
'{timestamp}' =>time(),
'{randomkey16}' =>self::getRandomKey(16),
'{randomkey8}' =>self::getRandomKey(8),
);
if($type == "qiniu"){
$policy = array_merge($policy,array("{originname}" => "$(fname)"));
}else if($type == "local"){
$policy = array_merge($policy,array("{originname}" => $origin));
}else if ($type="oss"){
$policy = array_merge($policy,array("{originname}" => '${filename}'));
}else if ($type="upyun"){
$policy = array_merge($policy,array("{originname}" => '{filename}{.suffix}'));
}
return strtr($expression,$policy);
}
public function getDirName($expression){
$policy = array(
'{date}' =>date("Ymd"),
'{datetime}' =>date("YmdHis"),
'{uid}' =>$this->userId,
'{timestamp}' =>time(),
'{randomkey16}' =>self::getRandomKey(16),
'{randomkey8}' =>self::getRandomKey(8),
);
return trim(strtr($expression,$policy),"/");
}
public function getQiniuToken(){
$callbackKey = $this->getRandomKey();
$sqlData = [
'callback_key' => $callbackKey,
'pid' => $this->policyId,
'uid' => $this->userId
];
Db::name('callback')->insert($sqlData);
$auth = new Auth($this->policyContent['ak'], $this->policyContent['sk']);
$policy = array(
'callbackUrl' =>Option::getValue("siteURL").'Callback/Qiniu',
'callbackBody' => '{"fname":"$(fname)","objname":"$(key)","fsize":"$(fsize)","callbackkey":"'.$callbackKey.'","path":"$(x:path)","picinfo":"$(imageInfo.width),$(imageInfo.height)"}',
'callbackBodyType' => 'application/json',
'fsizeLimit' => (int)$this->policyContent['max_size'],
);
$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']));
}
$token = $auth->uploadToken($this->policyContent['bucketname'], null, 3600, $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){
if ($v){
$elems[] = $v;
}
}
$value = implode('&', $elems);
$sign = base64_encode(hash_hmac('sha1', $value, $secret, true));
return 'UPYUN ' . $key . ':' . $sign;
}
public function getUpyunToken(){
$callbackKey = $this->getRandomKey();
$sqlData = [
'callback_key' => $callbackKey,
'pid' => $this->policyId,
'uid' => $this->userId
];
Db::name('callback')->insert($sqlData);
$options = Option::getValues(["oss","basic"]);
$dateNow = gmdate('D, d M Y H:i:s \G\M\T');
$policy=[
"bucket" => $this->policyContent['bucketname'],
"expiration" => time()+$options["timeout"],
"notify-url" => $options["siteURL"]."Callback/Upyun",
"content-length-range" =>"0,".$this->policyContent['max_size'],
"date" => $dateNow,
"ext-param"=>json_encode([
"path"=>cookie("path"),
"uid" => $this->userId,
"pid" => $this->policyId,
]),
];
$allowedExt = self::getAllowedExt(json_decode($this->policyContent["filetype"],true));
if(!empty($allowedExt)){
$policy = array_merge($policy,array("allow-file-type" => $allowedExt));
}
$dirName = $this->getObjName($this->policyContent['dirrule']);
$policy = array_merge($policy,array("save-key" => $dirName.(empty($dirName)?"":"/").uniqid()."CLSUFF{filename}{.suffix}"));
$this->upyunPolicy = base64_encode(json_encode($policy));
return self::upyunSign($this->policyContent['op_name'], md5($this->policyContent['op_pwd']), "POST", "/".$this->policyContent['bucketname'],$dateNow,$this->upyunPolicy);
}
public function ossCallback(){
$callbackKey = $this->getRandomKey();
$sqlData = [
'callback_key' => $callbackKey,
'pid' => $this->policyId,
'uid' => $this->userId
];
Db::name('callback')->insert($sqlData);
$returnValue["callbackUrl"] = Option::getValue("siteUrl").'Callback/Oss';
$returnValue["callbackBody"] = '{"fname":"${x:fname}","objname":"${object}","fsize":"${size}","callbackkey":"'.$callbackKey.'","path":"${x:path}","picinfo":"${imageInfo.width},${imageInfo.height}"}';
$this->ossCallBack = base64_encode(json_encode($returnValue));
return base64_encode(json_encode($returnValue));
}
public function getS3Token(){
$dirName = $this->getDirName($this->policyContent['dirrule']);
$longDate = gmdate('Ymd\THis\Z');
$shortDate = gmdate('Ymd');
$credential = $this->policyContent['ak'] . '/' . $shortDate . '/' . $this->policyContent['op_name'] . '/s3/aws4_request';
$callbackKey = $this->getRandomKey();
$sqlData = [
'callback_key' => $callbackKey,
'pid' => $this->policyId,
'uid' => $this->userId
];
Db::name('callback')->insert($sqlData);
$this->siteUrl = Option::getValue("siteUrl");
$returnValue = [
"expiration" => date("Y-m-d",time()+1800)."T".date("H:i:s",time()+1800).".000Z",
"conditions" => [
0 => ["bucket" => $this->policyContent['bucketname']],
1 => ["starts-with",'$key', $dirName],
2 => ["starts-with",'$success_action_redirect' ,$this->siteUrl."Callback/S3/key/".$callbackKey],
3 => ["content-length-range",1,(int)$this->policyContent['max_size']],
4 => ['x-amz-algorithm' => 'AWS4-HMAC-SHA256'],
5 => ['x-amz-credential' => $credential],
6 => ['x-amz-date' => $longDate],
7 => ["starts-with", '$name', ""],
8 => ["starts-with", '$Content-Type', ""],
]
];
$this->s3Policy = base64_encode(json_encode($returnValue));
$signingKey = hash_hmac("sha256",$shortDate,"AWS4".$this->policyContent['sk'],true);
$signingKey = hash_hmac("sha256",$this->policyContent['op_name'],$signingKey,true);
$signingKey = hash_hmac("sha256","s3",$signingKey,true);
$signingKey = hash_hmac("sha256","aws4_request",$signingKey,true);
$signingKey = hash_hmac("sha256",$this->s3Policy,$signingKey);
$this->s3Sign = $signingKey;
$this->dirName = $dirName;
$this->s3Credential = $credential;
$this->x_amz_date = $longDate;
$this->callBackKey = $callbackKey;
}
public function getOssToken(){
$dirName = $this->getObjName($this->policyContent['dirrule']);
$returnValu["expiration"] = date("Y-m-d",time()+1800)."T".date("H:i:s",time()+1800).".000Z";
$returnValu["conditions"][0]["bucket"] = $this->policyContent['bucketname'];
$returnValu["conditions"][1][0]="starts-with";
$returnValu["conditions"][1][1]='$key';
if($this->policyContent["autoname"]){
$this->ossFileName = $dirName.(empty($dirName)?"":"/").$this->getObjName($this->policyContent['namerule'],"oss");;
}else{
$this->ossFileName = $dirName.(empty($dirName)?"":"/").'${filename}';
}
$returnValu["conditions"][1][2]=$dirName.(empty($dirName)?"":"/");
$returnValu["conditions"][2]=["content-length-range",1,(int)$this->policyContent['max_size']];
$returnValu["conditions"][3]["callback"] = $this->ossCallback();
$this->ossToken=base64_encode(json_encode($returnValu));
$this->ossSignToken();
$this->ossAccessId = $this->policyContent['ak'];
return false;
}
public function ossSignToken(){
$this->ossSign = base64_encode(hash_hmac("sha1", $this->ossToken, $this->policyContent['sk'],true));
}
public function getLocalToken(){
$auth = new Auth($this->policyContent['ak'], $this->policyContent['sk']);
$policy = array(
'callbackBody' => '{"path":"'.cookie('path').'"}',
'callbackBodyType' => 'application/json',
);
$token = $auth->uploadToken($this->policyContent['bucketname'], null, 3600, $policy);
return $token;
}
static function getRandomKey($length = 16){
$charTable = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$result = "";
for ( $i = 0; $i < $length; $i++ ){
$result .= $charTable[ mt_rand(0, strlen($charTable) - 1) ];
}
return $result;
}
static function b64Decode($string) {
$data = str_replace(array('-','_'),array('+','/'),$string);
$mod4 = strlen($data) % 4;
if ($mod4) {
$data .= substr('====', $mod4);
}
return base64_decode($data);
}
}
?>

@ -0,0 +1,375 @@
<?php
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;
class User extends Model{
public $uid;
public $varifyKey;
public $groupId;
public $regDate;
public $loginStatus = false;
public $userNick;
public $userMail;
public $groupData;
public $userSQLData;
/**
* [__construct description]
* @param [type] $userId [description]
* @param [type] $userKey [description]
*/
public function __construct($userId,$userKey,$ignoreLogin = false){
$userData = Db::name('users')->where('id',$userId)->where('user_status',0)->find();
if(empty($userData)){
$this->loginStatus = false;
$this->setUser();
return false;
}
if(!$ignoreLogin){
if(md5($userData['user_email'].$userData['user_pass'].config('salt')) != $userKey){
$this->loginStatus = false;
$this->setUser();
return false;
}
}
$this->groupData = Db::name('groups')->where('id',$userData['user_group'])->find();
$this->loginStatus = true;
$this->uid = $userId;
$this->groupId = $userData['user_group'];
$this->regDate = $userData['user_date'];
$this->userNick = $userData['user_nick'];
$this->userMail = $userData['user_email'];
$this->varifyKey = $userKey;
$this->userSQLData = $userData;
}
public function setUser(){
$this->groupData = Db::name('groups')->where('id',2)->find();
$this->uid = -1;
}
static function resetPwd($key,$pwd){
$key = explode("_",$key);
$resetKey = $key[0]."_".$key[1];
$userId = $key[2];
$keyCheck = self::resetUser($resetKey,$userId);
if(!$keyCheck[0]){
return $keyCheck;
}else{
if ((mb_strlen($pwd,'UTF8')>64) || (mb_strlen($pwd,'UTF8')<4)){
return [false,"密码不符合规范"];
}
self::Reset($userId,$pwd);
return [true,"密码重设成功"];
}
}
static function Reset($uid,$pwd){
Db::name('users')->where('id',$uid)
->update([
'user_pass' => md5(config('salt').$pwd),
]);
}
/**
* [register description]
* @param [type] $userEmail [description]
* @param [type] $userPass [description]
* @return [type] [description]
*/
static function register($userEmail,$userPass,$captchaCode){
if(Option::getValue("login_captcha")=="1"){
if(!self::checkCaptcha($captchaCode)){
return [false,"验证码错误"];
}
}
if (\app\index\model\Option::getValue("regStatus") == '1'){
return [false,"当前站点关闭注册"];
}
$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)){
return [false,"邮箱或密码不符合规范"];
}
if(Db::name('users')->where('user_email',$userName)->find() !=null){
return [false,"该邮箱已被注册"];
}
$defaultGroup = (int)\app\index\model\Option::getValue("defaultGroup");
$regOptions = Option::getValues(["register"]);
if($regOptions["email_active"] == "1"){
$activationKey = md5(uniqid(rand(), TRUE));
$userStatus = 1;
}else{
$activationKey = "n";
$userStatus = 0;
}
$sqlData = [
'user_email' => $userName,
'user_pass' => md5(config('salt').$passWord),
'user_status' => $userStatus,
'user_group' => $defaultGroup,
'group_primary' => 0,
'user_date' => date("Y-m-d H:i:s"),
'user_nick' => explode("@",$userName)[0],
'user_activation_key' => $activationKey,
'used_storage' => 0,
'two_step'=>"0",
'webdav_key' =>md5(config('salt').$passWord),
'delay_time' =>0,
'avatar' => "default",
'profile' => true,
];
if(Db::name('users')->insert($sqlData)){
$userId = Db::name('users')->getLastInsID();
Db::name('folders')->insert( [
'folder_name' => '根目录',
'parent_folder' => 0,
'position' => '.',
'owner' => $userId,
'date' => date("Y-m-d H:i:s"),
'position_absolute' => '/',
]);
if($regOptions["email_active"] == "1"){
$options = Option::getValues(["basic","mail_template"]);
$replace = array(
'{siteTitle}' =>$options["siteName"],
'{userName}' =>explode("@",$userName)[0],
'{siteUrl}' =>$options["siteURL"],
'{siteSecTitle}' =>$options["siteTitle"],
'{activationUrl}' =>$options["siteURL"]."Member/emailActivate/".$activationKey,
);
$mailContent = strtr($options["mail_activation_template"],$replace);
$mailObj = new Mail();
$mailObj->Send($userName,explode("@",$userName)[0],"【".$options["siteName"]."】"."注册激活",$mailContent);
return [true,"ec"];
}
return [true,"注册成功"];
}
}
static function activicateUser($key){
$userData = Db::name('users')
->where('user_activation_key','neq','n')
->where("user_activation_key",$key)->find();
if(empty($userData)){
return [0,"激活失败,用户在不存在"];
}else{
Db::name('users')->where("id",$userData["id"])->update([
"user_activation_key" => "n",
"user_status" => 0,
]);
return [1,1];
}
}
static function resetUser($key,$uid){
$timeNow = time();
if(empty($key)||empty($uid)){
return [0,"URL参数错误"];
}
$key = explode("_",$key);
$userData = Db::name('users')
->where('user_status',0)
->where("id",$uid)->find();
if(empty($userData)){
return [0,"用户不存在"];
}
if(md5($userData["user_pass"].$key[1]) != $key[0]){
return [0,"参数无效,请检查邮件链接"];
}
if(($timeNow - $key[1])>7200){
return [0,"重设链接过期,请重新提交"];
}
return [1,1];
}
static function findPwd($email,$captchaCode){
if(Option::getValue("login_captcha")=="1"){
if(!self::checkCaptcha($captchaCode)){
return [false,"验证码错误"];
}
}
$userData = Db::name('users')->where('user_email',$email)->find();
if(empty($userData)){
return [1,1];
}
$timeNow = time();
$resetHash = md5($userData["user_pass"].$timeNow);
$resetKey = $resetHash."_".$timeNow;
$options = Option::getValues(["basic","mail_template"]);
$replace = array(
'{siteTitle}' =>$options["siteName"],
'{userName}' =>$userData["user_nick"],
'{siteUrl}' =>$options["siteURL"],
'{siteSecTitle}' =>$options["siteTitle"],
'{resetUrl}' =>$options["siteURL"]."Member/resetPwd/".$resetKey."?uid=".$userData["id"],
);
$mailContent = strtr($options["mail_reset_pwd_template"],$replace);
$mailObj = new Mail();
$mailObj->Send($email,$userData["user_nick"],"【".$options["siteName"]."】"."密码重置",$mailContent);
return [true,"ec"];
}
/**
* [login description]
* @param [type] $userEmail [description]
* @param [type] $userPass [description]
* @return [type] [description]
*/
static function login($userEmail,$userPass,$captchaCode){
$userEmail = str_replace(" ", "", $userEmail);
$userData =Db::name('users')->where('user_email',$userEmail)->find();
if(empty($userEmail) || empty($userPass)){
return [false,"表单不完整"];
}
if(Option::getValue("login_captcha")=="1"){
if(!self::checkCaptcha($captchaCode)){
return [false,"验证码错误"];
}
}
if(Db::name('users')->where('user_email',$userEmail)->value('user_pass') != md5(config('salt').$userPass)){
return [false,"用户名或密码错误"];
}
if(Db::name('users')->where('user_email',$userEmail)->value('user_status') != 0){
return [false,"账号被禁用或未激活"];
}
if($userData["two_step"] != "0"){
session("user_id_tmp",Db::name('users')->where('user_email',$userEmail)->value('id'));
session("login_status_tmp","ok");
session("login_key_tmp",md5($userEmail.md5(config('salt').$userPass).config('salt')));
return [false,"tsp"];
}
$loginKey = md5($userEmail.md5(config('salt').$userPass).config('salt'));
cookie('user_id',Db::name('users')->where('user_email',$userEmail)->value('id'),604800);
cookie('login_status','ok',604800);
cookie('login_key',$loginKey,604800);
return [true,"登录成功",$loginKey];
}
static function checkCaptcha($code){
if(!captcha_check($code)){
return false;
}
return true;
}
/**
* [clear description]
* @return [type] [description]
*/
public function clear(){
$this->loginStatus = false;
$this->uid = null;
$this->groupId = null;
$this->regDate = null;
$this->varifyKey = null;
cookie('user_id', null);
cookie('login_status', null);
cookie('login_key', null);
}
/**
* [getInfo description]
* @return [type] [description]
*/
public function getInfo(){
return [
'uid' => $this->uid,
'groupId' => $this->groupId,
'regDate' => $this->regDate,
'loginStatus' => $this->loginStatus,
'userNick' => $this->userNick,
'userMail' => $this->userMail,
'groupData' => $this->groupData,
'sqlData' => $this->userSQLData,
];
}
public function getSQLData(){
return $this->userSQLData;
}
public function getPolicy(){
return Db::name('policy')->where('id',$this->groupData["policy_name"])->find();
}
public function getGroupData(){
return $this->groupData;
}
public function getMemory($notEcho = false){
$usedMemory = $this->userSQLData["used_storage"];
$groupStorage = (int)$this->groupData["max_storage"];
$packetStorage = (int)Db::name('storage_pack')
->where('uid',$this->uid)
->where('dlay_time',">",time())
->sum('pack_size');
$returnData["used"] = self::countSize((int)$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);
if($usedMemory > $groupStorage){
$returnData["r1"] = floor((int)$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["r3"] = 100-$returnData["r1"]-$returnData["r2"];
}
if($notEcho){
return json_encode($returnData);
}
echo json_encode($returnData);
}
static function countSize($bit) {
$type = array('Bytes','KB','MB','GB','TB');
for($i = 0; $bit >= 1024; $i++) {
$bit/=1024;
}
return (floor($bit*100)/100).$type[$i];
}
public function changeNick($nick){
$nick=["nick" => $nick];
$rules = [
'nick' => ['require','max'=>'25','chsDash'],
];
$validate = new Validate($rules);
if (!$validate->check($nick)) {
return [0,"昵称必须是1-25位字符只能包含中英文等常见字符"];
}else{
Db::name("users")->where("id",$this->uid)->update(["user_nick" => $nick["nick"]]);
return [1,1];
}
}
public function changePwd($origin,$new){
if(md5(config('salt').$origin) != $this->userSQLData["user_pass"]){
return [0,"原密码错误"];
}
if ((mb_strlen($new,'UTF8')>64) || (mb_strlen($new,'UTF8')<4)){
return [false,"密码不符合规范"];
}
self::Reset($this->uid,$new);
return [true,"密码重设成功"];
}
public function homePageToggle($status){
Db::name("users")->where("id",$this->uid)->update(["profile" => $status=="true"?1:0]);
return [1,1];
}
}
?>

@ -0,0 +1,72 @@
{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="row">
<div class="col">
<div class="card">
<div class="card-header" >
<i class="fa fa-eye fa-fw" aria-hidden="true"></i>
系统信息
</div>
<div class="card-body">
<ul>
<li>服务器信息:{:$_SERVER ['SERVER_SOFTWARE']}</li>
<li>服务端系统:{:PHP_OS}</li>
<li>最大上传限制:{:get_cfg_var ("upload_max_filesize")?get_cfg_var ("upload_max_filesize"):"不允许上传"}</li>
<li>脚本最大执行时间:{:get_cfg_var("max_execution_time")."s "}</li>
<li>脚本最大内存:{:get_cfg_var ("memory_limit")?get_cfg_var("memory_limit"):"无"}</li>
<li>PHP扩展curl{eq name=":extension_loaded('curl')" value="true"}√{else/}×{/eq} openssl{eq name=":extension_loaded('openssl')" value="true"}√{else/}×{/eq} GD{eq name=":extension_loaded('gd')" value="true"}√{else/}×{/eq} fileinfo{eq name=":extension_loaded('fileinfo')" value="true"}√{else/}×{/eq}</li>
</ul>
</div>
</div>
</div>
<div class="col">
<div class="card" style="min-height: 269px;">
<div class="card-header">
<i class="fa fa-cloud fa-fw" aria-hidden="true"></i>
关于Cloudreve
</div>
<div class="card-body">
<h5 class="card-title">Cloudreve {$programVersion.type} {$programVersion.version}</h5>
<ul>
<li>主页:<a href="https://cloudreve.org" target="_blank">https://cloudreve.org</a></li>
<li>Github<a href="https://github.com/HFO4/Cloudreve" target="_blank">https://github.com/HFO4/Cloudreve</a></li>
<li>许可证:<a href="https://github.com/HFO4/Cloudreve/LICENSE" target="_blank">GPL V3</a>(社区版)</li>
<li>其他链接:<a href="https://github.com/HFO4/Cloudreve/graphs/contributors" target="_blank">代码贡献者</a> <a href="https://cloudreve.org/joingroup" target="_blank">Telegram群组</a> <a href="https://forum.cloudreve.org" target="_blank">社区</a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Example DataTables Card-->
</div>
<!-- /.container-fluid-->
</div>
{/block}
{block name="js"}
<script type="text/javascript">
</script>
{/block}

@ -0,0 +1,164 @@
{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>
<form id="addGroup">
<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 type="text" class="form-control" name="group_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="colFormLabelSm" class="col-form-label col-form-label-sm">上传策略</label>
</div>
<div class="col-md-4">
<select name="policy_name" required class="form-control">
{volist name="policy" id="p"}
<option value="{$p.id}">{$p.policy_name}</option>
{/volist}
</select>
</div>
<div class="col-md-4 option-des"> 为该用户组绑定一个上传策略</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-group mb-3">
<input type="number" class="form-control" name="max_storage" 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="colFormLabelSm" 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="speed" spellcheck="false" min="0" placeholder="留空表示不限速0表示禁止下载">
<div class="input-group-append">
<span class="input-group-text" id="basic-addon2">
Kb/s
</span>
</div>
</div>
<div class="col-md-4 option-des"> 限制该用户组下的用户上传的文件的下载速度,<strong>此设置仅对本地上传方案有效</strong></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="range_transfer" value="1" id="allow_range_1" checked>
<label class="" for="allow_range_1" >允许</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="range_transfer" id="allow_range_0" value="0" >
<label class="" for="allow_range_0">禁止</label></div>
<div class="col-md-4 option-des"> 是否断点续传及多线程下载,关闭后预览视频不支持拖拽播放,<strong>此设置仅对本地上传方案有效</strong></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="allow_share" value="1" id="allow_share_1" checked>
<label class="" for="allow_share_1" >允许</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="allow_share" id="allow_share_0" value="0" >
<label class="" for="allow_share_0">禁止</label></div>
<div class="col-md-4 option-des"> 是否允许创建文件分享链接</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">WebDAV支持</label>
</div>
<div class="col-md-4"> <input class="" type="radio" name="webdav" value="1" id="webdav1" checked>
<label class="" for="webdav1" >允许</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="webdav" id="webdav0" value="0" >
<label class="" for="webdav0">禁止</label></div>
<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="color" value="default" id="default" checked>
<label class="" for="default" ><span class="badge badge-primary">蓝色</span></label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="color" value="primary" id="primary">
<label class="" for="primary" ><span class="badge badge-secondary">灰色</span></label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="color" value="success" id="success">
<label class="" for="success" ><span class="badge badge-success">绿色</span></label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="color" value="danger" id="danger">
<label class="" for="danger" ><span class="badge badge-danger">红色</span></label>
<br>
<input class="" type="radio" name="color" value="warning" id="warning">
<label class="" for="warning" ><span class="badge badge-warning">黄色</span></label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="color" value="info" id="info">
<label class="" for="info" ><span class="badge badge-info">浅蓝色</span></label>
&nbsp;&nbsp;&nbsp;
</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="saveGroup">添加</button></div>
<div class="col-md-4 option-des"> </div>
<br><br><br>
</div>
</form>
</div>
</div>
<!-- Example DataTables Card-->
</div>
<!-- /.container-fluid-->
</div>
<!-- /.content-wrapper-->
{/block}
{block name="js"}
<script src="/static/js/admin/add_group.js"></script>
<script type="text/javascript">
</script>
{/block}

@ -0,0 +1,815 @@
{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 id="choose">
<div class="row">
<div class="col-md-3 md-2 mt-2">
<div class="card cloud">
<img class="card-img-top" src="/static/img/local.png" alt="Card image cap">
<div class="card-body">
<h5 class="card-title">本地服务器</h5>
<p class="card-text">将文件存放在Cloudreve主程序的同一个服务器上</p>
<a href="javascript:void()" class="btn btn-primary" id="addLocal">添加</a>
</div>
</div>
</div>
<div class="col-md-3 md-2 mt-2">
<div class="card cloud">
<img class="card-img-top" src="/static/img/qiniu.png" alt="Card image cap">
<div class="card-body">
<h5 class="card-title">七牛云存储</h5>
<p class="card-text">使用<a href="https://www.qiniu.com/" target="_blank">七牛云</a>提供的云存储及CDN服务</p>
<a href="javascript:void();" class="btn btn-primary" id="addQiniu">添加</a>
</div>
</div>
</div>
<div class="col-md-3 md-2 mt-2">
<div class="card cloud">
<img class="card-img-top" src="/static/img/oss.png" alt="Card image cap">
<div class="card-body">
<h5 class="card-title">阿里云OSS</h5>
<p class="card-text">使用<a href="https://www.aliyun.com/product/oss?spm=5176.doc54464.765261.286.v2y7Hk" target="_blank">OSS对象存储</a>存放文件推荐配合阿里云CDN使用</p>
<a href="javascript:void()" class="btn btn-primary" id="addOss">添加</a>
</div>
</div>
</div>
<div class="col-md-3 md-2 mt-2">
<div class="card cloud">
<img class="card-img-top" src="/static/img/upyun.png" alt="Card image cap">
<div class="card-body">
<h5 class="card-title">又拍云</h5>
<p class="card-text">使用<a href="https://console.upyun.com/register/?invite=ryPX265PW" target="_blank">又拍云存储</a>提供的服务,每月有一定免费额度</p>
<a href="javascript:void()" class="btn btn-primary" id="addUpyun">添加</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/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>
<a href="/Admin/PolicyAddS3" class="btn btn-primary">添加</a>
</div>
</div>
</div>
</div>
</div>
<div class="card" id="local" style="display: none">
<div class="card-header">
添加本地上传策略
</div>
<div class="card-body">
<form id="localPolicy">
<input type="text" class="form-control" name="policy_type" value="local" 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="policy_name" class="col-form-label col-form-label-sm">允许获取外链</label>
</div>
<div class="col-md-4">
<input class="" type="radio" name="origin_link" id="local_allowd_origin1" value="1" >
<label class="" for="local_allowd_origin1" >允许</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="origin_link" id="local_allowd_origin2" value="0" checked>
<label class="" for="local_allowd_origin2">禁止</label>
</div>
<div class="col-md-4 option-des"> 是否允许获取文件的源URL推荐禁止</div>
</div>
<div class="row form-setting" id="localOrigin" style="display: none">
<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="{$options.siteURL}public/uploads/">
</div>
<div class="col-md-4 option-des"> 一般保持默认。如果你设置了融合CDN等产品这里可以填写CDN域名,结尾要加"/"</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 type="text" class="form-control" name="filetype" value="image/*,jpg,png,gif,bmp,mp4,mp3,txt" spellcheck="false">
</div>
<div class="col-md-4 option-des"> 多个请以半角逗号","隔开,留空表示不限制。如果允许图片类型文件,除了图片类型后缀外,请额外添加一项"image/*"</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>
&nbsp;&nbsp;&nbsp;
<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"> 你可以使用<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="{date}/{uid}" 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>
<div class="card" id="qiniu" style="display: none">
<div class="card-header">
添加七牛上传策略
</div>
<div class="card-body">
<form id="qiniuPolicy">
<input type="text" class="form-control" name="policy_type" value="qiniu" 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">AccessKey </label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="ak" required></div>
<div class="col-md-4 option-des"> 七牛账号的AccessKey请在七牛控制面板查看</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="sk" class="col-form-label col-form-label-sm">SecretKey </label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="sk" required></div>
<div class="col-md-4 option-des"> 七牛账号的SecretKey请在七牛控制面板查看</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">存储空间名称 </label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="bucketname" 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="policy_name" class="col-form-label col-form-label-sm">空间属性</label>
</div>
<div class="col-md-4">
<input class="" type="radio" name="bucket_private" id="bucket_private_1" value="1" checked>
<label class="" for="bucket_private_1" >私有空间</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="bucket_private" id="bucket_private_0" value="0">
<label class="" for="bucket_private_0">公开空间</label>
</div>
<div class="col-md-4 option-des"> 与七牛空间访问控制设置保持一致,推荐设置为私有空间</div>
</div>
<div class="row form-setting" id="outlink" style="display: none">
<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 class="" type="radio" name="origin_link" id="qiniu_allowd_origin1" value="1" >
<label class="" for="qiniu_allowd_origin1" >允许</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="origin_link" id="qiniu_allowd_origin2" value="0" checked>
<label class="" for="qiniu_allowd_origin2">禁止</label>
</div>
<div class="col-md-4 option-des"> 是否允许获取文件的源URL推荐禁止</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="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 type="text" class="form-control" name="filetype" value="image/*,jpg,png,gif,bmp,mp4,mp3,txt" spellcheck="false">
</div>
<div class="col-md-4 option-des"> 多个请以半角逗号","隔开,留空表示不限制。如果允许图片类型文件,除了图片类型后缀外,请额外添加一项"image/*"</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="mimetype" class="col-form-label col-form-label-sm">允许的mimeType</label>
</div>
<div class="col-md-4">
<input type="text" class="form-control" name="mimetype" spellcheck="false">
</div>
<div class="col-md-4 option-des"> 多个请以半角分号";"隔开留空表示不限制。示例image/*表示只允许上传图片类型image/jpeg;image/png表示只允许上传jpg和png类型的图片!application/json;text/plain表示禁止上传json文本和纯文本。注意最前面的感叹号</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="qiniu_autoname1" value="1" checked>
<label class="" for="qiniu_autoname1" >开启</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="autoname" id="qiniu_autoname2" value="0" >
<label class="" for="qiniu_autoname2">关闭</label>
</div>
<div class="col-md-4 option-des"> 是否对存储的文件自动重命名。推荐开启,重命名不会影响用户端文件名展示,开启后可以避免文件重名</div>
</div>
<div class="row form-setting" id="qiniu_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"> 你可以使用<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">
<input type="text" class="form-control" name="dirrule" spellcheck="false" value="{date}/{uid}" 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></div>
<div class="col-md-4 option-des"> </div>
<br> <br>
</div>
</form>
</div>
<bn>
</div>
<div id="oss" style="display: none">
<div class="alert alert-primary" role="alert">
阿里云OSS创建空间后请进行如下操作否则无法正常上传。
<ul>
<li>转到 空间管理 - 基础设置 - 跨域设置;</li>
<li>创建规则,其中来源填写“*”,允许 Methods全部勾选允许 Headers填写“*”,其他保持默认,点击确定保存.</li>
</ul>
</div>
<div class="card" >
<div class="card-header">
添加阿里云OSS上传策略
</div>
<div class="card-body">
<form id="ossPolicy">
<input type="text" class="form-control" name="policy_type" value="oss" 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">Access Key ID </label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="ak" pattern="[^\s]+" title="请不要包含空格" required></div>
<div class="col-md-4 option-des"> 阿里云账号的Access Key ID请在阿里云控制面板-Access Key管理中创建或查看</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="sk" class="col-form-label col-form-label-sm"> Access Key Secret </label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="sk" pattern="[^\s]+" title="请不要包含空格" 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">Bucket名称 </label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="bucketname" required></div>
<div class="col-md-4 option-des"> 创建空间时填写的Bucket名</div>
</div>
<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 class="" type="radio" name="bucket_private" id="oss_private_1" value="1" checked>
<label class="" for="oss_private_1" >私有</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="bucket_private" id="oss_private_0" value="0">
<label class="" for="oss_private_0">公共读</label>
</div>
<div class="col-md-4 option-des"> 与OSS空间访问控制设置保持一致推荐设置为私有空间</div>
</div>
<div class="row form-setting" id="oss_outlink" style="display: none">
<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 class="" type="radio" name="origin_link" id="oss_allowd_origin1" value="1" >
<label class="" for="oss_allowd_origin1" >允许</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="origin_link" id="oss_allowd_origin2" value="0" checked>
<label class="" for="oss_allowd_origin2">禁止</label>
</div>
<div class="col-md-4 option-des"> 是否允许获取文件的源URL推荐禁止</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="url" required>
</div>
<div class="col-md-4 option-des"> OSS空间绑定的域名用于文件下载、访问结尾要加"/"推荐配合阿里云CDN使用此处填写CDN域名</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<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>
</div>
<div class="col-md-4 option-des"> OSS空间的域名一般与上一项保持一致。如果上一项填写的是CDN域名则此处与上一项不应相同</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 type="text" class="form-control" name="filetype" value="image/*,jpg,png,gif,bmp,mp4,mp3,txt" spellcheck="false">
</div>
<div class="col-md-4 option-des"> 多个请以半角逗号","隔开,留空表示不限制。如果允许图片类型文件,除了图片类型后缀外,请额外添加一项"image/*"</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="oss_autoname1" value="1" checked>
<label class="" for="oss_autoname1" >开启</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="autoname" id="oss_autoname2" value="0" >
<label class="" for="oss_autoname2">关闭</label>
</div>
<div class="col-md-4 option-des"> 是否对存储的文件自动重命名。推荐开启,重命名不会影响用户端文件名展示,开启后可以避免文件重名</div>
</div>
<div class="row form-setting" id="oss_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"> 你可以使用<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">
<input type="text" class="form-control" name="dirrule" spellcheck="false" value="{date}/{uid}" 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="saveOss">保存设置</button></div>
<div class="col-md-4 option-des"> </div>
<br> <br>
</div>
</form>
</div>
<bn>
</div>
</div>
<div class="card" id="upyun" style="display: none">
<div class="card-header">
又拍云
</div>
<div class="card-body">
<form id="upyunPolicy">
<input type="text" class="form-control" name="policy_type" value="upyun" 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">操作员名称 </label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="op_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="sk" class="col-form-label col-form-label-sm">操作员密码 </label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="op_pwd" 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">存储服务名 </label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="bucketname" 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="policy_name" class="col-form-label col-form-label-sm">Token 防盗链</label>
</div>
<div class="col-md-4">
<input class="" type="radio" name="bucket_private" id="upyun_bucket_private_1" value="1" checked>
<label class="" for="upyun_bucket_private_1" >开启</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="bucket_private" id="upyun_bucket_private_0" value="0">
<label class="" for="upyun_bucket_private_0">关闭</label>
</div>
<div class="col-md-4 option-des"> 与 功能配置-访问配置-Token 防盗链 保持一致,推荐设置为开启</div>
</div>
<div class="row form-setting" id="upyun_token" style="">
<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="sk"></div>
<div class="col-md-4 option-des"> 与 功能配置-访问配置-Token防盗链 中的密钥保持一致</div>
</div>
<div class="row form-setting" id="upyun_outlink" style="display: none">
<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 class="" type="radio" name="origin_link" id="upyun_allowd_origin1" value="1" >
<label class="" for="upyun_allowd_origin1" >允许</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="origin_link" id="upyun_allowd_origin2" value="0" checked>
<label class="" for="upyun_allowd_origin2">禁止</label>
</div>
<div class="col-md-4 option-des"> 是否允许获取文件的源URL推荐禁止</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="url" required>
</div>
<div class="col-md-4 option-des"> 绑定的域名开头要加http(s)://结尾要加"/"</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 type="text" class="form-control" name="filetype" value="image/*,jpg,png,gif,bmp,mp4,mp3,txt" spellcheck="false">
</div>
<div class="col-md-4 option-des"> 多个请以半角逗号","隔开,留空表示不限制。如果允许图片类型文件,除了图片类型后缀外,请额外添加一项"image/*"</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>
<input type="text" name="autoname" value="1" style="display: none">
<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="text" class="form-control" name="dirrule" spellcheck="false" value="{date}/{uid}" 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="saveUpyun">保存设置</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>
<!-- /.content-wrapper-->
<div class="modal fade" tabindex="-1" role="dialog" id="varTable">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">自动重命名变量对照表</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th >变量字段</th>
<th >说明</th>
<th >示例</th>
<th >适用范围</th>
</tr>
</thead>
<tbody>
<tr>
<td >{date}</td>
<td>上传日期</td>
<td>20180118</td>
<td>全部</td>
</tr>
<tr>
<td >{datetime}</td>
<td>上传日期时间</td>
<td>20180118121049</td>
<td>全部</td>
</tr>
<tr>
<td >{uid}</td>
<td>上传者UID</td>
<td>154</td>
<td>全部</td>
</tr>
<tr>
<td >{timestamp}</td>
<td>时间戳</td>
<td>1516277624</td>
<td>全部</td>
</tr>
<tr>
<td >{randomkey16}</td>
<td>16位随机字符</td>
<td>16D8lhjErTDWAQjW</td>
<td>全部</td>
</tr>
<tr>
<td >{randomkey8}</td>
<td>8位随机字符</td>
<td>hM4Tpdh6</td>
<td>全部</td>
</tr>
<tr>
<td >{originname}</td>
<td>原始文件名</td>
<td>plus1s.jpg</td>
<td>全部</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
</div>
</div>
</div>
</div>
<div class="modal fade" tabindex="-1" role="dialog" id="varTableFolder">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">目录变量对照表</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th >变量字段</th>
<th >说明</th>
<th >示例</th>
<th >适用范围</th>
</tr>
</thead>
<tbody>
<tr>
<td >{date}</td>
<td>上传日期</td>
<td>20180118</td>
<td>全部</td>
</tr>
<tr>
<td >{datetime}</td>
<td>上传日期时间</td>
<td>20180118121049</td>
<td>全部</td>
</tr>
<tr>
<td >{uid}</td>
<td>上传者UID</td>
<td>154</td>
<td>全部</td>
</tr>
<tr>
<td >{timestamp}</td>
<td>时间戳</td>
<td>1516277624</td>
<td>全部</td>
</tr>
<tr>
<td >{randomkey16}</td>
<td>16位随机字符</td>
<td>16D8lhjErTDWAQjW</td>
<td>全部</td>
</tr>
<tr>
<td >{randomkey8}</td>
<td>8位随机字符</td>
<td>hM4Tpdh6</td>
<td>全部</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
</div>
</div>
</div>
</div>
{/block}
{block name="js"}
<script src="/static/js/admin/add_policy.js"></script>
<script type="text/javascript">
</script>
{/block}

@ -0,0 +1,175 @@
{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-primary" role="alert">
创建储存桶后请在储存桶控制面板添加CORS跨域规则允许本站的POST请求。请确保您的服务器和用户可以正常连接到AWS服务器。
</ul>
</div>
<div class="card" id="s3" >
<div class="card-header">
添加S3上传策略
</div>
<div class="card-body">
<form id="qiniuPolicy">
<input type="text" class="form-control" name="policy_type" value="s3" 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">AWSAccessKeyId </label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="ak" required></div>
<div class="col-md-4 option-des"> AWS账户的访问秘钥信息请在 控制面板 - 您的安全凭证 中创建</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="sk" class="col-form-label col-form-label-sm">AWSSecretKey </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>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="bucketname" class="col-form-label col-form-label-sm">存储桶名称 </label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="bucketname" required></div>
<div class="col-md-4 option-des"> 创建桶时填写的名称</div>
</div>
<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="url" required>
</div>
<div class="col-md-4 option-des"> 一般格式为https://s3-分区名.amazonaws.com/储存桶名/ 结尾要加"/"</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" required>
</div>
<div class="col-md-4 option-des"> 一般格式为https://储存桶名.s3-分区代号.amazonaws.com/</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="op_name" required>
</div>
<div class="col-md-4 option-des"> 例如ap-southeast-1</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">EndPoint</label>
</div>
<div class="col-md-4">
<input type="text" class="form-control" name="op_name" required>
</div>
<div class="col-md-4 option-des"> 一般格式为s3-储存区域.amazonaws.com只填写域名部分</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 type="text" class="form-control" name="filetype" value="image/*,jpg,png,gif,bmp,mp4,mp3,txt" spellcheck="false">
</div>
<div class="col-md-4 option-des"> 多个请以半角逗号","隔开,留空表示不限制。如果允许图片类型文件,除了图片类型后缀外,请额外添加一项"image/*"</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>
<input type="text" name="autoname" value="0" style="display: none">
<input type="text" class="form-control" name="dirrule" spellcheck="false" value="{uid}" style="display: none" required>
<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">
</script>
{/block}

@ -0,0 +1,229 @@
{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="#">管理面板</a>
</li>
<li class="breadcrumb-item active">数据概况</li>
</ol>
<!-- Icon Cards-->
<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">
<div class="card-body-icon">
<i class="fa fa-fw fa-users"></i>
</div>
<div class="mr-5">{$statics.userNum} 位用户</div>
</div>
<a class="card-footer text-white clearfix small z-1" href="/Admin/Users">
<span class="float-left">查看详情</span>
<span class="float-right">
<i class="fa fa-angle-right"></i>
</span>
</a>
</div>
</div>
<div class="col-xl-3 col-sm-6 mb-3">
<div class="card text-white bg-warning o-hidden h-100">
<div class="card-body">
<div class="card-body-icon">
<i class="fa fa-fw fa-file"></i>
</div>
<div class="mr-5">{$statics.fileNum} 个文件</div>
</div>
<a class="card-footer text-white clearfix small z-1" href="/Admin/Files">
<span class="float-left">查看详情</span>
<span class="float-right">
<i class="fa fa-angle-right"></i>
</span>
</a>
</div>
</div>
<div class="col-xl-3 col-sm-6 mb-3">
<div class="card text-white bg-success o-hidden h-100">
<div class="card-body">
<div class="card-body-icon">
<i class="fa fa-fw fa-share-alt"></i>
</div>
<div class="mr-5">{$statics.publicShareNum} 个公开分享</div>
</div>
<a class="card-footer text-white clearfix small z-1" href="/Admin/Shares">
<span class="float-left">查看详情</span>
<span class="float-right">
<i class="fa fa-angle-right"></i>
</span>
</a>
</div>
</div>
<div class="col-xl-3 col-sm-6 mb-3">
<div class="card text-white bg-danger o-hidden h-100">
<div class="card-body">
<div class="card-body-icon">
<i class="fa fa-fw fa-lock"></i>
</div>
<div class="mr-5">{$statics.privateShareNum} 个私密分享</div>
</div>
<a class="card-footer text-white clearfix small z-1" href="/Admin/Shares">
<span class="float-left">查看详情</span>
<span class="float-right">
<i class="fa fa-angle-right"></i>
</span>
</a>
</div>
</div>
</div>
<!-- Area Chart Example-->
<div class="card mb-3">
<div class="card-header">
<i class="fa fa-area-chart"></i> 近期趋势</div>
<div class="card-body">
<canvas id="myAreaChart" width="100%" height="30"></canvas>
</div>
</div>
<div class="row">
<div class="col-lg-8">
<!-- Example Bar Chart Card-->
<div class="card mb-3">
<div class="card-header">
<i class="fa fa-bell-o"></i> 订阅新闻</div>
<div class="list-group list-group-flush small" id="news">
</div>
</div>
<!-- Card Columns Example Social Feed-->
<!-- /Card Columns-->
</div>
<div class="col-lg-4">
<!-- Example Pie Chart Card-->
<div class="card mb-3">
<div class="card-header">
<i class="fa fa-pie-chart"></i> 文件组成</div>
<div class="card-body">
<canvas id="myPieChart" width="100%" height="80"></canvas>
</div>
<div class="card-footer small text-muted">*此结果仅供参考</div>
</div>
<!-- Example Notifications Card-->
</div>
</div>
<!-- Example DataTables Card-->
</div>
<!-- /.container-fluid-->
<!-- /.content-wrapper-->
<footer class="sticky-footer">
<div class="container">
<div class="text-center">
<small>Copyright © Cloudreve {php}echo date("Y");{/php} </small>
</div>
</div>
</footer>
<!-- Scroll to Top Button-->
<a class="scroll-to-top rounded" href="#page-top">
<i class="fa fa-angle-up"></i>
</a>
<!-- Logout Modal-->
<!-- Bootstrap core JavaScript-->
{/block}
{block name="js"}
<script type="text/javascript">
$(document).ready(function() {
$.getJSON("https://cloudreve.org/api/notice/?callback=?", function(data){
$("#news").html(data[0]);
})
})
Chart.defaults.global.defaultFontFamily = '-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif',
Chart.defaults.global.defaultFontColor = "#292b2c";
var ctx = document.getElementById("myAreaChart"),
myLineChart = new Chart(ctx, {
type: "line",
data: {
labels: [{$statics.trendDate}],
datasets: [{
label: "上传文件",
lineTension: .3,
backgroundColor: "rgba(2,117,216,0.2)",
borderColor: "rgba(2,117,216,1)",
pointRadius: 5,
pointBackgroundColor: "rgba(2,117,216,1)",
pointBorderColor: "rgba(255,255,255,0.8)",
pointHoverRadius: 5,
pointHoverBackgroundColor: "rgba(2,117,216,1)",
pointHitRadius: 20,
pointBorderWidth: 2,
data: [{$statics.trendFile}]
},{
label: "注册用户",
lineTension: .3,
backgroundColor: "rgba(83, 216, 2, 0.2)",
borderColor: "#4CAF50",
pointRadius: 5,
pointBackgroundColor: "#4CAF50",
pointBorderColor: "rgba(255,255,255,0.8)",
pointHoverRadius: 5,
pointHoverBackgroundColor: "#4CAF50",
pointHitRadius: 20,
pointBorderWidth: 2,
data: [{$statics.trendUser}]
},
]
},
options: {
scales: {
xAxes: [{
time: {
unit: "date"
},
gridLines: {
display: !1
},
ticks: {
maxTicksLimit: 7
}
}],
yAxes: [{
ticks: {
maxTicksLimit: 5
},
gridLines: {
color: "rgba(0, 0, 0, .125)"
}
}]
},
legend: {
display: !1
}
}
}),
ctx = document.getElementById("myPieChart"),
myPieChart = new Chart(ctx, {
type: "pie",
data: {
labels: ["其他", "图片", "音频", "视频"],
datasets: [{
data: [{$statics.otherRate}, {$statics.imgRate}, {$statics.audioRate}, {$statics.videoRate}],
backgroundColor: ["#007bff", "#dc3545", "#ffc107", "#28a745"]
}]
}
});
</script>
{/block}

@ -0,0 +1,83 @@
{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>
<form id="basicOptionsForm">
<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 type="text" class="form-control" name="siteName" value="{$options.siteName}"></div>
<div class="col-md-4 option-des"> 站点的主标题,将会展示在个页面的标题尾部、邮件中。</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 type="text" class="form-control" name="siteTitle" value="{$options.siteTitle}"></div>
<div class="col-md-4 option-des"> 只会展示在首页的副标题。</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">站点URL</label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="siteURL" value="{$options.siteURL}" spellcheck="false"></div>
<div class="col-md-4 option-des"> 站点的URL此设置很重要请如实填写否则会影响系统正常工作.</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 type="text" class="form-control" name="siteKeywords" value="{$options.siteKeywords}"></div>
<div class="col-md-4 option-des"> 位于首页meta标签内的站点关键词</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 type="text" class="form-control" name="siteDes" value="{$options.siteDes}"></div>
<div class="col-md-4 option-des"> 位于首页meta标签内的站点描述</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"> <textarea class="form-control" name="js_code" rows="4" spellcheck="false">{$options.js_code}</textarea></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="button" class="btn btn-primary" id="saveBasic">保存设置</button></div>
<div class="col-md-4 option-des"> </div>
<br> <br>
</div>
</form>
</div>
</div>
<!-- Example DataTables Card-->
</div>
<!-- /.container-fluid-->
</div>
{/block}
{block name="js"}
<script src="/static/js/admin/setting.js"></script>
<script type="text/javascript">
</script>
{/block}

@ -0,0 +1,51 @@
{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>
{$path}
<br> <br>
<div class="row">
<div class="col-md-9">
<input type="text" id="configType" value="{$type}" style="display: none">
<textarea rows="15" class="form-control" spellcheck="false">{$content}</textarea>
<br>
<button class="btn btn-primary" id="save">保存</button>
<br><br>
</div>
<div class="col-md-3">
<div class="nav flex-column nav-pills" id="v-pills-tab" role="tablist" aria-orientation="vertical">
<a class="nav-link" id="v-pills-home-tab" href="/Admin/Config/type/common" role="tab" data-type="common">系统公共配置</a>
<a class="nav-link" id="v-pills-profile-tab" href="/Admin/Config/type/database" role="tab" data-type="database">数据库</a>
<a class="nav-link" id="v-pills-messages-tab" href="/Admin/Config/type/route" role="tab" data-type="route">路由</a>
<a class="nav-link" id="v-pills-settings-tab" href="/Admin/Config/type/tags" role="tab" data-type="tags">行为扩展</a>
</div>
</div>
</div>
</div>
</div>
<!-- Example DataTables Card-->
</div>
<!-- /.container-fluid-->
</div>
{/block}
{block name="js"}
<script src="/static/js/admin/config.js"></script>
<script type="text/javascript">
</script>
{/block}

@ -0,0 +1,84 @@
{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>
{eq name="neverExcute" value="true"}
<div class="alert alert-warning" role="alert">
定时任务从未执行!请将 {$options.siteURL}Cron 加入到您的定时任务列队中如Crontab
</div>
{/eq}
{volist name="cron" id="c"}
<div class="card">
<div class="card-header">
{$c.name}
</div>
<div class="card-body">
<blockquote class="blockquote mb-0">
<p>{$c.des}</p>
</blockquote><form id="cronForm" method="post" action="/Admin/SaveCron">
<div class="row">
<input type="text" name="id" value="{$c.id}" style="display: none;">
<div class="col-md-4">
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="basic-addon1">优先级</span>
</div>
<input type="number" min="0" class="form-control" name="rank" placeholder="值越高越优先" value="{$c.rank}">
</div>
</div>
<div class="col-md-4">
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="basic-addon1">执行间隔(s)</span>
</div>
<input type="number" min="1" class="form-control" name="interval_s" value="{$c.interval_s}">
</div>
</div>
<div class="col-md-4">
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="basic-addon1">启用</span>
</div>
<input type="number" min="0" max="1" class="form-control" name="enable" value="{$c.enable}">
</div>
</div>
</div>
<input type="submit" class="btn btn-primary" value="保存">
</form>
</div>
<div class="card-footer text-muted">
上次执行:{eq name="c.last_excute" value="0"}从未执行{else/}{:date("Y-m-d H:i:s",$c.last_excute)}{/eq}
</div>
</div><br>
{/volist}
</div>
</div>
<!-- Example DataTables Card-->
</div>
<!-- /.container-fluid-->
</div>
{/block}
{block name="js"}
<script type="text/javascript">
</script>
{/block}

@ -0,0 +1,171 @@
{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>
<form id="editGroup">
<div class="row form-setting">
<div class="col-md-1 form-label ">
<input type="text" name="id" value="{$group.id}" style="display: none">
<label for="colFormLabelSm" class="col-form-label col-form-label-sm">用户组名</label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="group_name" value="{$group.group_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="colFormLabelSm" class="col-form-label col-form-label-sm">上传策略</label>
</div>
<div class="col-md-4">
<select name="policy_name" required class="form-control" >
{volist name="policy" id="p"}
<option value="{$p.id}">{$p.policy_name}</option>
{/volist}
</select>
</div>
<div class="col-md-4 option-des"> 为该用户组绑定一个上传策略</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-group mb-3">
<input type="number" class="form-control" name="max_storage" spellcheck="false" min="0" value="{:countSize($group.max_storage,true)[0]}" required>
<div class="input-group-append">
<span class="input-group-text" id="basic-addon2">
<select name="sizeTimes" class="selectIn" data-value="{:countSize($group.max_storage,true)[1]}">
<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="colFormLabelSm" 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="speed" spellcheck="false" min="0" placeholder="留空表示不限速0表示禁止下载" value="{$group.speed}">
<div class="input-group-append">
<span class="input-group-text" id="basic-addon2">
Kb/s
</span>
</div>
</div>
<div class="col-md-4 option-des"> 限制该用户组下的用户上传的文件的下载速度,<strong>此设置仅对本地上传方案有效</strong></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="range_transfer" value="1" id="allow_range_1">
<label class="" for="allow_range_1" >允许</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="range_transfer" id="allow_range_0" value="0" >
<label class="" for="allow_range_0">禁止</label></div>
<div class="col-md-4 option-des"> 是否断点续传及多线程下载,关闭后预览视频不支持拖拽播放,<strong>此设置仅对本地上传方案有效</strong></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="allow_share" value="1" id="allow_share_1" checked>
<label class="" for="allow_share_1" >允许</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="allow_share" id="allow_share_0" value="0" >
<label class="" for="allow_share_0">禁止</label></div>
<div class="col-md-4 option-des"> 是否允许创建文件分享链接</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">WebDAV支持</label>
</div>
<div class="col-md-4"> <input class="" type="radio" name="webdav" value="1" id="webdav1" checked>
<label class="" for="webdav1" >允许</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="webdav" id="webdav0" value="0" >
<label class="" for="webdav0">禁止</label></div>
<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="color" value="default" id="default" checked>
<label class="" for="default" ><span class="badge badge-primary">蓝色</span></label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="color" value="primary" id="primary">
<label class="" for="primary" ><span class="badge badge-secondary">灰色</span></label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="color" value="success" id="success">
<label class="" for="success" ><span class="badge badge-success">绿色</span></label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="color" value="danger" id="danger">
<label class="" for="danger" ><span class="badge badge-danger">红色</span></label>
<br>
<input class="" type="radio" name="color" value="warning" id="warning">
<label class="" for="warning" ><span class="badge badge-warning">黄色</span></label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="color" value="info" id="info">
<label class="" for="info" ><span class="badge badge-info">浅蓝色</span></label>
&nbsp;&nbsp;&nbsp;
</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="saveGroup">保存</button></div>
<div class="col-md-4 option-des"> </div>
<br><br><br>
</div>
</form>
</div>
</div>
<!-- Example DataTables Card-->
</div>
<!-- /.container-fluid-->
</div>
<!-- /.content-wrapper-->
{/block}
{block name="js"}
<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);
$("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);
</script>
{/block}

@ -0,0 +1,962 @@
{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/PolicyList">上传策略</a>
</li>
<li class="breadcrumb-item active">编辑</li>
</ol>
<!-- Area Chart Example-->
<div class="row">
<div class="col-12">
<h2>编辑上传策略</h2>
<br>
{switch name="policy.policy_type"}
{case value="local"}
<div class="card" id="local">
<div class="card-header">
编辑上传策略
</div>
<div class="card-body">
<form id="Policy">
<div class="row form-setting">
<div class="col-md-1 form-label ">
<input type="text" value="{$policy.id}" name="id" style="display: none">
<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" value="{$policy.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="policy_name" class="col-form-label col-form-label-sm">允许获取外链</label>
</div>
<div class="col-md-4">
{eq name="$policy.origin_link" value="1"}
<input class="" type="radio" name="origin_link" id="local_allowd_origin1" value="1" checked>
<label class="" for="local_allowd_origin1" >允许</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="origin_link" id="local_allowd_origin2" value="0">
<label class="" for="local_allowd_origin2">禁止</label>
{else/}
<input class="" type="radio" name="origin_link" id="local_allowd_origin1" value="1" >
<label class="" for="local_allowd_origin1" >允许</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="origin_link" id="local_allowd_origin2" value="0" checked>
<label class="" for="local_allowd_origin2">禁止</label>
{/eq}
</div>
<div class="col-md-4 option-des"> 是否允许获取文件的源URL推荐禁止</div>
</div>
<div class="row form-setting" id="localOrigin" style="{eq name="$policy.origin_link" value="0"}display:none;{/eq}">
<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}">
</div>
<div class="col-md-4 option-des"> 一般与主站URL保持相同。如果你设置了融合CDN等产品这里可以填写CDN域名,结尾要加"/"</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 type="text" class="form-control" name="filetype" value="{:getAllowedExt($policy.filetype)}" spellcheck="false">
</div>
<div class="col-md-4 option-des"> 多个请以半角逗号","隔开,留空表示不限制。如果允许图片类型文件,除了图片类型后缀外,请额外添加一项"image/*"</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>
&nbsp;&nbsp;&nbsp;
<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>
&nbsp;&nbsp;&nbsp;
<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="qiniu"}
<div class="card" id="qiniu">
<div class="card-header">
编辑上传策略
</div>
<div class="card-body">
<form id="Policy">
<div class="row form-setting">
<div class="col-md-1 form-label ">
<input type="text" value="{$policy.id}" name="id" style="display: none">
<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" value="{$policy.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">AccessKey </label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="ak" value="{$policy.ak}" pattern="[^\s]+" title="请不要包含空格" required></div>
<div class="col-md-4 option-des"> 七牛账号的AccessKey请在七牛控制面板查看</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="sk" class="col-form-label col-form-label-sm">SecretKey </label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="sk" value="{$policy.sk}" pattern="[^\s]+" title="请不要包含空格" required></div>
<div class="col-md-4 option-des"> 七牛账号的SecretKey请在七牛控制面板查看</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">存储空间名称 </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"> 创建空间时填写的空间名</div>
</div>
<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">
{eq name="policy.bucket_private" value="1"}
<input class="" type="radio" name="bucket_private" id="bucket_private_1" value="1" checked>
<label class="" for="bucket_private_1" >私有空间</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="bucket_private" id="bucket_private_0" value="0">
<label class="" for="bucket_private_0">公开空间</label>
{else/}
<input class="" type="radio" name="bucket_private" id="bucket_private_1" value="1">
<label class="" for="bucket_private_1" >私有空间</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="bucket_private" id="bucket_private_0" value="0" checked>
<label class="" for="bucket_private_0">公开空间</label>
{/eq}
</div>
<div class="col-md-4 option-des"> 与七牛空间访问控制设置保持一致,推荐设置为私有空间</div>
</div>
<div class="row form-setting" id="outlink" style="{eq name="policy.bucket_private" value="1"}display:none{/eq}">
<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">
{eq name="policy.origin_link" value="1"}
<input class="" type="radio" name="origin_link" id="qiniu_allowd_origin1" value="1" >
<label class="" for="qiniu_allowd_origin1" checked>允许</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="origin_link" id="qiniu_allowd_origin2" value="0" >
<label class="" for="qiniu_allowd_origin2">禁止</label>
{else/}
<input class="" type="radio" name="origin_link" id="qiniu_allowd_origin1" value="1" >
<label class="" for="qiniu_allowd_origin1" >允许</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="origin_link" id="qiniu_allowd_origin2" value="0" checked>
<label class="" for="qiniu_allowd_origin2">禁止</label>
{/eq}
</div>
<div class="col-md-4 option-des"> 是否允许获取文件的源URL推荐禁止</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="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 type="text" class="form-control" name="filetype" value="{:getAllowedExt($policy.filetype)}" spellcheck="false">
</div>
<div class="col-md-4 option-des"> 多个请以半角逗号","隔开,留空表示不限制。如果允许图片类型文件,除了图片类型后缀外,请额外添加一项"image/*"</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="mimetype" class="col-form-label col-form-label-sm">允许的mimeType</label>
</div>
<div class="col-md-4">
<input type="text" class="form-control" name="mimetype" spellcheck="false" value="{$policy.mimetype}">
</div>
<div class="col-md-4 option-des"> 多个请以半角分号";"隔开留空表示不限制。示例image/*表示只允许上传图片类型image/jpeg;image/png表示只允许上传jpg和png类型的图片!application/json;text/plain表示禁止上传json文本和纯文本。注意最前面的感叹号</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>
&nbsp;&nbsp;&nbsp;
<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>
&nbsp;&nbsp;&nbsp;
<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">
<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="oss"}
<div id="oss">
<div class="card" >
<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" name="policy_name" value="{$policy.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">Access Key ID </label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="ak" pattern="[^\s]+" title="请不要包含空格" value="{$policy.ak}" required></div>
<div class="col-md-4 option-des"> 阿里云账号的Access Key ID请在阿里云控制面板-Access Key管理中创建或查看</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="sk" class="col-form-label col-form-label-sm"> Access Key Secret </label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="sk" pattern="[^\s]+" title="请不要包含空格" 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="bucketname" class="col-form-label col-form-label-sm">Bucket名称 </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"> 创建空间时填写的Bucket名</div>
</div>
<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">
{eq name="policy.bucket_private" value="1"}
<input class="" type="radio" name="bucket_private" id="oss_private_1" value="1" checked>
<label class="" for="oss_private_1" >私有</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="bucket_private" id="oss_private_0" value="0">
<label class="" for="oss_private_0">公共读</label>
{else/}
<input class="" type="radio" name="bucket_private" id="oss_private_1" value="1">
<label class="" for="oss_private_1" >私有</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="bucket_private" id="oss_private_0" value="0" checked>
<label class="" for="oss_private_0">公共读</label>
{/eq}
</div>
<div class="col-md-4 option-des"> 与OSS空间访问控制设置保持一致推荐设置为私有空间</div>
</div>
<div class="row form-setting" id="oss_outlink" style="{eq name="policy.bucket_private" value="1"}display:none{/eq}">
<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">
{eq name="policy.origin_link" value="0"}
<input class="" type="radio" name="origin_link" id="oss_allowd_origin1" value="1" >
<label class="" for="oss_allowd_origin1" >允许</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="origin_link" id="oss_allowd_origin2" value="0" checked>
<label class="" for="oss_allowd_origin2">禁止</label>
{else/}
<input class="" type="radio" name="origin_link" id="oss_allowd_origin1" value="1" checked>
<label class="" for="oss_allowd_origin1" >允许</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="origin_link" id="oss_allowd_origin2" value="0">
<label class="" for="oss_allowd_origin2">禁止</label>
{/eq}
</div>
<div class="col-md-4 option-des"> 是否允许获取文件的源URL推荐禁止</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="url" value="{$policy.url}" required>
</div>
<div class="col-md-4 option-des"> OSS空间绑定的域名用于文件下载、访问结尾要加"/"推荐配合阿里云CDN使用此处填写CDN域名</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<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" value="{$policy.server}" required>
</div>
<div class="col-md-4 option-des"> OSS空间的域名一般与上一项保持一致。如果上一项填写的是CDN域名则此处与上一项不应相同</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 type="text" class="form-control" name="filetype" value="{:getAllowedExt($policy.filetype)}" spellcheck="false">
</div>
<div class="col-md-4 option-des"> 多个请以半角逗号","隔开,留空表示不限制。如果允许图片类型文件,除了图片类型后缀外,请额外添加一项"image/*"</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="oss_autoname1" value="1" checked>
<label class="" for="oss_autoname1" >开启</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="autoname" id="oss_autoname2" value="0" >
<label class="" for="oss_autoname2">关闭</label>
{else/}
<input class="" type="radio" name="autoname" id="oss_autoname1" value="1" >
<label class="" for="oss_autoname1" >开启</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="autoname" id="oss_autoname2" value="0" checked>
<label class="" for="oss_autoname2">关闭</label>
{/eq}
</div>
<div class="col-md-4 option-des"> 是否对存储的文件自动重命名。推荐开启,重命名不会影响用户端文件名展示,开启后可以避免文件重名</div>
</div>
<div class="row form-setting" id="oss_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">
<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>
</div>
{/case}
{case value="upyun"}
<div class="card" id="upyun">
<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" name="policy_name" value="{$policy.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">操作员名称 </label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="op_name" value="{$policy.op_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="sk" class="col-form-label col-form-label-sm">操作员密码 </label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="op_pwd" value="{$policy.op_pwd}" 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">存储服务名 </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"> 创建存储服务时填写的名称</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="policy_name" class="col-form-label col-form-label-sm">Token 防盗链</label>
</div>
<div class="col-md-4">
{eq name="policy.bucket_private" value="1"}
<input class="" type="radio" name="bucket_private" id="upyun_bucket_private_1" value="1" checked>
<label class="" for="upyun_bucket_private_1" >开启</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="bucket_private" id="upyun_bucket_private_0" value="0">
<label class="" for="upyun_bucket_private_0">关闭</label>
{else/}
<input class="" type="radio" name="bucket_private" id="upyun_bucket_private_1" value="1">
<label class="" for="upyun_bucket_private_1" >开启</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="bucket_private" id="upyun_bucket_private_0" value="0" checked>
<label class="" for="upyun_bucket_private_0">关闭</label>
{/eq}
</div>
<div class="col-md-4 option-des"> 与 功能配置-访问配置-Token 防盗链 保持一致,推荐设置为开启</div>
</div>
<div class="row form-setting" id="upyun_token" style="{eq name="policy.bucket_private" value="0"}display:none{/eq}">
<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="sk" value="{$policy.sk}"></div>
<div class="col-md-4 option-des"> 与 功能配置-访问配置-Token防盗链 中的密钥保持一致</div>
</div>
<div class="row form-setting" id="upyun_outlink" style="{eq name="policy.bucket_private" value="1"}display:none{/eq}">
<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">
{eq name="policy.origin_link" value="0"}
<input class="" type="radio" name="origin_link" id="upyun_allowd_origin1" value="1" >
<label class="" for="upyun_allowd_origin1" >允许</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="origin_link" id="upyun_allowd_origin2" value="0" checked>
<label class="" for="upyun_allowd_origin2">禁止</label>
{else/}
<input class="" type="radio" name="origin_link" id="upyun_allowd_origin1" value="1" checked>
<label class="" for="upyun_allowd_origin1" >允许</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="origin_link" id="upyun_allowd_origin2" value="0" >
<label class="" for="upyun_allowd_origin2">禁止</label>
{/eq}
</div>
<div class="col-md-4 option-des"> 是否允许获取文件的源URL推荐禁止</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="url" value="{$policy.url}" required>
</div>
<div class="col-md-4 option-des"> 绑定的域名开头要加http(s)://结尾要加"/"</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 type="text" class="form-control" name="filetype" value="{:getAllowedExt($policy.filetype)}" spellcheck="false">
</div>
<div class="col-md-4 option-des"> 多个请以半角逗号","隔开,留空表示不限制。如果允许图片类型文件,除了图片类型后缀外,请额外添加一项"image/*"</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>
<input type="text" name="autoname" value="1" style="display: none">
<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="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="saveUpyun">保存设置</button></div>
<div class="col-md-4 option-des"> </div>
<br> <br>
</div>
</form>
</div>
<bn>
</div>
{/case}
{case value="s3"}
<div class="card" id="s3" >
<div class="card-header">
添加S3上传策略
</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">AWSAccessKeyId </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"> AWS账户的访问秘钥信息请在 控制面板 - 您的安全凭证 中创建</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="sk" class="col-form-label col-form-label-sm">AWSSecretKey </label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" value="{$policy.sk}" name="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="bucketname" class="col-form-label col-form-label-sm">存储桶名称 </label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" value="{$policy.bucketname}" name="bucketname" 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"> 一般格式为https://s3-分区名.amazonaws.com/储存桶名/ 结尾要加"/"</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"> 一般格式为https://储存桶名.s3-分区代号.amazonaws.com/</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" value="{$policy.op_name}" name="op_name" required>
</div>
<div class="col-md-4 option-des"> 例如ap-southeast-1</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">EndPoint</label>
</div>
<div class="col-md-4">
<input type="text" class="form-control" name="op_pwd" value="{$policy.op_pwd}" required>
</div>
<div class="col-md-4 option-des"> 一般格式为s3-储存区域.amazonaws.com只填写域名部分</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 type="text" class="form-control" name="filetype" value="{:getAllowedExt($policy.filetype)}" spellcheck="false">
</div>
<div class="col-md-4 option-des"> 多个请以半角逗号","隔开,留空表示不限制。如果允许图片类型文件,除了图片类型后缀外,请额外添加一项"image/*"</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 ">
</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}
{/switch}
<br>
</div>
</div>
<!-- Example DataTables Card-->
</div>
<!-- /.container-fluid-->
</div>
<!-- /.content-wrapper-->
<div class="modal fade" tabindex="-1" role="dialog" id="varTable">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">自动重命名变量对照表</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th >变量字段</th>
<th >说明</th>
<th >示例</th>
<th >适用范围</th>
</tr>
</thead>
<tbody>
<tr>
<td >{date}</td>
<td>上传日期</td>
<td>20180118</td>
<td>全部</td>
</tr>
<tr>
<td >{datetime}</td>
<td>上传日期时间</td>
<td>20180118121049</td>
<td>全部</td>
</tr>
<tr>
<td >{uid}</td>
<td>上传者UID</td>
<td>154</td>
<td>全部</td>
</tr>
<tr>
<td >{timestamp}</td>
<td>时间戳</td>
<td>1516277624</td>
<td>全部</td>
</tr>
<tr>
<td >{randomkey16}</td>
<td>16位随机字符</td>
<td>16D8lhjErTDWAQjW</td>
<td>全部</td>
</tr>
<tr>
<td >{randomkey8}</td>
<td>8位随机字符</td>
<td>hM4Tpdh6</td>
<td>全部</td>
</tr>
<tr>
<td >{originname}</td>
<td>原始文件名</td>
<td>plus1s.jpg</td>
<td>全部</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
</div>
</div>
</div>
</div>
<div class="modal fade" tabindex="-1" role="dialog" id="varTableFolder">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">目录变量对照表</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th >变量字段</th>
<th >说明</th>
<th >示例</th>
<th >适用范围</th>
</tr>
</thead>
<tbody>
<tr>
<td >{date}</td>
<td>上传日期</td>
<td>20180118</td>
<td>全部</td>
</tr>
<tr>
<td >{datetime}</td>
<td>上传日期时间</td>
<td>20180118121049</td>
<td>全部</td>
</tr>
<tr>
<td >{uid}</td>
<td>上传者UID</td>
<td>154</td>
<td>全部</td>
</tr>
<tr>
<td >{timestamp}</td>
<td>时间戳</td>
<td>1516277624</td>
<td>全部</td>
</tr>
<tr>
<td >{randomkey16}</td>
<td>16位随机字符</td>
<td>16D8lhjErTDWAQjW</td>
<td>全部</td>
</tr>
<tr>
<td >{randomkey8}</td>
<td>8位随机字符</td>
<td>hM4Tpdh6</td>
<td>全部</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
</div>
</div>
</div>
</div>
{/block}
{block name="js"}
<script src="/static/js/admin/edit_policy.js"></script>
<script type="text/javascript">
</script>
{/block}

@ -0,0 +1,194 @@
{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>
<div class="row">
<div class="col-12">
<h2>文件</h2>
<br>
<div class="card mb-3">
<div class="card-header">
<i class="fa fa-tags"></i> 条件检索</div>
<div class="card-body">
<div class="row">
<div class="col-1 form-label-search mb-2">排序方式</div>
<div class="col-md-10">
<ul class="nav nav-pills" id="order">
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-method="id DESC">日期</a>
</li>
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-method="orign_name ASC">文件名</a>
</li>
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-method="size DESC">大小</a>
</li>
</ul>
</div>
</div>
<div class="row">
<div class="col-1 form-label-search mb-2">上传策略</div>
<div class="col-md-10">
<ul class="nav nav-pills" id="policy_select">
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-policy="">全部</a>
</li>
{volist name="policy" id="policy"}
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-policy="{$policy.id}">{$policy.policy_name}</a>
</li>
{/volist}
</ul>
</div>
</div>
<div class="row" style="margin-top: 5px;">
<div class="col-1 form-label-search mb-2">高级检索</div>
<div class="col-md-10">
<div class="row">
<div class="col-md-2">
<select class="form-control form-control-sm" id="searchCol">
<option value="id" selected>ID</option>
<option value="orign_name">文件名</option>
<option value="pre_name">实际文件名</option>
<option value="upload_user">上传者UID</option>
<option value="upload_date">上传日期</option>
<option value="pic_info">图像尺寸</option>
<option value="parent_folder">所属目录ID</option>
<option value="policy_id">上传策略ID</option>
<option value="dir">目录路径</option>
</select>
</div>
<div class="col-md-2">
<input type="text" class="form-control form-control-sm" placeholder="检索表达式" id="searchValue">
</div>
<div class="col-md-1">
<button type="button" class="btn btn-primary btn-sm" id="applySearch">应用</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="card mb-3">
<div class="card-header">
<i class="fa fa-table"></i> 文件列表</div>
<div class="card-body">
<div class="table-responsive">
<div id="dataTable_wrapper" class="dataTables_wrapper container-fluid dt-bootstrap4"><div class="row"><div class="col-sm-12 col-md-6"><div class="dataTables_length" ><label>每页展示 <select id="dataTable_length" aria-controls="dataTable" class="form-control form-control-sm"><option value="10">10</option><option value="25">25</option><option value="50">50</option><option value="100">100</option></select></label></div></div><div class="col-sm-12 col-md-6"><div id="dataTable_filter" class="dataTables_filter"><label>搜索:<input type="search" class="form-control form-control-sm" placeholder="" id="searchFrom"></label></div></div></div><div class="row"><div class="col-sm-12">
<div class="table-responsive">
<table class="table table-bordered dataTable" id="dataTable" width="100%" cellspacing="0" role="grid" aria-describedby="dataTable_info" style="width: 100%;">
<thead>
<tr role="row" class="textCenter"><th><input type="checkbox" data-type="all"></th><th>文件名</th><th class="textCenter">大小</th><th class="textCenter">上传者</th><th class="textCenter">日期</th><th class="textCenter">操作</th></tr>
</thead>
<tfoot>
<tr><th rowspan="1" colspan="1" class="textCenter"><input type="checkbox" data-type="all"></th><th rowspan="1" colspan="1">文件名</th><th rowspan="1" colspan="1" class="textCenter">大小</th><th rowspan="1" colspan="1" class="textCenter">上传者</th><th rowspan="1" colspan="1" class="textCenter">日期</th><th rowspan="1" colspan="1" class="textCenter">操作</th></tr>
</tfoot>
<tbody>
<tr role="row" class="odd" id="fileList">
{volist name='list' id='file'}
<tr role="row" class="odd">
<td class="sorting_1 textCenter"><input type="checkbox" data-type="mark" data-path="{:rtrim($file.dir,'/')}/{$file.orign_name}" data-uid="{$file.upload_user}"></td>
<td>
{eq name=":isPreview($file.orign_name)" value="yes"}
<a href="/Admin/Preview/id/{$file.id}" class="noAColor" target="_blank">{$file.orign_name|htmlspecialchars=ENT_NOQUOTES}</a>
{else}
<a href="/Admin/Download/id/{$file.id}" class="noAColor" target="_blank">{$file.orign_name|htmlspecialchars=ENT_NOQUOTES}</a>
{/eq}
</td>
<td class="textCenter">{:countSize($file.size)}</td>
<td class="textCenter">{$originList[$key]["user"]["user_nick"]}</td>
<td class="textCenter">{$file.upload_date}</td>
<td class="textCenter"><button type="button" class="btn btn-secondary fix" data-toggle="tooltip" data-placement="top" title="删除" data-action="delete" data-id="{$file.id}"><i class="fa fa-trash" aria-hidden="true"></i></button>
<button type="button" class="btn btn-secondary fix" data-toggle="tooltip" data-placement="top" title="下载" data-action="download" data-id="{$file.id}"><i class="fa fa-download" aria-hidden="true"></i></button>
<button type="button" class="btn btn-secondary fix" data-toggle="tooltip" data-placement="top" title="详情" data-action="info" data-id="{$file.id}"><i class="fa fa-info-circle" aria-hidden="true"></i></button>
</td>
</tr>
{/volist}
</tbody>
</table>
</div>
<div class="col-md-5 mb-2 mt-2" style="display: none" id="del">
<button type="button" class="btn btn-danger" id="delAll"><i class="fa fa-trash" aria-hidden="true"></i> 删除选中文件</button>
</div>
</div></div><div class="row"><div class="col-sm-12 col-md-5"><div class="dataTables_info" id="dataTable_info" role="status" aria-live="polite">展示第 {$pageNow} 页,共 {$pageTotal} 页 {$dataTotal} 条数据</div></div><div class="col-sm-12 col-md-7">
<div class="dataTables_paginate paging_simple_numbers" id="dataTable_paginate">
{$list->render()}
</div></div></div></div>
</div>
</div>
</div>
</div>
</div>
<!-- Example DataTables Card-->
</div>
<!-- /.container-fluid-->
</div>
<div class="modal fade bd-example-modal-sm" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true" id="fileInfo">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">文件详情</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="row">
<div class="col-md-12"><strong>ID:</strong></div>
<div class="col-md-12 break" id="fileId">12</div>
</div>
<div class="row">
<div class="col-md-12"><strong>文件名:</strong></div>
<div class="col-md-12 break" id="fileName">5c06e532e7afdb4389e4ae846ea7876c_w - 副本 - 副本.jpg</div>
</div>
<div class="row">
<div class="col-md-12"><strong>源文件名:</strong></div>
<div class="col-md-12 break" id="fileOrigin">5c06e532e7afdb4389e4ae846ea7876c_w - 副本 - 副本.jpg</div>
</div>
<div class="row">
<div class="col-md-12"><strong>上传者UID:</strong></div>
<div class="col-md-12 break" id="fileUID">17</div>
</div>
<div class="row">
<div class="col-md-12"><strong>大小(字节):</strong></div>
<div class="col-md-12 break" id="fileSize">7481817</div>
</div>
<div class="row">
<div class="col-md-12"><strong>图像尺寸:</strong></div>
<div class="col-md-12 break" id="filePic">147,445</div>
</div>
<div class="row">
<div class="col-md-12"><strong>上传策略:</strong></div>
<div class="col-md-12 break" id="filePolicy">147,445</div>
</div>
<div class="row">
<div class="col-md-12"><strong>所属目录:</strong></div>
<div class="col-md-12 break" id="fileDir">147,445</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
</div>
</div>
</div>
</div>
<!-- /.content-wrapper-->
{/block}
{block name="js"}
<script src="/static/js/admin/files.js"></script>
<script type="text/javascript">
</script>
{/block}

@ -0,0 +1,131 @@
{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>
<br>
<div class="card mb-3">
<div class="card-header">
<i class="fa fa-table"></i> 用户组列表</div>
<div class="card-body">
<div class="table-responsive">
<div id="dataTable_wrapper" class="dataTables_wrapper container-fluid dt-bootstrap4"><div class="row"><div class="col-sm-12 col-md-6"><div class="dataTables_length" ><label>每页展示 <select id="dataTable_length" aria-controls="dataTable" class="form-control form-control-sm"><option value="10">10</option><option value="25">25</option><option value="50">50</option><option value="100">100</option></select></label></div></div></div><div class="row"><div class="col-sm-12">
<div class="table-responsive">
<table class="table table-bordered dataTable" id="dataTable" width="100%" cellspacing="0" role="grid" aria-describedby="dataTable_info" style="width: 100%;">
<thead>
<tr role="row" class="textCenter"><th>#</th><th>名称</th><th class="textCenter">上传策略</th><th class="textCenter">最大容量</th><th class="textCenter">下属用户数</th><th class="textCenter">操作</th></tr>
</thead>
<tfoot>
<tr><th rowspan="1" colspan="1" class="textCenter">#</th><th rowspan="1" colspan="1">名称</th><th rowspan="1" colspan="1" class="textCenter">上传策略</th><th rowspan="1" colspan="1" class="textCenter">最大容量</th><th rowspan="1" colspan="1" class="textCenter">下属用户数</th><th rowspan="1" colspan="1" class="textCenter">操作</th></tr>
</tfoot>
<tbody>
<tr role="row" class="odd" id="fileList">
{volist name='list' id='group'}
<tr role="row" class="odd">
<td class="sorting_1 textCenter">{$group.id}</td>
<td>
{$group.group_name}
</td>
<td class="textCenter">
{$originList[$key]["policy"]["policy_name"]}
</td>
<td class="textCenter">{:countSize($group["max_storage"])}</td>
<td class="textCenter">{$originList[$key]["user_num"]}</td>
<td class="textCenter"><button type="button" class="btn btn-secondary fix" data-toggle="tooltip" data-placement="top" title="删除" data-action="delete" data-id="{$group.id}" data-unable="{eq name="$originList[$key]['user_num']" value="0"}0{else}1{/eq}"><i class="fa fa-trash" aria-hidden="true"></i></button>
<button type="button" class="btn btn-secondary fix" data-toggle="tooltip" data-placement="top" title="编辑" data-action="edit" data-id="{$group.id}"><i class="fa fa-edit" aria-hidden="true"></i></button>
</td>
</tr>
{/volist}
</tbody>
</table>
</div>
<div class="col-md-5 mb-2 mt-2" style="display: none" id="del">
<button type="button" class="btn btn-danger" id="delAll"><i class="fa fa-trash" aria-hidden="true"></i> 删除选中文件</button>
</div>
</div></div><div class="row"><div class="col-sm-12 col-md-5"><div class="dataTables_info" id="dataTable_info" role="status" aria-live="polite">展示第 {$pageNow} 页,共 {$pageTotal} 页 {$dataTotal} 条数据</div></div><div class="col-sm-12 col-md-7">
<div class="dataTables_paginate paging_simple_numbers" id="dataTable_paginate">
{$list->render()}
</div></div></div></div>
</div>
</div>
</div>
</div>
</div>
<!-- Example DataTables Card-->
</div>
<!-- /.container-fluid-->
</div>
<div class="modal fade bd-example-modal-sm" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true" id="fileInfo">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">文件详情</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="row">
<div class="col-md-12"><strong>ID:</strong></div>
<div class="col-md-12 break" id="fileId">12</div>
</div>
<div class="row">
<div class="col-md-12"><strong>文件名:</strong></div>
<div class="col-md-12 break" id="fileName">5c06e532e7afdb4389e4ae846ea7876c_w - 副本 - 副本.jpg</div>
</div>
<div class="row">
<div class="col-md-12"><strong>源文件名:</strong></div>
<div class="col-md-12 break" id="fileOrigin">5c06e532e7afdb4389e4ae846ea7876c_w - 副本 - 副本.jpg</div>
</div>
<div class="row">
<div class="col-md-12"><strong>上传者UID:</strong></div>
<div class="col-md-12 break" id="fileUID">17</div>
</div>
<div class="row">
<div class="col-md-12"><strong>大小(字节):</strong></div>
<div class="col-md-12 break" id="fileSize">7481817</div>
</div>
<div class="row">
<div class="col-md-12"><strong>图像尺寸:</strong></div>
<div class="col-md-12 break" id="filePic">147,445</div>
</div>
<div class="row">
<div class="col-md-12"><strong>上传策略:</strong></div>
<div class="col-md-12 break" id="filePolicy">147,445</div>
</div>
<div class="row">
<div class="col-md-12"><strong>所属目录:</strong></div>
<div class="col-md-12 break" id="fileDir">147,445</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
</div>
</div>
</div>
</div>
<!-- /.content-wrapper-->
{/block}
{block name="js"}
<script src="/static/js/admin/group_list.js"></script>
<script type="text/javascript">
</script>
{/block}

@ -0,0 +1,206 @@
{extend name="header_admin" /}
{block name="title"}邮件收发- {$options.siteName}{/block}
{block name="content"}
<link href="/static/css/admin/summernote.css" rel="stylesheet">
<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>
<ul class="nav nav-pills mb-3" id="pills-tab" role="tablist">
<li class="nav-item">
<a class="nav-link active" id="pills-home-tab" data-toggle="pill" href="#basic" role="tab" aria-controls="pills-home" aria-selected="true">基本设置</a>
</li>
<li class="nav-item">
<a class="nav-link" id="pills-profile-tab" data-toggle="pill" href="#test" role="tab" aria-controls="pills-profile" aria-selected="false">发信测试</a>
</li>
<li class="nav-item">
<a class="nav-link" id="pills-contact-tab" data-toggle="pill" href="#template" role="tab" aria-controls="pills-contact" aria-selected="false">邮件模板</a>
</li>
</ul>
<div class="tab-content" >
<div class="tab-pane fade show active" id="basic" role="tabpanel" aria-labelledby="pills-home-tab">
<form id="basicOptionsForm">
<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="fromName" value="{$optionsForSet.fromName}" spellcheck="false"></div>
<div class="col-md-4 option-des"> 显示在邮件发件邮箱旁的发件人姓名</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="fromAdress" class="col-form-label col-form-label-sm">发件人邮箱</label>
</div>
<div class="col-md-4"> <input type="email" class="form-control" name="fromAdress" value="{$optionsForSet.fromAdress}" spellcheck="false"></div>
<div class="col-md-4 option-des"> 发件邮箱的地址</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="smtpHost" class="col-form-label col-form-label-sm">SMTP服务器</label>
</div>
<div class="col-md-4"> <input type="email" class="form-control" name="smtpHost" value="{$optionsForSet.smtpHost}" spellcheck="false"></div>
<div class="col-md-4 option-des"> 发信邮箱的SMTP服务器地址</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="smtpPort" class="col-form-label col-form-label-sm">端口</label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="smtpPort" value="{$optionsForSet.smtpPort}" spellcheck="false"></div>
<div class="col-md-4 option-des"> 发信邮箱SMTP服务器的端口</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="smtpPort" class="col-form-label col-form-label-sm">加密方式</label>
</div>
<div class="col-md-4">
<select class="form-control" name="encriptionType">
<option value="no" {eq name="$optionsForSet.encriptionType" value="no"}selected{/eq}>不启用</option>
<option value="tls" {eq name="$optionsForSet.encriptionType" value="tls"}selected{/eq}>TLS</option>
<option value="ssl" {eq name="$optionsForSet.encriptionType" value="ssl"}selected{/eq}>SSL</option>
</select>
</div>
<div class="col-md-4 option-des"> </div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="smtpUser" class="col-form-label col-form-label-sm">用户名</label>
</div>
<div class="col-md-4"> <input type="email" class="form-control" name="smtpUser" value="{$optionsForSet.smtpUser}" spellcheck="false"></div>
<div class="col-md-4 option-des"> 发信邮箱用户名,一般与邮箱相同</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="smtpPass" class="col-form-label col-form-label-sm">密码</label>
</div>
<div class="col-md-4"> <input type="password" class="form-control" name="smtpPass" value="{$optionsForSet.smtpPass}" spellcheck="false"></div>
<div class="col-md-4 option-des"> 发信邮箱密码</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="replyTo" class="col-form-label col-form-label-sm">回信邮箱</label>
</div>
<div class="col-md-4"> <input type="email" class="form-control" name="replyTo" value="{$optionsForSet.replyTo}" spellcheck="false"></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="button" class="btn btn-primary" id="saveMail">保存设置</button></div>
<div class="col-md-4 option-des"> </div>
<br><br><br>
</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">
<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="receiveMail" spellcheck="false"></div>
<div class="col-md-4 option-des"> 接受测试邮件的收件人邮箱</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="subject" spellcheck="false" value="这是一封测试邮件"></div>
<div class="col-md-4 option-des"> 测试邮件的主题</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-8"> <textarea class="form-control" name="content" spellcheck="false" id="content" > 这是一封由Cloudreve发出的测试邮件用于测试邮件设置是否正常工作。</textarea></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="sendMail">发送测试邮件</button></div>
<div class="col-md-4 option-des"> </div>
<br><br><br>
</div>
</form>
</div>
<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 ">
<label for="fromName" class="col-form-label col-form-label-sm">账户激活</label>
</div>
<div class="col-md-8"> <textarea class="form-control textEdit" name="mail_activation_template" spellcheck="false" > {$optionsForSet.mail_activation_template}</textarea>
</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-8"> <textarea class="form-control textEdit" name="mail_reset_pwd_template" spellcheck="false" > {$optionsForSet.mail_reset_pwd_template}</textarea>
</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="saveTemplate">保存设置</button></div>
<div class="col-md-4 option-des"> </div>
<br><br><br>
</div>
</form>
</div>
</div>
</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/setting.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$('#content').summernote({
lang:"zh-CN",
height: 150,
});
});
$(document).ready(function() {
$('.textEdit').summernote({
lang:"zh-CN",
height: 300,
});
});
</script>
{/block}

@ -0,0 +1,96 @@
{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>
<form id="mailTemplate">
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="maxEditSize" class="col-form-label col-form-label-sm">文本编辑大小限制</label>
</div>
<div class="col-md-4"> <input type="email" class="form-control" name="maxEditSize" value="{$optionsForSet.maxEditSize}" spellcheck="false"></div>
<div class="col-md-4 option-des"> 用户可在线编辑的文本类文件的最大尺寸。单位:字节</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="maxEditSize" class="col-form-label col-form-label-sm">允许游客下载</label>
</div>
<div class="col-md-4">
{eq name="$optionsForSet.allowdVisitorDownload" value="true"}
<input class="" type="radio" name="allowdVisitorDownload" id="inlineRadio1" value="true" checked>
<label class="" for="inlineRadio1" >允许</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="allowdVisitorDownload" id="inlineRadio2" value="false">
<label class="" for="inlineRadio2">拒绝</label>
{else}
<input class="" type="radio" name="allowdVisitorDownload" id="inlineRadio1" value="true">
<label class="" for="inlineRadio1" >允许</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="allowdVisitorDownload" id="inlineRadio2" value="false" checked>
<label class="" for="inlineRadio2">拒绝</label>
{/eq}
</div>
<div class="col-md-4 option-des"> 是否允许未登录用户下载被分享的文件</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="hot_share_num" class="col-form-label col-form-label-sm">热门分享展示数量</label>
</div>
<div class="col-md-4"> <input type="email" class="form-control" name="hot_share_num" value="{$optionsForSet.hot_share_num}" spellcheck="false"></div>
<div class="col-md-4 option-des"> 在用户个人主页展示的热门分享的个数</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">Gravatar服务器</label>
</div>
<div class="col-md-4"> <input type="email" class="form-control" name="gravatar_server" value="{$optionsForSet.gravatar_server}" spellcheck="false"></div>
<div class="col-md-4 option-des"> 用于展示用户头像的Gravatar服务器地址</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="saveTemplate">保存设置</button></div>
<div class="col-md-4 option-des"> </div>
<br><br><br>
</div>
</form>
</div>
</div>
<!-- Example DataTables Card-->
</div>
<!-- /.container-fluid-->
</div>
<!-- /.content-wrapper-->
{/block}
{block name="js"}
<script src="/static/js/admin/setting.js"></script>
<script type="text/javascript">
</script>
{/block}

@ -0,0 +1,168 @@
{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>
<br>
<div class="card mb-3">
<div class="card-header">
<i class="fa fa-tags"></i> 条件检索</div>
<div class="card-body">
<div class="row">
<div class="col-1 form-label-search mb-2">类型</div>
<div class="col-md-10">
<ul class="nav nav-pills" id="policyType">
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-policy="">全部</a>
</li>
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-policy="local">本地</a>
</li>
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-policy="qiniu">七牛</a>
</li>
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-policy="oss">OSS</a>
</li>
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-policy="upyun">又拍云</a>
</li>
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-policy="s3">S3</a>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="card mb-3">
<div class="card-header">
<i class="fa fa-table"></i> 上传策略列表</div>
<div class="card-body">
<div class="table-responsive">
<div id="dataTable_wrapper" class="dataTables_wrapper container-fluid dt-bootstrap4"><div class="row"><div class="col-sm-12 col-md-6"><div class="dataTables_length" ><label>每页展示 <select id="dataTable_length" aria-controls="dataTable" class="form-control form-control-sm"><option value="10">10</option><option value="25">25</option><option value="50">50</option><option value="100">100</option></select></label></div></div><div class="col-sm-12 col-md-6"><div id="dataTable_filter" class="dataTables_filter"><label>搜索:<input type="search" class="form-control form-control-sm" placeholder="" id="searchFrom"></label></div></div></div><div class="row"><div class="col-sm-12">
<div class="table-responsive">
<table class="table table-bordered dataTable" id="dataTable" width="100%" cellspacing="0" role="grid" aria-describedby="dataTable_info" style="width: 100%;">
<thead>
<tr role="row" class="textCenter"><th>#</th><th>名称</th><th class="textCenter">类型</th><th class="textCenter">下属文件数</th><th class="textCenter">数据量</th><th class="textCenter">操作</th></tr>
</thead>
<tfoot>
<tr><th rowspan="1" colspan="1" class="textCenter">#</th><th rowspan="1" colspan="1">名称</th><th rowspan="1" colspan="1" class="textCenter">类型</th><th rowspan="1" colspan="1" class="textCenter">下属文件数</th><th rowspan="1" colspan="1" class="textCenter">数据量</th><th rowspan="1" colspan="1" class="textCenter">操作</th></tr>
</tfoot>
<tbody>
<tr role="row" class="odd" id="fileList">
{volist name='list' id='policy'}
<tr role="row" class="odd">
<td class="sorting_1 textCenter">{$policy.id}</td>
<td>
{$policy.policy_name}
</td>
<td class="textCenter">
{switch name="policy.policy_type"}
{case value="local"}本地{/case}
{case value="qiniu"}七牛{/case}
{case value="oss"}OSS{/case}
{case value="upyun"}又拍云{/case}
{case value="s3"}Amazon S3{/case}
{default /}其他
{/switch}
</td>
<td class="textCenter">{$originList[$key]["file_num"]}</td>
<td class="textCenter">{:countSize($originList[$key]["file_size"])}</td>
<td class="textCenter"><button type="button" class="btn btn-secondary fix" data-toggle="tooltip" data-placement="top" title="删除" data-action="delete" data-id="{$policy.id}" data-unable="{eq name="$originList[$key]['file_num']" value="0"}0{else}1{/eq}"><i class="fa fa-trash" aria-hidden="true"></i></button>
<button type="button" class="btn btn-secondary fix" data-toggle="tooltip" data-placement="top" title="编辑" data-action="edit" data-id="{$policy.id}"><i class="fa fa-edit" aria-hidden="true"></i></button>
</td>
</tr>
{/volist}
</tbody>
</table>
</div>
<div class="col-md-5 mb-2 mt-2" style="display: none" id="del">
<button type="button" class="btn btn-danger" id="delAll"><i class="fa fa-trash" aria-hidden="true"></i> 删除选中文件</button>
</div>
</div></div><div class="row"><div class="col-sm-12 col-md-5"><div class="dataTables_info" id="dataTable_info" role="status" aria-live="polite">展示第 {$pageNow} 页,共 {$pageTotal} 页 {$dataTotal} 条数据</div></div><div class="col-sm-12 col-md-7">
<div class="dataTables_paginate paging_simple_numbers" id="dataTable_paginate">
{$list->render()}
</div></div></div></div>
</div>
</div>
</div>
</div>
</div>
<!-- Example DataTables Card-->
</div>
<!-- /.container-fluid-->
</div>
<div class="modal fade bd-example-modal-sm" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true" id="fileInfo">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">文件详情</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="row">
<div class="col-md-12"><strong>ID:</strong></div>
<div class="col-md-12 break" id="fileId">12</div>
</div>
<div class="row">
<div class="col-md-12"><strong>文件名:</strong></div>
<div class="col-md-12 break" id="fileName">5c06e532e7afdb4389e4ae846ea7876c_w - 副本 - 副本.jpg</div>
</div>
<div class="row">
<div class="col-md-12"><strong>源文件名:</strong></div>
<div class="col-md-12 break" id="fileOrigin">5c06e532e7afdb4389e4ae846ea7876c_w - 副本 - 副本.jpg</div>
</div>
<div class="row">
<div class="col-md-12"><strong>上传者UID:</strong></div>
<div class="col-md-12 break" id="fileUID">17</div>
</div>
<div class="row">
<div class="col-md-12"><strong>大小(字节):</strong></div>
<div class="col-md-12 break" id="fileSize">7481817</div>
</div>
<div class="row">
<div class="col-md-12"><strong>图像尺寸:</strong></div>
<div class="col-md-12 break" id="filePic">147,445</div>
</div>
<div class="row">
<div class="col-md-12"><strong>上传策略:</strong></div>
<div class="col-md-12 break" id="filePolicy">147,445</div>
</div>
<div class="row">
<div class="col-md-12"><strong>所属目录:</strong></div>
<div class="col-md-12 break" id="fileDir">147,445</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
</div>
</div>
</div>
</div>
<!-- /.content-wrapper-->
{/block}
{block name="js"}
<script src="/static/js/admin/policy.js"></script>
<script type="text/javascript">
</script>
{/block}

@ -0,0 +1,134 @@
{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>
<form id="basicOptionsForm">
<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">
{eq name="$optionsForSet.regStatus" value="0"}
<input class="" type="radio" name="regStatus" id="inlineRadio1" value="0"checked>
<label class="" for="inlineRadio1" ></label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="regStatus" id="inlineRadio2" value="1">
<label class="" for="inlineRadio2"></label>
{else}
<input class="" type="radio" name="regStatus" id="inlineRadio1" value="0">
<label class="" for="inlineRadio1" ></label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="regStatus" id="inlineRadio2" value="1" checked>
<label class="" for="inlineRadio2"></label>
{/eq}
</div>
<div class="col-md-4 option-des"> 是否允许新用户注册</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">
<select class="form-control" name="defaultGroup">
{volist name="groups" id="group"}
{eq name="$group.id" value="$optionsForSet.defaultGroup"}
<option value="{$group.id}" selected>{$group.group_name}</option>
{else}
<option value="{$group.id}">{$group.group_name}</option>
{/eq}
{/volist}
</select>
</div>
<div class="col-md-4 option-des"> 用户注册后默认属于的用户组</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 type="checkbox" id="inlineCheckbox3" name="email_active" value="1" {eq name="$optionsForSet.email_active" value="1" }checked{/eq}>
<label for="inlineCheckbox3">启用</label>
</div>
<div class="col-md-4 option-des"> 启用后,新用户注册需要点击邮件中的激活链接才能完成。请确认邮件发送设置是否正确,否则激活邮件无法送达</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 type="checkbox" id="login_captcha" name="login_captcha" value="1" {eq name="$optionsForSet.login_captcha" value="1" }checked{/eq}>
<label for="login_captcha">启用</label>
</div>
<div class="col-md-4 option-des"> 是否启用登录表单验证码</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 type="checkbox" id="reg_captcha" name="reg_captcha" value="1" {eq name="$optionsForSet.reg_captcha" value="1" }checked{/eq}>
<label for="reg_captcha">启用</label>
</div>
<div class="col-md-4 option-des"> 是否启用注册表单验证码</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 type="checkbox" id="forget_captcha" name="forget_captcha" value="1" {eq name="$optionsForSet.forget_captcha" value="1" }checked{/eq}>
<label for="forget_captcha">启用</label>
</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="button" class="btn btn-primary" id="saveReg">保存设置</button></div>
<div class="col-md-4 option-des"> </div>
<br><br><br>
</div>
</form>
</div>
</div>
<!-- Example DataTables Card-->
</div>
<!-- /.container-fluid-->
</div>
<!-- /.content-wrapper-->
{/block}
{block name="js"}
<script src="/static/js/admin/setting.js"></script>
<script type="text/javascript">
</script>
{/block}

@ -0,0 +1,110 @@
{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>
<br>
<div class="card mb-3">
<div class="card-header">
<i class="fa fa-tags"></i> 条件检索</div>
<div class="card-body">
<div class="row">
<div class="col-1 form-label-search mb-2">排序方式</div>
<div class="col-md-10">
<ul class="nav nav-pills" id="order">
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-method="id DESC">日期</a>
</li>
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-method="download_num DESC">下载次数</a>
</li>
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-method="view_num DESC">浏览次数</a>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="card mb-3">
<div class="card-header">
<i class="fa fa-table"></i> 分享列表</div>
<div class="card-body">
<div class="table-responsive">
<div id="dataTable_wrapper" class="dataTables_wrapper container-fluid dt-bootstrap4"><div class="row"><div class="col-sm-12 col-md-6"><div class="dataTables_length" ><label>每页展示 <select id="dataTable_length" aria-controls="dataTable" class="form-control form-control-sm"><option value="10">10</option><option value="25">25</option><option value="50">50</option><option value="100">100</option></select></label></div></div><div class="col-sm-12 col-md-6"><div id="dataTable_filter" class="dataTables_filter"><label>搜索:<input type="search" class="form-control form-control-sm" placeholder="" id="searchFrom"></label></div></div></div><div class="row"><div class="col-sm-12">
<div class="table-responsive">
<table class="table table-bordered dataTable" id="dataTable" width="100%" cellspacing="0" role="grid" aria-describedby="dataTable_info" style="width: 100%;">
<thead>
<tr role="row" class="textCenter"><th><input type="checkbox" data-type="all"></th><th>分享名称</th><th class="textCenter">分享者</th><th class="textCenter">类型</th><th class="textCenter">日期</th><th class="textCenter">浏览次数</th><th class="textCenter">下载次数</th><th class="textCenter">操作</th></tr>
</thead>
<tfoot>
<tr><th rowspan="1" colspan="1" class="textCenter"><input type="checkbox" data-type="all"></th><th rowspan="1" colspan="1" class="textCenter">分享名称</th><th rowspan="1" colspan="1" class="textCenter">分享者</th><th rowspan="1" colspan="1" class="textCenter">类型</th><th rowspan="1" colspan="1" class="textCenter">日期</th><th rowspan="1" colspan="1" class="textCenter">浏览次数</th><th rowspan="1" colspan="1" class="textCenter">下载次数</th><th rowspan="1" colspan="1" class="textCenter">操作</th></tr>
</tfoot>
<tbody>
<tr role="row" class="odd" id="fileList">
{volist name='list' id='share'}
<tr role="row" class="odd">
<td class="sorting_1 textCenter"><input type="checkbox" data-type="mark" data-id="{$share.id}"></td>
<td>
{eq name="$share.source_type" value="dir"}
<i class="fa fa-folder-open-o" aria-hidden="true"></i> <a href="/S/{$share.share_key}?pwd={$share.share_pwd}" class="noAColor" target="_blank">{:htmlspecialchars(getDirName($share.source_name),ENT_NOQUOTES)}</a>
{else}
<i class="fa fa-file" aria-hidden="true"></i> <a href="/S/{$share.share_key}?pwd={$share.share_pwd}" class="noAColor" target="_blank">{$share.origin_name|htmlspecialchars=ENT_NOQUOTES}</a>
{/eq}
</td>
<td class="textCenter">{$originList[$key]["user"]["user_nick"]}</td>
<td class="textCenter">
{eq name="share.type" value="public"}
<i class="fa fa-eye" aria-hidden="true"></i> 公开
{else/}
<i class="fa fa-lock" aria-hidden="true"></i> 私密
{/eq}
</td>
<td class="textCenter">{$share.share_time}</td>
<td class="textCenter">{$share.view_num}</td>
<td class="textCenter">{$share.download_num}</td>
<td class="textCenter"><button type="button" class="btn btn-secondary fix" data-toggle="tooltip" data-placement="top" title="删除" data-action="delete" data-id="{$share.id}"><i class="fa fa-trash" aria-hidden="true"></i></button> <button type="button" class="btn btn-secondary fix" data-toggle="tooltip" data-placement="top" title="变更分享类型" data-action="change" data-id="{$share.share_key}"><i class="fa fa-lock" aria-hidden="true"></i></button></td>
</tr>
{/volist}
</tbody>
</table>
</div>
<div class="col-md-5 mb-2 mt-2" style="display: none" id="del">
<button type="button" class="btn btn-danger" id="delAll"><i class="fa fa-trash" aria-hidden="true"></i> 删除选中文件</button>
</div>
</div></div><div class="row"><div class="col-sm-12 col-md-5"><div class="dataTables_info" id="dataTable_info" role="status" aria-live="polite">展示第 {$pageNow} 页,共 {$pageTotal} 页 {$dataTotal} 条数据</div></div><div class="col-sm-12 col-md-7">
<div class="dataTables_paginate paging_simple_numbers" id="dataTable_paginate">
{$list->render()}
</div></div></div></div>
</div>
</div>
</div>
</div>
</div>
<!-- Example DataTables Card-->
</div>
<!-- /.container-fluid-->
</div>
<!-- /.content-wrapper-->
{/block}
{block name="js"}
<script src="/static/js/admin/shares.js"></script>
<script type="text/javascript">
</script>
{/block}

@ -0,0 +1,51 @@
{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>
application/index/view/{:rtrim($path,"/")}/{$name}.html
<br> <br>
<div class="row">
<div class="col-md-9">
<input type="text" id="fileName" value="{$name}" style="display: none">
<textarea rows="15" class="form-control" spellcheck="false" style=" font-family: 'Courier New';">{:htmlspecialchars($content)}</textarea>
<br>
<button class="btn btn-primary" id="saveTheme">保存</button>
<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">
{volist name="list" id="file"}
<a class="nav-link" id="v-pills-home-tab" href="/Admin/Theme/name/{:str_replace(".html","",$file)}" role="tab" data-name="{:str_replace(".html","",$file)}">{$file}</a>
{/volist}
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Example DataTables Card-->
</div>
<!-- /.container-fluid-->
</div>
{/block}
{block name="js"}
<script src="/static/js/admin/config.js"></script>
<script type="text/javascript">
</script>
{/block}

@ -0,0 +1,298 @@
{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>用户 <button class="btn btn-secondary btn-sm" data-toggle="modal" data-target="#addUser"><li class="fa fa-plus"></li></button></h2>
<br>
<div class="card mb-3">
<div class="card-header">
<i class="fa fa-tags"></i> 条件检索</div>
<div class="card-body">
<div class="row">
<div class="col-1 form-label-search mb-2">排序方式</div>
<div class="col-md-10">
<ul class="nav nav-pills" id="order">
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-method="user_nick ASC">用户名</a>
</li>
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-method="id DESC">注册日期</a>
</li>
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-method="used_storage DESC">已用空间</a>
</li>
</ul>
</div>
</div>
<div class="row">
<div class="col-1 form-label-search mb-2">用户组</div>
<div class="col-md-10">
<ul class="nav nav-pills" id="groupS">
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-group="">全部</a>
</li>
{volist name="group" id="group"}
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-group="{$group.id}">{$group.group_name}</a>
</li>
{/volist}
</ul>
</div>
</div>
<div class="row">
<div class="col-1 form-label-search mb-2">用户状态</div>
<div class="col-md-10">
<ul class="nav nav-pills" id="status">
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-status="">全部</a>
</li>
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-status="1">正常</a>
</li>
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-status="2">封禁/未激活</a>
</li>
</ul>
</div>
</div>
<div class="row" style="margin-top: 5px;">
<div class="col-1 form-label-search mb-2">高级检索</div>
<div class="col-md-10">
<div class="row">
<div class="col-md-2">
<select class="form-control form-control-sm" id="searchColUser">
<option value="id">用户UID</option>
<option value="user_nick">用户昵称</option>
<option value="user_date">注册日期</option>
<option value="user_email">邮箱</option>
<option value="group_primary">初始用户组</option>
<option value="user_activation_key">邮箱激活密钥</option>
<option value="used_storage">已用空间</option>
<option value="delay_time">用户组过期日期</option>
<option value="avatar">头像标识</option>
<option value="profile">个人主页状态</option>
</select>
</div>
<div class="col-md-2">
<input type="text" class="form-control form-control-sm" placeholder="检索表达式" id="searchValueUser">
</div>
<div class="col-md-1">
<button type="button" class="btn btn-primary btn-sm" id="applySearch">应用</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="card mb-3">
<div class="card-header">
<i class="fa fa-table"></i> 用户列表 </div>
<div class="card-body">
<div class="table-responsive">
<div id="dataTable_wrapper" class="dataTables_wrapper container-fluid dt-bootstrap4"><div class="row"><div class="col-sm-12 col-md-6"><div class="dataTables_length" ><label>每页展示 <select id="dataTable_length" aria-controls="dataTable" class="form-control form-control-sm"><option value="10">10</option><option value="25">25</option><option value="50">50</option><option value="100">100</option></select></label></div></div><div class="col-sm-12 col-md-6"><div id="dataTable_filter" class="dataTables_filter"><label>搜索:<input type="search" class="form-control form-control-sm" placeholder="" id="searchFrom"></label></div></div></div><div class="row"><div class="col-sm-12">
<div class="table-responsive">
<table class="table table-bordered dataTable" id="dataTable" width="100%" cellspacing="0" role="grid" aria-describedby="dataTable_info" style="width: 100%;">
<thead>
<tr role="row" class="textCenter"><th><input type="checkbox" data-type="all"></th><th>UID</th><th>昵称</th><th class="textCenter">邮箱</th><th class="textCenter">用户组</th><th class="textCenter">空间用量</th><th class="textCenter">状态</th><th class="textCenter">操作</th></tr>
</thead>
<tfoot>
<tr><th rowspan="1" colspan="1" class="textCenter"><input type="checkbox" data-type="all"></th><th rowspan="1" colspan="1" class="textCenter">UID</th><th rowspan="1" colspan="1" class="textCenter">昵称</th><th rowspan="1" colspan="1" class="textCenter">邮箱</th><th rowspan="1" colspan="1" class="textCenter">用户组</th><th rowspan="1" colspan="1" class="textCenter">空间用量</th><th rowspan="1" colspan="1" class="textCenter">状态</th><th rowspan="1" colspan="1" class="textCenter">操作</th></tr>
</tfoot>
<tbody>
<tr role="row" class="odd" id="userList">
{volist name='list' id='user'}
<tr role="row" class="odd">
<td class="sorting_1 textCenter"><input type="checkbox" data-type="mark" data-id="{$user.id}"></td>
<td class="textCenter">{$user.id}</td>
<td class="textCenter">{$user.user_nick}</td>
<td class="textCenter">{$user.user_email}</td>
<td class="textCenter">{:$originList[$key]["group"]["group_name"]}</td>
<td class="textCenter">{:countSize($user.used_storage)}</td>
<td class="textCenter">
{eq name="user.user_status" value="0"}
<span class="order_success">正常</span>
{else/}
<span class="order_warning">封禁/未激活</span>
{/eq}
</td>
<td class="textCenter">
<button type="button" class="btn btn-secondary fix" data-toggle="tooltip" data-placement="top" title="删除" data-action="delete" data-id="{$user.id}" data-unable="{eq name="user.used_storage" value="0"}0{else/}1{/eq}"><i class="fa fa-trash" aria-hidden="true"></i></button>
<button type="button" class="btn btn-secondary fix" data-toggle="tooltip" data-placement="top" title="编辑" data-action="edit" data-id="{$user.id}"><i class="fa fa-id-card" aria-hidden="true"></i></button>
<button type="button" class="btn btn-secondary fix" data-toggle="tooltip" data-placement="top" title="封号/解封" data-action="ban" data-id="{$user.id}"><i class="fa fa-ban" aria-hidden="true"></i></button>
</td>
</tr>
{/volist}
</tbody>
</table>
</div>
<div class="col-md-5 mb-2 mt-2" style="display: none" id="del">
<button type="button" class="btn btn-danger" id="delAll"><i class="fa fa-trash" aria-hidden="true"></i> 删除选中用户</button>
</div>
</div></div><div class="row"><div class="col-sm-12 col-md-5"><div class="dataTables_info" id="dataTable_info" role="status" aria-live="polite">展示第 {$pageNow} 页,共 {$pageTotal} 页 {$dataTotal} 条数据</div></div><div class="col-sm-12 col-md-7">
<div class="dataTables_paginate paging_simple_numbers" id="dataTable_paginate">
{$list->render()}
</div></div></div></div>
</div>
</div>
</div>
</div>
</div>
<!-- Example DataTables Card-->
</div>
<!-- /.container-fluid-->
</div>
<div class="modal fade bd-example-modal-sm" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true" id="editUser">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">用户详情</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<form id="editUserForm">
<div class="form-group">
<label>
头像
</label>
<img src="" id="user_avatar">
</div>
<div class="form-group">
<label for="name">UID</label>
<input type="text" name="uid" id="uid" style="display: none;">
<input class="form-control" id="id" type="text" value="17" readonly>
</div>
<div class="form-group">
<label for="lovelyname">昵称</label>
<input type="text " class="form-control" id="user_nick" name="user_nick" required>
</div>
<div class="form-group">
<label for="InputPassword1">密码</label>
<input type="password" class="form-control" id="user_pass" name="user_pass" placeholder="如果不修改密码则留空" >
</div>
<div class="form-group">
<label for="InputEmail1">邮箱</label>
<input type="email" class="form-control" id="user_email" name="user_email" placeholder="Email" required>
</div>
<div class="form-group">
<label for="date">注册日期</label>
<input class="form-control" id="user_date" type="text" value="2017.12.31" readonly>
</div>
<div class="form-group">
<label for="space">已用空间</label>
<input class="form-control" id="used_storage" type="text" value="500M" readonly>
</div>
<div class="form-group">
<label for="openid">二步验证秘钥</label>
<input type="text " class="form-control" id="two_step" name="two_step" placeholder="取消二步验证请填写0" required="">
</div>
<div class="form-group">
<label for="inputState">用户状态</label>
<select class="form-control" id="user_status" name="user_status">
<option value="0">正常</option>
<option value="1">封禁/未激活</option>
</select>
</div>
<div class="form-group">
<label for="inputState">用户组</label>
<select id="user_group" class="form-control" name="user_group">
{foreach $groups as $g}
<option value="{$g.id}">{$g.group_name}</option>
{/foreach}
</select>
</div>
<div class="form-group">
<label for="inputState">个人主页状态</label>
<div class="radio">
<label>
<input type="radio" name="profile" id="profile1" value="1">
开启
</label>
<label>
<input type="radio" name="profile" id="profile0" value="0">
关闭
</label>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
<button type="submit" class="btn btn-primary" id="editUserSubmit">保存</button>
</div></form>
</div>
</div>
</div>
<div class="modal fade bd-example-modal-sm" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true" id="addUser">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">添加用户</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<form id="addUserForm">
<div class="form-group">
<label for="lovelyname">昵称</label>
<input type="text " class="form-control" id="user_nick" name="user_nick" required>
</div>
<div class="form-group">
<label for="InputPassword1">密码</label>
<input type="password" class="form-control" id="user_pass" name="user_pass" required>
</div>
<div class="form-group">
<label for="InputEmail1">邮箱</label>
<input type="email" class="form-control" id="user_email" name="user_email" placeholder="Email" required>
</div>
<div class="form-group">
<label for="inputState">用户状态</label>
<select class="form-control" name="user_status">
<option value="0">正常</option>
<option value="1">封禁/未激活</option>
</select>
</div>
<div class="form-group">
<label for="inputState">用户组</label>
<select class="form-control" name="user_group">
{foreach $groups as $g}
<option value="{$g.id}">{$g.group_name}</option>
{/foreach}
</select>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
<button type="submit" class="btn btn-primary" id="addUserSubmit">保存</button>
</div></form>
</div>
</div>
</div>
<!-- /.content-wrapper-->
{/block}
{block name="js"}
<script src="/static/js/admin/users.js"></script>
<script type="text/javascript">
</script>
{/block}

@ -0,0 +1,23 @@
{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">
<div class="container" align="center">
<header align="left">
<br>
<img src="/img/logo_s.png" style="width:192px;">
</header>
<div class="error_content" >
<div class="jumbotron animated bounce" style="padding-left:30px;">
<h1>支付成功</h1>
<br>
<p> 付款成功,您所购买的服务已开通。</p>
<p><a class="btn btn-primary btn-lg" href="/Home/Quota">查看详情</a></p>
</div>
</div>
</div>
</body>
{/block}

@ -0,0 +1,24 @@
{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">
<div class="container" align="center">
<header align="left">
<br>
<img src="/static/img/logo_s.png" style="width:192px;">
</header>
<div class="error_content" >
<div class="jumbotron animated bounce" style="padding-left:30px;">
<h1>发生错误</h1>
<br>
<p> {$msg}</p>
<p><a class="btn btn-primary btn-lg" onclick="history.go(-1);"><< 返回</a></p>
</div>
</div>
</div>
{$options.js_code}
</body>
{/block}

@ -0,0 +1,24 @@
{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">
<div class="container" align="center">
<header align="left">
<br>
<img src="/static/img/logo_s.png" style="width:192px;">
</header>
<div class="error_content" >
<div class="jumbotron animated bounce" style="padding-left:30px;">
<h1>发生错误</h1>
<br>
<p> {$msg}</p>
<p><a class="btn btn-primary btn-lg" onclick="history.go(-1);"><< 返回</a></p>
</div>
</div>
</div>
{$options.js_code}
</body>
{/block}

@ -0,0 +1,76 @@
{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}

@ -0,0 +1,47 @@
{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}

@ -0,0 +1,5 @@
下载已开始...
<a href="{$url}" download="" id="downloadA">手动下载</a>
<script type="text/javascript">
document.getElementById("downloadA").click();
</script>

@ -0,0 +1,36 @@
<!DOCTYPE html>
<html class="full-height">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="keywords" content="{$options.siteKeywords}"/>
<meta name="description" content="{$options.siteDes}"/>
<title>{$options.siteName} - {$options.siteTitle}</title>
<!-- Font Awesome -->
<link rel="stylesheet" href="/static/css/font-awesome.min.css">
<!-- Bootstrap core CSS -->
<link href="/static/css/bootstrap4/bootstrap.min.css" rel="stylesheet">
<!-- Material Design Bootstrap -->
<link href="/static/css/mdb.css" rel="stylesheet">
</head>
<body class="grey-skin intro-page creative-lp">
<!--Navigation & Intro-->
<header>
<!--Navbar-->
<nav class="navbar fixed-top navbar-dark ">
<div class="container">
<a class="navbar-brand" href="#">
<img src="static/img/logo_s.png" style=" width: 192px;">
</a>
</div>
</nav>
<!--/Navbar-->

@ -0,0 +1,194 @@
<!DOCTYPE html>
<html lang="zh_cn">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>{block name="title"}{/block}</title>
<!-- Bootstrap core CSS-->
<link href="/static/css/bootstrap4/bootstrap.min.css" rel="stylesheet">
<!-- Custom fonts for this template-->
<link href="/static/css/font-awesome.min.css" rel="stylesheet" type="text/css">
<!-- Page level plugin CSS-->
<link href="/static/css/datatables/dataTables.bootstrap4.css" rel="stylesheet">
<link href="/static/css/toastr.min.css" rel="stylesheet">
<!-- Custom styles for this template-->
<link href="/static/css/sb-admin.css" rel="stylesheet">
</head>
<body class="{$options.admin_color_body}" id="page-top">
<!-- Navigation-->
<nav class="{$options.admin_color_nav}" id="mainNav">
<a class="navbar-brand" href="index.html">Cloudreve</a>
<button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarResponsive">
<ul class="navbar-nav navbar-sidenav" id="exampleAccordion">
<li class="nav-item" data-toggle="tooltip" data-placement="right" title="面板首页">
<a class="nav-link" href="/Admin">
<i class="fa fa-fw fa-dashboard"></i>
<span class="nav-link-text">面板首页</span>
</a>
</li>
<li class="nav-item" data-toggle="tooltip" data-placement="right" title="设置">
<a class="nav-link nav-link-collapse collapsed" data-toggle="collapse" href="#collapseComponents" data-parent="#exampleAccordion">
<i class="fa fa-fw fa-wrench"></i>
<span class="nav-link-text">设置</span>
</a>
<ul class="sidenav-second-level collapse" id="collapseComponents">
<li>
<a href="/Admin/Setting">基础设置</a>
</li>
<li>
<a href="/Admin/SettingReg">注册访问</a>
</li>
<li>
<a href="/Admin/SettingMail">邮件发送</a>
</li>
<li>
<a href="/Admin/Config">配置文件</a>
</li>
<li>
<a href="/Admin/SettingOther">杂项</a>
</li>
</ul>
</li>
<li class="nav-item" data-toggle="tooltip" data-placement="right" title="模板">
<a class="nav-link" href="/Admin/Theme">
<i class="fa fa-fw fa-paint-brush"></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/Files">
<i class="fa fa-fw fa-folder"></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/Shares">
<i class="fa fa-fw fa-send"></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>
<span class="nav-link-text">用户</span>
</a>
</li>
<li class="nav-item" data-toggle="tooltip" data-placement="right" title="用户组">
<a class="nav-link nav-link-collapse collapsed" data-toggle="collapse" href="#group" data-parent="#group">
<i class="fa fa-fw fa-users"></i>
<span class="nav-link-text">用户组</span>
</a>
<ul class="sidenav-second-level collapse" id="group">
<li>
<a href="/Admin/GroupList">管理</a>
</li>
<li>
<a href="/Admin/GroupAdd">添加</a>
</li>
</ul>
</li>
<li class="nav-item" data-toggle="tooltip" data-placement="right" title="上传策略">
<a class="nav-link nav-link-collapse collapsed" data-toggle="collapse" href="#policy" data-parent="#policy">
<i class="fa fa-fw fa-upload"></i>
<span class="nav-link-text">上传策略</span>
</a>
<ul class="sidenav-second-level collapse" id="policy">
<li>
<a href="/Admin/PolicyList">管理</a>
</li>
<li>
<a href="/Admin/PolicyAdd">添加</a>
</li>
</ul>
</li>
<li class="nav-item" data-toggle="tooltip" data-placement="right" title="其他">
<a class="nav-link nav-link-collapse collapsed" data-toggle="collapse" href="#else" data-parent="#else">
<i class="fa fa-fw fa-ellipsis-h"></i>
<span class="nav-link-text">其他</span>
</a>
<ul class="sidenav-second-level collapse" id="else">
<li>
<a href="/Admin/Cron">定时任务</a>
</li>
<li>
<a href="/Admin/About">关于</a>
</li>
</ul>
</li>
</ul>
<ul class="navbar-nav sidenav-toggler">
<li class="nav-item">
<a class="nav-link text-center" id="sidenavToggler">
<i class="fa fa-fw fa-angle-left"></i>
</a>
</li>
</ul>
<ul class="navbar-nav ml-auto">
<li class="nav-item">
<a class="nav-link" href="javascript:void" id="toggleNavColor">
<i class="fa fa-fw fa-toggle-on" aria-hidden="true"></i>切换配色</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/">
<i class="fa fa-fw fa-home"></i>返回首页</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="modal" data-target="#exampleModal">
<i class="fa fa-fw fa-sign-out"></i>登出</a>
</li>
</ul>
</div>
</nav>
{block name="content"}{/block}
<footer class="sticky-footer">
<div class="container">
<div class="text-center">
<small>Copyright © Cloudreve {php}echo date("Y");{/php} </small>
</div>
</div>
</footer>
<!-- Scroll to Top Button-->
<a class="scroll-to-top rounded" href="#page-top">
<i class="fa fa-angle-up"></i>
</a>
<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">确认</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">点击“登出”按钮退出当前账户。</div>
<div class="modal-footer">
<button class="btn btn-secondary" type="button" data-dismiss="modal">取消</button>
<a class="btn btn-primary" href="/Member/LogOut">登出</a>
</div>
</div>
</div>
</div>
<script src="/static/js/jquery.min.js"></script>
<script src="/static/js/bootstrap4/bootstrap.bundle.min.js"></script>
<!-- Core plugin JavaScript-->
<script src="/static/js/chart.js/Chart.min.js"></script>
<!-- Custom scripts for all pages-->
<script src="/static/js/sb-admin.min.js"></script>
<script type="text/javascript" src="/static/js/toastr.min.js"></script>
{block name="js"}
{/block}
</div>
</body>
</html>

@ -0,0 +1,15 @@
<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>{block name="title"}{/block}</title>
<!-- third party -->
<link rel="stylesheet" href="/static/css/bootstrap.min.css" />
<link rel="stylesheet" href="/static/css/material.css" />
<link rel="stylesheet" href="/static/css/animate.css" />
<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/toastr.min.css" rel="stylesheet">
<!-- /Comment if you need to use raw source code -->
{block name="content"}{/block}

@ -0,0 +1,27 @@
<!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 -->
<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}

@ -0,0 +1,19 @@
<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>{block name="title"}{/block}</title>
<!-- third party -->
<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" />
<link rel="stylesheet" href="/static/css/animate.css" />
<script src="/static/js/material.js"></script>
<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/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 -->
{block name="content"}{/block}

@ -0,0 +1,82 @@
<!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,109 @@
<!doctype html>
<html lang="en" 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="/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>
<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">
<!-- /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="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>

@ -0,0 +1,48 @@
{include file="header" /}
<!--Video-->
<div class="intro-video view" id="home">
<img src="static/img/output.jpg">
<div class="hm-gradient">
<div class="full-bg-img flex-center">
<div class="container smooth-scroll">
<div class="row">
<div class="col-md-12 white-text text-center smooth-scroll">
<div class="fadeInDown" data-wow-delay="0.2s">
<h3 class="brand-name font-bold white-text mb-2">开始云上之旅</h3>
<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>
</div>
</div>
</div>
</div>
</div>
</div>
<!--/Video-->
</header>
<!--/.Content-->
</div>
</div>
<!-- JQuery -->
<script type="text/javascript" src="/static/js/jquery.min.js"></script>
<script>
</script>
</body>
</html>

@ -0,0 +1,59 @@
{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}

@ -0,0 +1,185 @@
{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}

@ -0,0 +1,122 @@
{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}

@ -0,0 +1,70 @@
{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}

@ -0,0 +1,265 @@
{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">&times;</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">&times;</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">&times;</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}

@ -0,0 +1,66 @@
{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}

@ -0,0 +1,140 @@
<nav class="navbar navbar-inverse" >
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<a class="navbar-brand" href="/">
</a>
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<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>
<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>
<li><a href="/Member/LogOut">退出登录</a></li>
</ul>
</li>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
<!-- Modal -->
<div class="modal fade" id="upload_modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" onclick = "closeUpload()" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
<span class="sr-only">Close</span>
</button>
<h4 class="modal-title" id="myModalLabel">上传文件</h4>
</div>
<div class="modal-body">
<div class="row" style="margin-top: 20px;">
<input type="hidden" id="domain" value="http://7xocov.com1.z0.glb.clouddn.com/">
<input type="hidden" id="uptoken_url" value="uptoken">
<div class="up_button col-md-4">
<div id="container">
<button class="btn btn-raised btn-info btn-lg upload_button" id="pickfiles" >
<i class="glyphicon glyphicon-plus"></i>
<span id="up_text"></span>
</button>
</div>
</div>
<div style="display:none" id="success" class="indo col-md-8">
<div class="alert alert-success">
队列全部文件处理完毕
</div>
</div>
<div class="col-md-12 " align="center">
<div class="info_box" id="info_box">
<br>
<div class="drag_info">
<span class="info_icon"><i class="glyphicon glyphicon-inbox"></i></span>
<div class="info_text">拖动文件至此开始上传</div>
</div>
</div>
<div class="upload_box" style="display:none;" id="upload_box">
<table class="table table-striped table-hover text-left" style="display:none;">
<thead>
<tr>
<th class="col-md-4">文件名</th>
<th class="col-md-2">大小</th>
<th class="col-md-6">进度</th>
</tr>
</thead>
<tbody id="fsUploadProgress">
</tbody>
</table>
</div>
</div>
<div class="container" style="display: none;">
<div class="body">
</div>
</div>
</div>
<div class="modal-footer">
</div>
</div>
</div>
</div>
</div>
<div class="col-md-2 s" id="side">
<div class="list-group" id="b">
<a href="/Home" class="list-group-item">
<i class="fa fa-file" aria-hidden="true"></i>&nbsp;&nbsp;&nbsp; 我的文件
</a>
<a href="/Share/My" class="list-group-item"> <i class="fa fa-share-alt" aria-hidden="true"></i>&nbsp;&nbsp;&nbsp; 我的分享
</a>
<a href="/Explore/Search" class="list-group-item">
<i class="fa fa-search" aria-hidden="true"></i>&nbsp;&nbsp;&nbsp; 搜索分享
</a>
<a href="/Home/Album" class="list-group-item">
<i class="fa fa-picture-o" aria-hidden="true"></i>&nbsp;&nbsp;&nbsp; 图片集
</a>
</div>
<div clss="usage" style=" visibility: visible;
position: absolute;
width: 100%;
height: 100px;
top: auto;
bottom: 0px;
background-color: #f9f9f9;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>

@ -0,0 +1,42 @@
<div class="navbar-header">
<div >
<a class="navbar-brand" href="/">
</a>
</div>
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<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>
<ul class="dropdown-menu">
<li><a href="/Home">我的文件</a></li>
<li><a href="/Profile/{$userData.id}">个人主页</a></li>
<li><a href="/Member/Setting">设置</a></li>
<li role="separator" class="divider"></li>
<li><a href="/Member/LogOut">退出登录</a></li>
</ul>
</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>
</li>
{/eq}
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</div>
</nav>

@ -0,0 +1,115 @@
{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}

@ -0,0 +1,83 @@
<!doctype html>
<html lang="en" 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>&nbsp;&nbsp;&nbsp; 我的文件
</a>
<a href="/Share" class="list-group-item"> <i class="fa fa-share-alt" aria-hidden="true"></i>&nbsp;&nbsp;&nbsp; 我的分享
</a>
<a href="#" class="list-group-item"><i class="fa fa-database" aria-hidden="true"></i>&nbsp;&nbsp;&nbsp; 容量配额
</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>

@ -0,0 +1,130 @@
{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">
shareInfo={
shareDate : "{$shareData.share_time}",
ownerUid:"{$userInfo.id}",
ownerNick:"{$userInfo.user_nick}",
downloadNum:"{$shareData.download_num}",
ViewNum:"{$shareData.view_num}",
shareId:"{$shareData.share_key}",
dirName:"{$dirData.folder_name}",
groupName:"{$groupData.group_name}",
color:"{$groupData.color}",
{eq name="$loginStatus" value="1"}
allowPreview:true,
{else/}
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}

@ -0,0 +1,98 @@
{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">&times;</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">&times;</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}

@ -0,0 +1,53 @@
{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}

@ -0,0 +1,154 @@
{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}&nbsp;&nbsp;
</div>
<div class="file_info"><span id="size"></span>&nbsp;&nbsp;<span><i class="fa fa-cloud-download" aria-hidden="true"></i> <span id="down_num"></span></span>&nbsp;&nbsp;<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}

@ -0,0 +1,27 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
use think\Route;
Route::rule([
'Upload/mkblk/:chunkSize'=>'index/Upload/chunk',
'Upload/mkfile/:fileSize/key/:keyValue/fname/:fname/path/:path'=>'index/Upload/mkFile',
's/:key'=>'index/Share/index',
'Share/Download/:key'=>'index/Share/Download',
'Share/Preview/:key'=>'index/Share/Preview',
'Share/List/:key'=>'index/Share/List',
'Login'=>'index/Member/LoginForm',
'Member/emailActivate/:key'=>'index/Member/emailActivate',
'Member/resetPwd/:key'=>'index/Member/resetPwd',
'Callback/Payment/Jinshajiang' => 'index/Callback/Jinshajiang',
'Explore/S/:key' => 'index/Explore/S',
'Member/Avatar/:uid/:size' => ['Member/Avatar',[],['uid'=>'\d+']],
'Profile/:uid' => ['Profile/index',[],['uid'=>'\d+']],
'Callback/Payment/Jinshajiang' => 'index/Callback/Jinshajiang',
]);

@ -0,0 +1,28 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// 应用行为扩展定义文件
return [
// 应用初始化
'app_init' => [],
// 应用开始
'app_begin' => [],
// 模块初始化
'module_init' => [],
// 操作开始执行
'action_begin' => [],
// 视图内容过滤
'view_filter' => [],
// 日志写入
'log_write' => [],
// 应用结束
'app_end' => [],
];

@ -0,0 +1 @@
{"type":"","version":"1.0 Beta","version_id":1}

@ -0,0 +1,40 @@
{
"name": "HFO4/Cloudreve",
"description": "A program help you build your own cloud in minutes.",
"keywords": ["php", "cloud", "ThinkPHP", "file-sharing"],
"homepage": "https://cloudreve.org",
"type": "project",
"license": "GPL-3.0",
"authors": [
{
"name": "Aaron",
"email": "abslant@foxmail.com",
"homepage": "https://aoaoao.me",
"role": "Developer"
},
{
"name": "Qnner",
"email": "admin@qnner.com",
"homepage": "http://me.qnner.com",
"role": "Developer"
},
{
"name": "dune",
"email": "rainaysann@gmail.com",
"homepage": "https://github.com/rainays",
"role": "Developer"
}
],
"require": {
"php": ">=5.6.0",
"ext-curl":"*",
"ext-fileinfo":"*",
"ext-gd":"*",
"topthink/think-captcha":"1.*",
"phpgangsta/googleauthenticator": "dev-master",
"endroid/qrcode": "1.*@dev",
"aliyuncs/oss-sdk-php": "~2.0",
"sabre/dav":"~3.2.0",
"upyun/sdk": "^3.3"
}
}

@ -0,0 +1,39 @@
<?php
/**
* PHPMailer Exception class.
* PHP Version 5.5.
*
* @see https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
*
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
* @author Brent R. Matzelle (original founder)
* @copyright 2012 - 2017 Marcus Bointon
* @copyright 2010 - 2012 Jim Jagielski
* @copyright 2004 - 2009 Andy Prevost
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
* @note This program is distributed in the hope that it will be useful - WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*/
namespace PHPMailer\PHPMailer;
/**
* PHPMailer exception handler.
*
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
*/
class Exception extends \Exception
{
/**
* Prettify error message output.
*
* @return string
*/
public function errorMessage()
{
return '<strong>' . htmlspecialchars($this->getMessage()) . "</strong><br />\n";
}
}

@ -0,0 +1,504 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

@ -0,0 +1,138 @@
<?php
/**
* PHPMailer - PHP email creation and transport class.
* PHP Version 5.5.
*
* @see https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
*
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
* @author Brent R. Matzelle (original founder)
* @copyright 2012 - 2015 Marcus Bointon
* @copyright 2010 - 2012 Jim Jagielski
* @copyright 2004 - 2009 Andy Prevost
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
* @note This program is distributed in the hope that it will be useful - WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*/
namespace PHPMailer\PHPMailer;
use League\OAuth2\Client\Grant\RefreshToken;
use League\OAuth2\Client\Provider\AbstractProvider;
use League\OAuth2\Client\Token\AccessToken;
/**
* OAuth - OAuth2 authentication wrapper class.
* Uses the oauth2-client package from the League of Extraordinary Packages.
*
* @see http://oauth2-client.thephpleague.com
*
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
*/
class OAuth
{
/**
* An instance of the League OAuth Client Provider.
*
* @var AbstractProvider
*/
protected $provider = null;
/**
* The current OAuth access token.
*
* @var AccessToken
*/
protected $oauthToken = null;
/**
* The user's email address, usually used as the login ID
* and also the from address when sending email.
*
* @var string
*/
protected $oauthUserEmail = '';
/**
* The client secret, generated in the app definition of the service you're connecting to.
*
* @var string
*/
protected $oauthClientSecret = '';
/**
* The client ID, generated in the app definition of the service you're connecting to.
*
* @var string
*/
protected $oauthClientId = '';
/**
* The refresh token, used to obtain new AccessTokens.
*
* @var string
*/
protected $oauthRefreshToken = '';
/**
* OAuth constructor.
*
* @param array $options Associative array containing
* `provider`, `userName`, `clientSecret`, `clientId` and `refreshToken` elements
*/
public function __construct($options)
{
$this->provider = $options['provider'];
$this->oauthUserEmail = $options['userName'];
$this->oauthClientSecret = $options['clientSecret'];
$this->oauthClientId = $options['clientId'];
$this->oauthRefreshToken = $options['refreshToken'];
}
/**
* Get a new RefreshToken.
*
* @return RefreshToken
*/
protected function getGrant()
{
return new RefreshToken();
}
/**
* Get a new AccessToken.
*
* @return AccessToken
*/
protected function getToken()
{
return $this->provider->getAccessToken(
$this->getGrant(),
['refresh_token' => $this->oauthRefreshToken]
);
}
/**
* Generate a base64-encoded OAuth token.
*
* @return string
*/
public function getOauth64()
{
// Get a new token if it's not available or has expired
if (null === $this->oauthToken or $this->oauthToken->hasExpired()) {
$this->oauthToken = $this->getToken();
}
return base64_encode(
'user=' .
$this->oauthUserEmail .
"\001auth=Bearer " .
$this->oauthToken .
"\001\001"
);
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,49 @@
<?php
/**
* PHPMailer SPL autoloader.
* PHP Version 5
* @package PHPMailer
* @link https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
* @author Brent R. Matzelle (original founder)
* @copyright 2012 - 2014 Marcus Bointon
* @copyright 2010 - 2012 Jim Jagielski
* @copyright 2004 - 2009 Andy Prevost
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
* @note This program is distributed in the hope that it will be useful - WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*/
/**
* PHPMailer SPL autoloader.
* @param string $classname The name of the class to load
*/
function PHPMailerAutoload($classname)
{
//Can't use __DIR__ as it's only in PHP 5.3+
$filename = dirname(__FILE__).DIRECTORY_SEPARATOR.'class.'.strtolower($classname).'.php';
if (is_readable($filename)) {
require $filename;
}
}
if (version_compare(PHP_VERSION, '5.1.2', '>=')) {
//SPL autoloading was introduced in PHP 5.1.2
if (version_compare(PHP_VERSION, '5.3.0', '>=')) {
spl_autoload_register('PHPMailerAutoload', true, true);
} else {
spl_autoload_register('PHPMailerAutoload');
}
} else {
/**
* Fall back to traditional autoload for old PHP versions
* @param string $classname The name of the class to load
*/
function __autoload($classname)
{
PHPMailerAutoload($classname);
}
}

@ -0,0 +1,197 @@
<?php
/**
* PHPMailer - PHP email creation and transport class.
* PHP Version 5.4
* @package PHPMailer
* @link https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
* @author Brent R. Matzelle (original founder)
* @copyright 2012 - 2014 Marcus Bointon
* @copyright 2010 - 2012 Jim Jagielski
* @copyright 2004 - 2009 Andy Prevost
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
* @note This program is distributed in the hope that it will be useful - WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*/
/**
* PHPMailerOAuth - PHPMailer subclass adding OAuth support.
* @package PHPMailer
* @author @sherryl4george
* @author Marcus Bointon (@Synchro) <phpmailer@synchromedia.co.uk>
*/
class PHPMailerOAuth extends PHPMailer
{
/**
* The OAuth user's email address
* @var string
*/
public $oauthUserEmail = '';
/**
* The OAuth refresh token
* @var string
*/
public $oauthRefreshToken = '';
/**
* The OAuth client ID
* @var string
*/
public $oauthClientId = '';
/**
* The OAuth client secret
* @var string
*/
public $oauthClientSecret = '';
/**
* An instance of the PHPMailerOAuthGoogle class.
* @var PHPMailerOAuthGoogle
* @access protected
*/
protected $oauth = null;
/**
* Get a PHPMailerOAuthGoogle instance to use.
* @return PHPMailerOAuthGoogle
*/
public function getOAUTHInstance()
{
if (!is_object($this->oauth)) {
$this->oauth = new PHPMailerOAuthGoogle(
$this->oauthUserEmail,
$this->oauthClientSecret,
$this->oauthClientId,
$this->oauthRefreshToken
);
}
return $this->oauth;
}
/**
* Initiate a connection to an SMTP server.
* Overrides the original smtpConnect method to add support for OAuth.
* @param array $options An array of options compatible with stream_context_create()
* @uses SMTP
* @access public
* @return bool
* @throws phpmailerException
*/
public function smtpConnect($options = array())
{
if (is_null($this->smtp)) {
$this->smtp = $this->getSMTPInstance();
}
if (is_null($this->oauth)) {
$this->oauth = $this->getOAUTHInstance();
}
// Already connected?
if ($this->smtp->connected()) {
return true;
}
$this->smtp->setTimeout($this->Timeout);
$this->smtp->setDebugLevel($this->SMTPDebug);
$this->smtp->setDebugOutput($this->Debugoutput);
$this->smtp->setVerp($this->do_verp);
$hosts = explode(';', $this->Host);
$lastexception = null;
foreach ($hosts as $hostentry) {
$hostinfo = array();
if (!preg_match('/^((ssl|tls):\/\/)*([a-zA-Z0-9\.-]*):?([0-9]*)$/', trim($hostentry), $hostinfo)) {
// Not a valid host entry
continue;
}
// $hostinfo[2]: optional ssl or tls prefix
// $hostinfo[3]: the hostname
// $hostinfo[4]: optional port number
// The host string prefix can temporarily override the current setting for SMTPSecure
// If it's not specified, the default value is used
$prefix = '';
$secure = $this->SMTPSecure;
$tls = ($this->SMTPSecure == 'tls');
if ('ssl' == $hostinfo[2] or ('' == $hostinfo[2] and 'ssl' == $this->SMTPSecure)) {
$prefix = 'ssl://';
$tls = false; // Can't have SSL and TLS at the same time
$secure = 'ssl';
} elseif ($hostinfo[2] == 'tls') {
$tls = true;
// tls doesn't use a prefix
$secure = 'tls';
}
//Do we need the OpenSSL extension?
$sslext = defined('OPENSSL_ALGO_SHA1');
if ('tls' === $secure or 'ssl' === $secure) {
//Check for an OpenSSL constant rather than using extension_loaded, which is sometimes disabled
if (!$sslext) {
throw new phpmailerException($this->lang('extension_missing').'openssl', self::STOP_CRITICAL);
}
}
$host = $hostinfo[3];
$port = $this->Port;
$tport = (integer)$hostinfo[4];
if ($tport > 0 and $tport < 65536) {
$port = $tport;
}
if ($this->smtp->connect($prefix . $host, $port, $this->Timeout, $options)) {
try {
if ($this->Helo) {
$hello = $this->Helo;
} else {
$hello = $this->serverHostname();
}
$this->smtp->hello($hello);
//Automatically enable TLS encryption if:
// * it's not disabled
// * we have openssl extension
// * we are not already using SSL
// * the server offers STARTTLS
if ($this->SMTPAutoTLS and $sslext and $secure != 'ssl' and $this->smtp->getServerExt('STARTTLS')) {
$tls = true;
}
if ($tls) {
if (!$this->smtp->startTLS()) {
throw new phpmailerException($this->lang('connect_host'));
}
// We must resend HELO after tls negotiation
$this->smtp->hello($hello);
}
if ($this->SMTPAuth) {
if (!$this->smtp->authenticate(
$this->Username,
$this->Password,
$this->AuthType,
$this->Realm,
$this->Workstation,
$this->oauth
)
) {
throw new phpmailerException($this->lang('authenticate'));
}
}
return true;
} catch (phpmailerException $exc) {
$lastexception = $exc;
$this->edebug($exc->getMessage());
// We must have connected, but then failed TLS or Auth, so close connection nicely
$this->smtp->quit();
}
}
}
// If we get here, all connection attempts have failed, so close connection hard
$this->smtp->close();
// As we've caught all exceptions, just report whatever the last one was
if ($this->exceptions and !is_null($lastexception)) {
throw $lastexception;
}
return false;
}
}

@ -0,0 +1,419 @@
<?php
/**
* PHPMailer POP-Before-SMTP Authentication Class.
* PHP Version 5.5.
*
* @see https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
*
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
* @author Brent R. Matzelle (original founder)
* @copyright 2012 - 2017 Marcus Bointon
* @copyright 2010 - 2012 Jim Jagielski
* @copyright 2004 - 2009 Andy Prevost
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
* @note This program is distributed in the hope that it will be useful - WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*/
namespace PHPMailer\PHPMailer;
/**
* PHPMailer POP-Before-SMTP Authentication Class.
* Specifically for PHPMailer to use for RFC1939 POP-before-SMTP authentication.
* 1) This class does not support APOP authentication.
* 2) Opening and closing lots of POP3 connections can be quite slow. If you need
* to send a batch of emails then just perform the authentication once at the start,
* and then loop through your mail sending script. Providing this process doesn't
* take longer than the verification period lasts on your POP3 server, you should be fine.
* 3) This is really ancient technology; you should only need to use it to talk to very old systems.
* 4) This POP3 class is deliberately lightweight and incomplete, and implements just
* enough to do authentication.
* If you want a more complete class there are other POP3 classes for PHP available.
*
* @author Richard Davey (original author) <rich@corephp.co.uk>
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
*/
class POP3
{
/**
* The POP3 PHPMailer Version number.
*
* @var string
*/
const VERSION = '6.0.1';
/**
* Default POP3 port number.
*
* @var int
*/
const DEFAULT_PORT = 110;
/**
* Default timeout in seconds.
*
* @var int
*/
const DEFAULT_TIMEOUT = 30;
/**
* Debug display level.
* Options: 0 = no, 1+ = yes.
*
* @var int
*/
public $do_debug = 0;
/**
* POP3 mail server hostname.
*
* @var string
*/
public $host;
/**
* POP3 port number.
*
* @var int
*/
public $port;
/**
* POP3 Timeout Value in seconds.
*
* @var int
*/
public $tval;
/**
* POP3 username.
*
* @var string
*/
public $username;
/**
* POP3 password.
*
* @var string
*/
public $password;
/**
* Resource handle for the POP3 connection socket.
*
* @var resource
*/
protected $pop_conn;
/**
* Are we connected?
*
* @var bool
*/
protected $connected = false;
/**
* Error container.
*
* @var array
*/
protected $errors = [];
/**
* Line break constant.
*/
const LE = "\r\n";
/**
* Simple static wrapper for all-in-one POP before SMTP.
*
* @param string $host The hostname to connect to
* @param int|bool $port The port number to connect to
* @param int|bool $timeout The timeout value
* @param string $username
* @param string $password
* @param int $debug_level
*
* @return bool
*/
public static function popBeforeSmtp(
$host,
$port = false,
$timeout = false,
$username = '',
$password = '',
$debug_level = 0
) {
$pop = new self();
return $pop->authorise($host, $port, $timeout, $username, $password, $debug_level);
}
/**
* Authenticate with a POP3 server.
* A connect, login, disconnect sequence
* appropriate for POP-before SMTP authorisation.
*
* @param string $host The hostname to connect to
* @param int|bool $port The port number to connect to
* @param int|bool $timeout The timeout value
* @param string $username
* @param string $password
* @param int $debug_level
*
* @return bool
*/
public function authorise($host, $port = false, $timeout = false, $username = '', $password = '', $debug_level = 0)
{
$this->host = $host;
// If no port value provided, use default
if (false === $port) {
$this->port = static::DEFAULT_PORT;
} else {
$this->port = (int) $port;
}
// If no timeout value provided, use default
if (false === $timeout) {
$this->tval = static::DEFAULT_TIMEOUT;
} else {
$this->tval = (int) $timeout;
}
$this->do_debug = $debug_level;
$this->username = $username;
$this->password = $password;
// Reset the error log
$this->errors = [];
// connect
$result = $this->connect($this->host, $this->port, $this->tval);
if ($result) {
$login_result = $this->login($this->username, $this->password);
if ($login_result) {
$this->disconnect();
return true;
}
}
// We need to disconnect regardless of whether the login succeeded
$this->disconnect();
return false;
}
/**
* Connect to a POP3 server.
*
* @param string $host
* @param int|bool $port
* @param int $tval
*
* @return bool
*/
public function connect($host, $port = false, $tval = 30)
{
// Are we already connected?
if ($this->connected) {
return true;
}
//On Windows this will raise a PHP Warning error if the hostname doesn't exist.
//Rather than suppress it with @fsockopen, capture it cleanly instead
set_error_handler([$this, 'catchWarning']);
if (false === $port) {
$port = static::DEFAULT_PORT;
}
// connect to the POP3 server
$this->pop_conn = fsockopen(
$host, // POP3 Host
$port, // Port #
$errno, // Error Number
$errstr, // Error Message
$tval
); // Timeout (seconds)
// Restore the error handler
restore_error_handler();
// Did we connect?
if (false === $this->pop_conn) {
// It would appear not...
$this->setError(
"Failed to connect to server $host on port $port. errno: $errno; errstr: $errstr"
);
return false;
}
// Increase the stream time-out
stream_set_timeout($this->pop_conn, $tval, 0);
// Get the POP3 server response
$pop3_response = $this->getResponse();
// Check for the +OK
if ($this->checkResponse($pop3_response)) {
// The connection is established and the POP3 server is talking
$this->connected = true;
return true;
}
return false;
}
/**
* Log in to the POP3 server.
* Does not support APOP (RFC 2828, 4949).
*
* @param string $username
* @param string $password
*
* @return bool
*/
public function login($username = '', $password = '')
{
if (!$this->connected) {
$this->setError('Not connected to POP3 server');
}
if (empty($username)) {
$username = $this->username;
}
if (empty($password)) {
$password = $this->password;
}
// Send the Username
$this->sendString("USER $username" . static::LE);
$pop3_response = $this->getResponse();
if ($this->checkResponse($pop3_response)) {
// Send the Password
$this->sendString("PASS $password" . static::LE);
$pop3_response = $this->getResponse();
if ($this->checkResponse($pop3_response)) {
return true;
}
}
return false;
}
/**
* Disconnect from the POP3 server.
*/
public function disconnect()
{
$this->sendString('QUIT');
//The QUIT command may cause the daemon to exit, which will kill our connection
//So ignore errors here
try {
@fclose($this->pop_conn);
} catch (Exception $e) {
//Do nothing
}
}
/**
* Get a response from the POP3 server.
*
* @param int $size The maximum number of bytes to retrieve
*
* @return string
*/
protected function getResponse($size = 128)
{
$response = fgets($this->pop_conn, $size);
if ($this->do_debug >= 1) {
echo 'Server -> Client: ', $response;
}
return $response;
}
/**
* Send raw data to the POP3 server.
*
* @param string $string
*
* @return int
*/
protected function sendString($string)
{
if ($this->pop_conn) {
if ($this->do_debug >= 2) { //Show client messages when debug >= 2
echo 'Client -> Server: ', $string;
}
return fwrite($this->pop_conn, $string, strlen($string));
}
return 0;
}
/**
* Checks the POP3 server response.
* Looks for for +OK or -ERR.
*
* @param string $string
*
* @return bool
*/
protected function checkResponse($string)
{
if (substr($string, 0, 3) !== '+OK') {
$this->setError("Server reported an error: $string");
return false;
}
return true;
}
/**
* Add an error to the internal error store.
* Also display debug output if it's enabled.
*
* @param string $error
*/
protected function setError($error)
{
$this->errors[] = $error;
if ($this->do_debug >= 1) {
echo '<pre>';
foreach ($this->errors as $error) {
print_r($error);
}
echo '</pre>';
}
}
/**
* Get an array of error messages, if any.
*
* @return array
*/
public function getErrors()
{
return $this->errors;
}
/**
* POP3 connection error handler.
*
* @param int $errno
* @param string $errstr
* @param string $errfile
* @param int $errline
*/
protected function catchWarning($errno, $errstr, $errfile, $errline)
{
$this->setError(
'Connecting to the POP3 server raised a PHP warning:' .
"errno: $errno errstr: $errstr; errfile: $errfile; errline: $errline"
);
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,163 @@
<?php
namespace Qiniu;
use Qiniu;
use Qiniu\Zone;
final class Auth
{
private $accessKey;
private $secretKey;
public function __construct($accessKey, $secretKey)
{
$this->accessKey = $accessKey;
$this->secretKey = $secretKey;
}
public function getAccessKey()
{
return $this->accessKey;
}
public function sign($data)
{
$hmac = hash_hmac('sha1', $data, $this->secretKey, true);
return $this->accessKey . ':' . \Qiniu\base64_urlSafeEncode($hmac);
}
public function signWithData($data)
{
$data = \Qiniu\base64_urlSafeEncode($data);
return $this->sign($data) . ':' . $data;
}
public function signRequest($urlString, $body, $contentType = null)
{
$url = parse_url($urlString);
$data = '';
if (array_key_exists('path', $url)) {
$data = $url['path'];
}
if (array_key_exists('query', $url)) {
$data .= '?' . $url['query'];
}
$data .= "\n";
if ($body !== null && $contentType === 'application/x-www-form-urlencoded') {
$data .= $body;
}
return $this->sign($data);
}
public function verifyCallback($contentType, $originAuthorization, $url, $body)
{
$authorization = 'QBox ' . $this->signRequest($url, $body, $contentType);
return $originAuthorization === $authorization;
}
public function privateDownloadUrl($baseUrl, $expires = 3600)
{
$deadline = time() + $expires;
$pos = strpos($baseUrl, '?');
if ($pos !== false) {
$baseUrl .= '&e=';
} else {
$baseUrl .= '?e=';
}
$baseUrl .= $deadline;
$token = $this->sign($baseUrl);
return "$baseUrl&token=$token";
}
public function uploadToken(
$bucket,
$key = null,
$expires = 3600,
$policy = null,
$strictPolicy = true,
Zone $zone = null
) {
$deadline = time() + $expires;
$scope = $bucket;
if ($key !== null) {
$scope .= ':' . $key;
}
$args = array();
$args = self::copyPolicy($args, $policy, $strictPolicy);
$args['scope'] = $scope;
$args['deadline'] = $deadline;
if ($zone === null) {
$zone = new Zone();
}
list($upHosts, $err) = $zone->getUpHosts($this->accessKey, $bucket);
if ($err === null) {
$args['upHosts'] = $upHosts;
}
$b = json_encode($args);
return $this->signWithData($b);
}
/**
*上传策略,参数规格详见
*http://developer.qiniu.com/docs/v6/api/reference/security/put-policy.html
*/
private static $policyFields = array(
'callbackUrl',
'callbackBody',
'callbackHost',
'callbackBodyType',
'callbackFetchKey',
'returnUrl',
'returnBody',
'endUser',
'saveKey',
'insertOnly',
'detectMime',
'mimeLimit',
'fsizeMin',
'fsizeLimit',
'persistentOps',
'persistentNotifyUrl',
'persistentPipeline',
'deleteAfterDays',
'upHosts',
);
private static $deprecatedPolicyFields = array(
'asyncOps',
);
private static function copyPolicy(&$policy, $originPolicy, $strictPolicy)
{
if ($originPolicy === null) {
return array();
}
foreach ($originPolicy as $key => $value) {
if (in_array((string) $key, self::$deprecatedPolicyFields, true)) {
throw new \InvalidArgumentException("{$key} has deprecated");
}
if (!$strictPolicy || in_array((string) $key, self::$policyFields, true)) {
$policy[$key] = $value;
}
}
return $policy;
}
public function authorization($url, $body = null, $contentType = null)
{
$authorization = 'QBox ' . $this->signRequest($url, $body, $contentType);
return array('Authorization' => $authorization);
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save