diff --git a/.htaccess b/.htaccess new file mode 100644 index 00000000..cbc78689 --- /dev/null +++ b/.htaccess @@ -0,0 +1,8 @@ + + Options +FollowSymlinks -Multiviews + RewriteEngine On + + RewriteCond %{REQUEST_FILENAME} !-d + RewriteCond %{REQUEST_FILENAME} !-f + RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L] + diff --git a/README.md b/README.md index 4ff8281c..0ede4302 100644 --- a/README.md +++ b/README.md @@ -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 \ No newline at end of file diff --git a/application/.htaccess b/application/.htaccess new file mode 100644 index 00000000..3418e55a --- /dev/null +++ b/application/.htaccess @@ -0,0 +1 @@ +deny from all \ No newline at end of file diff --git a/application/command.php b/application/command.php new file mode 100644 index 00000000..826bb2b2 --- /dev/null +++ b/application/command.php @@ -0,0 +1,12 @@ + +// +---------------------------------------------------------------------- + +return []; diff --git a/application/common.php b/application/common.php new file mode 100644 index 00000000..fb70d169 --- /dev/null +++ b/application/common.php @@ -0,0 +1,41 @@ + +// +---------------------------------------------------------------------- + +// 应用公共文件 +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]; +} \ No newline at end of file diff --git a/application/config.php b/application/config.php new file mode 100644 index 00000000..a7d2ce8a --- /dev/null +++ b/application/config.php @@ -0,0 +1,270 @@ + +// +---------------------------------------------------------------------- + +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], +]; diff --git a/application/database.lock b/application/database.lock new file mode 100644 index 00000000..e69de29b diff --git a/application/database.php b/application/database.php new file mode 100644 index 00000000..192c8c30 --- /dev/null +++ b/application/database.php @@ -0,0 +1,53 @@ + +// +---------------------------------------------------------------------- + +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, +]; diff --git a/application/database_sample.php b/application/database_sample.php new file mode 100644 index 00000000..47841bd6 --- /dev/null +++ b/application/database_sample.php @@ -0,0 +1,53 @@ + +// +---------------------------------------------------------------------- + +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, +]; diff --git a/application/index/autoload.php b/application/index/autoload.php new file mode 100644 index 00000000..4379b91d --- /dev/null +++ b/application/index/autoload.php @@ -0,0 +1,14 @@ += 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); +} +?> \ No newline at end of file diff --git a/application/index/controller/Admin.php b/application/index/controller/Admin.php new file mode 100644 index 00000000..00bceabe --- /dev/null +++ b/application/index/controller/Admin.php @@ -0,0 +1,448 @@ +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(), + ]); + } + +} diff --git a/application/index/controller/Callback.php b/application/index/controller/Callback.php new file mode 100644 index 00000000..c8f20563 --- /dev/null +++ b/application/index/controller/Callback.php @@ -0,0 +1,84 @@ + 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); + } + +} diff --git a/application/index/controller/Cron.php b/application/index/controller/Cron.php new file mode 100644 index 00000000..d7c600eb --- /dev/null +++ b/application/index/controller/Cron.php @@ -0,0 +1,17 @@ +Doit(); + } + +} diff --git a/application/index/controller/Explore.php b/application/index/controller/Explore.php new file mode 100644 index 00000000..2b4b3321 --- /dev/null +++ b/application/index/controller/Explore.php @@ -0,0 +1,60 @@ +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, + ]); + } + +} diff --git a/application/index/controller/File.php b/application/index/controller/File.php new file mode 100644 index 00000000..eb729005 --- /dev/null +++ b/application/index/controller/File.php @@ -0,0 +1,175 @@ +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); + } +} \ No newline at end of file diff --git a/application/index/controller/Home.php b/application/index/controller/Home.php new file mode 100644 index 00000000..5f9f78c8 --- /dev/null +++ b/application/index/controller/Home.php @@ -0,0 +1,75 @@ +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, + ]); + } + +} diff --git a/application/index/controller/Index.php b/application/index/controller/Index.php new file mode 100644 index 00000000..ec35d4ea --- /dev/null +++ b/application/index/controller/Index.php @@ -0,0 +1,23 @@ +userObj = new User(cookie('user_id'),cookie('login_key')); + $userInfo = $this->userObj->getInfo(); + return view('index', [ + 'options' => Option::getValues(['basic']), + 'userInfo' => $userInfo, + ]); + } + +} diff --git a/application/index/controller/Member.php b/application/index/controller/Member.php new file mode 100644 index 00000000..aa7e2398 --- /dev/null +++ b/application/index/controller/Member.php @@ -0,0 +1,300 @@ + '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(); + } + } + +} diff --git a/application/index/controller/Profile.php b/application/index/controller/Profile.php new file mode 100644 index 00000000..4e2979db --- /dev/null +++ b/application/index/controller/Profile.php @@ -0,0 +1,80 @@ +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, + ]); + } + +} diff --git a/application/index/controller/Share.php b/application/index/controller/Share.php new file mode 100644 index 00000000..67aa253b --- /dev/null +++ b/application/index/controller/Share.php @@ -0,0 +1,185 @@ +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 + ]); + } + +} diff --git a/application/index/controller/Upload.php b/application/index/controller/Upload.php new file mode 100644 index 00000000..c8b307d4 --- /dev/null +++ b/application/index/controller/Upload.php @@ -0,0 +1,78 @@ +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); + } + +} diff --git a/application/index/controller/WebDav.php b/application/index/controller/WebDav.php new file mode 100644 index 00000000..19f6f01a --- /dev/null +++ b/application/index/controller/WebDav.php @@ -0,0 +1,45 @@ +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(); + } + +} diff --git a/application/index/model/AdminHandler.php b/application/index/model/AdminHandler.php new file mode 100644 index 00000000..92518f7b --- /dev/null +++ b/application/index/model/AdminHandler.php @@ -0,0 +1,657 @@ +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"=>"设置已保存"]; + } + +} +?> \ No newline at end of file diff --git a/application/index/model/Avatar.php b/application/index/model/Avatar.php new file mode 100644 index 00000000..d95f530f --- /dev/null +++ b/application/index/model/Avatar.php @@ -0,0 +1,146 @@ +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]); + } + +} \ No newline at end of file diff --git a/application/index/model/BasicCallBack.php b/application/index/model/BasicCallBack.php new file mode 100644 index 00000000..1c00bad5 --- /dev/null +++ b/application/index/model/BasicCallBack.php @@ -0,0 +1,39 @@ +callBack = $callBack; + $this->realm = 'CloudreveWebDav'; + + } + + + public function getDigestHash($realm, $username){ + $cb = $this->callBack; + return $cb($realm,$username); + } + +} \ No newline at end of file diff --git a/application/index/model/CallbackHandler.php b/application/index/model/CallbackHandler.php new file mode 100644 index 00000000..486994e8 --- /dev/null +++ b/application/index/model/CallbackHandler.php @@ -0,0 +1,206 @@ +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; + } + } + +} + + +?> \ No newline at end of file diff --git a/application/index/model/CronHandler.php b/application/index/model/CronHandler.php new file mode 100644 index 00000000..d57314d7 --- /dev/null +++ b/application/index/model/CronHandler.php @@ -0,0 +1,73 @@ +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
"); + } + + private function deleteCallbackData($interval){ + echo("deleteCallbackData..."); + Db::name("callback")->delete(true); + echo("Complete
"); + $this->setComplete("delete_callback_data"); + } + +} +?> \ No newline at end of file diff --git a/application/index/model/DavAuth.php b/application/index/model/DavAuth.php new file mode 100644 index 00000000..2462bc10 --- /dev/null +++ b/application/index/model/DavAuth.php @@ -0,0 +1,30 @@ +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"]; + } + +} + +?> \ No newline at end of file diff --git a/application/index/model/Directory.php b/application/index/model/Directory.php new file mode 100644 index 00000000..72f881a7 --- /dev/null +++ b/application/index/model/Directory.php @@ -0,0 +1,186 @@ +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"]); + } + } +} +?> \ No newline at end of file diff --git a/application/index/model/FileManage.php b/application/index/model/FileManage.php new file mode 100644 index 00000000..bb034543 --- /dev/null +++ b/application/index/model/FileManage.php @@ -0,0 +1,1238 @@ +filePath = $path; + $fileInfo = $this->getFileName($path); + $fileName = $fileInfo[0]; + $path = $fileInfo[1]; + $fileRecord = Db::name('files')->where('upload_user',$uid)->where('orign_name',$fileName)->where('dir',$path)->find(); + if (empty($fileRecord)){ + die('{ "result": { "success": false, "error": "文件不存在" } }'); + } + $this->fileData = $fileRecord; + $this->userID = $uid; + $this->userData = Db::name('users')->where('id',$uid)->find(); + $this->policyData = Db::name('policy')->where('id',$this->fileData["policy_id"])->find(); + } + + public function Source(){ + if(!$this->policyData["origin_link"]){ + die('{"url":"此文件不支持获取源文件URL"}'); + }else{ + echo ('{"url":"'.$this->policyData["url"].$this->fileData["pre_name"].'"}'); + } + } + + public function getContent(){ + $sizeLimit=(int)Option::getValue("maxEditSize"); + if($this->fileData["size"]>$sizeLimit){ + die('{ "result": { "success": false, "error": "您当前用户组最大可编辑'.$sizeLimit.'字节的文件"} }'); + }else{ + switch ($this->policyData["policy_type"]) { + case 'local': + $filePath = ROOT_PATH . 'public/uploads/' . $this->fileData["pre_name"]; + $fileContent = $this->getLocalFileContent($filePath); + break; + case 'qiniu': + $fileContent = $this->getQiniuFileContent(); + break; + case 'oss': + $fileContent = $this->getOssFileContent(); + break; + case 'upyun': + $fileContent = $this->getUpyunFileContent(); + break; + case 's3': + $fileContent = $this->getS3FileContent(); + break; + default: + # code... + break; + } + $result["result"] = $fileContent; + if(empty(json_encode($result))){ + $result["result"] = iconv('gb2312','utf-8',$fileContent); + } + echo json_encode($result); + } + } + + public function getLocalFileContent($path){ + $fileObj = fopen($path,"r"); + $fileContent = fread($fileObj,filesize($path)+1); + return $fileContent; + } + + public function getQiniuFileContent(){ + return file_get_contents($this->qiniuPreview()[1]); + } + + public function getOssFileContent(){ + return file_get_contents($this->ossPreview()[1]); + } + + public function getUpyunFileContent(){ + return file_get_contents($this->upyunPreview()[1]); + } + + public function getS3FileContent(){ + return file_get_contents($this->s3Preview()[1]); + } + + public function saveContent($content){ + $contentSize = strlen($content); + $originSize = $this->fileData["size"]; + if(!FileManage::sotrageCheck($this->userID,$contentSize)){ + die('{ "result": { "success": false, "error": "空间容量不足" } }'); + } + switch ($this->policyData["policy_type"]) { + case 'local': + $filePath = ROOT_PATH . 'public/uploads/' . $this->fileData["pre_name"]; + file_put_contents($filePath, ""); + file_put_contents($filePath, $content); + break; + case 'qiniu': + $this->saveQiniuContent($content); + break; + case 'oss': + $this->saveOssContent($content); + break; + case 'upyun': + $this->saveUpyunContent($content); + break; + case 's3': + $this->saveS3Content($content); + break; + default: + # code... + break; + } + FileManage::storageGiveBack($this->userID,$originSize); + FileManage::storageCheckOut($this->userID,$contentSize); + Db::name('files')->where('id', $this->fileData["id"])->update(['size' => $contentSize]); + echo ('{ "result": { "success": true} }'); + } + + public function saveQiniuContent($content){ + $auth = new Auth($this->policyData["ak"], $this->policyData["sk"]); + $expires = 3600; + $keyToOverwrite = $this->fileData["pre_name"]; + $upToken = $auth->uploadToken($this->policyData["bucketname"], $keyToOverwrite, $expires, null, true); + $uploadMgr = new \Qiniu\Storage\UploadManager(); + list($ret, $err) = $uploadMgr->put($upToken, $keyToOverwrite, $content); + if ($err !== null) { + die('{ "result": { "success": false, "error": "编辑失败" } }'); + } else { + return true; + } + } + + public function saveOssContent($content){ + $accessKeyId = $this->policyData["ak"]; + $accessKeySecret = $this->policyData["sk"]; + $endpoint = "http".ltrim(ltrim($this->policyData["server"],"https"),"http"); + try { + $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, true); + } catch (OssException $e) { + die('{ "result": { "success": false, "error": "鉴权失败" } }'); + } + try{ + $ossClient->putObject($this->policyData["bucketname"], $this->fileData["pre_name"], $content); + } catch(OssException $e) { + die('{ "result": { "success": false, "error": "编辑失败" } }'); + } + } + + public function saveUpyunContent($content){ + $bucketConfig = new Config($this->policyData["bucketname"], $this->policyData["op_name"], $this->policyData["op_pwd"]); + $client = new Upyun($bucketConfig); + if(empty($content)){ + $content = " "; + } + $res=$client->write($this->fileData["pre_name"],$content); + } + + public function saveS3Content($content){ + $s3 = new \S3\S3($this->policyData["ak"], $this->policyData["sk"],false,$this->policyData["op_pwd"]); + $s3->setSignatureVersion('v4'); + $s3->putObjectString($content, $this->policyData["bucketname"], $this->fileData["pre_name"]); + } + + static function fileNameValidate($value){ + $validate = new Validate([ + 'val' => 'require|max:250', + 'val' => 'chsDash' + ]); + $data = [ + 'val' => $value + ]; + if (!$validate->check($data)) { + return false; + } + return true; + } + + static function RenameHandler($fname,$new,$uid,$notEcho = false){ + $folderTmp = $new; + $originFolder = $fname; + $new = str_replace("/", "", self::getFileName($new)[0]); + if(!$notEcho){ + $new = str_replace(" ", "", $new); + } + if(!self::fileNameValidate($new)){ + if($notEcho){ + return '{ "result": { "success": false, "error": "文件名只支持数字、字母、下划线" } }'; + } + die('{ "result": { "success": false, "error": "文件名只支持数字、字母、下划线" } }'); + } + $path = self::getFileName($fname)[1]; + $fname = self::getFileName($fname)[0]; + $fileRecord = Db::name('files')->where('upload_user',$uid)->where('orign_name',$fname)->where('dir',$path)->find(); + if (empty($new)){ + if($notEcho){ + return '{ "result": { "success": false, "error": "文件重名或文件名非法" } }'; + } + die('{ "result": { "success": false, "error": "文件重名或文件名非法" } }'); + } + if(empty($fileRecord)){ + self::folderRename($originFolder,$folderTmp,$uid,$notEcho); + die(); + } + $originSuffix = explode(".",$fileRecord["orign_name"]); + $newSuffix = explode(".",$new); + if(end($originSuffix) != end($newSuffix)){ + if($notEcho){ + return '{ "result": { "success": false, "error": "请不要更改文件扩展名" } }'; + } + die('{ "result": { "success": false, "error": "请不要更改文件扩展名" } }'); + } + Db::name('files')->where([ + 'upload_user' => $uid, + 'dir' => $path, + 'orign_name' =>$fname, + ])->setField('orign_name', $new); + if($notEcho){ + return '{ "result": { "success": true} }'; + } + echo ('{ "result": { "success": true} }'); + } + + static function folderRename($fname,$new,$uid,$notEcho = false){ + $newTmp = $new; + $nerFolderTmp = explode("/",$new); + $new = array_pop($nerFolderTmp); + $oldFolderTmp = explode("/",$fname); + $old = array_pop($oldFolderTmp); + if(!self::fileNameValidate($new)){ + if($notEcho){ + return '{ "result": { "success": false, "error": "目录名只支持数字、字母、下划线" } }'; + } + die('{ "result": { "success": false, "error": "目录名只支持数字、字母、下划线" } }'); + } + $folderRecord = Db::name('folders')->where('owner',$uid)->where('position_absolute',$fname)->find(); + if(empty($folderRecord)){ + if($notEcho){ + return '{ "result": { "success": false, "error": "目录不存在" } }'; + } + die('{ "result": { "success": false, "error": "目录不存在" } }'); + } + $newPositionAbsolute = substr($fname, 0, strrpos( $fname, '/'))."/".$new; + Db::name('folders')->where('owner',$uid)->where('position_absolute',$fname)->update([ + 'folder_name' => $new, + 'position_absolute' => $newPositionAbsolute, + ]); + $childFolder = Db::name('folders')->where('owner',$uid)->where('position',"like",$fname."%")->select(); + foreach ($childFolder as $key => $value) { + $tmpPositionAbsolute = ""; + $tmpPosition = ""; + $pos = strpos($value["position_absolute"], $fname); + if ($pos === false) { + $tmpPositionAbsolute = $value["position_absolute"]; + } + $tmpPositionAbsolute = substr_replace($value["position_absolute"], $newTmp, $pos, strlen($fname)); + $pos = strpos($value["position"], $fname); + if ($pos === false) { + $tmpPosition = $value["position"]; + } + $tmpPosition = substr_replace($value["position"], $newTmp, $pos, strlen($fname)); + Db::name('folders')->where('id',$value["id"])->update([ + 'position_absolute' => $tmpPositionAbsolute, + 'position' =>$tmpPosition, + ]); + } + $childFiles = Db::name('files')->where('upload_user',$uid)->where('dir',"like",$fname."%")->select(); + foreach ($childFiles as $key => $value) { + $tmpPosition = ""; + $pos = strpos($value["dir"], $fname); + if ($pos === false) { + $tmpPosition = $value["dir"]; + } + $tmpPosition = substr_replace($value["dir"], $newTmp, $pos, strlen($fname)); + Db::name('files')->where('id',$value["id"])->update([ + 'dir' =>$tmpPosition, + ]); + } + if($notEcho){ + return '{ "result": { "success": true} }'; + } + echo ('{ "result": { "success": true} }'); + } + + static function getFileName($path){ + $pathSplit = explode("/",$path); + $fileName = end($pathSplit); + $pathSplitDelete = array_pop($pathSplit); + $path=""; + foreach ($pathSplit as $key => $value) { + if (empty($value)){ + + }else{ + $path =$path."/".$value; + } + } + $path = empty($path)?"/":$path; + return [$fileName,$path]; + } + + public function PreviewHandler($isAdmin=false){ + switch ($this->policyData["policy_type"]) { + case 'qiniu': + $Redirect = $this->qiniuPreview(); + return $Redirect; + break; + case 'local': + $Redirect = $this->localPreview($isAdmin); + return $Redirect; + break; + case 'oss': + $Redirect = $this->ossPreview(); + return $Redirect; + break; + case 'upyun': + $Redirect = $this->upyunPreview(); + return $Redirect; + break; + case 's3': + $Redirect = $this->s3Preview(); + return $Redirect; + break; + default: + # code... + break; + } + } + + public function getThumb(){ + switch ($this->policyData["policy_type"]) { + case 'qiniu': + $Redirect = $this->getQiniuThumb(); + return $Redirect; + case 'local': + $Redirect = $this->getLocalThumb(); + return $Redirect; + break; + case 'oss': + $Redirect = $this->getOssThumb(); + return $Redirect; + break; + case 'upyun': + $Redirect = $this->getUpyunThumb(); + return $Redirect; + break; + default: + # code... + break; + } + } + + public function Download($isAdmin=false){ + switch ($this->policyData["policy_type"]) { + case 'qiniu': + return $DownloadHandler = $this->qiniuDownload(); + break; + case 'local': + return $DownloadHandler = $this->localDownload($isAdmin); + break; + case 'oss': + return $DownloadHandler = $this->ossDownload(); + break; + case 'upyun': + return $DownloadHandler = $this->upyunDownload(); + break; + case 's3': + return $DownloadHandler = $this->s3Download(); + break; + default: + # code... + break; + } + } + + static function DirDeleteHandler($path,$uid){ + global $toBeDeleteDir; + global $toBeDeleteFile; + $toBeDeleteDir = []; + $toBeDeleteFile = []; + foreach ($path as $key => $value) { + array_push($toBeDeleteDir,$value); + } + + foreach ($path as $key => $value) { + self::listToBeDelete($value,$uid); + } + if(!empty($toBeDeleteFile)){ + self::DeleteHandler($toBeDeleteFile,$uid); + } + if(!empty($toBeDeleteDir)){ + self::deleteDir($toBeDeleteDir,$uid); + } + } + + static function listToBeDelete($path,$uid){ + global $toBeDeleteDir; + global $toBeDeleteFile; + $fileData = Db::name('files')->where([ + 'dir' => $path, + 'upload_user' => $uid, + ])->select(); + foreach ($fileData as $key => $value) { + array_push($toBeDeleteFile,$path."/".$value["orign_name"]); + } + $dirData = Db::name('folders')->where([ + 'position' => $path, + 'owner' => $uid, + ])->select(); + foreach ($dirData as $key => $value) { + array_push($toBeDeleteDir,$value["position_absolute"]); + self::listToBeDelete($value["position_absolute"],$uid); + } + } + + static function deleteDir($path,$uid){ + Db::name('folders') + ->where("owner",$uid) + ->where([ + 'position_absolute' => ["in",$path], + ])->delete(); + } + + static function DeleteHandler($path,$uid){ + if(empty($path)){ + return ["result"=>["success"=>true,"error"=>null]]; + } + foreach ($path as $key => $value) { + $fileInfo = self::getFileName($value); + $fileName = $fileInfo[0]; + $filePath = $fileInfo[1]; + $fileNames[$key] = $fileName; + $filePathes[$key] = $filePath; + } + $fileData = Db::name('files')->where([ + 'orign_name' => ["in",$fileNames], + 'dir' => ["in",$filePathes], + 'upload_user' => $uid, + ])->select(); + $fileListTemp=[]; + $uniquePolicy = self::uniqueArray($fileData); + foreach ($fileData as $key => $value) { + if(empty($fileListTemp[$value["policy_id"]])){ + $fileListTemp[$value["policy_id"]] = []; + } + array_push($fileListTemp[$value["policy_id"]],$value); + } + foreach ($fileListTemp as $key => $value) { + if(in_array($key,$uniquePolicy["qiniuList"])){ + self::qiniuDelete($value,$uniquePolicy["qiniuPolicyData"][$key][0]); + }else if(in_array($key,$uniquePolicy["localList"])){ + self::localDelete($value,$uniquePolicy["localPolicyData"][$key][0]); + }else if(in_array($key,$uniquePolicy["ossList"])){ + self::ossDelete($value,$uniquePolicy["ossPolicyData"][$key][0]); + }else if(in_array($key,$uniquePolicy["upyunList"])){ + self::upyunDelete($value,$uniquePolicy["upyunPolicyData"][$key][0]); + }else if(in_array($key,$uniquePolicy["s3List"])){ + self::s3Delete($value,$uniquePolicy["s3PolicyData"][$key][0]); + } + } + return ["result"=>["success"=>true,"error"=>null]]; + } + + static function MoveHandler($file,$dir,$new,$uid){ + if(in_array($new,$dir)){ + die('{ "result": { "success": false, "error": "不能移动目录到自身" } }'); + } + if(Db::name('folders')->where('owner',$uid)->where('position_absolute',$new)->find() == null){ + die('{ "result": { "success": false, "error": "目录不存在" } }'); + } + $moveName=[]; + $movePath=[]; + foreach ($file as $key => $value) { + $fileInfo = self::getFileName($value); + $moveName[$key] = $fileInfo[0]; + $movePath[$key] = $fileInfo[1]; + } + $dirName=[]; + $dirPa=[]; + foreach ($dir as $key => $value) { + $dirInfo = self::getFileName($value); + $dirName[$key] = $dirInfo[0]; + $dirPar[$key] = $dirInfo[1]; + } + $nameCheck = Db::name('files')->where([ + 'upload_user' => $uid, + 'dir' => $new, + 'orign_name' =>["in",$moveName], + ])->find(); + $dirNameCheck = array_merge($dirName,$moveName); + $dirCheck = Db::name('folders')->where([ + 'owner' => $uid, + 'position' => $new, + 'folder_name' =>["in",$dirNameCheck], + ])->find(); + if($nameCheck || $dirCheck){ + die('{ "result": { "success": false, "error": "文件名冲突,请检查是否重名" } }'); + } + if(!empty($dir)){ + die('{ "result": { "success": false, "error": "暂不支持移动目录" } }'); + } + Db::name('files')->where([ + 'upload_user' => $uid, + 'dir' => ["in",$movePath], + 'orign_name' =>["in",$moveName], + ])->setField('dir', $new); + echo ('{ "result": { "success": true} }'); + } + + static function moveFile($file,$path){ + + } + + static function localDelete($fileList,$policyData){ + $fileListTemp = array_column($fileList, 'pre_name'); + foreach ($fileListTemp as $key => $value) { + @unlink(ROOT_PATH . 'public/uploads/'.$value); + if(file_exists(ROOT_PATH . 'public/thumb/'.$value."_thumb")){ + @unlink(ROOT_PATH . 'public/thumb/'.$value."_thumb"); + } + } + self::deleteFileRecord(array_column($fileList, 'id'),array_sum(array_column($fileList, 'size')),$fileList[0]["upload_user"]); + } + + static function qiniuDelete($fileList,$policyData){ + $auth = new Auth($policyData["ak"], $policyData["sk"]); + $config = new \Qiniu\Config(); + $bucketManager = new \Qiniu\Storage\BucketManager($auth); + $fileListTemp = array_column($fileList, 'pre_name'); + $ops = $bucketManager->buildBatchDelete($policyData["bucketname"], $fileListTemp); + list($ret, $err) = $bucketManager->batch($ops); + self::deleteFileRecord(array_column($fileList, 'id'),array_sum(array_column($fileList, 'size')),$fileList[0]["upload_user"]); + } + + static function ossDelete($fileList,$policyData){ + $accessKeyId = $policyData["ak"]; + $accessKeySecret = $policyData["sk"]; + $endpoint = "http".ltrim(ltrim($policyData["server"],"https"),"http"); + try { + $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, true); + } catch (OssException $e) { + return false; + } + try{ + $ossClient->deleteObjects($policyData["bucketname"], array_column($fileList, 'pre_name')); + } catch(OssException $e) { + return false; + } + self::deleteFileRecord(array_column($fileList, 'id'),array_sum(array_column($fileList, 'size')),$fileList[0]["upload_user"]); + } + + static function upyunDelete($fileList,$policyData){ + foreach (array_column($fileList, 'pre_name') as $key => $value) { + self::deleteUpyunFile($value,$policyData); + } + self::deleteFileRecord(array_column($fileList, 'id'),array_sum(array_column($fileList, 'size')),$fileList[0]["upload_user"]); + } + + static function s3Delete($fileList,$policyData){ + foreach (array_column($fileList, 'pre_name') as $key => $value) { + self::deleteS3File($value,$policyData); + } + self::deleteFileRecord(array_column($fileList, 'id'),array_sum(array_column($fileList, 'size')),$fileList[0]["upload_user"]); + } + + static function deleteFileRecord($id,$size,$uid){ + Db::name('files')->where([ + 'id' => ["in",$id], + ])->delete(); + Db::name('shares') + ->where(['owner' => $uid]) + ->where(['source_type' => "file"]) + ->where(['source_name' => ["in",$id],]) + ->delete(); + Db::name('users')->where([ + 'id' => $uid, + ])->setDec('used_storage', $size); + } + + static function getThumbSize($width,$height){ + $rate = $width/$height; + $maxWidth = 90; + $maxHeight = 39; + $changeWidth = 39*$rate; + $changeHeight = 90/$rate; + if($changeWidth>=$maxWidth){ + return [(int)$changeHeight,90]; + } + return [39,(int)$changeWidth]; + } + + static function outputThumb($path){ + ob_end_clean(); + if(!input("get.cache")=="no"){ + header("Cache-Control: max-age=10800"); + } + header('Content-Type: '.self::getMimetype($path)); + $fileObj = fopen($path,"r"); + echo fread($fileObj,filesize($path)); + fclose($file); + } + + public function getLocalThumb(){ + $picInfo = explode(",",$this->fileData["pic_info"]); + $picInfo = self::getThumbSize($picInfo[0],$picInfo[1]); + if(file_exists(ROOT_PATH . "public/thumb/".$this->fileData["pre_name"]."_thumb")){ + self::outputThumb(ROOT_PATH . "public/thumb/".$this->fileData["pre_name"]."_thumb"); + return [0,0]; + } + $thumbImg = new Thumb(ROOT_PATH . "public/uploads/".$this->fileData["pre_name"]); + $thumbImg->thumb($picInfo[1], $picInfo[0]); + if(!is_dir(dirname(ROOT_PATH . "public/thumb/".$this->fileData["pre_name"]))){ + mkdir(dirname(ROOT_PATH . "public/thumb/".$this->fileData["pre_name"]),0777,true); + } + $thumbImg->out(ROOT_PATH . "public/thumb/".$this->fileData["pre_name"]."_thumb"); + self::outputThumb(ROOT_PATH . "public/thumb/".$this->fileData["pre_name"]."_thumb"); + return [0,0]; + } + + public function getOssThumb(){ + if(!$this->policyData['bucket_private']){ + $fileUrl = $this->policyData["url"].$this->fileData["pre_name"]."?x-oss-process=image/resize,m_lfit,h_39,w_90"; + return[true,$fileUrl]; + }else{ + $accessKeyId = $this->policyData["ak"]; + $accessKeySecret = $this->policyData["sk"]; + $endpoint = $this->policyData["url"]; + try { + $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, true); + } catch (OssException $e) { + return [false,0]; + } + $baseUrl = $this->policyData["url"].$this->fileData["pre_name"]; + try{ + $signedUrl = $ossClient->signUrl($this->policyData["bucketname"], $this->fileData["pre_name"], Option::getValue("timeout"),'GET', array("x-oss-process" => 'image/resize,m_lfit,h_39,w_90')); + } catch(OssException $e) { + return [false,0]; + } + return[true,$signedUrl]; + } + } + + public function getQiniuThumb(){ + return $this->qiniuPreview("?imageView2/2/w/90/h/39"); + } + + private function getUpyunThumb(){ + $picInfo = explode(",",$this->fileData["pic_info"]); + $thumbSize = self::getThumbSize($picInfo[0],$picInfo[1]); + $baseUrl =$this->policyData["url"].$this->fileData["pre_name"]."!/fwfh/90x39"; + return [1,$this->upyunPreview($baseUrl,$this->fileData["pre_name"]."!/fwfh/90x39")[1]]; + } + + public function s3Preview(){ + $timeOut = Option::getValue("timeout"); + return [1,\S3\S3::aws_s3_link($this->policyData["ak"], $this->policyData["sk"],$this->policyData["bucketname"],"/".$this->fileData["pre_name"],3600,$this->policyData["op_name"])]; + } + + public function upyunPreview($base=null,$name=null){ + if(!$this->policyData['bucket_private']){ + $fileUrl = $this->policyData["url"].$this->fileData["pre_name"]."?auth=0"; + if(!empty($base)){ + $fileUrl = $base; + } + return[true,$fileUrl]; + }else{ + $baseUrl = $this->policyData["url"].$this->fileData["pre_name"]; + if(!empty($base)){ + $baseUrl = $base; + } + $etime = time() + Option::getValue("timeout"); + $key = $this->policyData["sk"]; + $path = "/".$this->fileData["pre_name"]; + if(!empty($name)){ + $path = "/".$name; + } + $sign = substr(md5($key.'&'.$etime.'&'.$path), 12, 8).$etime; + $signedUrl = $baseUrl."?_upt=".$sign; + return[true,$signedUrl]; + } + } + + public function qiniuPreview($thumb=null){ + if(!$this->policyData['bucket_private']){ + $fileUrl = $this->policyData["url"].$this->fileData["pre_name"].$thumb; + return[true,$fileUrl]; + }else{ + $auth = new Auth($this->policyData["ak"], $this->policyData["sk"]); + $baseUrl = $this->policyData["url"].$this->fileData["pre_name"].$thumb; + $signedUrl = $auth->privateDownloadUrl($baseUrl); + return[true,$signedUrl]; + } + } + + public function ossPreview(){ + if(!$this->policyData['bucket_private']){ + $fileUrl = $this->policyData["url"].$this->fileData["pre_name"]; + return[true,$fileUrl]; + }else{ + $accessKeyId = $this->policyData["ak"]; + $accessKeySecret = $this->policyData["sk"]; + $endpoint = $this->policyData["url"]; + try { + $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, true); + } catch (OssException $e) { + return [false,0]; + } + $baseUrl = $this->policyData["url"].$this->fileData["pre_name"]; + try{ + $signedUrl = $ossClient->signUrl($this->policyData["bucketname"], $this->fileData["pre_name"], Option::getValue("timeout")); + } catch(OssException $e) { + return [false,0]; + } + return[true,$signedUrl]; + } + } + + public function qiniuDownload(){ + if(!$this->policyData['bucket_private']){ + $fileUrl = $this->policyData["url"].$this->fileData["pre_name"]."?attname=".urlencode($this->fileData["orign_name"]); + return[true,$fileUrl]; + }else{ + $auth = new Auth($this->policyData["ak"], $this->policyData["sk"]); + $baseUrl = $this->policyData["url"].$this->fileData["pre_name"]."?attname=".urlencode($this->fileData["orign_name"]); + $signedUrl = $auth->privateDownloadUrl($baseUrl); + return[true,$signedUrl]; + } + } + + public function upyunDownload(){ + return [true,$this->upyunPreview()[1]."&_upd=".urlencode($this->fileData["orign_name"])]; + } + + public function s3Download(){ + $timeOut = Option::getValue("timeout"); + return [1,\S3\S3::aws_s3_link($this->policyData["ak"], $this->policyData["sk"],$this->policyData["bucketname"],"/".$this->fileData["pre_name"],3600,$this->policyData["op_name"],array(),false)]; + } + + public function ossDownload(){ + if(!$this->policyData['bucket_private']){ + $fileUrl = $this->policyData["url"].$this->fileData["pre_name"]."?response-content-disposition=".urlencode('attachment; filename='.$this->fileData["orign_name"]); + return[true,$fileUrl]; + }else{ + $accessKeyId = $this->policyData["ak"]; + $accessKeySecret = $this->policyData["sk"]; + $endpoint = $this->policyData["url"]; + try { + $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, true); + } catch (OssException $e) { + return [false,0]; + } + $baseUrl = $this->policyData["url"].$this->fileData["pre_name"]; + try{ + $signedUrl = $ossClient->signUrl($this->policyData["bucketname"], $this->fileData["pre_name"], Option::getValue("timeout"),'GET', array("response-content-disposition" => 'attachment; filename='.$this->fileData["orign_name"])); + } catch(OssException $e) { + return [false,0]; + } + return[true,$signedUrl]; + } + } + + public function localPreview($isAdmin=false){ + $speedLimit = Db::name('groups')->where('id',$this->userData["user_group"])->find(); + $rangeTransfer = $speedLimit["range_transfer"]; + $speedLimit = $speedLimit["speed"]; + if($isAdmin){ + $speedLimit=""; + } + if($speedLimit == "0"){ + exit(); + }else if(empty($speedLimit)){ + header("Cache-Control: max-age=10800"); + $this->outputWithoutLimit(false,$rangeTransfer); + exit(); + }else if((int)$speedLimit > 0){ + header("Cache-Control: max-age=10800"); + $this->outputWithLimit($speedLimit); + } + } + + public function localDownload($isAdmin=false){ + $speedLimit = Db::name('groups')->where('id',$this->userData["user_group"])->find(); + $rangeTransfer = $speedLimit["range_transfer"]; + $speedLimit = $speedLimit["speed"]; + if($isAdmin){ + $speedLimit = ""; + } + if($speedLimit == "0"){ + exit(); + }else if(empty($speedLimit)){ + $this->outputWithoutLimit(true,$rangeTransfer); + exit(); + }else if((int)$speedLimit > 0){ + $this->outputWithLimit($speedLimit,true); + } + } + + public function outputWithoutLimit($download = false,$reload = false){ + ignore_user_abort(false); + $filePath = ROOT_PATH . 'public/uploads/' . $this->fileData["pre_name"]; + set_time_limit(0); + session_write_close(); + $file_size = filesize($filePath); + $ranges = $this->getRange($file_size); + if($reload == 1 && $ranges!=null){ + header('HTTP/1.1 206 Partial Content'); + header('Accept-Ranges:bytes'); + header(sprintf('content-length:%u',$ranges['end']-$ranges['start'])); + header(sprintf('content-range:bytes %s-%s/%s', $ranges['start'], $ranges['end']-1, $file_size)); + } + if($download){ + header('Cache-control: private'); + header('Content-Type: application/octet-stream'); + header('Content-Length: '.filesize($filePath)); + header('Content-Disposition: filename='.str_replace(",","",$this->fileData["orign_name"])); + ob_flush(); + flush(); + } + if(file_exists($filePath)){ + if(!$download){ + header('Content-Type: '.self::getMimetype($filePath)); + ob_flush(); + flush(); + } + $fileObj = fopen($filePath,"rb"); + if($reload == 1){ + fseek($fileObj, sprintf('%u', $ranges['start'])); + } + while(!feof($fileObj)){ + echo fread($fileObj,10240); + ob_flush(); + flush(); + } + fclose($fileObj); + } + } + + public function outputWithLimit($speed,$download = false){ + ignore_user_abort(false); + $filePath = ROOT_PATH . 'public/uploads/' . $this->fileData["pre_name"]; + set_time_limit(0); + session_write_close(); + if($download){ + header('Cache-control: private'); + header('Content-Type: application/octet-stream'); + header('Content-Length: '.filesize($filePath)); + header('Content-Disposition: filename='.$this->fileData["orign_name"]); + ob_flush(); + flush(); + }else{ + header('Content-Type: '.self::getMimetype($filePath)); + ob_flush(); + flush(); + } + if(file_exists($filePath)){ + $fileObj = fopen($filePath,"r"); + while (!feof($fileObj)){ + echo fread($fileObj,round($speed*1024)); + ob_flush(); + flush(); + sleep(1); + } + fclose($fileObj); + } + } + + static function getMimetype($path){ + $finfoObj = finfo_open(FILEINFO_MIME); + $mimetype = finfo_file($finfoObj, $path); + finfo_close($finfoObj); + return $mimetype; + } + + private function getRange($file_size){ + if(isset($_SERVER['HTTP_RANGE']) && !empty($_SERVER['HTTP_RANGE'])){ + $range = $_SERVER['HTTP_RANGE']; + $range = preg_replace('/[\s|,].*/', '', $range); + $range = explode('-', substr($range, 6)); + if(count($range)<2){ + $range[1] = $file_size; + } + $range = array_combine(array('start','end'), $range); + if(empty($range['start'])){ + $range['start'] = 0; + } + if(empty($range['end'])){ + $range['end'] = $file_size; + } + return $range; + } + return null; + } + + /** + * [List description] + * @param [type] $path [description] + * @param [type] $uid [description] + */ + static function ListFile($path,$uid){ + $fileList = Db::name('files')->where('upload_user',$uid)->where('dir',$path)->select(); + $dirList = Db::name('folders')->where('owner',$uid)->where('position',$path)->select(); + $count= 0; + $fileListData=[]; + foreach ($dirList as $key => $value) { + $fileListData['result'][$count]['name'] = $value['folder_name']; + $fileListData['result'][$count]['rights'] = "drwxr-xr-x"; + $fileListData['result'][$count]['size'] = "0"; + $fileListData['result'][$count]['date'] = $value['date']; + $fileListData['result'][$count]['type'] = 'dir'; + $fileListData['result'][$count]['name2'] = ""; + $fileListData['result'][$count]['id'] = $value['id']; + $fileListData['result'][$count]['pic'] = ""; + $count++; + } + foreach ($fileList as $key => $value) { + $fileListData['result'][$count]['name'] = $value['orign_name']; + $fileListData['result'][$count]['rights'] = "drwxr-xr-x"; + $fileListData['result'][$count]['size'] = $value['size']; + $fileListData['result'][$count]['date'] = $value['upload_date']; + $fileListData['result'][$count]['type'] = 'file'; + $fileListData['result'][$count]['name2'] = $value["dir"]; + $fileListData['result'][$count]['id'] = $value["id"]; + $fileListData['result'][$count]['pic'] = $value["pic_info"]; + $count++; + } + + return $fileListData; + } + + static function listPic($path,$uid,$url="/File/Preview?"){ + $firstPreview = self::getFileName($path); + $path=$firstPreview[1]; + $fileList = Db::name('files') + ->where('upload_user',$uid) + ->where('dir',$path) + ->where('pic_info',"<>"," ") + ->where('pic_info',"<>","0,0") + ->where('pic_info',"<>","null,null") + ->select(); + $count= 0; + $fileListData=[]; + foreach ($fileList as $key => $value) { + if($value["orign_name"] == $firstPreview[0]){ + $previewPicInfo = explode(",",$value["pic_info"]); + $previewSrc = $url."action=preview&path=".$path."/".$value["orign_name"]; + }else{ + $picInfo = explode(",",$value["pic_info"]); + $fileListData[$count]['src'] = $url."action=preview&path=".$path."/".$value["orign_name"]; + $fileListData[$count]['w'] = $picInfo[0]; + $fileListData[$count]['h'] = $picInfo[1]; + $fileListData[$count]['title'] = $value["orign_name"]; + $count++; + } + } + array_unshift($fileListData,array( + 'src' => $previewSrc, + 'w' => $previewPicInfo[0], + 'h' => $previewPicInfo[1], + 'title' => $firstPreview[0], + )); + return $fileListData; + } + + /** + * [createFolder description] + * @param [type] $dirName [description] + * @param [type] $dirPosition [description] + * @param [type] $uid [description] + * @return [type] [description] + */ + static function createFolder($dirName,$dirPosition,$uid){ + $dirName = str_replace(" ","",$dirName); + $dirName = str_replace("/","",$dirName); + if(empty($dirName)){ + return ["result"=>["success"=>false,"error"=>"目录名不能为空"]]; + } + if(Db::name('folders')->where('position_absolute',$dirPosition)->find() ==null || Db::name('folders')->where('position',$dirPosition)->where('folder_name',$dirName)->find() !=null || Db::name('files')->where('dir',$dirPosition)->where('pre_name',$dirName)->find() !=null){ + return ["result"=>["success"=>false,"error"=>"路径不存在或文件已存在"]]; + } + $sqlData = [ + 'folder_name' => $dirName, + 'parent_folder' => Db::name('folders')->where('position_absolute',$dirPosition)->value('id'), + 'position' => $dirPosition, + 'owner' => $uid, + 'date' => date("Y-m-d H:i:s"), + 'position_absolute' => ($dirPosition == "/")?($dirPosition.$dirName):($dirPosition."/".$dirName), + ]; + if(Db::name('folders')->insert($sqlData)){ + return ["result"=>["success"=>true,"error"=>null]]; + } + + } + + static function getTotalStorage($uid){ + $userData = Db::name('users')->where('id',$uid)->find(); + $basicStronge = Db::name('groups')->where('id',$userData['user_group'])->find(); + $addOnStorage = Db::name('storage_pack') + ->where('uid',$uid) + ->where('dlay_time',">",time()) + ->sum('pack_size'); + return (int)$addOnStorage+(int)$basicStronge["max_storage"]; + } + + static function getUsedStorage($uid){ + $userData = Db::name('users')->where('id',$uid)->find(); + return $userData['used_storage']; + } + + static function sotrageCheck($uid,$fsize){ + $totalStorage = self::getTotalStorage($uid); + $usedStorage = self::getUsedStorage($uid); + return ($totalStorage > ($usedStorage + $fsize)) ? True : False; + } + + static function storageCheckOut($uid,$size){ + Db::name('users')->where('id',$uid)->setInc('used_storage',$size); + } + + static function storageGiveBack($uid,$size){ + Db::name('users')->where('id',$uid)->setDec('used_storage',$size); + } + + static function addFile($jsonData,$policyData,$uid,$picInfo=" "){ + $dir = "/".str_replace(",","/",$jsonData['path']); + $fname = $jsonData['fname']; + if(self::isExist($dir,$fname,$uid)){ + return[false,"文件已存在"]; + } + $folderBelong = Db::name('folders')->where('owner',$uid)->where('position_absolute',$dir)->find(); + if($folderBelong ==null){ + return[false,"目录不存在"]; + } + $sqlData = [ + 'orign_name' => $jsonData['fname'], + 'pre_name' => $jsonData['objname'], + 'upload_user' => $uid, + 'size' => $jsonData['fsize'], + 'upload_date' => date("Y-m-d H:i:s"), + 'parent_folder' => $folderBelong['id'], + 'policy_id' => $policyData['id'], + 'dir' => $dir, + 'pic_info' => $picInfo, + ]; + if(Db::name('files')->insert($sqlData)){ + return [true,"上传成功"]; + } + + } + + static function isExist($dir,$fname,$uid){ + if(Db::name('files')->where('upload_user',$uid)->where('dir',$dir)->where('orign_name',$fname)->find() !=null){ + return true; + }else{ + return false; + } + } + + static function deleteFile($fname,$policy){ + switch ($policy['policy_type']) { + case 'qiniu': + return self::deleteQiniuFile($fname,$policy); + break; + case 'oss': + return self::deleteOssFile($fname,$policy); + break; + case 'upyun': + return self::deleteUpyunFile($fname,$policy); + break; + case 's3': + return self::deleteS3File($fname,$policy); + break; + default: + # code... + break; + } + } + + static function deleteQiniuFile($fname,$policy){ + $auth = new Auth($policy["ak"], $policy["sk"]); + $config = new \Qiniu\Config(); + $bucketManager = new \Qiniu\Storage\BucketManager($auth); + $err = $bucketManager->delete($policy["bucketname"], $fname); + if ($err) { + return false; + }else{ + return true; + } + } + + static function deleteOssFile($fname,$policy){ + $accessKeyId = $policy["ak"]; + $accessKeySecret = $policy["sk"]; + $endpoint = "http".ltrim(ltrim($policy["server"],"https"),"http"); + try { + $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, true); + } catch (OssException $e) { + return false; + } + try{ + $ossClient->deleteObject($policy["bucketname"], $fname); + } catch(OssException $e) { + return false; + } + return true; + } + + static function deleteUpyunFile($fname,$policy){ + $bucketConfig = new Config($policy["bucketname"], $policy["op_name"], $policy["op_pwd"]); + $client = new Upyun($bucketConfig); + $res=$client->delete($fname,true); + } + + static function deleteS3File($fname,$policy){ + $s3 = new \S3\S3($policy["ak"], $policy["sk"],false,$policy["op_pwd"]); + $s3->setSignatureVersion('v4'); + return $s3->deleteObject($policy["bucketname"],$fname); + } + + static function uniqueArray($data = array()){ + $tempList = []; + $qiniuList = []; + $qiniuPolicyData = []; + $localList = []; + $localPolicyData = []; + $ossList = []; + $ossPolicyData = []; + $upyunList = []; + $upyunPolicyData = []; + $s3List = []; + $s3PolicyData = []; + foreach ($data as $key => $value) { + if(!in_array($value['policy_id'],$tempList)){ + array_push($tempList,$value['policy_id']); + $policyTempData = Db::name('policy')->where('id',$value['policy_id'])->find(); + switch ($policyTempData["policy_type"]) { + case 'qiniu': + array_push($qiniuList,$value['policy_id']); + if(empty($qiniuPolicyData[$value['policy_id']])){ + $qiniuPolicyData[$value['policy_id']] = []; + } + array_push($qiniuPolicyData[$value['policy_id']],$policyTempData); + break; + case 'local': + array_push($localList,$value['policy_id']); + if(empty($localPolicyData[$value['policy_id']])){ + $localPolicyData[$value['policy_id']] = []; + } + array_push($localPolicyData[$value['policy_id']],$policyTempData); + break; + case 'oss': + array_push($ossList,$value['policy_id']); + if(empty($ossPolicyData[$value['policy_id']])){ + $ossPolicyData[$value['policy_id']] = []; + } + array_push($ossPolicyData[$value['policy_id']],$policyTempData); + break; + case 'upyun': + array_push($upyunList,$value['policy_id']); + if(empty($upyunPolicyData[$value['policy_id']])){ + $upyunPolicyData[$value['policy_id']] = []; + } + array_push($upyunPolicyData[$value['policy_id']],$policyTempData); + break; + case 's3': + array_push($s3List,$value['policy_id']); + if(empty($s3PolicyData[$value['policy_id']])){ + $s3PolicyData[$value['policy_id']] = []; + } + array_push($s3PolicyData[$value['policy_id']],$policyTempData); + break; + default: + # code... + break; + } + } + } + $returenValue=array( + 'policyId' => $tempList , + 'qiniuList' => $qiniuList, + 'qiniuPolicyData' => $qiniuPolicyData, + 'localList' => $localList, + 'localPolicyData' => $localPolicyData, + 'ossList' => $ossList, + 'ossPolicyData' => $ossPolicyData, + 'upyunList' => $upyunList, + 'upyunPolicyData' => $upyunPolicyData, + 's3List' => $s3List, + 's3PolicyData' => $s3PolicyData, + ); + return $returenValue; + } + + public function signTmpUrl(){ + switch ($this->policyData["policy_type"]) { + case 'qiniu': + return $this->qiniuPreview()[1]; + break; + case 'oss': + return $this->ossPreview()[1]; + break; + case 'upyun': + return $this->upyunPreview()[1]; + break; + case 's3': + return $this->s3Preview()[1]; + break; + case 'local': + $options = Option::getValues(["oss","basic"]); + $timeOut = $options["timeout"]; + $delayTime = time()+$timeOut; + $key=$this->fileData["id"].":".$delayTime.":".md5($this->userData["user_pass"].$this->fileData["id"].$delayTime.config("salt")); + return $options['siteURL']."Callback/TmpPreview/key/".$key; + break; + default: + # code... + break; + } + } + +} +?> \ No newline at end of file diff --git a/application/index/model/Image.php b/application/index/model/Image.php new file mode 100644 index 00000000..c0658e51 --- /dev/null +++ b/application/index/model/Image.php @@ -0,0 +1,89 @@ +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); + } +} +?> \ No newline at end of file diff --git a/application/index/model/Mail.php b/application/index/model/Mail.php new file mode 100644 index 00000000..c7eb4dca --- /dev/null +++ b/application/index/model/Mail.php @@ -0,0 +1,60 @@ +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; + } +} +?> \ No newline at end of file diff --git a/application/index/model/Object.php b/application/index/model/Object.php new file mode 100644 index 00000000..917860da --- /dev/null +++ b/application/index/model/Object.php @@ -0,0 +1,95 @@ +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) + ) . '"'; + + } +} +?> \ No newline at end of file diff --git a/application/index/model/Option.php b/application/index/model/Option.php new file mode 100644 index 00000000..b85836d5 --- /dev/null +++ b/application/index/model/Option.php @@ -0,0 +1,16 @@ +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'); + } +} +?> \ No newline at end of file diff --git a/application/index/model/ShareHandler.php b/application/index/model/ShareHandler.php new file mode 100644 index 00000000..ebbd27cd --- /dev/null +++ b/application/index/model/ShareHandler.php @@ -0,0 +1,308 @@ +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; + } + +} +?> \ No newline at end of file diff --git a/application/index/model/Thumb.php b/application/index/model/Thumb.php new file mode 100644 index 00000000..6098f802 --- /dev/null +++ b/application/index/model/Thumb.php @@ -0,0 +1,91 @@ +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); + } +} +?> \ No newline at end of file diff --git a/application/index/model/TwoFactor.php b/application/index/model/TwoFactor.php new file mode 100644 index 00000000..430b0116 --- /dev/null +++ b/application/index/model/TwoFactor.php @@ -0,0 +1,53 @@ +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]); + } + +} +?> \ No newline at end of file diff --git a/application/index/model/UploadHandler.php b/application/index/model/UploadHandler.php new file mode 100644 index 00000000..8f9167f3 --- /dev/null +++ b/application/index/model/UploadHandler.php @@ -0,0 +1,452 @@ +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); + } + +} + + +?> \ No newline at end of file diff --git a/application/index/model/User.php b/application/index/model/User.php new file mode 100644 index 00000000..7497cbf0 --- /dev/null +++ b/application/index/model/User.php @@ -0,0 +1,375 @@ +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]; + } + +} +?> \ No newline at end of file diff --git a/application/index/view/admin/about.html b/application/index/view/admin/about.html new file mode 100644 index 00000000..5e553a8a --- /dev/null +++ b/application/index/view/admin/about.html @@ -0,0 +1,72 @@ +{extend name="header_admin" /} +{block name="title"}基础设置- {$options.siteName}{/block} +{block name="content"} +
+
+ + + + +
+
+

关于

+
+ +
+
+
+
+ + 系统信息 +
+
+
    +
  • 服务器信息:{:$_SERVER ['SERVER_SOFTWARE']}
  • +
  • 服务端系统:{:PHP_OS}
  • +
  • 最大上传限制:{:get_cfg_var ("upload_max_filesize")?get_cfg_var ("upload_max_filesize"):"不允许上传"}
  • +
  • 脚本最大执行时间:{:get_cfg_var("max_execution_time")."s "}
  • +
  • 脚本最大内存:{:get_cfg_var ("memory_limit")?get_cfg_var("memory_limit"):"无"}
  • +
  • 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}
  • +
+
+
+
+
+
+
+ + 关于Cloudreve +
+
+
Cloudreve {$programVersion.type} {$programVersion.version}
+ + +
+
+
+
+ + +
+
+ + +
+ +
+{/block} +{block name="js"} + +{/block} \ No newline at end of file diff --git a/application/index/view/admin/add_group.html b/application/index/view/admin/add_group.html new file mode 100644 index 00000000..7e190809 --- /dev/null +++ b/application/index/view/admin/add_group.html @@ -0,0 +1,164 @@ +{extend name="header_admin" /} +{block name="title"}注册访问- {$options.siteName}{/block} +{block name="content"} +
+
+ + + + +
+
+

添加用户组

+
+
+ +
+
+ +
+
+
用户组的名称
+
+ +
+
+ +
+
+ + +
+
为该用户组绑定一个上传策略
+
+ +
+
+ +
+
+ +
+ + + +
+
+
该用户组初始最大可用容量
+
+ +
+
+ +
+
+ +
+ + Kb/s + +
+
+
限制该用户组下的用户上传的文件的下载速度,此设置仅对本地上传方案有效
+
+ +
+
+ +
+
+ +     + +
+
是否断点续传及多线程下载,关闭后预览视频不支持拖拽播放,此设置仅对本地上传方案有效
+
+ +
+
+ +
+
+ +     + +
+
是否允许创建文件分享链接
+
+ +
+
+ +
+
+ +     + +
+
是否允许用户使用WebDAV协议同步文件。目前此功能仅支持本地上传方案
+
+ +
+
+ +
+
+ + +     + + +     + + +     + + +
+ + +     + + +     +
+
用户个人主页展示用户组时的徽章颜色
+
+ +
+
+
+
+
+


+
+
+
+
+ + +
+ +
+ +{/block} +{block name="js"} + + +{/block} \ No newline at end of file diff --git a/application/index/view/admin/add_policy.html b/application/index/view/admin/add_policy.html new file mode 100644 index 00000000..ce471801 --- /dev/null +++ b/application/index/view/admin/add_policy.html @@ -0,0 +1,815 @@ +{extend name="header_admin" /} +{block name="title"}添加上传策略- {$options.siteName}{/block} +{block name="content"} +
+
+ + + + +
+
+

添加上传策略

+
+
+
+
+
+ Card image cap +
+
本地服务器
+

将文件存放在Cloudreve主程序的同一个服务器上

+ 添加 +
+
+
+
+
+ Card image cap +
+
七牛云存储
+

使用七牛云提供的云存储及CDN服务

+ 添加 +
+
+
+
+
+ Card image cap +
+
阿里云OSS
+

使用OSS对象存储存放文件,推荐配合阿里云CDN使用

+ 添加 +
+
+
+
+
+ Card image cap +
+
又拍云
+

使用又拍云存储提供的服务,每月有一定免费额度

+ 添加 +
+
+
+ +
+
+ Card image cap +
+
Amazon S3
+

Amazon S3专为从任意位置存储和检索任意数量的数据而构建的对象存储

+ 添加 +
+
+
+
+
+ + + + + + + + + + +
+
+
+ + +
+ +
+ + + +{/block} +{block name="js"} + + +{/block} \ No newline at end of file diff --git a/application/index/view/admin/add_policy_s3.html b/application/index/view/admin/add_policy_s3.html new file mode 100644 index 00000000..8a3cf99b --- /dev/null +++ b/application/index/view/admin/add_policy_s3.html @@ -0,0 +1,175 @@ +{extend name="header_admin" /} +{block name="title"}添加上传策略- {$options.siteName}{/block} +{block name="content"} +
+
+ + + + +
+
+

添加上传策略

+
+ + + + + +
+
+ 添加S3上传策略 +
+
+
+ +
+
+ +
+
+
上传策略的名称,用于区别不同策略
+
+ +
+
+ +
+
+
AWS账户的访问秘钥信息,请在 控制面板 - 您的安全凭证 中创建
+
+ +
+
+ +
+
+
同上一项获取
+
+ +
+
+ +
+
+
创建桶时填写的名称
+
+ + + + +
+
+ +
+
+ +
+
一般格式为:https://s3-分区名.amazonaws.com/储存桶名/ 结尾要加"/"
+
+ +
+
+ +
+
+ +
+
一般格式为:https://储存桶名.s3-分区代号.amazonaws.com/
+
+ +
+
+ +
+
+ +
+
例如:ap-southeast-1
+
+
+
+ +
+
+ +
+
一般格式为:s3-储存区域.amazonaws.com,只填写域名部分
+
+ +
+
+ +
+
+ +
+
多个请以半角逗号","隔开,留空表示不限制。如果允许图片类型文件,除了图片类型后缀外,请额外添加一项"image/*"
+
+ +
+
+ +
+
+ +
+ + + +
+
+
允许上传的单个文件的最大尺寸
+
+ + + + + + +
+
+
+
+
+

+
+
+
+ +
+ + + + +
+
+
+ + +
+ +
+ +{/block} +{block name="js"} + + +{/block} \ No newline at end of file diff --git a/application/index/view/admin/admin_index.html b/application/index/view/admin/admin_index.html new file mode 100644 index 00000000..d14ba5d5 --- /dev/null +++ b/application/index/view/admin/admin_index.html @@ -0,0 +1,229 @@ +{extend name="header_admin" /} +{block name="title"}管理面板- {$options.siteName}{/block} +{block name="content"} +
+
+ + + +
+
+
+
+
+ +
+
{$statics.userNum} 位用户
+
+ + 查看详情 + + + + +
+
+
+
+
+
+ +
+
{$statics.fileNum} 个文件
+
+ + 查看详情 + + + + +
+
+
+
+
+
+ +
+
{$statics.publicShareNum} 个公开分享
+
+ + 查看详情 + + + + +
+
+
+
+
+
+ +
+
{$statics.privateShareNum} 个私密分享
+
+ + 查看详情 + + + + +
+
+
+ +
+
+ 近期趋势
+
+ +
+ +
+
+
+ +
+
+ 订阅新闻
+
+ +
+ +
+ + + + + +
+
+ +
+
+ 文件组成
+
+ +
+ +
+ + +
+
+ + +
+ + + + + + + + + + + + +{/block} +{block name="js"} + +{/block} \ No newline at end of file diff --git a/application/index/view/admin/basic_setting.html b/application/index/view/admin/basic_setting.html new file mode 100644 index 00000000..7a07d405 --- /dev/null +++ b/application/index/view/admin/basic_setting.html @@ -0,0 +1,83 @@ +{extend name="header_admin" /} +{block name="title"}基础设置- {$options.siteName}{/block} +{block name="content"} +
+
+ + + + +
+
+

基础设置

+
+
+
+
+ +
+
+
站点的主标题,将会展示在个页面的标题尾部、邮件中。
+
+
+
+ +
+
+
只会展示在首页的副标题。
+
+
+
+ +
+
+
站点的URL,此设置很重要,请如实填写,否则会影响系统正常工作.
+
+
+
+ +
+
+
位于首页meta标签内的站点关键词
+
+
+
+ +
+
+
位于首页meta标签内的站点描述
+
+
+
+ +
+
+
位于前台页面底部的页脚代码,你可以在此放置统计代码。
+
+
+
+
+
+
+

+
+
+
+
+ + +
+ +
+{/block} +{block name="js"} + + +{/block} \ No newline at end of file diff --git a/application/index/view/admin/config_file.html b/application/index/view/admin/config_file.html new file mode 100644 index 00000000..7fe722ba --- /dev/null +++ b/application/index/view/admin/config_file.html @@ -0,0 +1,51 @@ +{extend name="header_admin" /} +{block name="title"}基础设置- {$options.siteName}{/block} +{block name="content"} +
+
+ + + + +
+
+

配置文件

+ {$path} +

+
+
+ + +
+ +

+
+ + +
+
+
+ + +
+ +
+{/block} +{block name="js"} + + +{/block} \ No newline at end of file diff --git a/application/index/view/admin/cron_list.html b/application/index/view/admin/cron_list.html new file mode 100644 index 00000000..ea8ebaa0 --- /dev/null +++ b/application/index/view/admin/cron_list.html @@ -0,0 +1,84 @@ +{extend name="header_admin" /} +{block name="title"}基础设置- {$options.siteName}{/block} +{block name="content"} +
+
+ + + + +
+
+

定时任务

+
+ {eq name="neverExcute" value="true"} + + {/eq} + {volist name="cron" id="c"} +
+
+ {$c.name} +
+
+
+

{$c.des}

+
+
+ + +
+
+
+ 优先级 +
+ +
+
+ +
+
+
+ 执行间隔(s) +
+ +
+
+ +
+
+
+ 启用 +
+ +
+
+ +
+ +
+
+ +

+ {/volist} +
+
+ + +
+ +
+{/block} +{block name="js"} + +{/block} \ No newline at end of file diff --git a/application/index/view/admin/edit_group.html b/application/index/view/admin/edit_group.html new file mode 100644 index 00000000..56a625cc --- /dev/null +++ b/application/index/view/admin/edit_group.html @@ -0,0 +1,171 @@ +{extend name="header_admin" /} +{block name="title"}注册访问- {$options.siteName}{/block} +{block name="content"} +
+
+ + + + +
+
+

编辑用户组

+
+
+ +
+
+ + +
+
+
用户组的名称
+
+ +
+
+ +
+
+ + +
+
为该用户组绑定一个上传策略
+
+ +
+
+ +
+
+ +
+ + + +
+
+
该用户组初始最大可用容量
+
+ +
+
+ +
+
+ +
+ + Kb/s + +
+
+
限制该用户组下的用户上传的文件的下载速度,此设置仅对本地上传方案有效
+
+ +
+
+ +
+
+ +     + +
+
是否断点续传及多线程下载,关闭后预览视频不支持拖拽播放,此设置仅对本地上传方案有效
+
+ +
+
+ +
+
+ +     + +
+
是否允许创建文件分享链接
+
+ +
+
+ +
+
+ +     + +
+
是否允许用户使用WebDAV协议同步文件。目前此功能仅支持本地上传方案
+
+ +
+
+ +
+
+ + +     + + +     + + +     + + +
+ + +     + + +     +
+
用户个人主页展示用户组时的徽章颜色
+
+ +
+
+
+
+
+


+
+
+
+
+ + +
+ +
+ +{/block} +{block name="js"} + + +{/block} \ No newline at end of file diff --git a/application/index/view/admin/edit_policy.html b/application/index/view/admin/edit_policy.html new file mode 100644 index 00000000..dc5ea3ed --- /dev/null +++ b/application/index/view/admin/edit_policy.html @@ -0,0 +1,962 @@ +{extend name="header_admin" /} +{block name="title"}编辑上传策略- {$options.siteName}{/block} +{block name="content"} +
+
+ + + + +
+
+

编辑上传策略

+
+ {switch name="policy.policy_type"} + {case value="local"} +
+
+ 编辑上传策略 +
+
+
+
+
+ + +
+
+
上传策略的名称,用于区别不同策略
+
+
+
+ +
+
+ {eq name="$policy.origin_link" value="1"} + + +     + + + {else/} + + +     + + + {/eq} +
+
是否允许获取文件的源URL,推荐禁止
+
+
+
+ +
+
+ +
+
一般与主站URL保持相同。如果你设置了融合CDN等产品,这里可以填写CDN域名,结尾要加"/"
+
+
+
+ +
+
+ +
+
多个请以半角逗号","隔开,留空表示不限制。如果允许图片类型文件,除了图片类型后缀外,请额外添加一项"image/*"
+
+
+
+ +
+
+ +
+ + + +
+ +
+
允许上传的单个文件的最大尺寸
+
+
+
+ +
+
+ {eq name="$policy.autoname" value="1"} + + +     + + + {else/} + + +     + + + {/eq} +
+
是否对存储的文件自动重命名。推荐开启,重命名不会影响用户端文件名展示,开启后可以避免文件重名
+
+
+
+ +
+
+ +
+
你可以使用变量对照表中的字段填写
+
+
+
+ +
+
+
+ + /public/uploads/ + +
+ +
+
文件存放的目录,你可以使用目录变量对照表中的字段填写
+
+ +
+
+
+
+
+

+
+
+
+ +
+ {/case} + {case value="qiniu"} +
+
+ 编辑上传策略 +
+
+
+
+
+ + +
+
+
上传策略的名称,用于区别不同策略
+
+ +
+
+ +
+
+
七牛账号的AccessKey,请在七牛控制面板查看
+
+ +
+
+ +
+
+
七牛账号的SecretKey,请在七牛控制面板查看
+
+ +
+
+ +
+
+
创建空间时填写的空间名
+
+ +
+
+ +
+
+ {eq name="policy.bucket_private" value="1"} + + +     + + + {else/} + + +     + + + {/eq} +
+
与七牛空间访问控制设置保持一致,推荐设置为私有空间
+
+ + + +
+
+ +
+
+ +
+
七牛空间绑定的域名,结尾要加"/"
+
+ +
+
+ +
+
+ +
+
多个请以半角逗号","隔开,留空表示不限制。如果允许图片类型文件,除了图片类型后缀外,请额外添加一项"image/*"
+
+ +
+
+ +
+
+ +
+
多个请以半角分号";"隔开,留空表示不限制。示例:image/*表示只允许上传图片类型,image/jpeg;image/png表示只允许上传jpg和png类型的图片,!application/json;text/plain表示禁止上传json文本和纯文本。注意最前面的感叹号!
+
+ +
+
+ +
+
+ +
+ + + +
+
+
允许上传的单个文件的最大尺寸
+
+
+
+ +
+
+ {eq name="$policy.autoname" value="1"} + + +     + + + {else/} + + +     + + + {/eq} +
+
是否对存储的文件自动重命名。推荐开启,重命名不会影响用户端文件名展示,开启后可以避免文件重名
+
+
+
+ +
+
+ +
+
你可以使用变量对照表中的字段填写
+
+
+
+ +
+
+ + +
+
文件存放的目录,你可以使用目录变量对照表中的字段填写
+
+ +
+
+
+
+
+

+
+
+
+ +
+ {/case} + {case value="oss"} +
+ +
+
+ 编辑上传策略 +
+
+
+ +
+
+ +
+
+
上传策略的名称,用于区别不同策略
+
+ +
+
+ +
+
+
阿里云账号的Access Key ID,请在阿里云控制面板-Access Key管理中创建或查看
+
+ +
+
+ +
+
+
获取方法同上一项
+
+ +
+
+ +
+
+
创建空间时填写的Bucket名
+
+ +
+
+ +
+
+ {eq name="policy.bucket_private" value="1"} + + +     + + + {else/} + + +     + + + {/eq} +
+
与OSS空间访问控制设置保持一致,推荐设置为私有空间
+
+ + + +
+
+ +
+
+ +
+
OSS空间绑定的域名,用于文件下载、访问,结尾要加"/"(推荐配合阿里云CDN使用,此处填写CDN域名)
+
+ +
+
+ +
+
+ +
+
OSS空间的域名,一般与上一项保持一致。(如果上一项填写的是CDN域名,则此处与上一项不应相同)
+
+ +
+
+ +
+
+ +
+
多个请以半角逗号","隔开,留空表示不限制。如果允许图片类型文件,除了图片类型后缀外,请额外添加一项"image/*"
+
+ +
+
+ +
+
+ +
+ + + +
+
+
允许上传的单个文件的最大尺寸
+
+
+
+ +
+
+ {eq name="policy.autoname" value="1"} + + +     + + + {else/} + + +     + + + {/eq} +
+
是否对存储的文件自动重命名。推荐开启,重命名不会影响用户端文件名展示,开启后可以避免文件重名
+
+
+
+ +
+
+ +
+
你可以使用变量对照表中的字段填写
+
+
+
+ +
+
+ + +
+
文件存放的目录,你可以使用目录变量对照表中的字段填写
+
+ +
+
+
+
+
+

+
+
+
+ +
+
+{/case} + {case value="upyun"} +
+
+ 又拍云 +
+
+
+ +
+
+ +
+
+
上传策略的名称,用于区别不同策略
+
+ +
+
+ +
+
+
创建存储服务时授权的操作员名称
+
+ +
+
+ +
+
+
创建存储服务时授权的操作员密码
+
+ +
+
+ +
+
+
创建存储服务时填写的名称
+
+ +
+
+ +
+
+ {eq name="policy.bucket_private" value="1"} + + +     + + + {else/} + + +     + + + {/eq} +
+
与 功能配置-访问配置-Token 防盗链 保持一致,推荐设置为开启
+
+ +
+
+ +
+
+
与 功能配置-访问配置-Token防盗链 中的密钥保持一致
+
+ + + +
+
+ +
+
+ +
+
绑定的域名,开头要加http(s)://结尾要加"/"
+
+ +
+
+ +
+
+ +
+
多个请以半角逗号","隔开,留空表示不限制。如果允许图片类型文件,除了图片类型后缀外,请额外添加一项"image/*"
+
+ +
+
+ +
+
+ +
+ + + +
+
+
允许上传的单个文件的最大尺寸
+
+ +
+
+ +
+
+ + +
+
文件存放的目录,你可以使用目录变量对照表中的字段填写
+
+ +
+
+
+
+
+

+
+
+
+ +
+ {/case} + {case value="s3"} +
+
+ 添加S3上传策略 +
+
+
+ +
+
+ +
+
+
上传策略的名称,用于区别不同策略
+
+ +
+
+ +
+
+
AWS账户的访问秘钥信息,请在 控制面板 - 您的安全凭证 中创建
+
+ +
+
+ +
+
+
同上一项获取
+
+ +
+
+ +
+
+
创建桶时填写的名称
+
+ +
+
+ +
+
+ +
+
一般格式为:https://s3-分区名.amazonaws.com/储存桶名/ 结尾要加"/"
+
+ +
+
+ +
+
+ +
+
一般格式为:https://储存桶名.s3-分区代号.amazonaws.com/
+
+ +
+
+ +
+
+ +
+
例如:ap-southeast-1
+
+
+
+ +
+
+ +
+
一般格式为:s3-储存区域.amazonaws.com,只填写域名部分
+
+ +
+
+ +
+
+ +
+
多个请以半角逗号","隔开,留空表示不限制。如果允许图片类型文件,除了图片类型后缀外,请额外添加一项"image/*"
+
+ +
+
+ +
+
+ +
+ + + +
+
+
允许上传的单个文件的最大尺寸
+
+ + +
+
+
+
+
+

+
+
+
+ +
+ + {/case} +{/switch} +
+
+
+ + +
+ +
+ + + +{/block} +{block name="js"} + + +{/block} \ No newline at end of file diff --git a/application/index/view/admin/file_list.html b/application/index/view/admin/file_list.html new file mode 100644 index 00000000..0133cee9 --- /dev/null +++ b/application/index/view/admin/file_list.html @@ -0,0 +1,194 @@ +{extend name="header_admin" /} +{block name="title"}文件列表- {$options.siteName}{/block} +{block name="content"} +
+
+ + +
+
+

文件

+
+
+
+ 条件检索
+
+
+ +
+ +
+
+ +
+ +
+ +
+
+
+ +
+
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+ +
+
+ 文件列表
+
+
+
+
+ + + + + + + + + + + {volist name='list' id='file'} + + + + + + + + + {/volist} + +
文件名大小上传者日期操作
文件名大小上传者日期操作
+ {eq name=":isPreview($file.orign_name)" value="yes"} + {$file.orign_name|htmlspecialchars=ENT_NOQUOTES} + {else} + {$file.orign_name|htmlspecialchars=ENT_NOQUOTES} + {/eq} + {:countSize($file.size)}{$originList[$key]["user"]["user_nick"]}{$file.upload_date} + + +
+
+ +
展示第 {$pageNow} 页,共 {$pageTotal} 页 {$dataTotal} 条数据
+
+ {$list->render()} +
+
+
+ +
+
+
+ + +
+ +
+ + + {/block} + {block name="js"} + + + {/block} \ No newline at end of file diff --git a/application/index/view/admin/group_list.html b/application/index/view/admin/group_list.html new file mode 100644 index 00000000..cca5f268 --- /dev/null +++ b/application/index/view/admin/group_list.html @@ -0,0 +1,131 @@ +{extend name="header_admin" /} +{block name="title"}上传策略- {$options.siteName}{/block} +{block name="content"} +
+
+ + + + +
+
+

用户组

+
+ + +
+
+ 用户组列表
+
+
+
+
+ + + + + + + + + + + {volist name='list' id='group'} + + + + + + + + + {/volist} + +
#名称上传策略最大容量下属用户数操作
#名称上传策略最大容量下属用户数操作
{$group.id} + {$group.group_name} + + {$originList[$key]["policy"]["policy_name"]} + {:countSize($group["max_storage"])}{$originList[$key]["user_num"]} + + +
+
+ +
展示第 {$pageNow} 页,共 {$pageTotal} 页 {$dataTotal} 条数据
+
+ {$list->render()} +
+
+
+ +
+
+
+ + +
+ +
+ + + {/block} + {block name="js"} + + + {/block} \ No newline at end of file diff --git a/application/index/view/admin/mail_setting.html b/application/index/view/admin/mail_setting.html new file mode 100644 index 00000000..278d72ab --- /dev/null +++ b/application/index/view/admin/mail_setting.html @@ -0,0 +1,206 @@ +{extend name="header_admin" /} +{block name="title"}邮件收发- {$options.siteName}{/block} +{block name="content"} + +
+
+ + + + +
+
+

邮件收发

+
+ +
+
+
+
+
+ +
+
+
显示在邮件发件邮箱旁的发件人姓名
+
+
+
+ +
+
+
发件邮箱的地址
+
+
+
+ +
+
+
发信邮箱的SMTP服务器地址
+
+
+
+ +
+
+
发信邮箱SMTP服务器的端口
+
+
+
+ +
+
+ +
+
+
+
+
+ +
+
+
发信邮箱用户名,一般与邮箱相同
+
+
+
+ +
+
+
发信邮箱密码
+
+
+
+ +
+
+
用户回复系统发送的邮件时,用于接收回信的邮箱
+
+
+
+
+
+
+


+
+
+
+ +
+
+
+ +
+ +
+
+
接受测试邮件的收件人邮箱
+
+ +
+
+ +
+
+
测试邮件的主题
+
+ +
+
+ +
+
+ +
+ +
+
+
+
+
+


+
+ +
+
+ +
+
+ +
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+ +
+ +
+
+
+
+
+


+
+ + +
+ +
+
+
+ + +
+ +
+ +{/block} +{block name="js"} + + + + +{/block} \ No newline at end of file diff --git a/application/index/view/admin/other_setting.html b/application/index/view/admin/other_setting.html new file mode 100644 index 00000000..db5bf6e5 --- /dev/null +++ b/application/index/view/admin/other_setting.html @@ -0,0 +1,96 @@ +{extend name="header_admin" /} +{block name="title"}注册访问- {$options.siteName}{/block} +{block name="content"} +
+
+ + + + + +
+
+

杂项设置

+
+
+ +
+
+ +
+
+
用户可在线编辑的文本类文件的最大尺寸。单位:字节
+
+ +
+
+ +
+
+ {eq name="$optionsForSet.allowdVisitorDownload" value="true"} + + +     + + + {else} + + +     + + + {/eq} +
+
是否允许未登录用户下载被分享的文件
+
+ +
+
+ +
+
+
在用户个人主页展示的热门分享的个数
+
+ +
+
+ +
+
+
用于展示用户头像的Gravatar服务器地址
+
+ +
+
+
+
+
+


+
+
+
+
+ + + +
+ +
+ + + + + +{/block} +{block name="js"} + + +{/block} \ No newline at end of file diff --git a/application/index/view/admin/policy_list.html b/application/index/view/admin/policy_list.html new file mode 100644 index 00000000..9a12a06b --- /dev/null +++ b/application/index/view/admin/policy_list.html @@ -0,0 +1,168 @@ +{extend name="header_admin" /} +{block name="title"}上传策略- {$options.siteName}{/block} +{block name="content"} +
+
+ + + + +
+
+

上传策略

+
+
+
+ 条件检索
+
+
+ +
+ +
+
+
+
+ +
+
+ 上传策略列表
+
+
+
+
+ + + + + + + + + + + {volist name='list' id='policy'} + + + + + + + + + {/volist} + +
#名称类型下属文件数数据量操作
#名称类型下属文件数数据量操作
{$policy.id} + {$policy.policy_name} + + {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} + {$originList[$key]["file_num"]}{:countSize($originList[$key]["file_size"])} + + +
+
+ +
展示第 {$pageNow} 页,共 {$pageTotal} 页 {$dataTotal} 条数据
+
+ {$list->render()} +
+
+
+ +
+
+
+ + +
+ +
+ + + {/block} + {block name="js"} + + + {/block} \ No newline at end of file diff --git a/application/index/view/admin/reg_setting.html b/application/index/view/admin/reg_setting.html new file mode 100644 index 00000000..b2bf4af0 --- /dev/null +++ b/application/index/view/admin/reg_setting.html @@ -0,0 +1,134 @@ +{extend name="header_admin" /} +{block name="title"}注册访问- {$options.siteName}{/block} +{block name="content"} +
+
+ + + + + +
+
+

注册与访问

+
+
+
+
+ + +
+
+ {eq name="$optionsForSet.regStatus" value="0"} + + +     + + + {else} + + +     + + + {/eq} +
+
是否允许新用户注册
+
+ +
+
+ +
+
+ +
+
用户注册后默认属于的用户组
+
+ +
+
+ +
+
+ + +
+
启用后,新用户注册需要点击邮件中的激活链接才能完成。请确认邮件发送设置是否正确,否则激活邮件无法送达
+
+ +
+
+ +
+
+ +
+
是否启用登录表单验证码
+
+ +
+
+ +
+
+ +
+
是否启用注册表单验证码
+
+ +
+
+ +
+
+ +
+
是否启用找回密码表单验证码
+
+ + + +
+
+
+
+
+


+
+
+
+
+ + + +
+ +
+ + + + + +{/block} +{block name="js"} + + +{/block} \ No newline at end of file diff --git a/application/index/view/admin/share_list.html b/application/index/view/admin/share_list.html new file mode 100644 index 00000000..3a24b17e --- /dev/null +++ b/application/index/view/admin/share_list.html @@ -0,0 +1,110 @@ +{extend name="header_admin" /} +{block name="title"}文件列表- {$options.siteName}{/block} +{block name="content"} +
+
+ + + + +
+
+

分享

+
+
+
+ 条件检索
+
+
+ +
+ +
+
+ +
+
+ +
+
+ 分享列表
+
+
+
+
+ + + + + + + + + + + {volist name='list' id='share'} + + + + + + + + + + + {/volist} + +
分享名称分享者类型日期浏览次数下载次数操作
分享名称分享者类型日期浏览次数下载次数操作
+ {eq name="$share.source_type" value="dir"} + {:htmlspecialchars(getDirName($share.source_name),ENT_NOQUOTES)} + {else} + {$share.origin_name|htmlspecialchars=ENT_NOQUOTES} + {/eq} + {$originList[$key]["user"]["user_nick"]} + {eq name="share.type" value="public"} + 公开 + {else/} + 私密 + {/eq} + {$share.share_time}{$share.view_num}{$share.download_num}
+
+ +
展示第 {$pageNow} 页,共 {$pageTotal} 页 {$dataTotal} 条数据
+
+ {$list->render()} +
+
+
+
+
+
+ + +
+ +
+ + {/block} + {block name="js"} + + + {/block} \ No newline at end of file diff --git a/application/index/view/admin/theme.html b/application/index/view/admin/theme.html new file mode 100644 index 00000000..015f43c6 --- /dev/null +++ b/application/index/view/admin/theme.html @@ -0,0 +1,51 @@ +{extend name="header_admin" /} +{block name="title"}基础设置- {$options.siteName}{/block} +{block name="content"} +
+
+ + + + +
+
+

编辑模板

+ application/index/view/{:rtrim($path,"/")}/{$name}.html +

+
+
+ + +
+ +

+
+
+
+ +
+
+ +
+
+
+ + +
+ +
+{/block} +{block name="js"} + + +{/block} \ No newline at end of file diff --git a/application/index/view/admin/user_list.html b/application/index/view/admin/user_list.html new file mode 100644 index 00000000..f7048b44 --- /dev/null +++ b/application/index/view/admin/user_list.html @@ -0,0 +1,298 @@ +{extend name="header_admin" /} +{block name="title"}文件列表- {$options.siteName}{/block} +{block name="content"} +
+
+ + + + +
+
+

用户

+
+
+
+ 条件检索
+
+
+ +
+ +
+
+ +
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+ +
+
+ 用户列表
+
+
+
+
+ + + + + + + + + + + {volist name='list' id='user'} + + + + + + + + + + + {/volist} + +
UID昵称邮箱用户组空间用量状态操作
UID昵称邮箱用户组空间用量状态操作
{$user.id}{$user.user_nick}{$user.user_email}{:$originList[$key]["group"]["group_name"]}{:countSize($user.used_storage)} + {eq name="user.user_status" value="0"} + 正常 + {else/} + 封禁/未激活 + {/eq} + + + + +
+
+ +
展示第 {$pageNow} 页,共 {$pageTotal} 页 {$dataTotal} 条数据
+
+ {$list->render()} +
+
+
+ +
+
+
+ + +
+ +
+ + + + {/block} + {block name="js"} + + + {/block} \ No newline at end of file diff --git a/application/index/view/callback/payment_success.html b/application/index/view/callback/payment_success.html new file mode 100644 index 00000000..6594c8f5 --- /dev/null +++ b/application/index/view/callback/payment_success.html @@ -0,0 +1,23 @@ +{extend name="header_public" /} +{block name="title"}支付成功 - {$options.siteName}{/block} +{block name="content"} + + + + +
+
+
+ +
+
+
+

支付成功

+
+

付款成功,您所购买的服务已开通。

+

查看详情

+
+
+
+ +{/block} \ No newline at end of file diff --git a/application/index/view/error.html b/application/index/view/error.html new file mode 100644 index 00000000..c7e74ff2 --- /dev/null +++ b/application/index/view/error.html @@ -0,0 +1,24 @@ +{extend name="header_public" /} +{block name="title"}错误提示 - {$options.siteName}{/block} +{block name="content"} + + + + +
+
+
+ +
+
+
+

发生错误

+
+

{$msg}

+

<< 返回

+
+
+
+{$options.js_code} + +{/block} \ No newline at end of file diff --git a/application/index/view/exception.html b/application/index/view/exception.html new file mode 100644 index 00000000..c7e74ff2 --- /dev/null +++ b/application/index/view/exception.html @@ -0,0 +1,24 @@ +{extend name="header_public" /} +{block name="title"}错误提示 - {$options.siteName}{/block} +{block name="content"} + + + + +
+
+
+ +
+
+
+

发生错误

+
+

{$msg}

+

<< 返回

+
+
+
+{$options.js_code} + +{/block} \ No newline at end of file diff --git a/application/index/view/explore/result.html b/application/index/view/explore/result.html new file mode 100644 index 00000000..db89f0bc --- /dev/null +++ b/application/index/view/explore/result.html @@ -0,0 +1,76 @@ +{extend name="header_public" /} +{block name="title"}“{$keyWords}”搜索结果 - {$options.siteName}{/block} +{block name="content"} + + + +