Compare commits

..
921 Commits
Author SHA1 Message Date
Aaron Liu 88409cc1f0 release: 3.8.3 2023-10-07 20:08:38 +08:00
Darren YuandGitHub cd6eee0b60 Fix: doc preview src of local storage policy starts with ":/" (#1842) (#1844)
* Fix: doc preview src of local storage policy starts with ":/"

* Fix: doc preview src of local storage policy starts with ":/"
2023-10-06 12:34:49 +08:00
SamandGitHub 3ffce1e356 fix(admin): Able to change deafult user status (#1811) 2023-08-14 13:24:58 +08:00
Aaron Liu ce832bf13d release: 3.8.2 2023-08-07 20:09:23 +08:00
Aaron Liu 5642dd3b66 feat(webdav): support setting download proxy 2023-07-29 08:58:14 +08:00
Aaron Liu a1747073df feat(webdav): support setting download proxy 2023-07-29 08:53:26 +08:00
WeidiDengandGitHub ad6c6bcd93 feat(webdav): supoort rename in copy and move (#1774) 2023-07-18 15:27:56 +08:00
WeidiDengandGitHub f4a04ce3c3 fix webdav proppatch (#1771) 2023-07-18 15:25:43 +08:00
Aaron Liu 247e31079c fix(thumb): cannot generate thumb using ffmpeg for specific format (#1756) 2023-07-18 15:18:54 +08:00
Darren YuandGitHub a26893aabc Add: thumb quality for 3rd storage policy (#1763)
Add thumb quality for third party storage policy.
2023-07-05 22:13:24 +08:00
初雪andGitHub ce759c02b1 feat(redis): support confiuring username (#1752)
替换Golang Redis依赖: redigo的版本至当前最新版1.8.9
(v2.0.0被标记为已撤回,且长期未更新)

Redis 6 及以上版本均可配置为使用username+password认证的ACL,故作此变更。
2023-07-05 22:12:33 +08:00
Aaron Liu 9f6f9adc89 Merge remote-tracking branch 'origin/master' 2023-06-25 18:53:54 +08:00
Aaron Liu 91025b9f24 fix(thumb): cannot generate thumbnails in slave mode 2023-06-25 18:53:37 +08:00
hallucinationandGitHub a9bee3e638 Update docker-compose.yml (#1727)
add  Redis retains login sessions after restarting
2023-06-19 12:38:29 +08:00
Aaron Liu 243c312066 fix: failed UT 2023-06-11 09:50:57 +08:00
Aaron Liu 1d52ddd93a release: 3.8.0 2023-06-11 09:45:27 +08:00
Aaron Liu cbc549229b fix(wopi): anonymous users cannot preview files 2023-06-11 09:45:06 +08:00
Aaron Liu 173ca6cdf8 fix(preview): use absolute URL for local storage policy 2023-06-11 09:44:43 +08:00
Aaron Liu fb166fb3e4 release: 3.8.0-beta1 2023-05-27 14:06:19 +08:00
Aaron Liu b1344616b8 test: fix failed ut 2023-05-27 10:44:28 +08:00
Aaron Liu 89ee147961 feat(upload): detect and specify mime type for files uploaded to S3 and OSS (fix#1681) 2023-05-25 19:51:51 +08:00
Aaron Liu 4aafe1dc7a enhance(download): Use just-in-time host in download URl, instead of SiteURL in site settings 2023-05-25 19:49:32 +08:00
Aaron Liu 4c834e75fa adhoc: commit todo changes related to google drive 2023-05-25 19:46:05 +08:00
Aaron Liu 31d4a3445d fix(cache): panic if redis connection fails 2023-05-25 19:44:59 +08:00
Aaron Liu 37926e3133 feat(policy): add Google Drive Oauth client 2023-05-24 14:39:54 +08:00
WeidiDengandGitHub 4c18e5acd1 webdav兼容nextcloud propset设置修改时间 (#1710) 2023-05-24 12:10:03 +08:00
ArkylinandGitHub 6358740cc9 modified: models/policy.go (#1718)
modified:   models/policy_test.go
2023-05-24 12:09:24 +08:00
Aaron Liu 00d56d6d07 test: fix failed ut 2023-04-16 09:25:57 +08:00
Aaron Liu b9143b53f6 chore: update runner to ubuntu-latest 2023-04-16 09:20:30 +08:00
Aaron Liu b9d9e036c9 feat(kv): persist cache and session into disk before shutdown 2023-04-16 09:17:06 +08:00
Aaron Liu 4d131db504 test(hook): NewWebdavAfterUploadHook 2023-04-15 09:21:29 +08:00
Aaron Liu c5ffdbfcfb Merge remote-tracking branch 'origin/master' 2023-04-13 19:39:22 +08:00
Aaron Liu 8e2fc1a8f6 test(thumb): new changes in filesystem pkg 2023-04-13 19:39:12 +08:00
AaronLiuandGitHub ce579d387a Merge pull request #1690 from cloudreve/webdav-checksum
webdav兼容rclone的nextcloud选项(修改日期和checksum)
2023-04-08 10:10:46 +08:00
AaronLiuandGitHub f1e7af67bc Merge branch 'master' into webdav-checksum 2023-04-08 10:09:55 +08:00
AaronLiuandGitHub 98788dc72b Merge pull request #1679 from xkeyC/master
feat(Webdav): Add overwrite support for moveFiles and copyFiles
2023-04-08 10:08:13 +08:00
Weidi Deng 1b4eff624d webdav兼容rclone的nextcloud选项(修改日期和checksum) 2023-04-07 22:16:11 +08:00
Aaron Liu 408733a974 test(thumb): new changes in models/cache pkg 2023-04-07 20:33:05 +08:00
Aaron Liu c8b736bd8f fix(dashboard): add missing utils for thumb setting 2023-04-07 19:42:23 +08:00
Aaron Liu cf03206283 feat(thumb): generator settings and test button 2023-04-07 19:33:02 +08:00
Aaron Liu ac536408c6 feat(thumb): use libreoffice to generate thumb 2023-04-07 19:31:43 +08:00
Aaron Liu 98b86b37de feat(thumb): use ffmpeg to generate thumb 2023-04-07 19:30:41 +08:00
Aaron Liu b55344459d feat(thumb): use libvips to generate thumb 2023-04-07 19:30:10 +08:00
Aaron Liu bde4459519 feat(thumb): add ext whitelist for all policy types 2023-04-07 19:29:43 +08:00
Aaron Liu f5a21a7e6f feat(thumb): set size limit for original file 2023-04-07 19:28:39 +08:00
Aaron Liu b910254cc5 feat(thumb): delete generated thumb file
fix(s3): return empty list of file failed to be deleted
2023-04-07 19:27:57 +08:00
Aaron Liu e115497dfe feat(thumb): generate thumb for OneDrive files 2023-04-07 19:27:31 +08:00
Aaron Liu 62b73b577b feat(thumb): generate and return sidecar thumb 2023-04-07 19:26:39 +08:00
Aaron Liu 7cb5e68b78 refactor(thumb): thumb logic for slave policy 2023-04-07 19:25:29 +08:00
Aaron Liu ae118c337e refactor(thumb): reset thumb status after renaming a file with no thumb available 2023-04-07 19:09:13 +08:00
Aaron Liu f36e39991d refactor(thumb): new thumb pipeline model to generate thumb on-demand 2023-04-07 19:08:54 +08:00
Aaron Liu da1eaf2d1f fix(wopi): cannot set preferred language for LibreOffice online 2023-04-07 19:06:46 +08:00
xkeyC 42f7613bfa moveFiles 修改回无条件 overwrite (Move 或 Rename 都会处罚冲突问题) 2023-03-29 20:16:09 +08:00
xkeyC e8e38029ca fix:error code 2023-03-28 00:19:18 +08:00
xkeyC cd9e9e25b9 fix:仅在需要移动时 overwrite 2023-03-28 00:06:10 +08:00
xkeyC ca7b21dc3e feat(Webdav):Add overwrite support for moveFiles and copyFiles 2023-03-27 22:55:20 +08:00
Aaron Liu f172220825 release: 3.7.1 2023-02-13 19:28:00 +08:00
Aaron Liu 37cb292530 fix(db): SQLite3 dialects return empty rows in HasColumn method 2023-02-12 20:02:35 +08:00
Aaron Liu 835605a5cb chore: keep artifacts naming consistent 2023-02-10 13:02:37 +08:00
Aaron Liu 35c4215c0f chore: update archive config to keep original arch name 2023-02-10 12:13:14 +08:00
Aaron Liu 3db803ed38 chore: update readme and archive config 2023-02-09 20:29:38 +08:00
Aaron Liu c2d7168c26 release: 3.7.0 2023-02-09 19:03:52 +08:00
Aaron Liu b441d884f6 chore: fix amd64.v1 inconsistency 2023-02-08 22:10:58 +08:00
Aaron Liu d4c79cb962 chore: fix amd64.v1 inconsistency 2023-02-08 21:39:04 +08:00
Aaron Liu e134826bd1 chore: skip git validation before release 2023-02-08 21:10:55 +08:00
Aaron Liu b78f475df8 chore: use goreleaser to build docker images 2023-02-08 21:06:14 +08:00
Aaron Liu e7de7e868d chore: use goreleaser to build artifacts 2023-02-08 20:04:45 +08:00
Aaron Liu a58e3b19ec Revert "chore(build): add go-task support (#1608)"
This reverts commit abe90e4c88.

Revert "chore: fix env in task yaml and test new build action"

This reverts commit 7dfe8fb439.

Revert "remove unused env"

This reverts commit 076aa2c567.

Revert "fix: ci build failed as env in go tasks cannot be overwritten"

This reverts commit 71cc332109.
2023-02-08 15:42:42 +08:00
Aaron Liu 71cc332109 fix: ci build failed as env in go tasks cannot be overwritten 2023-02-08 15:32:34 +08:00
Aaron Liu 076aa2c567 remove unused env 2023-02-08 15:11:53 +08:00
Aaron Liu 7dfe8fb439 chore: fix env in task yaml and test new build action 2023-02-08 15:08:20 +08:00
Aaron Liu b1b74b7be5 Merge remote-tracking branch 'origin/master' 2023-02-08 13:57:54 +08:00
mritdandGitHub abe90e4c88 chore(build): add go-task support (#1608)
* chore(build): add go-task support

add go-task support

Signed-off-by: kovacs <mritd@linux.com>

* chore(docker): build with go-task

build with go-task

Signed-off-by: kovacs <mritd@linux.com>

* chore(task): support cross compile

support cross compile

Signed-off-by: kovacs <mritd@linux.com>

* chore(task): remove GCC build

remove GCC build

Signed-off-by: kovacs <mritd@linux.com>

* docs(task): update README

update README

Signed-off-by: kovacs <mritd@linux.com>

---------

Signed-off-by: kovacs <mritd@linux.com>
2023-02-08 13:57:21 +08:00
Aaron Liu 95027e4f5d refactor(db): move dialects to a standalone pkg 2023-02-08 10:06:24 +08:00
VigorFoxandGitHub 9c58278e08 refactor(db): change SQLite driver from github.com/jinzhu/gorm/dialects/sqlite to github.com/glebarez/go-sqlite (#1626)
* sqlite 驱动从 github.com/jinzhu/gorm/dialects/sqlite 改为 github.com/glebarez/go-sqlite,以移除对 cgo 的依赖

* // 兼容已有配置中的 "sqlite3" 配置项

* Update models/init.go: 修改变量名
2023-02-08 09:53:41 +08:00
Aaron Liu 6d1c44f21b test: fix failed ut 2023-02-07 20:24:21 +08:00
Aaron Liu 489a2bab4f test: delete file while user not found 2023-02-07 20:18:13 +08:00
Aaron Liu d67d0512f8 feat(explorer): advance delete options for users 2023-02-07 20:08:22 +08:00
Aaron Liu 1c1cd9b342 feat(dashboard): unlink file while not deleting its physical source (#789) 2023-02-07 20:07:05 +08:00
Aaron Liu 2a1e82aede fix(fs): cannot delete file while user is deleted (fix #1586) 2023-02-07 20:04:53 +08:00
WeidiDengandGitHub a93ea2cfa0 feat(webdav): add read-only option (#1629) 2023-02-07 19:43:28 +08:00
HFO4 ffbafca994 Merge remote-tracking branch 'origin/master' 2023-01-10 19:56:59 +08:00
HFO4 99434d7aa5 test(wopi): add tests for wopi client 2023-01-10 19:56:02 +08:00
HFO4 f7fdf10d70 feat(wopi): edit WOPI related settings 2023-01-09 19:38:55 +08:00
HFO4 9ad2c3508f enhancement(upload): keep original file content after failed to update document files 2023-01-09 19:38:31 +08:00
HFO4 5a8c86c72e feat(wopi): adapt libreoffice online 2023-01-09 19:38:12 +08:00
HFO4 1c922ac981 feat(wopi): implement required rest api as a WOPI host 2023-01-09 19:37:46 +08:00
HFO4 4541400755 feat(wopi): change doc preview config based on WOPI discovery results 2023-01-09 19:36:41 +08:00
HFO4 c39daeb0d0 feat(wopi): fetch discover endpoint 2023-01-09 19:34:39 +08:00
5aaee9andGitHub 8dafb4f40a feat: support connect to mysql with unix socket (#1571) 2022-12-19 19:23:47 +08:00
HFO4 42a31f2fd1 fix: timeout while fetching yarn pkgs in building docker image action 2022-12-19 18:22:18 +08:00
HFO4 ca80051a89 release: 3.6.2 2022-12-19 17:53:11 +08:00
HFO4 bc0c374f00 feat(mobile): only allow request from mobile client to copy session 2022-12-19 17:35:39 +08:00
HFO4 e4c87483d6 feat(session): generate temp URL to copy/refresh user session 2022-12-19 17:34:57 +08:00
HFO4 1227f35d3c doc: change readme link 2022-12-19 17:33:15 +08:00
HFO4 08fa6964a9 doc: change readme link 2022-12-16 21:13:17 +08:00
HFO4 9eafe07f4e doc: add English README 2022-12-16 21:12:09 +08:00
HFO4 73d0f2db9b release: 3.6.1 2022-12-16 17:37:21 +08:00
HFO4 82b4e29a80 enhance: escalate ProxyHeader as a global config 2022-12-16 16:58:06 +08:00
HFO4 9860ebbca9 feat(doc preview): add magic variable for file name 2022-12-16 16:55:47 +08:00
HFO4 435a03dd34 fix: nil reference while trying to shut down DB in slave mode (#1416) 2022-12-16 16:55:28 +08:00
HFO4 4e8ab75211 feat(s3): support setting for force using path style endpoint (#1559) 2022-12-16 16:54:58 +08:00
HFO4 6ceb255512 dep: git mod tidy 2022-12-16 14:01:59 +08:00
74e1bd6a43 Added same-site policy for session options (#1381)
* Feat: added same-site policy for session options

* Feat: configurations in conf package to control the `SameSite` mode and `Secure` value of the session.

Co-authored-by: AaronLiu <abslant@126.com>
2022-12-16 13:59:26 +08:00
topjohncianandGitHub fd59d1b5ca Enhance(dashboard): optimize get policies request (#1539) 2022-12-16 13:55:52 +08:00
CodeandGitHub 2bb28a9845 fix(s3): use HEAD method to get file info (#1521)
建议更换成更好的 HeadObject 方法因为 HeadObject 方法并不会返回文件 Body 因此不需要 defer res.Body.Close()
2022-12-16 13:54:12 +08:00
vvisionnnandGitHub 5f4f6bd91a refactor: build docker image using build.sh (#1562) 2022-12-15 22:23:34 +08:00
Nya CandyandGitHub 053e4352b4 fix: Dockerfile (#1561) 2022-12-14 22:31:36 +08:00
HFO4 08e4d2257a release: 3.6.0 2022-12-14 20:17:14 +08:00
HFO4 f02b6f0286 feat(net): customize socket file permission 2022-12-14 15:28:45 +08:00
HFO4 50a3917a65 feat(cache): set max-age for public accessible static resources 2022-12-14 15:28:19 +08:00
HFO4 8c5ba89f7d feat: mobile app promotion page 2022-12-12 20:35:48 +08:00
HFO4 4519dc025b update(version): 3.6.0-beta1 2022-11-23 20:44:09 +08:00
HFO4 92cbc9f312 i18n: logs in database script 2022-11-23 18:31:43 +08:00
HFO4 756769335f feat(dashboard): edit and remove 2FA secret for users 2022-11-23 17:55:23 +08:00
HFO4 6b63195d28 enhance(session): increase default cookie ttl to 60 days 2022-11-21 19:09:54 +08:00
HFO4 db6681f448 fix(avatar): add default cache max age for avatar response 2022-11-21 19:09:37 +08:00
HFO4 4b85541d73 fix(security): CVE-2022-32167 2022-11-21 19:08:51 +08:00
HFO4 f8ed4b4a5a feat(remote download): show download node in list page 2022-10-30 10:45:25 +08:00
HFO4 7dda81368d test(source link): add unit test 2022-10-30 09:41:14 +08:00
HFO4 1c25232b06 feat(source link): record downloads for redirected source link 2022-10-29 11:08:16 +08:00
HFO4 8d7ecedf47 feat(source link): create perm source link with shorter url 2022-10-29 11:06:07 +08:00
HFO4 1f836a4b8b feat(task): not fail immediately after failed upload in transfer tasks 2022-10-17 19:26:09 +08:00
HFO4 c17cf1946a fix(static): add placeholder empty zip file for go embed 2022-10-15 16:40:00 +08:00
HFO4 392c824a33 feat(OneDrive): support Retry-After throttling control from Graph API (#280) 2022-10-15 16:35:02 +08:00
HFO4 8494bd6eb9 fix(request): deep copy shared header object in request options 2022-10-15 16:16:17 +08:00
HFO4 c7dc143d30 Merge remote-tracking branch 'origin/master' 2022-10-15 10:16:08 +08:00
HFO4 8b30593822 fix: cannot delete mass files (>=333) in SQLite (#622) 2022-10-15 10:12:23 +08:00
HFO4 56fa01ed61 fix: failed UT 2022-10-15 09:55:44 +08:00
HFO4 560097145b fix: metadata mismatch if file name contains % while uploading to OneDrive/SharePoint 2022-10-15 09:20:25 +08:00
topjohncianandGitHub 8cec65b0a7 Fix: cannot finish callback when uploading an office file using sharepoint.cn (#1503) 2022-10-15 09:06:12 +08:00
WeidiDengandGitHub f89653cea7 feat(static): release static files into memory while startup (#1471)
* 初始化时解压zip文件读取内存中

* update go.mod

* 更新各种go版本
2022-10-15 09:05:05 +08:00
HFO4 6b0b44f6d0 test: fix failed UT 2022-10-15 09:02:28 +08:00
HFO4 63b536e5db Merge remote-tracking branch 'origin/master' 2022-10-08 19:24:57 +08:00
HFO4 19a2f69a19 test: fix failed UT 2022-10-08 19:24:38 +08:00
SuperHgOandGitHub 2271fcfdef fix: s3(minio) file remove operation hangout (#1491) 2022-10-08 19:21:38 +08:00
HFO4 16b5fc3f60 fix: failed test due to missing error message in filesystem 2022-10-08 19:20:41 +08:00
HFO4 f431eb0cbd fix: metadata mismatch if file name contains % while uploading to OneDrive/SharePoint (#1301) 2022-10-08 19:09:51 +08:00
HFO4 644a326580 i18n: logs in rest pkgs 2022-10-08 18:51:52 +08:00
HFO4 f2c53dda31 Merge remote-tracking branch 'origin/master' 2022-09-29 17:43:06 +08:00
HFO4 28c2ffe72e i18n: logs in filesystem 2022-09-29 17:42:23 +08:00
HFO4 196729bae8 i18n: logs in conf/crontab/email/fs.driver 2022-09-29 17:42:05 +08:00
HFO4 9bb4a5263c i18n: logs in aria2/auth/cache/cluster/serializer 2022-09-29 17:40:56 +08:00
HFO4 7366ff534e i18n: logs in models 2022-09-29 17:40:22 +08:00
HFO4 db23f4061d i18n: logs in bootstrapper and response code in middleware 2022-09-29 17:39:48 +08:00
HFO4 16d17ac1e6 i18n: user setting route 2022-09-29 17:38:52 +08:00
HFO4 9464ee2103 i18n: user route 2022-09-29 17:37:05 +08:00
topjohncianandGitHub 88e10aeaa2 Fix: unexpected querying all files when deleting an empty folder (#1469) 2022-09-29 09:26:30 +08:00
XYenonandGitHub b1685d2863 feat: seeding status for aria2 download tasks (#1422)
* feat: add aria2 seeding

* fix: move RecycleTaskType to the bottom

* refactor: refactor recycle aria2 temp file
2022-09-29 09:24:58 +08:00
WeidiDengandGitHub 846438e3af graceful 关闭服务器 (#1416) 2022-08-22 19:49:19 +08:00
HFO4 96daed26b4 i18n: objects / share / slave / tag operations 2022-07-20 20:03:41 +08:00
HFO4 906e9857bc i18n: file operation 2022-07-20 20:01:34 +08:00
HFO4 08104646ba i18n: error codes for aria2 / callback/ directory operation 2022-07-20 19:59:13 +08:00
HFO4 a1880672b1 i18n: error codes for dashboard operations 2022-07-18 20:03:57 +08:00
9869671633 fix: incorrect progress count (#1379)
* fix: incorrect progress count

文件中转 已完成文件计数 应在文件成功上传后+1 #1367

* fix failed ut

Co-authored-by: HFO4 <912394456@qq.com>
2022-07-12 19:30:41 +08:00
AHdarkandGitHub c99b36f788 chore: better way to remove frontend map files (#1380)
* Feat: better way to remove frontend map files

* Feat: Docker use `GENERATE_SOURCEMAP` in the frontend build section to avoid generating map files.
2022-07-12 19:20:14 +08:00
topjohncianandGitHub 25d56fad6e Fix: admin summary cannot be cached in redis (#1329) 2022-06-14 14:42:02 +08:00
HFO4 f083d52e17 feat: tps limit for OneDrive policy 2022-06-09 16:11:36 +08:00
HFO4 4859ea6ee5 feat: update user storage in calibrating no matter if the actual storage match presisted 2022-06-09 16:11:10 +08:00
HFO4 21d2b817f4 Merge remote-tracking branch 'origin/master' 2022-05-25 20:02:43 +08:00
HFO4 04b0b87082 enhance: remove icp footer 2022-05-25 20:02:13 +08:00
HFO4 2a3759c315 i18n: reading dashboard announcements from custom tag 2022-05-25 20:01:41 +08:00
WeidiDengandGitHub 36b310133c fix: IP address is empty in unix socket mode (#1314) 2022-05-24 11:01:00 +08:00
WeidiDengandGitHub 3fa1249678 fix: use file extension to search for content-type (#1313) 2022-05-24 10:57:20 +08:00
vvisionnnandGitHub fb56b27062 fix: delete socket file before run (fixed #1262) (#1279)
* fix: delete socket file before run (fixed #1262)

* refactor: remove useless logs
2022-05-09 19:24:40 +08:00
HFO4 e705dedc22 Merge remote-tracking branch 'origin/master' 2022-05-09 19:06:21 +08:00
HFO4 7bd5a8e3cd dep: update webautn client for better compatibility 2022-05-09 14:51:11 +08:00
XYenonandGitHub 5bd711afc6 fix: catch s3 presign err (#1277) 2022-05-05 14:24:35 +08:00
AaronLiuandGitHub eef6c40441 Merge pull request #1259 from xb2016/master
Update how to build
2022-05-05 13:48:26 +08:00
HFO4 a78407d878 i18n: tag management 2022-05-02 10:29:33 +08:00
HFO4 46c6ee9be7 i18n: add error codes related to sign up 2022-05-02 10:27:51 +08:00
HFO4 c9eefcb946 i18n: captcha, reset password 2022-04-30 16:51:24 +08:00
HFO4 4fe79859a9 enhance: generate error message for parameter error
i18n: use explicit error code for login controlelr
2022-04-30 16:50:59 +08:00
小白-白 4d4a31c250 Update how to build 2022-04-30 14:21:47 +08:00
HFO4 0e5683bc3b test: search file with limited parent ids 2022-04-30 10:02:57 +08:00
HFO4 a31ac2299a update version number 2022-04-29 20:15:20 +08:00
HFO4 3b16d7d77c fix: error code overlap 2022-04-29 20:04:26 +08:00
HFO4 8ab0fe0e2f feat: search file under current folder 2022-04-29 20:03:52 +08:00
HFO4 d51351eebd fix: cannot generate thumbnail for COS policy 2022-04-29 20:02:55 +08:00
HFO4 6af1eeb9fb fix: increase SharePoint size verify tolerance to 1 MB 2022-04-29 20:02:29 +08:00
HFO4 94507fe609 feat: create aria2 task in batch 2022-04-29 20:01:43 +08:00
HFO4 1038bae238 feat: get file source link in batch 2022-04-29 19:59:25 +08:00
HFO4 4a4375a796 fix: recursive .map file is not deleted in build script 2022-04-26 19:57:33 +08:00
HFO4 862c7b2fd8 Merge remote-tracking branch 'origin/master' 2022-04-26 19:48:16 +08:00
HFO4 9ab643a71b fix: zip assets folder path error 2022-04-26 19:47:22 +08:00
AaronLiuandGitHub 7bdbf3e754 Merge pull request #1239 from vvisionnn/master
Keep updated at column when rename
2022-04-26 19:38:34 +08:00
AaronLiuandGitHub da68e8ede4 Merge pull request #1240 from vvisionnn/dockerHubDescription
Automatically update docker hub description at each version released
2022-04-26 19:38:06 +08:00
HFO4 23642d7597 test: fix failed test related to Folder.Create 2022-04-26 19:34:19 +08:00
HFO4 a523fc4e2c test: Folder.Create 2022-04-26 19:22:37 +08:00
HFO4 70b30f8d5f release: 3.5.2 2022-04-26 19:10:03 +08:00
HFO4 7c8e9054ce fix: OneDrive chunk upload time should be 0, avoiding upload timeouts when chunk size is large 2022-04-26 19:08:30 +08:00
HFO4 853bd4c280 fix: duplicate entry in insert transaction 2022-04-26 19:07:42 +08:00
HFO4 d845824bd8 fix: overwrite should be disabled when copy on write 2022-04-26 19:07:23 +08:00
HFO4 ae33e077a3 fix: text too long for some option field 2022-04-26 19:06:51 +08:00
HFO4 11043b43e6 fix: should use CompressSize to check size of files before creating compress task 2022-04-26 19:06:17 +08:00
HFO4 c62e355345 fix: cannot use LAN OSS endpoint for uploading 2022-04-26 19:05:54 +08:00
AaronLiuandGitHub a3d0291f41 Merge pull request #1244 from cloudreve/webdav-root
fix: cannot redirect root folder (close #1242)
2022-04-26 16:42:03 +08:00
Weidi Deng 024f09f666 修复webdav上传的根目录 2022-04-26 14:37:03 +08:00
vvisionnn f46e40f31c fix: remove unused script 2022-04-25 20:50:06 +08:00
vvisionnn b29bf11748 feat: auto update docker hub description 2022-04-25 20:36:40 +08:00
vvisionnn 2dcf1664a6 fix: keep update at column when rename 2022-04-25 20:23:53 +08:00
AaronLiuandGitHub dc69a63217 Merge pull request #1232 from cloudreve/archiver-decompress
Archiver decompress
2022-04-25 18:11:23 +08:00
HFO4 86876a1c11 feat: select encoding for decompressing zip file 2022-04-25 18:07:47 +08:00
HFO4 cb51046305 test: new changes in decompress method 2022-04-25 17:23:42 +08:00
HFO4 ac78e9db02 add empty assets.zip for placeholder 2022-04-25 16:53:57 +08:00
HFO4 d10639fd19 release: 3.5.1 2022-04-24 15:33:29 +08:00
HFO4 ba0e3278e3 fix: signature error when finishing oss upload 2022-04-24 15:16:47 +08:00
HFO4 0fb31f4523 fix: deadlock while creating default user in SQLite 2022-04-24 15:16:25 +08:00
HFO4 d0779f564e release: 3.5.0 2022-04-22 20:29:53 +08:00
HFO4 350954911e fix: add no-cache option to service worker file 2022-04-22 16:18:20 +08:00
HFO4 b8bc5bed13 test: new overwrite param in CreateUploadSession 2022-04-22 16:05:57 +08:00
HFO4 91377f4676 fix: cached folder props should ignore date and policy 2022-04-22 15:58:39 +08:00
HFO4 b1803fa51f fix: cannot overwrite file to slave policy / fix: remove lock system for webdav to resolve Windows Explorer issue. 2022-04-22 15:57:21 +08:00
HFO4 f8b7e086ba fix: database is locked when using sqlite 2022-04-22 15:56:45 +08:00
Weidi Deng 23bd1389bc 使用archiver对压缩文件进行解压 2022-04-21 16:33:10 +08:00
HFO4 ff22f5c8b9 Merge remote-tracking branch 'origin/master' 2022-04-21 14:49:10 +08:00
HFO4 aaf8a793ee test: new changes related to filesystem.CreateDirectory 2022-04-21 14:29:10 +08:00
HFO4 2ab2662fcd fix: cannot upload file to onedrive because file info not match (fix #1215)
Path in onedrive is not case-sensitive while Cloudreve cares, thus file size is not matching when finishing upload.
2022-04-21 13:58:54 +08:00
HFO4 71df067a76 fix: create directory now ignore conflict error, it will return the existed folder 2022-04-21 13:58:22 +08:00
Weidi Deng 7a3d44451b precompress embedded frontend. import mholt/archiver. 2022-04-20 19:56:00 +08:00
AaronLiuandGitHub d34cb3e5d3 Update README.md 2022-04-20 19:20:26 +08:00
AaronLiuandGitHub b5e8e4843f chore: add codecov to test workflow 2022-04-20 19:05:21 +08:00
HFO4 86877aef4b fix: failed ut 2022-04-20 18:59:09 +08:00
HFO4 3d9b9ae5d6 Merge remote-tracking branch 'origin/master' 2022-04-20 18:52:39 +08:00
HFO4 8741c3cc78 feat: return create date while list files 2022-04-20 18:51:43 +08:00
HFO4 6c93e37777 Update version number 2022-04-20 18:50:46 +08:00
HFO4 841a2e258d fix: ignore folder name conflict while creating upload session 2022-04-20 18:50:07 +08:00
HFO4 da2f6c5b07 chore: upgrade gin to 1.7.7 2022-04-20 11:50:15 +08:00
HFO4 a26183875f fix: in decompress, file stream should be closed after copy it to temp file. 2022-04-20 11:49:01 +08:00
vvisionnnandGitHub 79913a5dfa fix: Dockerfile build issue (#1217) 2022-04-20 09:14:17 +08:00
HFO4 4f6989f1b8 Update submodule 2022-04-19 21:27:38 +08:00
HFO4 fcc29e31eb Update version number 2022-04-19 20:17:37 +08:00
HFO4 00e2b26294 fix: remove filesystem upload log 2022-04-19 20:05:01 +08:00
HFO4 4f65d0e859 fix: use default chunk size if it is set as 0 2022-04-19 19:41:03 +08:00
HFO4 3804efd792 enhance: use transaction to update site settings 2022-04-19 15:36:29 +08:00
HFO4 0c9383e329 feat: cache dashboard site summary 2022-04-19 15:15:50 +08:00
HFO4 13d36c25d4 test: fix failed test in model/file/deleteFile 2022-04-15 16:03:00 +08:00
HFO4 18f5bffed1 test: fix failed test 2022-04-15 15:53:10 +08:00
HFO4 478d390867 Fix: show modified date instead of creating date in file list 2022-04-13 17:54:10 +08:00
HFO4 febbd0c5a0 Feat: batch download in streamming paradism
Fix: add cache-controler header in API call responses
2022-04-13 17:53:46 +08:00
HFO4 32a655f84e Merge remote-tracking branch 'origin/master' 2022-04-12 19:13:26 +08:00
HFO4 0a18d984ab Fix: embed static file not work (introduced in #1107)
embed file system should be declared in main pkg
2022-04-12 19:11:44 +08:00
AaronLiuandGitHub 265bc099b2 Update .travis.yml 2022-04-12 17:20:02 +08:00
AaronLiuandGitHub 90a47c9ec0 chore: trigger build manually 2022-04-12 17:13:49 +08:00
HFO4 6451e4c903 Merge branch 'master' of https://github.com/cloudreve/Cloudreve 2022-04-12 16:39:09 +08:00
vvisionnnandGitHub b50756dbcb feat: docker/docker-compose support (#1203)
* Feat: add official Dockerfile

* Feat: add dev docker build actions

* update github actions for docker

* update docker actions

* update docker actions

* update docker actions

* update docker actions

* update docker actions

* update docker actions

* fix: add npm default registry

* fix: remove yarn.lock

* fix: update frontend checksum

* remove set registry

* update Dockerfile

* feat: basic docker-compose solution

* remove old Dockerfile

* fix typo

* fix: frontend version

* fix: remove unused comments
2022-04-11 22:13:33 +08:00
AaronLiuandGitHub 23dc7e370e Create stale.yml 2022-04-09 21:07:52 +08:00
1f3c1d7ce2 Chore(deps): Bump github.com/gin-gonic/gin from 1.5.0 to 1.7.0 (#1198)
Bumps [github.com/gin-gonic/gin](https://github.com/gin-gonic/gin) from 1.5.0 to 1.7.0.
- [Release notes](https://github.com/gin-gonic/gin/releases)
- [Changelog](https://github.com/gin-gonic/gin/blob/master/CHANGELOG.md)
- [Commits](https://github.com/gin-gonic/gin/compare/v1.5.0...v1.7.0)

---
updated-dependencies:
- dependency-name: github.com/gin-gonic/gin
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-09 21:02:14 +08:00
84807be1ca use go:embed for static resources (#1107)
* feat: use go:embed to embed static files

* ci: fix broken test

* docs: update readme.md

* chore: remove statik

* feat: simplify code

Co-authored-by: AaronLiu <abslant@126.com>
2022-04-09 20:58:07 +08:00
HFO4 20e90e3963 Improve error message when uploading is conflicted 2022-04-09 09:57:22 +08:00
HFO4 ace398d87b Fix: file size is ready dirty when clean upload sessions
After listing to be deleted files, before delete is committed to database, file size might be changed by ongoing upload, causing inconsistent user storage.
2022-04-03 20:39:50 +08:00
HFO4 ec776ac837 Test: new changes in pkg request, serializer, task, xml, router 2022-03-31 20:17:01 +08:00
HFO4 d117080991 Test: new changes pkg filesystem 2022-03-30 20:38:02 +08:00
HFO4 1c0a735df8 Test: new changes pkg remote, fsctx, part of filesystem 2022-03-29 20:13:05 +08:00
HFO4 c6130ab078 Feat: new changes in pkg: chunk, backoff, local, onedrive 2022-03-27 11:14:30 +08:00
HFO4 31315c86ee Feat: support option for cache streamed chunk data into temp file for potential retry. 2022-03-26 15:33:31 +08:00
HFO4 636ac52a3f Test: new changes in pkg: cache, cluster, conf 2022-03-26 15:32:57 +08:00
HFO4 1821923b74 Test: new changes in model pkg 2022-03-24 20:07:56 +08:00
HFO4 a568e5e45a Test: new changes in middleware pkg 2022-03-23 20:05:10 +08:00
HFO4 e51c5cd70d Fix: root folder should not be deleted 2022-03-23 19:32:31 +08:00
HFO4 5a3ea89866 Feat: support {ext} and {uuid} magic variable 2022-03-23 19:26:25 +08:00
HFO4 eaa8c9e12d Refactor: move thumbnail config from ini file to database 2022-03-23 19:02:39 +08:00
HFO4 d54ca151b2 Feat: overwrite database settings in conf.ini for slave node. 2022-03-23 18:58:18 +08:00
HFO4 7eb8173101 Feat: adapt new uploader for s3 like policy
This commit also fix #730, #713, #756, #5
2022-03-20 11:29:50 +08:00
HFO4 d3016b60af Feat: adapt new uploader for upyun policy 2022-03-20 11:27:43 +08:00
HFO4 9e5713b139 Feat: adapt new uploader for COS policy 2022-03-20 11:27:17 +08:00
HFO4 07f13cc350 Refactor: factory method for OSS client
Fix: use HTTPS schema by default in OSS client
Feat: new handler for Qiniu policy
2022-03-20 11:26:26 +08:00
HFO4 0df9529b32 Feat: generating token and callback url for OSS muiltpart upload, support resume upload in sever-side uploading for OSS 2022-03-20 11:23:55 +08:00
HFO4 015ccd5026 Feat: use new ChunkManager for OneDrive API client 2022-03-20 11:20:09 +08:00
HFO4 5802161102 Fix: inherited policy ID didn't pass through second layer in Folder / version verification in Ping router 2022-03-20 11:17:04 +08:00
HFO4 b6efca1878 Feat: uploading OneDrive files in client side 2022-03-20 11:16:25 +08:00
HFO4 15e3e3db5c Fix: unused import and Ping router return wrong version 2022-03-16 11:44:40 +08:00
HFO4 24dfb2c24e Fix: undefined method in transfer task 2022-03-13 19:27:33 +08:00
HFO4 dd4c3e05d3 Feat: show pro flag in ping response 2022-03-13 16:21:32 +08:00
HFO4 5bda037d74 Fix: cannot list multiple pages in async task page 2022-03-13 16:21:09 +08:00
HFO4 c89327631e Fix: panics inside of task was not correctly logged into DB
Feat: slave node use new API to upload file to master
2022-03-13 16:20:50 +08:00
HFO4 9136f3caec Fix: while placeholder file got conflict, original file might be deleted 2022-03-13 16:19:05 +08:00
HFO4 0650684dd9 Feat: cancel upload session in slave node 2022-03-13 16:18:39 +08:00
HFO4 effbc8607e Refactor: use chunk manager to manage resume upload in server side 2022-03-13 16:17:20 +08:00
HFO4 b96019be7c Feat: client method to upload file from master node to slave node 2022-03-13 16:16:58 +08:00
HFO4 081e75146c Fix: add optimism lock when updating file size 2022-03-13 16:15:19 +08:00
HFO4 e0714fdd53 Feat: process upload callback sent from slave node 2022-03-03 19:17:25 +08:00
HFO4 4925a356e3 Enable overwrite for non-first chunk uploading request 2022-03-03 19:15:25 +08:00
HFO4 050a68a359 Chore: update golang version to 1.17.x 2022-03-02 19:29:18 +08:00
HFO4 7214e59c25 Feat: creating upload session and credential from master server 2022-02-28 17:52:59 +08:00
HFO4 118d738797 Feat: support apply append mode and overwrite mode for FileStream 2022-02-28 17:49:00 +08:00
HFO4 285611baf7 Feat: truncate file if uploaded chunk is overlapped 2022-02-28 17:47:57 +08:00
HFO4 521c5c8dc4 Feat: use transactions to manipulate user's used storage 2022-02-27 14:24:17 +08:00
HFO4 285e80ba76 Feat: use database transactions to delete / update file size 2022-02-27 14:23:26 +08:00
HFO4 2811ee3285 Feat: slave policy creating upload session API 2022-02-27 14:22:09 +08:00
HFO4 7dd636da74 Feat: upload session recycle crontab job / API for cleanup all upload session 2022-02-27 14:16:36 +08:00
HFO4 3444b4a75e Feat: chunk upload handling for local policy 2022-02-27 14:13:39 +08:00
HFO4 c301bd6045 Feat: API for receiviing chunk data 2022-02-27 14:11:01 +08:00
HFO4 72173bf894 Refactor: create placeholder file and record upload session id in it 2022-02-27 14:07:12 +08:00
HFO4 6fdf77e00e Feat: support setting "last modified" props when creating upload session 2022-02-27 14:05:21 +08:00
HFO4 e37e93a7b6 Feat: create hidden file when creating upload session 2022-02-27 14:04:30 +08:00
HFO4 868a88e5fc Refactor: use universal FileHeader when handling file upload, remove usage of global ctx with FileHeader, SavePath, DisableOverwrite 2022-02-27 14:03:07 +08:00
KAAAsSandGitHub 8a222e7df4 fix: nil pointer in qiniu and upyun driver (#1146) 2022-02-26 08:39:47 +08:00
HFO4 8443a30fb1 Feat: support chunk size option in policy 2022-02-10 19:31:06 +08:00
HFO4 de9c41082c Feat: create upload session and pre-upload check 2022-02-10 19:30:08 +08:00
HFO4 855c9d92c4 Feat: get policy from directory props / Feat: return source enabled flag in file list 2022-02-10 19:25:38 +08:00
vvisionnnandGitHub c84d0114ae Fix: trigger err when move folder into itself (#1128) 2022-02-04 12:07:56 +08:00
HFO4 c31c77a089 Merge remote-tracking branch 'origin/master' 2021-11-30 19:31:48 +08:00
HFO4 6b15cae0b5 Update version number 2021-11-30 19:27:09 +08:00
HFO4 84d81f201f Fix: refresh interval not working 2021-11-30 19:26:35 +08:00
HFO4 af4d9767c2 Fix: slave node cannot transfer files to other slave node 2021-11-30 19:26:07 +08:00
milkiceandGitHub 45597adcd3 Integrate aria2c support & fix unintended behavior for docker image (#1073)
* Update Dockerfile

* Create docker-bootstrap.sh

In addition to spawn cloudreve, this script generates password for aria2 so that users can take advantage of aria2 more conveniently instead of configuring aria2 by themselves.
2021-11-29 17:45:33 +08:00
AaronLiuandGitHub 762f0f9c68 Update app.go 2021-11-26 15:48:19 +08:00
AaronLiuandGitHub c5074df1c7 Update README.md 2021-11-26 11:17:19 +08:00
HFO4 7ea72cf364 Fix: default CORS setting header should be applied with new change 2021-11-26 11:05:12 +08:00
HFO4 4eb7525c51 Fix: cannot transfer tasks with multiple files in slave node 2021-11-26 10:58:01 +08:00
HFO4 3948ee7f3a Fix: use X-Cr- as custom header prefix 2021-11-23 21:22:23 +08:00
HFO4 865a801fa8 Update version number 2021-11-22 21:08:35 +08:00
HFO4 05941616df Fix: node should not be refreshed when editing node with status=inactive 2021-11-22 20:48:16 +08:00
HFO4 51b1e5b854 Merge remote-tracking branch 'origin/master' 2021-11-22 20:38:21 +08:00
HFO4 4dbe867020 Fix: failed unit test due to import cycle 2021-11-22 20:38:03 +08:00
WeidiDengandGitHub 8c8ad3e149 Fix: WebDAV cannot move and rename at the same time (#1056) 2021-11-22 20:29:45 +08:00
HFO4 fce38209bc Merge remote-tracking branch 'origin/master' 2021-11-22 20:27:07 +08:00
HFO4 700e13384e Fix: using url escape instead of unescape in remote handler (#1051) 2021-11-22 20:23:34 +08:00
HFO4 7fd984f95d Feat: support custom office preview service (Fix #1050) 2021-11-22 20:16:24 +08:00
HFO4 9fc08292a0 Feat: migration DB support custom upgrade scripts 2021-11-22 19:53:42 +08:00
milkiceandGitHub 8c5445a26d Fix problems in Dockerfile (#1059)
Fix js heap out of memory
Fix can't find cloudreve for cloudreve has been renamed to Cloudreve
2021-11-20 17:43:31 +08:00
HFO4 96b84bb5e5 Test: tasks pkg 2021-11-20 17:14:45 +08:00
HFO4 9056ef9171 Test: new changes in 3.4.0 2021-11-20 16:59:29 +08:00
HFO4 532bff820a Test: new modifications in filesystem pkg 2021-11-16 20:54:21 +08:00
HFO4 fcd9eddc54 Test: pkg/cluster 2021-11-16 20:14:27 +08:00
HFO4 6c9967b120 Test: cluster/node.go and controller.go 2021-11-15 20:30:25 +08:00
HFO4 416f4c1dd2 Test: balancer / auth / controller in pkg 2021-11-11 20:56:16 +08:00
HFO4 f0089045d7 Test: aria2 task monitor 100% cover 2021-11-11 19:49:02 +08:00
WeidiDengandGitHub 4b88eacb6a Remove unnecessary import "C" (#1048)
There are no C binding in this file. And for users to compile themselves, this line will cause compilation to fail for those who don't need sqlite support.

移除不必要的c binding,使用CGO=0时,这行会导致编译失败。禁用CGO会导致sqlite无法使用,但可以方便编译(不需要安装gcc,跨平台编译方便),这点可以在文档中说明。
2021-11-11 17:45:51 +08:00
kikoqiuandGitHub 54ed7e43ca Feat: improve thumbnails proformance and GC for local policy (#1044)
* thumb generating improvement

Replace "github.com/nfnt/resize" with "golang.org/x/image/draw". Add thumb task queue to avoid oom when batch thumb operation

* thumb improvement

* Add some tests for thumbnail generation
2021-11-11 17:45:22 +08:00
HFO4 4d7b8685b9 Test: aria2 task monitor
Fix: tmp file not deleted after transfer task failed to create
2021-11-09 20:53:42 +08:00
HFO4 eeee43d569 Test: newly added sb models 2021-11-09 19:29:56 +08:00
HFO4 3064ed60f3 Test: new database models and middlewares 2021-11-08 20:49:07 +08:00
HFO4 e41ec9defa Refactor: move slave pkg inside of cluster
Test: middleware for node communication
2021-11-08 19:54:26 +08:00
HFO4 eaa0f6be91 Update version number 2021-11-07 10:14:30 +08:00
HFO4 5db476634a Fix: deadlock and sync issue in node pool 2021-11-03 21:27:53 +08:00
HFO4 1f06ee3af6 Fix: node cannot be reloaded when db model changes 2021-11-01 19:23:19 +08:00
HFO4 22bbfe7da1 Merge remote-tracking branch 'origin/master' 2021-10-31 09:50:55 +08:00
HFO4 f1dc4c4758 Chore: update ubuntu image version 2021-10-31 09:50:07 +08:00
HFO4 5f861b963a Update submodule version 2021-10-31 09:48:31 +08:00
AaronLiuandGitHub 056de22edb Feat: aria2 download and transfer in slave node (#1040)
* Feat: retrieve nodes from data table

* Feat: master node ping slave node in REST API

* Feat: master send scheduled ping request

* Feat: inactive nodes recover loop

* Modify: remove database operations from aria2 RPC caller implementation

* Feat: init aria2 client in master node

* Feat: Round Robin load balancer

* Feat: create and monitor aria2 task in master node

* Feat: salve receive and handle heartbeat

* Fix: Node ID will be 0 in download record generated in older version

* Feat: sign request headers with all `X-` prefix

* Feat: API call to slave node will carry meta data in headers

* Feat: call slave aria2 rpc method from master

* Feat: get slave aria2 task status
Feat: encode slave response data using gob

* Feat: aria2 callback to master node / cancel or select task to slave node

* Fix: use dummy aria2 client when caller initialize failed in master node

* Feat: slave aria2 status event callback / salve RPC auth

* Feat: prototype for slave driven filesystem

* Feat: retry for init aria2 client in master node

* Feat: init request client with global options

* Feat: slave receive async task from master

* Fix: competition write in request header

* Refactor: dependency initialize order

* Feat: generic message queue implementation

* Feat: message queue implementation

* Feat: master waiting slave transfer result

* Feat: slave transfer file in stateless policy

* Feat: slave transfer file in slave policy

* Feat: slave transfer file in local policy

* Feat: slave transfer file in OneDrive policy

* Fix: failed to initialize update checker http client

* Feat: list slave nodes for dashboard

* Feat: test aria2 rpc connection in slave

* Feat: add and save node

* Feat: add and delete node in node pool

* Fix: temp file cannot be removed when aria2 task fails

* Fix: delete node in admin panel

* Feat: edit node and get node info

* Modify: delete unused settings
2021-10-31 09:41:56 +08:00
想出网名啦andGitHub a3b4a22dbc bug fix: can't connect to postgres database (#992)
* bug fix: can't connect to postgres database

* remove useless arg

* remove vscode setting
2021-10-29 20:30:26 +08:00
WeidiDengandGitHub 9ff1b47646 fix webdav prop get (#1023)
修复了displayname为空,potplayer可以正常使用webdav功能
2021-09-27 22:28:36 +08:00
AaronLiuandGitHub 65c4367689 Revert "delete $name policy (#831)" (#961)
This reverts commit e6959a5026.
2021-07-30 11:22:18 +08:00
HFO4 db7489fb61 Update version number 2021-07-11 20:10:51 +08:00
HFO4 622b928a90 Feat: support database charset option and more DMBS driver 2021-07-11 14:46:01 +08:00
HFO4 c0158ea224 Merge branch 'master' of https://github.com/cloudreve/Cloudreve 2021-07-11 14:33:42 +08:00
SongtaoandGitHub e6959a5026 delete $name policy (#831) 2021-07-11 14:32:47 +08:00
HFO4 9d64bdd9f6 Fix: attr field overflow when downloading large torrent (#941) 2021-07-11 14:20:19 +08:00
kleinseaandGitHub c85c2da523 feat: append config parameter: registerEnabled (#911) 2021-05-29 09:58:11 +08:00
HFO4 8659bdcf77 Fix: unable to read file from UPYUN (#472, #472, #836) 2021-05-11 21:52:55 +08:00
HFO4 641fe352da Fix: user encryption setting will now overwrite the default one in gomail (#869 #857 #723 #545) 2021-04-25 16:06:22 +08:00
HFO4 96712fb066 Feat: use RFC3339 time format in returned results (#811) 2021-04-03 16:57:13 +08:00
HFO4 a1252c810b Update version number to 3.3.1 2021-03-23 10:46:17 +08:00
HFO4 e781185ad2 Test: captcha verify middleware 2021-03-22 21:19:43 +08:00
HFO4 95802efcec Merge remote-tracking branch 'origin/master' 2021-03-22 18:28:57 +08:00
topjohncianandGitHub 233648b956 Refactor: captcha (#796) 2021-03-22 02:28:12 -08:00
HFO4 53acadf098 Modify: limit forum threads numbers in admin index 2021-03-22 16:35:58 +08:00
HFO4 c0f7214cdb Revert "Fix: OSS SDK will encode all object key (#694)"
This reverts commit 270f617b and fix #802
2021-03-22 16:22:21 +08:00
HFO4 ccaefdab33 Fix: unable to upload file in WebDAV (#803) 2021-03-22 13:50:43 +08:00
HFO4 6efd8e8183 Fix: file size not match while uploading office docs to SharePoint sites 2021-03-21 21:02:31 +08:00
AaronLiuandGitHub 144b534486 Update build.yml 2021-03-20 22:46:01 -08:00
AaronLiuandGitHub e160154d3b Update test.yml 2021-03-20 22:43:40 -08:00
AaronLiuandGitHub 2381eca230 Rename build.yaml to build.yml 2021-03-20 22:42:13 -08:00
AaronLiuandGitHub adde486a30 Create build.yaml 2021-03-20 22:41:58 -08:00
AaronLiuandGitHub a9c0d6ed17 Update and rename build.yml to test.yml 2021-03-20 22:41:28 -08:00
HFO4 595f4a1350 Test: get parament source in OneDrive handler 2021-03-21 14:32:10 +08:00
HFO4 a5f80a4431 Feat: get permanent URL for OneDrive policy 2021-03-20 12:33:39 +08:00
AaronLiuandGitHub 6fb419d998 Fix: downgrade glibc 2021-03-18 00:48:47 -08:00
AaronLiuandGitHub 3f0f33b4fc Update build.yml 2021-03-18 00:44:32 -08:00
HFO4 052e6be393 Update submodule version 2021-03-18 11:29:26 +08:00
HFO4 a4b0ad81e9 Feat: database script for resetting admin password 2021-03-17 14:34:12 +08:00
HFO4 8431906b94 Update version number 2021-03-17 14:21:32 +08:00
HFO4 40476953aa Fix: stop listening HTTP port if unix socket is enabled (#729) 2021-03-17 14:19:05 +08:00
ihipopandGitHub 270f617b9d Fix: OSS SDK will encode all object key (#694)
(cherry picked from commit b9cd82b849065f0d1ad093708f09c8722339bf2a)
2021-03-16 21:56:14 -08:00
HFO4 170f2279c1 Fix: failed to get thumbnails under global OneDrive policy 2021-03-14 11:03:10 +08:00
HFO4 d1377262e3 Fix: ignore requiring SharePoint site ID after edit / nil pointer in user setting routers 2021-03-14 10:26:45 +08:00
HFO4 c9acf7e64e Update submodule 2021-03-12 17:06:10 +08:00
HFO4 4e2f243436 Feat: support using SharePoint site to store files 2021-03-12 17:05:13 +08:00
HFO4 a54acd71c2 Merge remote-tracking branch 'origin/master' 2021-03-11 14:52:27 +08:00
HFO4 fec2fe14f8 Modify: json tag for QueryDate 2021-03-11 14:50:32 +08:00
HFO4 1f1bc056e3 Feat: API for getting object property 2021-03-11 14:50:02 +08:00
AaronLiuandGitHub e44ec0e6bf Update issue templates 2021-03-05 15:44:33 +08:00
HFO4 a93b964d8b Modify: OneDrive file URL cache will refreshed after file is updated 2021-03-03 17:07:26 +08:00
HFO4 d9cff24c75 Modify: disable association_autoupdate in model.File.UpdateSourceName 2021-03-03 14:10:08 +08:00
HFO4 e2488841b4 Test: #765 2021-03-02 12:45:54 +08:00
日下部 詩andGitHub a276be4098 注册帐号时,如果尚未验证,再发一次验证信 (#765)
* 注册帐号时,如果尚未验证,再发一次验证信

* 修正2个bug。 1:未验证显示密码错误 2:未验证无法重发email

* 小修正,如果已存在user,拿已有user资讯取代掉新user资讯来寄送激活码

* 激活码改成激活邮件

* 忘记密码以后,重设二步验证设定

* Revert "忘记密码以后,重设二步验证设定"

This reverts commit c5ac10b11c.

* 實作 https://github.com/cloudreve/Cloudreve/pull/765#discussion_r584313520
2021-03-02 12:43:14 +08:00
HFO4 4cf6c81534 Fix: failed unit test 2021-03-02 12:32:34 +08:00
HFO4 5a66af3105 Fix: failed unit test 2021-03-02 12:21:43 +08:00
HFO4 fc5c67cc20 Feat: disable overwrite for OneDrive policy 2021-03-01 13:27:18 +08:00
HFO4 5e226efea1 Feat: disable overwrite for non-updating put request, only works under local,slave,OneDrive,OSS policy. (#764) 2021-03-01 13:03:49 +08:00
HFO4 c949d47161 Update submodule version 2021-02-28 16:51:27 +08:00
HFO4 e699287ffd Modify: mark as success when deleting a file that does not exist;
Fix: minio is not usable in S3 policy
Modify: use batch request to delete S3 files
2021-02-28 16:48:51 +08:00
Cinhi YoungandGitHub 9c78515c72 Fix: email address should be lowercase for requesting Gravatar (#758) 2021-02-08 19:33:09 +08:00
HFO4 3b22b4fd25 Update version number 2021-01-06 18:18:24 +08:00
HFO4 08d998b41e Update submodule 2021-01-06 17:38:20 +08:00
Breeze ChenandGitHub 488e62f762 Fix qiniu last modify time. (#691) 2021-01-06 17:01:24 +08:00
HFO4 f35ad3fe0a Fix: #663 2021-01-06 16:35:31 +08:00
HFO4 61e6d9b591 Update version number 2020-12-10 17:26:39 +08:00
HFO4 feb1134a7c Update submodule 2020-12-10 17:05:06 +08:00
HFO4 9f2f14cacf Fix: https://github.com/cloudreve/Cloudreve/issues/504 2020-12-10 16:59:45 +08:00
HFO4 055ed0e075 Fix: standardize the use of error codes related to login credentials 2020-12-08 20:13:42 +08:00
HFO4 c87109c8b1 Fix: incorrect attr column type in download table 2020-12-08 19:55:23 +08:00
HFO4 8057c4b8bc Update: submodule 2020-12-08 18:53:20 +08:00
HFO4 5ab93a6e0d Test: frontend middleware 2020-12-08 18:15:02 +08:00
HFO4 5d406f1c6a Feat: use history router mode 2020-12-08 17:36:19 +08:00
HFO4 5b44606276 Test: replace cdn proxy url for OneDrive policy 2020-12-08 17:31:37 +08:00
HFO4 bd2bdf253b Feat: using custom reverse proxying in OneDrive file downloading 2020-12-08 17:30:22 +08:00
HFO4 0cfa61e264 Test: user storage calibration script 2020-12-06 16:50:08 +08:00
HFO4 f7c8039116 Feat: execute database script to calibrate user storage 2020-12-06 16:49:49 +08:00
HFO4 6486e8799b Fix: user storage might be returned twice when canceling uploading request (#645) 2020-12-03 18:10:10 +08:00
HFO4 7279be2924 Fix: user storage might be returned twice when OneDrive uploading canceled in WebDAV requests 2020-12-01 19:22:52 +08:00
HFO4 33f8419999 Merge remote-tracking branch 'origin/master' 2020-11-29 19:16:24 +08:00
HFO4 a5805b022a Feat: enable using LAN endpoint in serverside request of OSS policy (#399) 2020-11-29 19:15:35 +08:00
ae89b402f6 fix: statik data needs to be initialized (#640)
Co-authored-by: xuc2 <xuc2@knownsec.com>
2020-11-25 21:23:26 +08:00
HFO4 0d210e87b3 Fix: aria2 task failed due to limited size of attr filed in DB 2020-11-24 18:47:44 +08:00
HFO4 f0a68236a8 Feat: delete aria2 record in client side (#335) 2020-11-23 19:24:56 +08:00
HFO4 c6110e9e75 Feat: keep folder structure in aria2 transferring 2020-11-23 18:44:13 +08:00
HFO4 d97bc26042 Fix: add recycleLock preventing recycle FileSystem used by another goroutine 2020-11-21 19:32:25 +08:00
HFO4 11c218eb94 Merge branch 'master' of https://github.com/cloudreve/Cloudreve 2020-11-21 18:19:24 +08:00
LoyalsoldierandGitHub 79b8784934 Comply with Golang semantic import versioning (#630)
* Code: compatible with semantic import versioning

* Tools & Docs: compatible with semantic import versioning

* Clean go.mod & go.sum
2020-11-21 17:34:55 +08:00
HFO4 59d50b1b98 Modify: change Unix to UnixSocket in config section 2020-10-26 15:42:18 +08:00
HFO4 746aa3e8ef Test: s3 policy 2020-10-26 15:33:28 +08:00
HFO4 95f318e069 Feat: adapt minio for S3 policy and fix listing files 2020-10-26 15:06:02 +08:00
HFO4 77394313aa Fix: S3 adaption for minio 2020-10-11 13:05:14 +08:00
HFO4 41eb84a221 Update submodule version 2020-10-10 13:38:39 +08:00
mritdandGitHub 40414fe6ae chore(dockerfile): update node image to lts-buster (#557)
* chore(dockerfile): update node image to lts-buster

update node image to lts-buster, because the alpine image cannot be obtained on arm/arm64,
it will support `docker buildx` build after the upgrade.

Signed-off-by: mritd <mritd@linux.com>

* chore(docker): update golang build image

update golang build image

Signed-off-by: mritd <mritd@linux.com>
2020-09-09 14:56:14 +08:00
mritdandGitHub 7df09537e0 fix(db_driver): fix the panic when sqlite3 is used in the conf (#551)
* fix(db_driver): fix the panic when sqlite3 is used in the conf

fix the panic when sqlite3 is used in the conf

ref cloudreve/Cloudreve#550

Signed-off-by: mritd <mritd@linux.com>

* fix(nullpointer): fix possible null pointer error

fix possible null pointer error

Signed-off-by: mritd <mritd@linux.com>
2020-09-03 12:07:38 +08:00
mritdandGitHub f478c38307 chore(docker): add dockerfile (#549)
* chore(docker): add dockerfile

add dockerfile

Signed-off-by: mritd <mritd@linux.com>

* chore(docker): fix docker file

fix docker file

Signed-off-by: mritd <mritd@linux.com>

* chore(docker): mv bin file to /cloudreve

mv bin file to /cloudreve

Signed-off-by: mritd <mritd@linux.com>

* chore(docker): remove GOPROXY

remove GOPROXY

Signed-off-by: mritd <mritd@linux.com>
2020-09-03 12:05:00 +08:00
GuerraMorganandGitHub bfd2340732 Add: Unix Socket support (#466)
* Update conf.go

* Update driver.go

* Update session.go

* Update defaults.go

* Update main.go

* Update conf.go

* Update defaults.go
2020-08-12 20:31:28 +08:00
ZZFandGitHub dd50ef1c25 添加S3策略的支持 (#425)
* 添加亚马逊S3策略的支持

* 添加CDN支持,公有目录删除无用参数

* 增加Region
2020-06-05 14:45:24 +08:00
HFO4 27bf8ca9b2 Fix: node js version 2020-06-01 20:27:06 +08:00
HFO4 c71a2c5b64 Modify: version number to 3.1.1 2020-06-01 20:22:14 +08:00
HFO4 a7ba357cb8 Fix: hash mark in file name lead to 404 error (#405) 2020-05-30 19:35:28 +08:00
HFO4 14f5982b47 Modify: set node_js version to node_js in travis.yml 2020-05-24 11:31:00 +08:00
HFO4 e607311268 Update: version number for 3.1.0 2020-05-24 10:47:30 +08:00
HFO4 acc5d53bab Update: submodules 2020-05-24 10:36:48 +08:00
HFO4 aa3e8913ab Feat: add ".zip" suffix if not specified while creating compressed file 2020-05-24 10:36:26 +08:00
HFO4 ee0f8e964d Feat: eject internal static files 2020-05-23 13:57:02 +08:00
HFO4 60745ac8ba Merge remote-tracking branch 'origin/master' 2020-05-23 13:19:10 +08:00
HFO4 bfb5b34edc Fix: concurrent logging lock / Feat: listen SSL (#287) 2020-05-23 13:17:48 +08:00
hiCasperandGitHub a5000c0621 Modify: update actions (#398) 2020-05-20 11:48:00 +08:00
HFO4 e038350cf0 Merge branch 'master' of https://github.com/cloudreve/Cloudreve 2020-05-19 11:25:12 +08:00
HFO4 5af3c4e244 Fix: directory renaming should not be limited by file extensions (#395) 2020-05-19 11:25:01 +08:00
AaronLiuandGitHub 7ed14c4d81 Update FUNDING.yml 2020-05-19 11:12:45 +08:00
AaronLiuandGitHub 869c0006c5 Create FUNDING.yml 2020-05-19 11:11:56 +08:00
HFO4 4c458df666 Fix: failed tests while static files not loaded 2020-05-19 10:34:16 +08:00
HFO4 ed684420a2 Modify: actions should not perform clean before build 2020-05-19 10:26:24 +08:00
HFO4 2076d56f0f Feat: dynamic writing site title, favicon, description, custom html (#286) 2020-05-19 10:24:15 +08:00
HFO4 280308bc05 Modify: increase OneDrive client uploading chunk size to 100MB 2020-05-13 09:09:11 +08:00
HFO4 1172765c58 Feat: option for using SSL connection in mail queue 2020-05-11 09:29:19 +08:00
HFO4 58856612e2 Feat: create empty file in web panel (#305) 2020-05-09 10:35:18 +08:00
HFO4 ee0f224cbb Feat: use Monaco code editor 2020-05-03 13:16:40 +08:00
HFO4 e8a6df9a86 Feat: import file from existing outer folder 2020-05-02 10:22:28 +08:00
HFO4 b02d27ca0a Merge branch 'master' of https://github.com/cloudreve/Cloudreve 2020-05-02 10:15:57 +08:00
TSandGitHub 51f66eb06b Feat: ICP 备案信息 (#348) 2020-05-01 13:50:16 +08:00
HFO4 0df8a9ba65 Modify: search shares without login required 2020-05-01 09:33:59 +08:00
HFO4 79daf92896 Test: List files in OneDrive 2020-05-01 09:22:27 +08:00
HFO4 8a2be58ef3 Feat: List files in OneDrive 2020-04-30 11:45:35 +08:00
HFO4 ce7784090f Feat: List files in upyun bucket 2020-04-30 10:37:48 +08:00
HFO4 dfb663a6e0 Feat: List files in Qiniu bucket 2020-04-29 10:37:15 +08:00
HFO4 cfaf20926f Feat: List files in COS bucket 2020-04-29 10:36:52 +08:00
HFO4 305497e7cb Test: oss.List 2020-04-29 09:18:26 +08:00
HFO4 52c2422be9 Feat: list oss files 2020-04-28 11:43:32 +08:00
HFO4 1afc750dae Modify: create folder if not exist while importing files 2020-04-28 10:47:40 +08:00
HFO4 960c886496 Test: slave side list file 2020-04-28 10:16:04 +08:00
HFO4 5d579cdadc Feat: slave side list file 2020-04-28 10:02:53 +08:00
HFO4 d5fc5745b4 Fix: failed test due to missing AdminCreateImportTask controller 2020-04-27 14:45:27 +08:00
HFO4 a732025d5a Update: submodules 2020-04-27 14:40:09 +08:00
HFO4 030fd4ac57 Test: task.ImportTask 2020-04-27 14:39:49 +08:00
HFO4 9eeb4b6d19 Feat: task for importing file from existing filesystem 2020-04-27 14:39:16 +08:00
HFO4 36e5b31f73 Modify: add recursive options for list method
Test: local.List
2020-04-27 10:31:34 +08:00
cha0sCatandGitHub 26d4d34837 Feat: webdav 适配 rclone (#330)
rclone在传输时会反复创建父目录, 导致cloudreve返回409, 最终导致传输失败.
因此检测如果是rclone则忽略文目录已存在错误
2020-04-27 10:01:00 +08:00
HFO4 8c547a05fd Fix: mismatched pointer receiver in oss.Driver 2020-04-24 11:14:32 +08:00
HFO4 f7311f906b Feat: add List method to Handler interface / implement local.List 2020-04-24 11:08:07 +08:00
HFO4 6006ff4d22 Feat: regenerate when thumbnail files not exist 2020-04-24 10:18:01 +08:00
ihipopandGitHub 034ed956a3 Bad syntax for struct tag value authn (#314) 2020-04-23 09:30:19 +08:00
hiCasperandGitHub 700c5795f5 Support Github Actions (#310) 2020-04-22 11:15:26 +08:00
HFO4 8c3287d380 Test: Policy.IsThumbExist / filesystem.AddFile 2020-04-22 11:10:43 +08:00
HFO4 304e7b502c Feat: thumbnail support for COS policy 2020-04-22 11:09:33 +08:00
HFO4 514e069113 Refactor: decide if there is a thumbnail based on the file extension 2020-04-22 11:04:35 +08:00
HFO4 7b571499a7 Feat: forcibly delete files in dashboard (#277) 2020-04-21 09:47:54 +08:00
HFO4 8b68d46bdf Update: submodules 2020-04-19 10:12:26 +08:00
HFO4 ab3b59e63d Feat: add option to force delete file record in database 2020-04-19 10:09:16 +08:00
HFO4 9910f8d732 Modify: check static file version when statics folder exists 2020-04-12 12:46:59 +08:00
HFO4 99033d61c6 Add: arm64 build option 2020-04-12 12:00:01 +08:00
HFO4 e9f3a55eb8 Modify: migrate from travis.org to .com 2020-04-11 11:27:17 +08:00
HFO4 3cc9940924 Remove: arm64 build option 2020-04-11 11:17:34 +08:00
HFO4 bcdf94fd93 Fix: missing sys/cdefs.h in CI building 2020-04-11 10:59:51 +08:00
HFO4 3c09ad7c02 Feat: arm64 build option in CI 2020-04-11 10:45:18 +08:00
HFO4 7be0366b1f Dep: update submodule 2020-04-11 10:03:21 +08:00
HFO4 0575b0aa92 Fix: search function should not convert case (#288) 2020-04-11 09:42:22 +08:00
HFO4 2e342806b6 Fix: missing deps in login recaptcha service 2020-04-11 09:15:27 +08:00
HFO4 cf9dc1c24f Dep: update submodule 2020-04-11 09:11:07 +08:00
topjohncianandGitHub e58fb82463 Feat: ReCaptcha support (#292)
* Add custom mysql database port.

* Modify: add cloudreve bin file to .gitignore

* Feat:增加后端对ReCaptcha的支持
P.S.必须要执行迁移
2020-04-11 09:09:44 +08:00
HFO4 fa900b166a Feat: check static files version 2020-04-08 10:00:03 +08:00
HFO4 2e43f8ed5b Modify: use INT represent Database port 2020-04-08 09:04:03 +08:00
topjohncianandGitHub 554493dea4 Add custom mysql database port. (#289) 2020-04-08 08:59:43 +08:00
HFO4 816b537787 Fix: permission error while creating folder recursively 2020-04-07 11:09:27 +08:00
HFO4 e07b09186d Modify: use 644 permission when creating a new physical directory (#274) 2020-04-07 10:56:02 +08:00
HFO4 8c7d075484 Fix: repeated return of capacity when OneDrive WebDAV upload canceled 2020-04-07 10:51:54 +08:00
HFO4 46743f3c1e Fix: unsupported GET parameters in public OSS bucket 2020-04-07 10:15:11 +08:00
HFO4 1a1543f190 Fix: catch internal error in OneDrive OAuth callback 2020-04-07 10:08:34 +08:00
HFO4 4aef12bf7e Merge remote-tracking branch 'origin/master' 2020-04-06 09:05:57 +08:00
HFO4 691c9aeb7d Feat: gzip support for static files 2020-04-06 09:05:30 +08:00
yeungcandGitHub 6285e45e34 Fix: filename and code typo (#260)
* Rename handller.go to handler.go

* Rename handller.go to handler.go

* Rename handller_test.go to handler_test.go

* Rename handller.go to handler.go

* Rename handller.go to handler.go

* Rename handller.go to handler.go

* Rename handller.go to handler.go

* Fix typo
2020-03-23 13:44:59 +08:00
HFO4 f594d0ab83 Feat: check new versions while booting 2020-03-18 11:36:34 +08:00
HFO4 25d1735c1d Feat: compatible digest algorithm with V2 2020-03-18 11:21:04 +08:00
HFO4 c4c174f560 Fix: redirect should be 302 status in dashboard 2020-03-18 11:11:57 +08:00
HFO4 175c4d781f Fix: absolute path cannot be saved for new policy 2020-03-18 10:45:33 +08:00
HFO4 87fde687eb Fix: files with percent sign (%) cannot be deleted in OneDrive 2020-03-18 10:42:41 +08:00
HFO4 65cf0f57aa Fix: failed test due to policy cache 2020-03-18 09:47:06 +08:00
HFO4 0eb04ed0ea Feat: cache for OneDrive META request 2020-03-18 09:35:00 +08:00
HFO4 96983ddc70 Feat: custom SQLite db file path 2020-03-18 09:03:25 +08:00
HFO4 b98e5efb83 Merge remote-tracking branch 'origin/master' 2020-03-17 16:14:43 +08:00
HFO4 ff2dae80f0 Fix: incorrect thumb path detect while deleting files 2020-03-17 16:11:11 +08:00
HFO4 32c0232105 Fix: file preview URL in share page should not be accessed directly 2020-03-17 15:57:38 +08:00
AaronLiuandGitHub a05a3de0e1 Update: typo 2020-03-15 21:21:34 +08:00
HFO4 79f898e0a9 Update: submodule 2020-03-15 10:13:40 +08:00
HFO4 d1ca65461c Fix: incorrect capacity unit for OSS traffic limit 2020-03-15 09:56:50 +08:00
HFO4 15074015b3 Fix: file not deleted when aria2 download complete 2020-03-15 09:18:15 +08:00
HFO4 e1aced0f01 Modify: check DB version before migration 2020-03-14 18:12:26 +08:00
HFO4 75da09c339 Fix: mis-spelling 2020-03-13 11:28:03 +08:00
HFO4 7636e59dfe Update: license link 2020-03-12 19:22:07 +08:00
HFO4 e34e67648f Add: README & License 2020-03-12 19:20:40 +08:00
HFO4 da7b857e00 Merge branch 'master' of https://github.com/cloudreve/Cloudreve 2020-03-12 17:11:56 +08:00
HFO4 bdb9b5e1ca Update: submodule 2020-03-12 17:09:50 +08:00
hiCasperandGitHub 2a2221c8b7 Fix typo (#247) 2020-03-12 16:00:30 +08:00
HFO4 36cec067d9 Fix: OneDrive monitoring should continue when error occurs 2020-03-12 15:56:06 +08:00
HFO4 c142da17e5 Modify: use public URL for asserts module 2020-03-12 12:07:07 +08:00
HFO4 2f79f5bc07 Modify: use new frontend repo 2020-03-12 11:08:43 +08:00
HFO4 4533e654a5 Fix: apt-get update before travis CI install dependency 2020-03-12 10:25:21 +08:00
HFO4 40f8a73f89 Release: 3.0.0-beta1 2020-03-12 10:15:55 +08:00
HFO4 c74ed10dbd Test: aria2 / filesystem.image 2020-03-12 10:12:13 +08:00
HFO4 297fc8d5bb Fix: failed test due to relative path 2020-03-12 09:40:29 +08:00
HFO4 71876a79cd Fix: failed test due to relative path 2020-03-12 09:30:57 +08:00
HFO4 37de715541 Fix: failed test due to relative path 2020-03-12 09:15:30 +08:00
HFO4 83b292c9ba Modify: travis CI build and test 2020-03-12 08:46:14 +08:00
HFO4 210af8f9e1 Fix: Root user should always have admin permission 2020-03-11 19:56:20 +08:00
HFO4 9a56c3c1af Feat: travis ci deploy 2020-03-11 19:42:22 +08:00
HFO4 7a0e466616 Feat: travis ci deploy 2020-03-11 19:04:55 +08:00
HFO4 de3a61561a Feat: travis ci deploy 2020-03-11 19:02:38 +08:00
HFO4 d0f04ca88e Feat: travis ci deploy 2020-03-11 18:48:58 +08:00
HFO4 2585e86a31 Feat: travis ci deploy 2020-03-11 18:46:03 +08:00
HFO4 c54679d06f Feat: travis ci deploy 2020-03-11 18:41:58 +08:00
HFO4 0ec97ca6a2 Feat: travis ci deploy 2020-03-11 18:37:57 +08:00
HFO4 074522cfda Feat: travis ci deploy 2020-03-11 18:25:31 +08:00
HFO4 8c49f40ed2 Feat: travis ci deploy 2020-03-11 18:22:48 +08:00
HFO4 2afab1022f Feat: travis ci deploy 2020-03-11 18:22:35 +08:00
HFO4 213c92b522 Ready for release 2020-03-11 18:03:37 +08:00
HFO4 439b5a2ce0 Modify: stop recycle filesystem when generate thumbnails 2020-03-11 16:34:19 +08:00
HFO4 4de0a2577a Fix: recycle error when handling upload task 2020-03-11 16:29:46 +08:00
HFO4 8ad7702736 Fix: relative path for SQLite file 2020-03-11 15:46:24 +08:00
HFO4 45b54b3455 Modify: clean useless codes 2020-03-11 15:45:00 +08:00
HFO4 09de05548f Modify: clean crontab 2020-03-11 15:25:27 +08:00
HFO4 4ba24e0cf1 Modify: clean modals 2020-03-11 15:22:21 +08:00
HFO4 4d70f9fa3e Fix: get execute file path dynamically 2020-03-11 10:32:35 +08:00
HFO4 b6e1e04ce0 Fix: panic while decompress files / Cannot edit policy 2020-03-11 09:34:29 +08:00
HFO4 45ec4b3f8b Fix: wrong upload URL for cos policy 2020-03-10 19:15:09 +08:00
HFO4 d0718433bc Update submodules 2020-03-10 14:39:54 +08:00
HFO4 6e3e81e031 Modify: service worker start url 2020-03-10 13:07:55 +08:00
HFO4 c2ec4cd8a7 Modify: add commit info in debug 2020-03-10 12:46:17 +08:00
HFO4 57e53116d9 Update sub module 2020-03-10 12:36:58 +08:00
HFO4 cb57fdbb59 Fix: nil pointer and initial policy file type wildcard 2020-03-10 12:10:30 +08:00
HFO4 27e1da8238 Modify: build asserts when release 2020-03-10 11:07:37 +08:00
HFO4 d16f9784e4 Fix: nil pointer in crontab 2020-03-10 11:05:17 +08:00
Aaron d80446d30f Feat: cross compile script 2020-03-10 02:39:19 +00:00
Aaron 98c122f047 Fix: mimatch shell in build.sh 2020-03-09 11:30:43 +00:00
HFO4 68d3131521 Feat: cross compile script 2020-03-09 16:53:01 +08:00
HFO4 30311d181d Feat: embed static files 2020-03-09 14:07:36 +08:00
HFO4 1d0d6e5f31 Feat: git submodule / static file 2020-03-09 13:23:13 +08:00
HFO4 beb16bc3c1 Feat: git submodule 2020-03-09 13:09:41 +08:00
HFO4 809af5bf4e Feat: task list in dashboard 2020-03-09 12:30:43 +08:00
HFO4 3b5af8da47 Feat: share file list in dashboard 2020-03-09 10:59:42 +08:00
HFO4 9166a4ecd6 Feat: delete file in dashboard 2020-03-09 10:17:59 +08:00
HFO4 768ffa24ec Feat: preview file in dashboard 2020-03-08 13:53:13 +08:00
HFO4 27c0b6e886 Feat: ban/un-ban user 2020-03-08 12:54:04 +08:00
HFO4 19c70f8cfc Feat: edit/add users 2020-03-08 10:49:34 +08:00
HFO4 38161250e8 Feat: list users 2020-03-07 14:04:18 +08:00
HFO4 c7247f5b87 Feat: edit/list user group 2020-03-07 13:00:51 +08:00
HFO4 be8aa7b01d Feat: OneDrive OAuth callback / edit policy 2020-03-02 16:20:33 +08:00
HFO4 2471dacec1 Feat: OneDrive OAuth 2020-03-01 17:57:18 +08:00
HFO4 c30c19ca3e Feat: create SFC for oss callback 2020-03-01 16:25:56 +08:00
HFO4 e8c4660c38 Feat: check policy update before upload 2020-02-27 17:12:59 +08:00
HFO4 2f1f619f2f Fix: failed test due to modifications 2020-02-27 15:34:16 +08:00
HFO4 c4eada2723 Modify: oss handle sign URL 2020-02-27 15:12:15 +08:00
HFO4 bd643fa2d5 Feat: remote test ping and ping-back 2020-02-27 11:17:59 +08:00
HFO4 f1ef21e195 Feat: add local policy 2020-02-26 15:11:06 +08:00
HFO4 c1d2b933aa Feat: RWMutex / reload for aira2 2020-02-25 14:02:14 +08:00
HFO4 48659f6952 Feat: uploading / transfer settings 2020-02-24 15:52:13 +08:00
HFO4 000a48ff06 Feat: mail SMTP settings 2020-02-23 18:40:14 +08:00
HFO4 ef42ec3927 Modify: create Web Authn instance when needed 2020-02-23 15:50:41 +08:00
HFO4 ce2a70df68 Feat: add read/write lock for authn 2020-02-23 15:33:53 +08:00
HFO4 3ce4b87f2b Feat: login / register setting in dashboard 2020-02-23 15:19:38 +08:00
HFO4 04d13bd071 Feat: dynamically generate manifest.json 2020-02-23 11:41:39 +08:00
HFO4 31d4a0e1c2 Feat: admin dashboard homepage 2020-02-23 10:19:13 +08:00
HFO4 49f784104e Fix: get site summary in dashboard 2020-02-22 16:22:04 +08:00
HFO4 22cec36751 Fix: failed uint test due to aria2 internal package 2020-02-22 12:30:57 +08:00
HFO4 8d9dee6e3d Test: migration modifications 2020-02-22 12:25:23 +08:00
HFO4 a8272a66b7 Modify: move aria2 into internal packages / migration version check 2020-02-22 12:18:49 +08:00
HFO4 1ac4767db7 Feat: reset password by Email 2020-02-22 10:36:50 +08:00
HFO4 7027a96258 Feat: user activation by Email 2020-02-22 09:50:34 +08:00
HFO4 81d6988a50 Feat: user register / send activate email 2020-02-21 15:15:14 +08:00
HFO4 7c07b623f6 Feat: 2-FA login verification 2020-02-21 13:48:34 +08:00
HFO4 11e45bc751 Fix: failed unit test due to update with callback 2020-02-21 12:47:32 +08:00
HFO4 7dcc7a4880 Test: Task list / file delete 2020-02-21 12:09:43 +08:00
HFO4 9b3f5b0efd Test: WebDAV model 2020-02-21 11:32:59 +08:00
HFO4 5363b90167 Test: options / WebDAV middleware 2020-02-21 11:16:25 +08:00
HFO4 c817f70f8e Feat: Webauthn / theme changing 2020-02-21 10:08:47 +08:00
HFO4 80268e33bf Feat: enable 2FA / password management 2020-02-20 12:42:38 +08:00
HFO4 58d8695c53 Fix: endless loop while creating nested folders 2020-02-20 08:59:11 +08:00
HFO4 4420a75c04 Feat: user setting 2020-02-19 16:05:54 +08:00
HFO4 33a917cc75 Feat: user profile 2020-02-18 15:34:40 +08:00
HFO4 f91792bc64 Feat: list tasks 2020-02-18 14:45:38 +08:00
HFO4 b4219927d6 Feat: WebDAV mount folders 2020-02-18 13:45:59 +08:00
HFO4 86889e2fac Feat: WebDAV account management 2020-02-18 12:10:28 +08:00
HFO4 663b827a1d Test: pkg modifications 2020-02-17 14:17:06 +08:00
HFO4 0502a0f212 Test: share/storage/user model 2020-02-17 14:04:48 +08:00
HFO4 0253b4e5b6 Feat: payjs payment 2020-02-17 13:14:18 +08:00
HFO4 f8c14b3826 Feat: vas alipay 2020-02-17 12:33:54 +08:00
HFO4 41f9f3497f Feat: vas redeem 2020-02-17 10:26:31 +08:00
HFO4 ca0f244109 Feat: vas for score 2020-02-17 09:48:39 +08:00
HFO4 e38a60ea44 Feat: vas for group / storage pack 2020-02-16 14:31:23 +08:00
HFO4 faf46745bc Feat: cron / Fix: users status check 2020-02-15 14:02:21 +08:00
HFO4 44d6ca487c Feat: mount storage policy for folders in WebDAV 2020-02-13 15:27:40 +08:00
HFO4 a0a9686959 Feat: search multiple keywords 2020-02-13 13:17:09 +08:00
HFO4 cfbfbc3c55 Feat: list/search/update/delete shares 2020-02-13 11:53:24 +08:00
HFO4 bb63ea7142 Test: model.Tags / modifications 2020-02-12 13:19:25 +08:00
HFO4 15f4b1819b Feat: add and delete file tags 2020-02-12 11:38:04 +08:00
HFO4 127d0236f9 Feat: filter and search file 2020-02-11 11:13:20 +08:00
HFO4 8f28a9c346 Modify: change raw object ID to Hash ID in share service 2020-02-10 14:29:27 +08:00
HFO4 9be1b4366f Modify: change raw object ID to Hash ID in file service 2020-02-10 13:10:59 +08:00
HFO4 f235ad1def Fix: aria2 RPC retry / return NoT_FOUND error while listing not existed path 2020-02-10 10:33:39 +08:00
HFO4 7a6c84a115 Fix: unsafe pointer while initializing unfinished aria2 task 2020-02-09 10:52:06 +08:00
HFO4 d30159579f Feat: list downloading file 2020-02-08 15:37:51 +08:00
HFO4 356ac8d608 Modify: delete temp file inside monitor lifecycle 2020-02-08 10:02:08 +08:00
HFO4 096483b6ee Fix: do hard-copy when put file content in WebDAV 2020-02-07 14:47:59 +08:00
HFO4 14982f5e70 Fix: handle none-utf8 encoding in decompression 2020-02-07 14:01:53 +08:00
HFO4 16613a6113 Modify: return parent folder id while listing objects 2020-02-07 13:54:37 +08:00
HFO4 4c530a26a0 Test: pkg/task / Fix: failed test due to policy cache 2020-02-07 11:47:52 +08:00
HFO4 fc5b7d42c8 Test: pkg/task 2020-02-06 16:01:06 +08:00
HFO4 2b853dddd3 Test: aria2 related 2020-02-06 13:53:47 +08:00
HFO4 60cd8c3a89 Test: download / task models 2020-02-06 11:07:00 +08:00
HFO4 cde49e6e98 Feat: group-defined aria2 download options 2020-02-06 10:27:20 +08:00
HFO4 c29695a40d Feat: cancel aria2 download task 2020-02-06 10:07:46 +08:00
HFO4 1a93c9a2b9 Feat: retry for Onedrive SimpleUpload 2020-02-05 15:17:49 +08:00
HFO4 491e4de9de Feat: download torrent / multiple file / select file 2020-02-05 15:11:34 +08:00
HFO4 3ed84ad5ec Feat: validate / cancel task while downloading file in aria2 2020-02-05 12:58:26 +08:00
HFO4 8c7e3883ee Feat: handle aria2 download complete 2020-02-05 11:22:19 +08:00
HFO4 fe8f1b1ef5 Feat: creat uri aria2 download task 2020-02-04 15:29:52 +08:00
HFO4 7804b4efb1 Fix: Onedrive have batch requests limit for 20 per request 2020-02-04 10:48:26 +08:00
HFO4 91e202c7e6 Feat: decompression task 2020-02-03 13:23:33 +08:00
HFO4 e722c33cd5 Feat: task queue / compression task 2020-02-02 14:40:07 +08:00
HFO4 b1490a665c Fix: missing x-oss-process params in thumb url in public oss bucket 2020-02-01 14:36:57 +08:00
HFO4 8bb2c2b0c5 Test: share related operation in filesystem 2020-02-01 14:26:21 +08:00
HFO4 ab739ea07c Test: Share related middleware 2020-02-01 13:47:10 +08:00
HFO4 b49202e7e1 Test: Share model 2020-02-01 13:14:50 +08:00
HFO4 437bdf46d4 Feat: thumb for shared folder 2020-02-01 10:34:23 +08:00
HFO4 9fe451ad4b Fix: cache-control header in thumb redirect request 2020-02-01 10:08:34 +08:00
HFO4 4f0c2bbb29 Feat: readme in shared folder 2020-01-31 15:12:15 +08:00
HFO4 cc2c3b3f0f Feat: archive download in shared folder 2020-01-31 13:18:32 +08:00
HFO4 f5d79b1f94 Feat: re-save shared folder to user's space 2020-01-31 11:27:52 +08:00
HFO4 b1a9943b0c Feat: download / preview files for shared folder 2020-01-30 14:22:03 +08:00
HFO4 0edbbfc9ea Feat: list files for shared folder 2020-01-30 13:21:21 +08:00
HFO4 a0c320b964 Feat: set default view method in file manager 2020-01-29 14:25:14 +08:00
HFO4 e2f6dab70c Feat: save re-save single shared file 2020-01-29 13:45:27 +08:00
HFO4 0d7c0793b2 Feat: preview shared text/doc file 2020-01-29 12:16:52 +08:00
HFO4 68704f8646 Feat: options to disable preview in file sharing 2020-01-29 11:03:09 +08:00
HFO4 1ff4d59978 Feat: preview shared file 2020-01-28 13:40:19 +08:00
HFO4 7f0feebf42 Feat: download file from single file share 2020-01-28 12:41:00 +08:00
HFO4 0977b36f8b Feat: get share info / unlock share 2020-01-27 13:34:39 +08:00
HFO4 94b13393a9 Feat: hash id decode and verification 2020-01-26 14:57:07 +08:00
HFO4 880d224169 Test: hash id generate 2020-01-26 13:16:02 +08:00
HFO4 0ee0ac5e89 Feat: generate share URL 2020-01-26 13:07:05 +08:00
HFO4 4abd5b2346 Feat: cos policy upload/download in server-side 2020-01-25 11:43:13 +08:00
HFO4 c34f211d7e Feat: get source url in COS 2020-01-25 11:20:31 +08:00
HFO4 dc32e85492 Fix: capacity should be returned back when put failed 2020-01-25 10:40:53 +08:00
HFO4 8d437a451c Feat: COS credential / upload callback 2020-01-23 12:38:32 +08:00
HFO4 e894450d5e Modify: cancel race test 2020-01-22 15:11:03 +08:00
HFO4 4baddecd8e Fix: ignore data-race detector in onedrive tests 2020-01-22 15:06:56 +08:00
HFO4 f3c7263b52 Fix: ignore data-race detector in onedrive tests 2020-01-22 14:57:10 +08:00
HFO4 a70bc7b908 Fix: ignore data-race detector in onedrive tests 2020-01-22 14:52:05 +08:00
HFO4 588514b4e0 Test: get filesystem from callback context 2020-01-22 14:41:12 +08:00
HFO4 8672042d61 Test: onedrive related 2020-01-22 14:26:13 +08:00
HFO4 0d2e3cc717 Test: Onedrive.OAuth 2020-01-22 10:50:47 +08:00
HFO4 d3f132de6d Fix: thumbnails for 21Vianet OneDrive 2020-01-22 08:58:59 +08:00
HFO4 752ce5ce62 Feat: resume upload in server side 2020-01-21 15:36:04 +08:00
HFO4 06ff8b5a50 Feat: get OneDrive thumbnails 2020-01-21 13:27:20 +08:00
HFO4 6aee31341f Feat: async monitor OneDrive resume upload progress 2020-01-21 11:49:46 +08:00
HFO4 dd5f6e3d25 Feat: onedrive client upload / callback 2020-01-20 14:34:21 +08:00
HFO4 807aa5ac18 Feat: OneDrive OAuth / refresh token 2020-01-19 12:52:36 +08:00
HFO4 fa3b51096a Feat: upyun download / thumb / sign 2020-01-18 14:08:43 +08:00
HFO4 84a6218d3a Test: oss callback signature verification 2020-01-18 12:51:07 +08:00
HFO4 5befbc21d0 Feat: upyun callback & authentication 2020-01-18 10:40:03 +08:00
HFO4 21ec3fc710 Modify: use base64-URLEncoding to encode signature hash 2020-01-17 14:39:30 +08:00
HFO4 68d4a86166 Fix: storage policy should be re-dispatched according to policy id in upload session 2020-01-17 14:35:21 +08:00
HFO4 b862ddb666 Fix: file should be deleted when callback return error 2020-01-17 14:24:51 +08:00
HFO4 f7ecbce64c Feat: generate upload credentials for upyun 2020-01-17 14:05:51 +08:00
HFO4 3da87ba7cf Test: oss driver 2020-01-17 13:04:14 +08:00
HFO4 83a17645a1 Feat: Put file in oss handler 2020-01-17 10:52:43 +08:00
HFO4 7eda63f089 Feat: Get file for oss handler 2020-01-16 15:50:58 +08:00
HFO4 286f76cbec Feat: download file / speed limit in oss policy 2020-01-16 14:28:35 +08:00
HFO4 dd198becce Feat: client-upload file in oss 2020-01-16 13:36:13 +08:00
HFO4 0e62665d7f Fix: do hard-copy when editing file with soft links 2020-01-16 10:11:16 +08:00
HFO4 098aa0a0c0 Fix: failed unit test due to setting name change 2020-01-15 16:10:25 +08:00
HFO4 90f82100cf Feat: put / get file in qiniu policy 2020-01-15 16:03:23 +08:00
HFO4 7fbbcefc57 Feat: get thumb & download file in qiniu policy 2020-01-15 14:15:25 +08:00
HFO4 534e127f87 Test: qiniu handler get token 2020-01-15 11:03:26 +08:00
HFO4 e8d21b1e9b Feat: qiniu upload & callback 2020-01-15 10:14:15 +08:00
HFO4 5be7ec98c1 Feat: user storage pack 2020-01-14 10:32:54 +08:00
HFO4 f3e78ec4ff Fix: failed unit test 2020-01-13 12:51:20 +08:00
HFO4 57d2ad9e5f Test: remote handler put 2020-01-13 11:03:51 +08:00
HFO4 37e78cb39b Feat: generate upload server url from policy 2020-01-13 10:03:45 +08:00
HFO4 6b6bfb4c6b Modify: FileName header in remote put request should be urlencoded 2020-01-13 09:47:04 +08:00
HFO4 4b6fbc0de2 Feat: remoter handler get content 2020-01-04 19:44:38 +08:00
HFO4 c23d129dbb Modify: use path package in app level 2020-01-04 16:21:43 +08:00
HFO4 d94896041e Fix: cannot edit file in remote server / Modify: separate preview and text-file content controller 2020-01-04 15:49:08 +08:00
HFO4 93dc25aabb Test: remote handler get & request chan operations / Modify: GET request to remote server should return error http status code 2020-01-04 15:17:27 +08:00
HFO4 aeca161186 Feat: cancel archive action / request with context 2020-01-02 15:36:13 +08:00
HFO4 1393659668 Feat: GET interface for remote policy 2020-01-02 14:51:17 +08:00
HFO4 0f93864c8e Modify: add time.Now for expiration inside signing function 2020-01-02 13:41:57 +08:00
HFO4 9c48f4b7ad Feat: remote file thumb preview 2020-01-02 13:31:41 +08:00
HFO4 b6102c3ae5 Fix: policy should be re-dispatch while getting thumbnails 2020-01-02 13:10:04 +08:00
HFO4 a75be3a927 Add: GetIntSetting helper 2020-01-02 12:44:53 +08:00
HFO4 fffcf1aa1b Test: remote handler.delete 2020-01-01 20:34:25 +08:00
HFO4 bf0998f3a5 Fix: unclosed file after get thumbnails 2020-01-01 20:17:50 +08:00
HFO4 ee08821361 Feat: remote delete file / Fix: broken Filesystem recycle in upload request 2020-01-01 20:15:05 +08:00
HFO4 e9f02940ee Test: remote handler.source 2019-12-31 14:38:28 +08:00
HFO4 b19910867e Feat: download / preview files in slave side 2019-12-31 14:21:57 +08:00
HFO4 35c2a5c977 Test: filesystem/Preview 2019-12-31 13:31:20 +08:00
HFO4 8a262a15d5 Modify: Decide whether to redirect when previewing based on storage policy 2019-12-31 13:09:26 +08:00
HFO4 eceee2fc76 Test: remote callback auth 2019-12-30 19:56:01 +08:00
HFO4 4a5782b4e5 Feat: remote upload callback / validation 2019-12-30 19:37:21 +08:00
HFO4 d29b7ef6f8 Feat: auth for remote callback / Modify: use map to store hooks in filesystem 2019-12-30 19:08:38 +08:00
HFO4 ca9f44c06c Test: SlaveAfterUpload hook 2019-12-29 17:11:54 +08:00
HFO4 64342fa88d Feat: send remote uploading callback 2019-12-29 17:04:08 +08:00
HFO4 5b9de0e097 Feat: use sync.pool to obtain new FileSystem instance 2019-12-29 14:31:03 +08:00
HFO4 de4793aacb Modify: auth instance as first param in SignURI/Request 2019-12-29 13:50:23 +08:00
HFO4 b5ee3ee609 Fix: cors middleware should be applied directly to root router 2019-12-29 13:15:09 +08:00
HFO4 ac2de841d2 Merge remote-tracking branch 'origin/master' 2019-12-28 15:55:09 +08:00
HFO4 2b8921e9fd Fix: untracked files 2019-12-28 15:54:16 +08:00
HFO4 cf8b5f4d1e Feat: file uploading token sign for remote policy 2019-12-28 15:50:56 +08:00
HFO4 132c7a8fcb Feat: file uploading in slave mode 2019-12-28 13:14:00 +08:00
HFO4 6470340104 Add: upload controller in slave mode 2019-12-27 21:15:05 +08:00
HFO4 4f8558d1e8 Add: uploadPolicy serializer 2019-12-24 11:50:44 +08:00
HFO4 f8c8604cda Feat: auth middleware for complex request 2019-12-24 11:42:23 +08:00
HFO4 90827b2441 Feat: sign http request / read running mode from config file 2019-12-23 13:27:18 +08:00
HFO4 fd7b6e33c8 Test: auth middleware for WebDAV 2019-12-23 11:22:46 +08:00
HFO4 cf90ab5a9a Fix: unable to save office file in root directory of WebDAV 2019-12-21 18:32:13 +08:00
HFO4 bb27d1d587 Test: remove test for internal xml package 2019-12-21 13:01:18 +08:00
HFO4 91b873065a Test: FileInfo interface 2019-12-21 12:49:48 +08:00
HFO4 327765a7be Fix: missing ttl check in memstore.Get 2019-12-21 12:29:58 +08:00
HFO4 3e49c9f4f6 Remove: azure-pipelines.yml 2019-12-21 12:18:33 +08:00
HFO4 acb741bfc2 Merge branch 'master' of github.com:HFO4/Backend-V3 2019-12-21 12:17:44 +08:00
AaronLiu 477c4f1a7e Update azure-pipelines.yml for Azure Pipelines 2019-12-20 21:24:52 +08:00
AaronLiu 0a877f5712 Set up CI with Azure Pipelines
[skip ci]
2019-12-20 21:21:25 +08:00
HFO4 e97ed216f2 Feat: finish WebDAV adaptation 2019-12-20 15:08:04 +08:00
HFO4 c1b02380ac Feat: adapt copy method for WebDAV 2019-12-20 11:59:09 +08:00
HFO4 9fdf2fe7ab Feat: adapt major methods of WebDAV for Cloudreve file system 2019-12-17 12:02:50 +08:00
HFO4 1dac66e632 Merge branch 'master' of github.com:HFO4/Backend-V3 2019-12-16 19:43:21 +08:00
HFO4 963100d60f Modify: add fs into webdav 2019-12-16 19:43:00 +08:00
HFO4 a6d16cc7ba Add: internal packages in webdav 2019-12-16 19:35:13 +08:00
HFO4 327a3c1edf Feat: ttl in memory-cache / Add: webdav from standard library 2019-12-16 18:56:25 +08:00
HFO4 e6d2a94809 Feat: preview doc file / Fix: chinese character encoding in attachment header 2019-12-16 13:24:09 +08:00
HFO4 9a942f8b48 Modify: decoupling getSignedURL modules 2019-12-16 12:52:35 +08:00
HFO4 6ada69f637 Test: update file content related hooks 2019-12-15 16:35:01 +08:00
HFO4 8bf2966d46 Feat: update file content 2019-12-15 14:01:37 +08:00
HFO4 2c75c73886 Modify: preview should use login session to enable http-range 2019-12-14 15:06:30 +08:00
HFO4 8557ed8e2e Fix: failed uint test due to cache 2019-12-14 14:44:29 +08:00
HFO4 ca07a94d41 Test: file compress / download 2019-12-14 14:28:01 +08:00
HFO4 03dcd9a9e0 Modify: add general ReaderCloserSeeker interface for handler GET method to return 2019-12-13 20:54:28 +08:00
HFO4 f262caf1f5 Feat: download file and get file downloading session 2019-12-13 20:46:11 +08:00
HFO4 ad02a659a6 Feat: read CORS config from file 2019-12-13 19:00:58 +08:00
HFO4 c102c74d6d Fix: download archived file anonymously 2019-12-13 18:07:15 +08:00
HFO4 00ef240bea Delete: test file for task/pool 2019-12-13 15:21:45 +08:00
HFO4 02c93be3bc Feat: download temporary archive file 2019-12-13 15:10:44 +08:00
HFO4 afc0b647ca Fix: failed unit test / Feat: support TTL in redis cache 2019-12-13 13:22:10 +08:00
HFO4 8703f97e20 Merge branch 'master' of github.com:HFO4/Backend-V3
 Conflicts:
	go.sum
2019-12-13 12:51:48 +08:00
HFO4 0b820e8417 Feat: add go.sum 2019-12-13 12:51:23 +08:00
HFO4 cf9416ef88 Feat: archive download and sign temp url 2019-12-13 11:41:22 +08:00
HFO4 012281c41f Feat: zip create 2019-12-13 09:46:53 +08:00
HFO4 d58898e364 Feat: task pool for goroutines 2019-12-12 11:33:41 +08:00
HFO4 e8aa0435c5 Feat: archive & download routers for test 2019-12-12 10:04:24 +08:00
HFO4 ba34a092d1 Feat: group options in database scheme 2019-12-12 09:16:24 +08:00
HFO4 2b25b9d315 Modify: add ini file to .gitignore 2019-12-12 08:54:48 +08:00
HFO4 18968458a4 Modify: close file in main routine 2019-12-11 18:52:41 +08:00
HFO4 d0bb123e03 Test: get source URL of files 2019-12-11 12:24:09 +08:00
HFO4 9f26c0c8ab Test: signRequired middleware 2019-12-10 21:26:19 +08:00
HFO4 297b507ca7 Feat: get file content via anonymous url 2019-12-10 20:42:40 +08:00
HFO4 ea7f034332 Feat: sign auth middleware 2019-12-10 20:17:21 +08:00
HFO4 36d5f51495 Feat: sign file source url 2019-12-10 17:10:34 +08:00
HFO4 1963a495fb Feat: get file source route / Fix: cache initialize at wrong time 2019-12-10 11:55:28 +08:00
HFO4 e871f6e421 Feat: HMAC auth and check 2019-12-10 11:13:33 +08:00
HFO4 4649ddbae2 Fix: failed uint test due to dirty cache 2019-12-09 19:45:04 +08:00
HFO4 5b01202844 Test: redis pool connection 2019-12-09 19:40:24 +08:00
HFO4 6d6255e759 Test: redis cache 2019-12-09 19:30:52 +08:00
HFO4 cb61945125 Feat: redis driver for cache 2019-12-09 15:20:02 +08:00
HFO4 f6da4cc7f0 Test: local handler.thumb 2019-12-09 12:18:30 +08:00
HFO4 c3c0e92964 Test: thumbnail and authn / Modify: read thumbnail config from file 2019-12-09 11:33:39 +08:00
HFO4 f35c585edf Feat experimental WebAuth API 2019-12-08 22:17:36 +08:00
HFO4 0932a10fed Feat: generate thumbnails for image file 2019-12-08 14:16:01 +08:00
HFO4 a445da5286 Fix: failed unit test due to missing mock.ExpectWereMatch() 2019-12-08 13:03:08 +08:00
HFO4 6eff13c80a Test: modified folder methods and filesystem 2019-12-08 10:57:43 +08:00
HFO4 05c802e0fa Test: modified folder methods 2019-12-07 20:27:20 +08:00
HFO4 56b1ae9f31 Modify: use pure tree structure in file system scheme 2019-12-07 19:47:22 +08:00
HFO4 10a2ef4267 Feat: rename file 2019-12-07 15:54:07 +08:00
HFO4 f4c414c0f6 Fix: uint may overflow / Test: get user storage 2019-12-07 15:05:48 +08:00
AaronLiu 9386371097 Set up CI with Azure Pipelines
[skip ci]
2019-12-06 10:36:52 +08:00
HFO4 13fb090194 Fix: failed unit tests 2019-12-05 19:10:55 +08:00
HFO4 5df8f688d1 Test: util / filesystem 2019-12-05 19:01:51 +08:00
HFO4 06bcb3d6eb Test: user.afterCreate 2019-12-05 17:22:43 +08:00
HFO4 7375cc01f1 Feat: cache in-memory store 2019-12-05 17:01:14 +08:00
HFO4 5d50e7ed1e Test: moveOrCopyFolder / File 2019-12-04 13:49:28 +08:00
HFO4 362a7c389d Test: middleware / file / folder 2019-12-03 21:25:10 +08:00
HFO4 c15b8a047d Feat: copy files and folders 2019-12-03 16:32:23 +08:00
HFO4 85bbb3d122 Remove: useless test file 2019-12-03 14:48:45 +08:00
HFO4 71b8ced742 Feat: unit test coverage report 2019-12-03 14:34:25 +08:00
HFO4 6630451f8b Feat: unit test coverage report 2019-12-03 14:24:56 +08:00
HFO4 c09fc535dc Feat: unit test coverage report 2019-12-03 14:20:23 +08:00
HFO4 5424115e51 Fix: failed test due to database type 2019-12-03 10:42:35 +08:00
HFO4 a13530f969 Fix: skip the wrong root folder in move path handler 2019-12-02 19:08:15 +08:00
HFO4 adf7f3deeb Fix: handler move files in top levels 2019-12-02 14:47:55 +08:00
HFO4 d28e5632d5 Fix: unique index check failed due to soft delete 2019-12-01 19:45:01 +08:00
HFO4 fd02425547 Feat: move files/directories 2019-12-01 18:31:29 +08:00
HFO4 081c92067f Test: delete objects related methods 2019-12-01 14:31:29 +08:00
HFO4 ceb25ce1c3 Modify: add unique index for folder & file 2019-12-01 11:23:54 +08:00
HFO4 b3f13c56bc Modify: remove PositionAbsolute scheme in folder 2019-12-01 10:57:44 +08:00
HFO4 8b3fd8ec66 Modify: test for local handler delete 2019-11-30 23:26:02 +08:00
HFO4 b4cfa6b601 Test: delete object route 2019-11-30 23:22:57 +08:00
HFO4 93010e3525 Feat: delete objects 2019-11-30 15:09:56 +08:00
HFO4 0cbbe5bb79 Modify: use uri parameter in Get File 2019-11-29 15:24:23 +08:00
HFO4 2c2ee5b1c1 Modify: code style 2019-11-28 21:21:46 +08:00
HFO4 e0ac1925d5 Fix: Redis should not be used in test mode 2019-11-27 21:53:07 +08:00
HFO4 b0e9c38732 Feat: redis for session storing 2019-11-27 19:53:39 +08:00
HFO4 7d5016ae40 Test: same folder check 2019-11-27 19:16:13 +08:00
HFO4 0982347f40 Fix: folder with the same name should not be created 2019-11-27 19:14:13 +08:00
HFO4 b3ef833afd Fix: test error / missing AfterFind hook in user model 2019-11-27 15:27:19 +08:00
HFO4 16067c3ac8 Test: download file in filesystem 2019-11-27 13:54:25 +08:00
HFO4 9bb432c220 Feat: download file with speed limit 2019-11-27 13:10:19 +08:00
HFO4 29def02489 Fix: upload was marked canceled when small file uploaded 2019-11-27 12:49:31 +08:00
HFO4 4156a71adf Feat: file download in service level 2019-11-26 20:59:57 +08:00
HFO4 a734493b65 Feat: custom error for general layer codes 2019-11-26 19:51:54 +08:00
HFO4 9a1665526c Test: local policy file uploading 2019-11-26 14:52:54 +08:00
HFO4 e07adb9d97 Test: filesystem/hooks 2019-11-26 11:52:09 +08:00
HFO4 0cb80f69f5 Modify: split hooks into small modules 2019-11-26 11:42:26 +08:00
HFO4 451bdb4ee1 Modify: parameters in headers should be URIEncoded 2019-11-25 21:12:28 +08:00
HFO4 28df5ca833 Modify: return user information in siteConfig while logged in 2019-11-25 14:08:11 +08:00
HFO4 5e1e76719f Test: list folder & filesystem/path & model/folder/list 2019-11-24 16:28:41 +08:00
HFO4 b431f3674c Feat: list objects in specific path 2019-11-24 13:06:15 +08:00
HFO4 a89c3cb11a Feat: create folder / Modify: add index to some column 2019-11-24 11:33:30 +08:00
HFO4 89b54e401c Modify: use lowercase route name 2019-11-23 16:58:56 +08:00
HFO4 5991fd66ce Modify: reorganize project structure 2019-11-23 16:38:43 +08:00
HFO4 a994a74f4e Fix: 0 length upload should be allowed 2019-11-23 15:39:30 +08:00
HFO4 671d031d00 Fix: able to upload empty file 2019-11-23 15:37:13 +08:00
HFO4 948059ec1c Feat: CORS / Test: site/config route 2019-11-23 15:09:46 +08:00
HFO4 370a1a0c9f Feat: GET Site/Config getting global configuration 2019-11-22 19:33:06 +08:00
HFO4 9d8a462dc4 Remove: mutipart file upload 2019-11-22 14:56:46 +08:00
HFO4 7cb27b2102 Test: filesystem/file, filesystem, filesystem/hook, model/file/Create 2019-11-20 17:21:30 +08:00
HFO4 438ce02420 Modify: re-organize structure of filesystem 2019-11-20 15:53:00 +08:00
HFO4 e09294d388 Feat: insert file record to database 2019-11-20 15:24:26 +08:00
HFO4 e835dafc88 Feat: colorful log output for log prefix 2019-11-20 12:39:27 +08:00
HFO4 f9b37a3359 Fix: test failed due to missing context 2019-11-19 18:10:18 +08:00
HFO4 20ea86eaf6 Fix: test failed due to Policy.AutoName 2019-11-19 17:20:59 +08:00
HFO4 88a543ef74 Feat: {path} marker in name rule representing the virtual path of the file 2019-11-19 16:42:36 +08:00
HFO4 2e9f256462 Feat: after uploading finished hook 2019-11-18 19:32:06 +08:00
HFO4 aa17aa8e6a Feat: after uploading hooks and checks 2019-11-18 19:09:56 +08:00
HFO4 0dddc12609 Modify: check whether file exist before deleting unfinished uploading 2019-11-18 18:29:37 +08:00
HFO4 5f7ece6d82 Fix: filepath.Dir behaves differently between, result in failed uint test 2019-11-18 14:08:27 +08:00
HFO4 631c23f065 Feat: recycling file storage and user capacity when uploading canceled 2019-11-18 14:06:15 +08:00
HFO4 160f964564 Feat: use goroutine to detect upload-canceling action / Object name validate 2019-11-18 13:26:32 +08:00
HFO4 331931e539 Fix: permission error 2019-11-17 20:30:25 +08:00
HFO4 861ba77b04 Feat: stream uploading 2019-11-17 19:12:10 +08:00
HFO4 5aa61301af Fix: letter case should be ignored while validating file extension 2019-11-17 14:35:28 +08:00
HFO4 3741da692b Test: filesystem/local & filesystem/validator 2019-11-17 14:33:00 +08:00
HFO4 99e7eecab7 Feat: file upload handler 2019-11-17 13:50:14 +08:00
HFO4 841832bb65 Add: context 2019-11-16 20:31:34 +08:00
HFO4 8dd411f5d4 Feat: memory database for testing 2019-11-16 16:58:10 +08:00
HFO4 f46b52b6ba Feat: support sqlite 2019-11-16 16:49:03 +08:00
HFO4 e05ba1030c Modify: package name 2019-11-16 16:11:37 +08:00
HFO4 79caf635f9 Feat: basic file validator 2019-11-16 16:05:10 +08:00
HFO4 003274162b Add: filesystem 2019-11-16 13:37:42 +08:00
HFO4 d86a3533ca Add: route for uploading file 2019-11-15 18:12:34 +08:00
HFO4 71e668c005 Add: model/file 2019-11-15 16:36:48 +08:00
HFO4 4c1ece4b96 Add: model/folder 2019-11-15 16:32:43 +08:00
HFO4 ceb8ee72d8 Fix: warnings in unit test 2019-11-14 14:51:59 +08:00
HFO4 ade2bf1812 Test: policy model 2019-11-14 14:45:06 +08:00
HFO4 c867916c3a Fix: uint test 2019-11-14 14:24:39 +08:00
HFO4 4309653160 Feat: model/policy 2019-11-14 14:18:10 +08:00
HFO4 41e0dec74c Test: captcha 2019-11-13 18:34:29 +08:00
HFO4 9660d2f9c1 Feat: captcha config 2019-11-13 17:22:45 +08:00
HFO4 7d4e212d4e Feat: captcha 2019-11-13 17:03:55 +08:00
HFO4 c7e47293db Add: model - group / Test: group 2019-11-13 16:28:14 +08:00
HFO4 079c730319 Test: SessionAuthCheck 2019-11-12 16:53:32 +08:00
HFO4 2cdbfde83a Fix: failed testing 2019-11-12 16:23:24 +08:00
HFO4 c8c85501e4 Test: middleware/auth 2019-11-12 16:18:58 +08:00
HFO4 589c399488 Feat: User/Me 2019-11-12 15:34:54 +08:00
HFO4 80f30465e9 Test: User login router 2019-11-12 14:45:27 +08:00
HFO4 2ae2c9b784 Modify: using memstore to store session 2019-11-12 13:55:33 +08:00
HFO4 1db0c6116e Test: Ping route 2019-11-11 19:20:33 +08:00
HFO4 6f96018223 Feat: User login 2019-11-11 19:13:17 +08:00
HFO4 943c84320c Feat: Setting model 2019-11-10 17:07:35 +08:00
HFO4 29fe6047a1 Modify: GetSettingByName returns string 2019-11-09 20:32:15 +08:00
HFO4 f453b3e918 Fix: rand seeding error / Test: conf/version and util 2019-11-09 19:47:26 +08:00
HFO4 3ed1a5dc43 Add: default settings rows in migration 2019-11-09 19:27:47 +08:00
HFO4 e858cbe2cf Feat: Decide whether to do database migration based on version.lock 2019-11-09 19:04:48 +08:00
HFO4 c5493fd1f1 Delete temp test file when exist 2019-11-09 18:09:32 +08:00
HFO4 ec7ab83d7c Test: conf 2019-11-09 18:06:29 +08:00
HFO4 53da4655ad Reading config file 2019-11-08 18:29:12 +08:00
HFO4 370ee8405d Update: compile test 2019-11-07 16:19:29 +08:00
AaronLiuandGitHub c44216e626 Create README.md 2019-11-07 16:17:21 +08:00
HFO4 46bd970824 Delete useless json 2019-11-07 16:16:07 +08:00
AaronLiuandGitHub 3d82521d42 Create .travis.yml 2019-11-07 16:04:42 +08:00
HFO4 aca8bde521 User model/migrations and gorm init 2019-11-07 15:56:05 +08:00
HFO4 ece1bca11a Update .gitignore 2019-11-06 22:36:24 +08:00
HFO4 2c9e0c1119 Testing for controller/main.go 2019-11-06 22:35:31 +08:00
HFO4 6ba4d1ae82 Param error message generate 2019-11-06 16:42:13 +08:00
HFO4 6539ae20fa Basic check for User controller 2019-11-05 19:49:56 +08:00
HFO4 74b5bf24a8 Add: Ping router 2019-11-05 12:31:22 +08:00
HFO4 86896aedd0 Init 2019-11-04 20:30:12 +08:00
AaronLiuandGitHub cd1f3be22d Initial commit 2019-11-04 20:28:34 +08:00
835 changed files with 58892 additions and 102987 deletions
+1
View File
@@ -0,0 +1 @@
custom: ["https://cloudreve.org/pricing"]
+38
View File
@@ -0,0 +1,38 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.
+20
View File
@@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
+61
View File
@@ -0,0 +1,61 @@
# Configuration for probot-stale - https://github.com/probot/stale
# Number of days of inactivity before an Issue or Pull Request becomes stale
daysUntilStale: 360
# Number of days of inactivity before an Issue or Pull Request with the stale label is closed.
# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
daysUntilClose: 30
# Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled)
onlyLabels: []
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
exemptLabels:
- pinned
- security
- "[Status] Maybe Later"
# Set to true to ignore issues in a project (defaults to false)
exemptProjects: true
# Set to true to ignore issues in a milestone (defaults to false)
exemptMilestones: true
# Set to true to ignore issues with an assignee (defaults to false)
exemptAssignees: true
# Label to use when marking as stale
staleLabel: wontfix
# Comment to post when marking as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when removing the stale label.
# unmarkComment: >
# Your comment here.
# Comment to post when closing a stale Issue or Pull Request.
# closeComment: >
# Your comment here.
# Limit the number of actions per hour, from 1-30. Default is 30
limitPerRun: 30
# Limit to only `issues` or `pulls`
# only: issues
# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
# pulls:
# daysUntilStale: 30
# markComment: >
# This pull request has been automatically marked as stale because it has not had
# recent activity. It will be closed if no further activity occurs. Thank you
# for your contributions.
# issues:
# exemptLabels:
# - confirmed
+31
View File
@@ -0,0 +1,31 @@
name: Build
on: workflow_dispatch
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Set up Go 1.20
uses: actions/setup-go@v2
with:
go-version: "1.20"
id: go
- name: Check out code into the Go module directory
uses: actions/checkout@v2
with:
clean: false
submodules: "recursive"
- run: |
git fetch --prune --unshallow --tags
- name: Build and Release
uses: goreleaser/goreleaser-action@v4
with:
distribution: goreleaser
version: latest
args: release --clean --skip-validate
env:
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
+57
View File
@@ -0,0 +1,57 @@
name: Build and push docker image
on:
push:
tags:
- 3.* # triggered on every push with tag 3.*
workflow_dispatch: # or just on button clicked
jobs:
docker-build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- run: git fetch --prune --unshallow
- name: Setup Environments
id: envs
run: |
CLOUDREVE_LATEST_TAG=$(git describe --tags --abbrev=0)
DOCKER_IMAGE="cloudreve/cloudreve"
echo "RELEASE_VERSION=${GITHUB_REF#refs}"
TAGS="${DOCKER_IMAGE}:latest,${DOCKER_IMAGE}:${CLOUDREVE_LATEST_TAG}"
echo "CLOUDREVE_LATEST_TAG:${CLOUDREVE_LATEST_TAG}"
echo ::set-output name=tags::${TAGS}
- name: Setup QEMU Emulator
uses: docker/setup-qemu-action@master
with:
platforms: all
- name: Setup Docker Buildx Command
id: buildx
uses: docker/setup-buildx-action@master
- name: Login to Dockerhub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Build Docker Image and Push
id: docker_build
uses: docker/build-push-action@v2
with:
push: true
builder: ${{ steps.buildx.outputs.name }}
context: .
file: ./Dockerfile
platforms: linux/amd64,linux/arm64,linux/arm/v7
tags: ${{ steps.envs.outputs.tags }}
- name: Update Docker Hub Description
uses: peter-evans/dockerhub-description@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_PASSWORD }}
repository: cloudreve/cloudreve
short-description: ${{ github.event.repository.description }}
- name: Image Digest
run: echo ${{ steps.docker_build.outputs.digest }}
+35
View File
@@ -0,0 +1,35 @@
name: Test
on:
pull_request:
branches:
- master
push:
branches: [master]
jobs:
test:
name: Test
runs-on: ubuntu-latest
steps:
- name: Set up Go 1.20
uses: actions/setup-go@v2
with:
go-version: "1.20"
id: go
- name: Check out code into the Go module directory
uses: actions/checkout@v2
with:
submodules: "recursive"
- name: Build static files
run: |
mkdir assets/build
touch assets/build/test.html
- name: Test
run: go test -coverprofile=coverage.txt -covermode=atomic ./...
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v2
+33
View File
@@ -0,0 +1,33 @@
# Binaries for programs and plugins
cloudreve
*.exe
*.exe~
*.dll
*.so
*.dylib
*.db
*.bin
/release/
assets.zip
# Test binary, build with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Development enviroment
.idea/*
uploads/*
temp
# Version control
version.lock
# Config file
*.ini
conf/conf.ini
/statik/
.vscode/
dist/
+3
View File
@@ -0,0 +1,3 @@
[submodule "assets"]
path = assets
url = https://github.com/cloudreve/frontend.git
+121
View File
@@ -0,0 +1,121 @@
env:
- CI=false
- GENERATE_SOURCEMAP=false
before:
hooks:
- go mod tidy
- sh -c "cd assets && rm -rf build && yarn install --network-timeout 1000000 && yarn run build && cd ../ && zip -r - assets/build >assets.zip"
builds:
-
env:
- CGO_ENABLED=0
binary: cloudreve
ldflags:
- -X 'github.com/cloudreve/Cloudreve/v3/pkg/conf.BackendVersion={{.Tag}}' -X 'github.com/cloudreve/Cloudreve/v3/pkg/conf.LastCommit={{.ShortCommit}}'
goos:
- linux
- windows
- darwin
goarch:
- amd64
- arm
- arm64
goarm:
- 5
- 6
- 7
ignore:
- goos: windows
goarm: 5
- goos: windows
goarm: 6
- goos: windows
goarm: 7
archives:
- format: tar.gz
# this name template makes the OS and Arch compatible with the results of uname.
name_template: >-
cloudreve_{{.Tag}}_{{- .Os }}_{{ .Arch }}
{{- if .Arm }}v{{ .Arm }}{{ end }}
# use zip for windows archives
format_overrides:
- goos: windows
format: zip
checksum:
name_template: 'checksums.txt'
snapshot:
name_template: "{{ incpatch .Version }}-next"
changelog:
sort: asc
filters:
exclude:
- '^docs:'
- '^test:'
release:
draft: true
prerelease: auto
target_commitish: '{{ .Commit }}'
name_template: "{{.Version}}"
dockers:
-
dockerfile: Dockerfile
use: buildx
build_flag_templates:
- "--platform=linux/amd64"
goos: linux
goarch: amd64
goamd64: v1
image_templates:
- "cloudreve/cloudreve:{{ .Tag }}-amd64"
-
dockerfile: Dockerfile
use: buildx
build_flag_templates:
- "--platform=linux/arm64"
goos: linux
goarch: arm64
image_templates:
- "cloudreve/cloudreve:{{ .Tag }}-arm64"
-
dockerfile: Dockerfile
use: buildx
build_flag_templates:
- "--platform=linux/arm/v6"
goos: linux
goarch: arm
goarm: '6'
image_templates:
- "cloudreve/cloudreve:{{ .Tag }}-armv6"
-
dockerfile: Dockerfile
use: buildx
build_flag_templates:
- "--platform=linux/arm/v7"
goos: linux
goarch: arm
goarm: '7'
image_templates:
- "cloudreve/cloudreve:{{ .Tag }}-armv7"
docker_manifests:
- name_template: "cloudreve/cloudreve:latest"
image_templates:
- "cloudreve/cloudreve:{{ .Tag }}-amd64"
- "cloudreve/cloudreve:{{ .Tag }}-arm64"
- "cloudreve/cloudreve:{{ .Tag }}-armv6"
- "cloudreve/cloudreve:{{ .Tag }}-armv7"
- name_template: "cloudreve/cloudreve:{{ .Tag }}"
image_templates:
- "cloudreve/cloudreve:{{ .Tag }}-amd64"
- "cloudreve/cloudreve:{{ .Tag }}-arm64"
- "cloudreve/cloudreve:{{ .Tag }}-armv6"
- "cloudreve/cloudreve:{{ .Tag }}-armv7"
-9
View File
@@ -1,9 +0,0 @@
<IfModule mod_rewrite.c>
Options +FollowSymlinks -Multiviews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?/$1 [QSA,PT,L]
</IfModule>
SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
-7
View File
@@ -1,7 +0,0 @@
language: php
php:
- 7.1
before_script:
- composer install
- chmod +x ./deploy.sh
script: ./deploy.sh
-114
View File
@@ -1,114 +0,0 @@
<?php
namespace CloudreveInstaller;
use Composer\Script\Event;
class Installer{
public static function startInstall(Event $event){
$version = json_decode(file_get_contents("application/version.json"),true)["version"];
$ioContext = $event->getIO();
$welcomMsg = "
___ _ _
/ __\ | ___ _ _ __| |_ __ _____ _____
/ / | |/ _ \| | | |/ _` | '__/ _ \ \ / / _ \
/ /___| | (_) | |_| | (_| | | | __/\ V / __/
\____/|_|\___/ \__,_|\__,_|_| \___| \_/ \___|
Ver $version
================================================
";
$ioContext->write($welcomMsg);
$sqlInfo = self::getSqlInformation($event);
$ioContext->write("");
$siteUrl=$ioContext->ask("The full-url to access to your Cloudreve (e.g. https://pan.aoaoao.me/ , 'http' must be included in the front and '/' must be included at the end):");
$ioContext->write("");
if(!file_exists('mysql.sql')){
$ioContext->writeError("[Error] The file mysql.sql not exist.\nInstaller will exit.To retry, run 'composer install'");
exit();
}
$sqlSource = file_get_contents('mysql.sql');
$sqlSource = str_replace("https://cloudreve.org/", $siteUrl, $sqlSource);
$mysqli = @new \mysqli($sqlInfo["hostname"], $sqlInfo["username"], $sqlInfo["password"], $sqlInfo["database"], $sqlInfo["hostport"]);
$ioContext->write("=======================");
$ioContext->write("Starting import sql file...");
if ($mysqli->multi_query($sqlSource)) {
$ioContext->write("Writing complete.");
$ioContext->write("Writing database.php...");
if(file_exists('application/database.php')){
$ioContext->writeError("[Error] The file database.php already exist.\nInstaller will exit.To retry, run 'composer install'");
$ioContext->write("=======================");
exit();
}
self::writrConfig($event,$sqlInfo);
$ioContext->write("=======================");
}else{
$ioContext->writeError("[Error] Writing failed.Installer will exit. To retry, run 'composer install'");
$ioContext->write("=======================");
}
$ioContext->write("");
$ioContext->write("Congratulations! Cloudreve has been installed successfully.");
$ioContext->write("");
$ioContext->write("Here's some informatioin about yor Cloudreve:");
$ioContext->write("Homepage: $siteUrl");
$ioContext->write("Admin Panel: ".$siteUrl."Admin");
$ioContext->write("Default username: admin@cloudreve.org");
$ioContext->write("Default password: admin");
$ioContext->write("");
$ioContext->write("=======================");
$ioContext->write("IMPORTANT! You may still have to configure the URL Rewrite to set everthing to work.");
$ioContext->write("Refer to the install manual for more informatioin.");
$ioContext->write("=======================");
self::sendFeedBack($siteUrl);
}
public static function writrConfig(Event $event,$sqlInfo){
$ioContext = $event->getIO();
try {
$fileContent = file_get_contents("CloudreveInstaller/database_sample.php");
$replacement = array(
'{hostname}' => $sqlInfo["hostname"],
'{database}' => $sqlInfo["database"],
'{username}' => $sqlInfo["username"],
'{password}' => $sqlInfo["password"],
'{hostport}' => $sqlInfo["hostport"],
);
$fileContent = strtr($fileContent,$replacement);
file_put_contents('application/database.php',$fileContent);
}catch (Exception $e) {
$ioContext->writeError("[Error] Writing failed.Installer will exit. To retry, run 'composer install'");
}
$ioContext->write("Writing complete.");
}
public static function getSqlInformation(Event $event){
$ioContext = $event->getIO();
$hostname=$ioContext->ask("Input the hostname of your MySQL server (Default:127.0.0.1):","127.0.0.1");
$database=$ioContext->ask("The database name:","127.0.0.1");
$username=$ioContext->ask("The username of your MySQL server (Default:root):","root");
$password=$ioContext->ask("The password of your MySQL server:");
$hostport=$ioContext->ask("The hostport of your MySQL server (Default:3306):","3306");
$mysqli = @new \mysqli($hostname, $username, $password, $database, $hostport);
if ($mysqli->connect_error) {
$ioContext->writeError("[Error] Cannot connect to MySQL server, Message:".$mysqli->connect_error);
$ioContext->write("");
$ioContext->write("Please confirm your connection informatioin:");
@$mysqli->close();
return self::getSqlInformation($event);
}
return [
"hostname" => $hostname,
"database" => $database,
"username" => $username,
"password" => $password,
"hostport" => $hostport,
];
}
public static function sendFeedBack($url){
@file_get_contents("http://aoaoao.me/api/feedback.php?url=".urlencode($url));
}
}
?>
-53
View File
@@ -1,53 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
return [
// 数据库类型
'type' => 'mysql',
// 服务器地址
'hostname' => '{hostname}',
// 数据库名
'database' => '{database}',
// 用户名
'username' => '{username}',
// 密码
'password' => '{password}',
// 端口
'hostport' => '{hostport}',
// 连接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,
];
+17
View File
@@ -0,0 +1,17 @@
FROM alpine:latest
WORKDIR /cloudreve
COPY cloudreve ./cloudreve
RUN apk update \
&& apk add --no-cache tzdata \
&& cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
&& echo "Asia/Shanghai" > /etc/timezone \
&& chmod +x ./cloudreve \
&& mkdir -p /data/aria2 \
&& chmod -R 766 /data/aria2
EXPOSE 5212
VOLUME ["/cloudreve/uploads", "/cloudreve/avatar", "/data"]
ENTRYPOINT ["./cloudreve"]
+1 -1
View File
@@ -671,4 +671,4 @@ into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
+83 -82
View File
@@ -1,103 +1,104 @@
![logo_white.png](https://raw.githubusercontent.com/HFO4/Cloudreve/master/static/img/logo_white.png)
[中文版本](https://github.com/cloudreve/Cloudreve/blob/master/README_zh-CN.md)
Cloudreve - Make the cloud easy for everyone
=========================
[![Packagist](https://img.shields.io/packagist/v/HFO4/Cloudreve.svg)](https://packagist.org/packages/hfo4/cloudreve)
[![Latest Unstable Version](https://poser.pugx.org/hfo4/cloudreve/v/unstable)](https://packagist.org/packages/hfo4/cloudreve)
[![License](https://poser.pugx.org/hfo4/cloudreve/license)](https://packagist.org/packages/hfo4/cloudreve)
<h1 align="center">
<br>
<a href="https://cloudreve.org/" alt="logo" ><img src="https://raw.githubusercontent.com/cloudreve/frontend/master/public/static/img/logo192.png" width="150"/></a>
<br>
Cloudreve
<br>
</h1>
<h4 align="center">Self-hosted file management system with muilt-cloud support.</h4>
[主页](https://cloudreve.org) | [论坛](https://forum.cloudreve.org) | [演示站](https://pan.aoaoao.me) | |[Telegram群组](https://github.com/HFO4/Cloudreve)
<p align="center">
<a href="https://github.com/cloudreve/Cloudreve/actions/workflows/test.yml">
<img src="https://img.shields.io/github/actions/workflow/status/cloudreve/Cloudreve/test.yml?branch=master&style=flat-square"
alt="GitHub Test Workflow">
</a>
<a href="https://codecov.io/gh/cloudreve/Cloudreve"><img src="https://img.shields.io/codecov/c/github/cloudreve/Cloudreve?style=flat-square"></a>
<a href="https://goreportcard.com/report/github.com/cloudreve/Cloudreve">
<img src="https://goreportcard.com/badge/github.com/cloudreve/Cloudreve?style=flat-square">
</a>
<a href="https://github.com/cloudreve/Cloudreve/releases">
<img src="https://img.shields.io/github/v/release/cloudreve/Cloudreve?include_prereleases&style=flat-square" />
</a>
<a href="https://hub.docker.com/r/cloudreve/cloudreve">
<img src="https://img.shields.io/docker/image-size/cloudreve/cloudreve?style=flat-square"/>
</a>
</p>
<p align="center">
<a href="https://cloudreve.org">Homepage</a> •
<a href="https://demo.cloudreve.org">Demo</a> •
<a href="https://forum.cloudreve.org/">Discussion</a> •
<a href="https://docs.cloudreve.org/v/en/">Documents</a> •
<a href="https://github.com/cloudreve/Cloudreve/releases">Download</a> •
<a href="https://t.me/cloudreve_official">Telegram Group</a> •
<a href="#scroll-License">License</a>
</p>
基于ThinkPHP构建的网盘系统,能够助您以较低成本快速搭建起公私兼备的网盘。
![homepage.png](https://download.aoaoao.me/homepage.png)
目前已经实现的特性:
![Screenshot](https://raw.githubusercontent.com/cloudreve/docs/master/images/homepage.png)
* 快速对接多家云存储,支持七牛、又拍云、阿里云OSS、AWS S3、自建远程服务器,当然,还有本地存储
* 可限制单文件最大大小、MIMEType、文件后缀、用户可用容量
* 图片、音频、视频、文本、Markdown、Ofiice文档 在线预览
* 移动端全站响应式布局
* 文件、目录分享系统,可创建私有分享或公开分享链接
* 用户个人主页,可查看用户所有分享
* 多用户系统、用户组支持
* 初步完善的后台,方便管理
* 拖拽上传、分片上传、断点续传、下载限速(*实验性功能)
* 多上传策略,可为不同用户组分配不同策略
* 用户组基础权限设置、二步验证
* WebDAV协议支持
## :sparkles: Features
安装需求
------------
* LNMP/AMP With PHP5.6+
* curl、fileinfo、gd扩展
* Composer
* :cloud: Support storing files into Local storage, Remote storage, Qiniu, Aliyun OSS, Tencent COS, Upyun, OneDrive, S3 compatible API.
* :outbox_tray: Upload/Download in directly transmission with speed limiting support.
* 💾 Integrate with Aria2 to download files offline, use multiple download nodes to share the load.
* 📚 Compress/Extract files, download files in batch.
* 💻 WebDAV support covering all storage providers.
* :zap:Drag&Drop to upload files or folders, with streaming upload processing.
* :card_file_box: Drag & Drop to manage your files.
* :family_woman_girl_boy: Multi-users with multi-groups.
* :link: Create share links for files and folders with expiration date.
* :eye_speech_bubble: Preview videos, images, audios, ePub files online; edit texts, Office documents online.
* :art: Customize theme colors, dark mode, PWA application, SPA, i18n.
* :rocket: All-In-One packing, with all features out-of-the-box.
* 🌈 ... ...
简要安装说明
------------
## :hammer_and_wrench: Deploy
#### 1.使用Composer安装主程序
```
#安装开发版
$ composer create-project hfo4/cloudreve:dev-master
Download the main binary for your target machine OS, CPU architecture and run it directly.
```shell
# Extract Cloudreve binary
tar -zxvf cloudreve_VERSION_OS_ARCH.tar.gz
# Grant execute permission
chmod +x ./cloudreve
# Start Cloudreve
./cloudreve
```
```
#等待安装依赖库后,会自动执行安装脚本,按照提示输入数据库账户信息
___ _ _
/ __\ | ___ _ _ __| |_ __ _____ _____
/ / | |/ _ \| | | |/ _` | '__/ _ \ \ / / _ \
/ /___| | (_) | |_| | (_| | | | __/\ V / __/
\____/|_|\___/ \__,_|\__,_|_| \___| \_/ \___|
Ver XX
================================================
#按提示输入信息
......
The above is a minimum deploy example, you can refer to [Getting started](https://docs.cloudreve.org/v/en/getting-started/install) for a completed deployment.
## :gear: Build
You need to have `Go >= 1.18`, `node.js`, `yarn`, `zip`, [goreleaser](https://goreleaser.com/intro/) and other necessary dependencies before you can build it yourself.
#### Install goreleaser
```shell
go install github.com/goreleaser/goreleaser@latest
```
```
#出现如下提示表示安装完成
Congratulations! Cloudreve has been installed successfully.
#### Clone the code
Here's some informatioin about yor Cloudreve:
Homepage: https://pan.aoaoao.me/
Admin Panel: https://pan.aoaoao.me/Admin
Default username: admin@cloudreve.org
Default password: admin
```shell
git clone --recurse-submodules https://github.com/cloudreve/Cloudreve.git
```
#### 2.目录权限
`runtime`目录需要写入权限,如果你使用本地存储,`public` 目录也需要有写入权限
#### Compile
#### 3.URL重写
对于Apache服务器,项目目录下的`.htaccess`已经配置好重写规则,如有需求酌情修改.
对于Nginx服务器,以下是一个可供参考的配置:
```
location / {
if (!-e $request_filename) {
rewrite ^(.*)$ /index.php?s=/$1 last;
break;
}
}
```shell
goreleaser build --clean --single-target --snapshot
```
#### 4.完成
后台地址:`http://您的域名/Admin` 初始用户名:`admin@cloudreve.org` 初始密码:`admin`
#### 后续操作
以下操作不是必须的,但仍推荐你完成这些操作:
* 修改初始账户密码
* 到 设置-基础设置 中更改站点URL,如果不更改,程序无法正常接受回调请求
* 添加Crontab定时任务 :你的域名/Cron
* 如果你打算使用本地上传策略并且不准备开启外链功能,请将·public/uploads·目录设置为禁止外部访问
* 如需启用二步验证功能,请依次执行`composer require phpgangsta/googleauthenticator:dev-master` `composer require endroid/qr-code`安装二步验证支持库
* 给本项目一个Star~
## :alembic: Stacks
文档
------------
* [完整安装说明](https://github.com/HFO4/Cloudreve/wiki/%E5%AE%89%E8%A3%85%E8%AF%B4%E6%98%8E)
* [安装及初次使用FAQ](https://github.com/HFO4/Cloudreve/wiki/%E5%AE%89%E8%A3%85%E5%8F%8A%E5%88%9D%E6%AC%A1%E4%BD%BF%E7%94%A8FAQ)
* [Go](https://golang.org/) + [Gin](https://github.com/gin-gonic/gin)
* [React](https://github.com/facebook/react) + [Redux](https://github.com/reduxjs/redux) + [Material-UI](https://github.com/mui-org/material-ui)
许可证
------------
GPLV3
## :scroll: License
GPL V3
+104
View File
@@ -0,0 +1,104 @@
[English Version](https://github.com/cloudreve/Cloudreve/blob/master/README.md)
<h1 align="center">
<br>
<a href="https://cloudreve.org/" alt="logo" ><img src="https://raw.githubusercontent.com/cloudreve/frontend/master/public/static/img/logo192.png" width="150"/></a>
<br>
Cloudreve
<br>
</h1>
<h4 align="center">支持多家云存储驱动的公有云文件系统.</h4>
<p align="center">
<a href="https://github.com/cloudreve/Cloudreve/actions/workflows/test.yml">
<img src="https://img.shields.io/github/actions/workflow/status/cloudreve/Cloudreve/test.yml?branch=master&style=flat-square"
alt="GitHub Test Workflow">
</a>
<a href="https://codecov.io/gh/cloudreve/Cloudreve"><img src="https://img.shields.io/codecov/c/github/cloudreve/Cloudreve?style=flat-square"></a>
<a href="https://goreportcard.com/report/github.com/cloudreve/Cloudreve">
<img src="https://goreportcard.com/badge/github.com/cloudreve/Cloudreve?style=flat-square">
</a>
<a href="https://github.com/cloudreve/Cloudreve/releases">
<img src="https://img.shields.io/github/v/release/cloudreve/Cloudreve?include_prereleases&style=flat-square" />
</a>
<a href="https://hub.docker.com/r/cloudreve/cloudreve">
<img src="https://img.shields.io/docker/image-size/cloudreve/cloudreve?style=flat-square"/>
</a>
</p>
<p align="center">
<a href="https://cloudreve.org">主页</a> •
<a href="https://demo.cloudreve.org">演示站</a> •
<a href="https://forum.cloudreve.org/">讨论社区</a> •
<a href="https://docs.cloudreve.org/">文档</a> •
<a href="https://github.com/cloudreve/Cloudreve/releases">下载</a> •
<a href="https://t.me/cloudreve_official">Telegram 群组</a> •
<a href="#scroll-许可证">许可证</a>
</p>
![Screenshot](https://raw.githubusercontent.com/cloudreve/docs/master/images/homepage.png)
## :sparkles: 特性
* :cloud: 支持本机、从机、七牛、阿里云 OSS、腾讯云 COS、又拍云、OneDrive (包括世纪互联版) 、S3兼容协议 作为存储端
* :outbox_tray: 上传/下载 支持客户端直传,支持下载限速
* 💾 可对接 Aria2 离线下载,可使用多个从机节点分担下载任务
* 📚 在线 压缩/解压缩、多文件打包下载
* 💻 覆盖全部存储策略的 WebDAV 协议支持
* :zap: 拖拽上传、目录上传、流式上传处理
* :card_file_box: 文件拖拽管理
* :family_woman_girl_boy: 多用户、用户组、多存储策略
* :link: 创建文件、目录的分享链接,可设定自动过期
* :eye_speech_bubble: 视频、图像、音频、 ePub 在线预览,文本、Office 文档在线编辑
* :art: 自定义配色、黑暗模式、PWA 应用、全站单页应用、国际化支持
* :rocket: All-In-One 打包,开箱即用
* 🌈 ... ...
## :hammer_and_wrench: 部署
下载适用于您目标机器操作系统、CPU架构的主程序,直接运行即可。
```shell
# 解压程序包
tar -zxvf cloudreve_VERSION_OS_ARCH.tar.gz
# 赋予执行权限
chmod +x ./cloudreve
# 启动 Cloudreve
./cloudreve
```
以上为最简单的部署示例,您可以参考 [文档 - 起步](https://docs.cloudreve.org/) 进行更为完善的部署。
## :gear: 构建
自行构建前需要拥有 `Go >= 1.18``node.js``yarn``zip`, [goreleaser](https://goreleaser.com/intro/) 等必要依赖。
#### 安装 goreleaser
```shell
go install github.com/goreleaser/goreleaser@latest
```
#### 克隆代码
```shell
git clone --recurse-submodules https://github.com/cloudreve/Cloudreve.git
```
#### 编译项目
```shell
goreleaser build --clean --single-target --snapshot
```
## :alembic: 技术栈
* [Go](https://golang.org/) + [Gin](https://github.com/gin-gonic/gin)
* [React](https://github.com/facebook/react) + [Redux](https://github.com/reduxjs/redux) + [Material-UI](https://github.com/mui-org/material-ui)
## :scroll: 许可证
GPL V3
-1
View File
@@ -1 +0,0 @@
database.php
-1
View File
@@ -1 +0,0 @@
deny from all
-12
View File
@@ -1,12 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
return [];
-41
View File
@@ -1,41 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: 流年 <liu21st@gmail.com>
// +----------------------------------------------------------------------
// 应用公共文件
function array_column_fix($array,$key){
if(count($array) == count($array,1)){
return array(0 =>$array[$key]);
}else{
return array_column($array,$key);
}
}
function getAllowedExt($ext){
$returnValue = "";
foreach (json_decode($ext,true) as $key => $value) {
$returnValue .= $value["ext"].",";
}
return rtrim($returnValue, ",");
}
function getDirName($name){
$explode = explode("/", $name);
return end($explode);
}
function getSize($bit,$array=false){
$type = array('Bytes','KB','MB','GB','TB');
$box = array('1','1024','1048576','1073741824','TB');
for($i = 0; $bit >= 1024; $i++) {
$bit/=1024;
}
if($array){
return [(floor($bit*100)/100),$box[$i]];
}
return (floor($bit*100)/100).$type[$i];
}
-270
View File
@@ -1,270 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
return [
// +----------------------------------------------------------------------
// | 应用设置
// +----------------------------------------------------------------------
//密码加盐
'salt' => 'sdshare',
// 应用命名空间
'app_namespace' => 'app',
// 应用调试模式
'app_debug' => false,
// 应用Trace
'app_trace' => false,
// 应用模式状态
'app_status' => '',
// 是否支持多模块
'app_multi_module' => true,
// 入口自动绑定模块
'auto_bind_module' => false,
// 注册的根命名空间
'root_namespace' => [],
// 扩展函数文件
'extra_file_list' => [THINK_PATH . 'helper' . EXT],
// 默认输出类型
'default_return_type' => 'html',
// 默认AJAX 数据返回格式,可选json xml ...
'default_ajax_return' => 'json',
// 默认JSONP格式返回的处理方法
'default_jsonp_handler' => 'jsonpReturn',
// 默认JSONP处理方法
'var_jsonp_handler' => 'callback',
// 默认时区
'default_timezone' => 'PRC',
// 是否开启多语言
'lang_switch_on' => false,
// 默认全局过滤方法 用逗号分隔多个
'default_filter' => '',
// 默认语言
'default_lang' => 'zh-cn',
// 应用类库后缀
'class_suffix' => false,
// 控制器类后缀
'controller_suffix' => false,
// +----------------------------------------------------------------------
// | 模块设置
// +----------------------------------------------------------------------
// 默认模块名
'default_module' => 'index',
// 禁止访问模块
'deny_module_list' => ['common'],
// 默认控制器名
'default_controller' => 'Index',
// 默认操作名
'default_action' => 'index',
// 默认验证器
'default_validate' => '',
// 默认的空控制器名
'empty_controller' => 'Error',
// 操作方法后缀
'action_suffix' => '',
// 自动搜索控制器
'controller_auto_search' => false,
// +----------------------------------------------------------------------
// | URL设置
// +----------------------------------------------------------------------
// PATHINFO变量名 用于兼容模式
'var_pathinfo' => 's',
'url_convert' => false,
// 兼容PATH_INFO获取
'pathinfo_fetch' => ['ORIG_PATH_INFO', 'REDIRECT_PATH_INFO', 'REDIRECT_URL'],
// pathinfo分隔符
'pathinfo_depr' => '/',
// URL伪静态后缀
'url_html_suffix' => '',
// URL普通方式参数 用于自动生成
'url_common_param' => false,
// URL参数方式 0 按名称成对解析 1 按顺序解析
'url_param_type' => 0,
// 是否开启路由
'url_route_on' => true,
// 路由使用完整匹配
'route_complete_match' => false,
// 路由配置文件(支持配置多个)
'route_config_file' => ['route'],
// 是否强制使用路由
'url_route_must' => false,
// 域名部署
'url_domain_deploy' => false,
// 域名根,如thinkphp.cn
'url_domain_root' => '',
// 是否自动转换URL中的控制器和操作名
'url_convert' => false,
// 默认的访问控制器层
'url_controller_layer' => 'controller',
// 表单请求类型伪装变量
'var_method' => '_method',
// 表单ajax伪装变量
'var_ajax' => '_ajax',
// 表单pjax伪装变量
'var_pjax' => '_pjax',
// 是否开启请求缓存 true自动缓存 支持设置请求缓存规则
'request_cache' => false,
// 请求缓存有效期
'request_cache_expire' => null,
// 全局请求缓存排除规则
'request_cache_except' => [],
// +----------------------------------------------------------------------
// | 模板设置
// +----------------------------------------------------------------------
'template' => [
// 模板引擎类型 支持 php think 支持扩展
'type' => 'Think',
// 模板路径
'view_path' => '',
// 模板后缀
'view_suffix' => 'html',
// 模板文件名分隔符
'view_depr' => DS,
// 模板引擎普通标签开始标记
'tpl_begin' => '{',
// 模板引擎普通标签结束标记
'tpl_end' => '}',
// 标签库标签开始标记
'taglib_begin' => '{',
// 标签库标签结束标记
'taglib_end' => '}',
],
// 视图输出字符串内容替换
'view_replace_str' => [],
// 默认跳转页面对应的模板文件
'dispatch_success_tmpl' => THINK_PATH . 'tpl' . DS . 'dispatch_jump.tpl',
'dispatch_error_tmpl' => "application/index/view/error.html",
// +----------------------------------------------------------------------
// | 异常及错误设置
// +----------------------------------------------------------------------
// 异常页面的模板文件
'exception_tmpl' => THINK_PATH . 'tpl' . DS . 'think_exception.tpl',
// 错误显示信息,非调试模式有效
'error_message' => '页面错误!请稍后再试~',
// 显示错误信息
'show_error_msg' => false,
// 异常处理handle类 留空使用 \think\exception\Handle
'exception_handle' => '',
// +----------------------------------------------------------------------
// | 日志设置
// +----------------------------------------------------------------------
'log' => [
// 日志记录方式,内置 file socket 支持扩展
'type' => 'File',
// 日志保存目录
'path' => LOG_PATH,
// 日志记录级别
'level' => ["error"],
],
// +----------------------------------------------------------------------
// | Trace设置 开启 app_trace 后 有效
// +----------------------------------------------------------------------
'trace' => [
// 内置Html Console 支持扩展
'type' => 'Html',
],
// +----------------------------------------------------------------------
// | 缓存设置
// +----------------------------------------------------------------------
'cache' => [
// 驱动方式
'type' => 'File',
// 缓存保存目录
'path' => CACHE_PATH,
// 缓存前缀
'prefix' => '',
// 缓存有效期 0表示永久缓存
'expire' => 0,
],
// +----------------------------------------------------------------------
// | 会话设置
// +----------------------------------------------------------------------
'session' => [
'id' => '',
// SESSION_ID的提交变量,解决flash上传跨域
'var_session_id' => '',
// SESSION 前缀
'prefix' => 'sd',
// 驱动方式 支持redis memcache memcached
'type' => '',
// 是否自动开启 SESSION
'auto_start' => true,
],
// +----------------------------------------------------------------------
// | Cookie设置
// +----------------------------------------------------------------------
'cookie' => [
// cookie 名称前缀
'prefix' => '',
// cookie 保存时间
'expire' => 0,
// cookie 保存路径
'path' => '/',
// cookie 有效域名
'domain' => '',
// cookie 启用安全传输
'secure' => false,
// httponly设置
'httponly' => '',
// 是否使用 setcookie
'setcookie' => true,
],
//分页配置
'paginate' => [
'type' => 'bootstrap',
'var_page' => 'page',
'list_rows' => 15,
],
// +----------------------------------------------------------------------
// | 验证码设置
// +----------------------------------------------------------------------
'captcha'=>[
'codeSet' => '2345678abcdefhijkmnpqrstuvwxyzABCDEFGHJKLMNPQRTUVWXY',
// 验证码字符集合
'expire' => 1800,
// 验证码过期时间(s
'useZh' => false,
// 使用背景图片
'fontSize' => 25,
// 验证码字体大小(px)
'useCurve' => true,
// 是否画混淆曲线
'useNoise' => true,
// 是否添加杂点
'imageH' => 0,
// 验证码图片高度
'imageW' => 0,
// 验证码图片宽度
'length' => 4,
// 验证码位数
'fontttf' => '',
// 验证码字体,不设置随机获取
'bg' => [243, 251, 254],
// 背景颜色
'reset' => true],
];
-53
View File
@@ -1,53 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
return [
// 数据库类型
'type' => 'mysql',
// 服务器地址
'hostname' => '127.0.0.1',
// 数据库名
'database' => 'tp',
// 用户名
'username' => 'root',
// 密码
'password' => 'root',
// 端口
'hostport' => '3306',
// 连接dsn
'dsn' => '',
// 数据库连接参数
'params' => [],
// 数据库编码默认采用utf8
'charset' => 'utf8',
// 数据库表前缀
'prefix' => 'sd_',
// 数据库调试模式
'debug' => true,
// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
'deploy' => 0,
// 数据库读写是否分离 主从式有效
'rw_separate' => false,
// 读写分离后 主服务器数量
'master_num' => 1,
// 指定从服务器序号
'slave_no' => '',
// 是否严格检查字段是否存在
'fields_strict' => true,
// 数据集返回类型
'resultset_type' => 'array',
// 自动写入时间戳字段
'auto_timestamp' => false,
// 时间字段取出后的默认时间格式
'datetime_format' => 'Y-m-d H:i:s',
// 是否需要进行SQL性能分析
'sql_explain' => false,
];
-14
View File
@@ -1,14 +0,0 @@
<?php
function classLoader($class)
{
$path = str_replace('\\', DIRECTORY_SEPARATOR, $class);
$file = __DIR__ . '/src/' . $path . '.php';
if (file_exists($file)) {
require_once $file;
}
}
spl_autoload_register('classLoader');
require_once __DIR__ . '/src/Qiniu/functions.php';
-25
View File
@@ -1,25 +0,0 @@
<?php
function countSize($bit,$array=false){
$type = array('Bytes','KB','MB','GB','TB');
$box = array('1','1024','1048576','1073741824','TB');
for($i = 0; $bit >= 1024; $i++) {
$bit/=1024;
}
if($array){
return [(floor($bit*100)/100),$box[$i]];
}
return (floor($bit*100)/100).$type[$i];
}
function isPreview($fileName){
$allowedSuffix=["jpg","jpeg","gif","bmp","png","svg","mp4","mp3","ogg"];
$suffix = explode(".",$fileName);
if(in_array(end($suffix),$allowedSuffix)){
return "yes";
}
return "no";
}
function getDay($sec){
return floor($sec/86400);
}
?>
-486
View File
@@ -1,486 +0,0 @@
<?php
namespace app\index\controller;
use think\Controller;
use app\index\model\User;
use think\Cookie;
use think\Db;
use \app\index\model\Option;
use \app\index\model\AdminHandler;
use \app\index\model\FileManage;
class Admin extends Controller{
public $userObj;
public $siteOptions;
public $adminObj;
public function _initialize(){
$this->siteOptions = Option::getValues(["basic","admin"]);
$this->userObj = new User(cookie('user_id'),cookie('login_key'));
if(!$this->userObj->loginStatus){
$this->redirect(url('/Login','',''));
exit();
}
if($this->userObj->groupData["id"] != 1){
$this->error('你无权访问此页面',403,$this->siteOptions);
}
$this->adminObj = new AdminHandler($this->siteOptions);
}
public function index(){
if($this->adminObj->checkDbVersion()){
$this->redirect(url('/Admin/UpdateDb','',''));
exit();
}
return view('admin_index', [
'options' => $this->siteOptions,
'statics' => $this->adminObj->getStatics(),
]);
}
public function UpdateDb(){
if(!$this->adminObj->checkDbVersion()){
$this->redirect(url('/Admin','',''));
exit();
}
echo "<meta charset='utf-8'>";
echo "准备升级数据库,当前数据库版本:".$this->adminObj->dbVerInfo["now"];
echo ", 目标数据库版本:".$this->adminObj->dbVerInfo["require"].";<br>";
$updatePath = ROOT_PATH . "update_".$this->adminObj->dbVerInfo["now"]."to".$this->adminObj->dbVerInfo["require"].".sql";
if(!file_exists($updatePath)){
die("数据库更新文件(".$updatePath.")不存在,升级中止.");
}
echo "获取升级SQL文件(".$updatePath.")<br>";
$updateContent = file_get_contents($updatePath);
echo "将执行以下指令:<br>";
echo "<code>".htmlspecialchars($updateContent)."</code><br>";
$sqlSingle = explode(";", $updateContent);
foreach ($sqlSingle as $key => $value){
if(empty($value)){
continue;
}
if(!Db::execute($value)){
echo "<strong>执行$value 时出现错误</strong><br>";
}
}
echo "<strong>升级完成,<a href='/Admin'>返回管理面板</a></strong>";
}
public function Setting(){
return view('basic_setting', [
'options' => $this->siteOptions,
]);
}
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","download"]),
]);
}
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 PolicyAddRemote(){
return view('add_policy_remote', [
'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(),
]);
}
}
-91
View File
@@ -1,91 +0,0 @@
<?php
namespace app\index\controller;
use think\Controller;
use think\Db;
use think\Request;
use \app\index\model\CallbackHandler;
use \app\index\model\User;
use \app\index\model\Option;
use \app\index\model\FileManage;
use think\Session;
class Callback extends Controller{
public function index(){
return "";
}
public function Qiniu(){
ob_end_clean();
header('Content-Type: application/json');
$handllerObj = new CallbackHandler(file_get_contents("php://input"));
$handllerObj -> qiniuHandler(Request::instance()->header('Authorization'));
}
public function Oss(){
ob_end_clean();
header('Content-Type: application/json');
$handllerObj = new CallbackHandler(file_get_contents("php://input"));
$handllerObj -> ossHandler(Request::instance()->header('Authorization'),Request::instance()->header('x-oss-pub-key-url'));
}
public function TmpPreview(){
$basicOptions = Option::getValues(['basic']);
$params = explode(":",input("param.key"));
$fileData = Db::name("files")->where("id",$params[0])->find();
if (empty($fileData)){
abort(404);
}
$userData = Db::name("users")->where("id",$fileData["upload_user"])->find();
if(md5($userData["user_pass"].$fileData["id"].$params[1].config("salt")) != $params[2] || time()<$params[0]){
abort(403);
}
$fileObj = new FileManage(rtrim($fileData["dir"],"/")."/".$fileData["orign_name"],$userData["id"]);
$Redirect = $fileObj->PreviewHandler();
}
public function Upyun(){
$signToken = Request::instance()->header('Authorization');
$reqDate = Request::instance()->header('Date');
$contentMd5 = Request::instance()->header('Content-MD5');
ob_end_clean();
header('Content-Type: application/json');
$callbackData = [
"code" => input("post.code"),
"file_size" => input("post.file_size"),
"url" => input("post.url"),
"image-width" => input("post.image-width"),
"image-height" => input("post.image-height"),
"ext-param" => json_decode(input("post.ext-param"),true),
];
$handllerObj = new CallbackHandler($callbackData);
$handllerObj -> upyunHandler($signToken,$reqDate,$contentMd5);
}
public function S3(){
$request = Request::instance();
if($request->method() == "OPTIONS"){
ob_end_clean();
header("Access-Control-Allow-Origin: *");
exit();
}
ob_end_clean();
header("Access-Control-Allow-Origin: *");
$callbackKey = input("param.key");
$callbackData = [
"bucket" => input("get.bucket"),
"key" => input("get.key"),
];
$handllerObj = new CallbackHandler($callbackData);
$handllerObj -> s3Handler($callbackKey);
}
public function Remote(){
ob_end_clean();
header('Content-Type: application/json');
$handllerObj = new CallbackHandler(file_get_contents("php://input"));
$handllerObj -> remoteHandler(Request::instance()->header('Authorization'));
}
}
-17
View File
@@ -1,17 +0,0 @@
<?php
namespace app\index\controller;
use think\Controller;
use think\Db;
use think\Request;
use \app\index\model\CronHandler;
use think\Session;
class Cron extends Controller{
public function index(){
$cornObj = new CronHandler();
$cornObj->Doit();
}
}
-60
View File
@@ -1,60 +0,0 @@
<?php
namespace app\index\controller;
use think\Controller;
use app\index\model\User;
use think\Cookie;
use think\Db;
use \app\index\model\Option;
class Explore extends Controller{
public $visitorObj;
public $userObj;
public $siteOptions;
public function _initialize(){
$this->siteOptions = Option::getValues(["basic"]);
}
public function Search(){
$this->visitorObj = new User(cookie('user_id'),cookie('login_key'));
return view("search",[
"options" => $this->siteOptions,
'loginStatus' => $this->visitorObj->loginStatus,
'userData' => $this->visitorObj->userSQLData,
]);
}
public function S(){
$this->visitorObj = new User(cookie('user_id'),cookie('login_key'));
$keyWords=input("param.key");
if(empty($keyWords)){
$this->redirect('/Explore/Search',302);
}
$list = Db::name('shares')
->where('type',"public")
->where('origin_name',"like","%".$keyWords."%")
->order('id DESC')
->paginate(10);
$listData = $list->all();
foreach ($listData as $key => $value) {
if($value["source_type"]=="file"){
$listData[$key]["fileData"] = $value["origin_name"];
}else{
$pathDir = explode("/",$value["source_name"]);
$listData[$key]["fileData"] = end($pathDir);
}
}
return view("result",[
"options" => $this->siteOptions,
'loginStatus' => $this->visitorObj->loginStatus,
'userData' => $this->visitorObj->userSQLData,
'list' => $listData,
'listOrigin' => $list,
'keyWords' => $keyWords,
]);
}
}
-175
View File
@@ -1,175 +0,0 @@
<?php
namespace app\index\controller;
use think\Controller;
use think\Db;
use think\Request;
use \app\index\model\Option;
use \app\index\model\User;
use \app\index\model\FileManage;
use \app\index\model\ShareHandler;
use think\Session;
class File extends Controller{
public $userObj;
/**
* [_initialize description]
* @return [type] [description]
*/
public function _initialize(){
$this->userObj = new User(cookie('user_id'),cookie('login_key'));
if(!$this->userObj->loginStatus){
echo "Bad request";
exit();
}
}
/**
* [index description]
* @Author Aaron
* @DateTime 2017-07-03
* @return [type] [description]
*/
public function index(){
return "";
}
/**
* [List description]
* @Author Aaron
* @DateTime 2017-07-03
*/
public function ListFile(){
$reqPath = stripslashes(json_decode(file_get_contents("php://input"),true)['path']);
return FileManage::ListFile($reqPath,$this->userObj->uid);
}
public function Delete(){
$reqPath = json_decode(file_get_contents("php://input"),true)['items'];
$dirPath = json_decode(file_get_contents("php://input"),true)['dirs'];
FileManage::DirDeleteHandler($dirPath,$this->userObj->uid);
return FileManage::DeleteHandler($reqPath,$this->userObj->uid);
}
public function Move(){
$reqPath = json_decode(file_get_contents("php://input"),true)['items'];
$dirPath = json_decode(file_get_contents("php://input"),true)['dirs'];
$newPath = json_decode(file_get_contents("php://input"),true)['newPath'];
return FileManage::MoveHandler($reqPath,$dirPath,$newPath,$this->userObj->uid);
}
public function Rename(){
$reqPath = json_decode(file_get_contents("php://input"),true)['item'];
$newPath = json_decode(file_get_contents("php://input"),true)['newItemPath'];
return FileManage::RenameHandler($reqPath,$newPath,$this->userObj->uid);
}
public function Preview(){
$reqPath = $_GET["path"];
$fileObj = new FileManage($reqPath,$this->userObj->uid);
$Redirect = $fileObj->PreviewHandler();
if($Redirect[0]){
$this->redirect($Redirect[1],302);
}
}
public function ListPic(){
$reqPath = $_GET["path"];
return FileManage::listPic($reqPath,$this->userObj->uid);
}
public function Download(){
$reqPath = $_GET["path"];
$fileObj = new FileManage($reqPath,$this->userObj->uid);
$FileHandler = $fileObj->Download();
if($FileHandler[0]){
$this->redirect($FileHandler[1],302);
}
}
public function Share(){
$reqPath = json_decode(file_get_contents("php://input"),true)['item'];
$shareType = json_decode(file_get_contents("php://input"),true)['shareType'];
ShareHandler::createShare($reqPath,$shareType,$this->userObj->getSQLData(),$this->userObj->getGroupData());
}
public function gerSource(){
$reqPath = $_POST["path"];
$fileObj = new FileManage($reqPath,$this->userObj->uid);
$FileHandler = $fileObj->Source();
}
public function Content(){
$reqPath = json_decode(file_get_contents("php://input"),true)['item'];
$fileObj = new FileManage($reqPath,$this->userObj->uid);
$FileHandler = $fileObj->getContent();
}
public function Edit(){
$reqPath = json_decode(file_get_contents("php://input"),true)['item'];
$fileContent = json_decode(file_get_contents("php://input"),true)['content'];
$fileObj = new FileManage($reqPath,$this->userObj->uid);
$FileHandler = $fileObj->saveContent($fileContent);
}
public function OssDownload(){
return view('oss_download', [
'url' => urldecode(input("get.url")),
'name' => urldecode(input("get.name")),
]);
}
public function DocPreview(){
$filePath = input("get.path");
$fileObj = new FileManage($filePath,$this->userObj->uid);
$tmpUrl = $fileObj->signTmpUrl();
$this->redirect("http://view.officeapps.live.com/op/view.aspx?src=".urlencode($tmpUrl),302);
}
public function Thumb(){
$filePath = input("get.path");
if(input("get.isImg") != "true"){
return "";
}
$fileObj = new FileManage($filePath,$this->userObj->uid);
$Redirect = $fileObj->getThumb();
if($Redirect[0]){
$this->redirect($Redirect[1],302);
}
}
public function GoogleDocPreview(){
$filePath = input("get.path");
$fileObj = new FileManage($filePath,$this->userObj->uid);
$tmpUrl = $fileObj->signTmpUrl();
$this->redirect("https://docs.google.com/viewer?url=".urlencode($tmpUrl),302);
}
/**
* [createFolder description]
* @Author Aaron
* @DateTime 2017-07-03
* @return [type] [description]
*/
public function createFolder(){
$reqPath = stripslashes(json_decode(file_get_contents("php://input"),true)['newPath']);
$pathSplit = explode("/",$reqPath);
$dirName = end($pathSplit);
$dirPosition="/";
foreach ($pathSplit as $key => $value) {
if (empty($value)){
}else if($key == (count($pathSplit)-2)){
$dirPosition = $dirPosition.$value;
}else if($key == (count($pathSplit)-1)){
}else{
$dirPosition = $dirPosition.$value."/";
}
}
return FileManage::createFolder($dirName,$dirPosition,$this->userObj->uid);
}
}
-75
View File
@@ -1,75 +0,0 @@
<?php
namespace app\index\controller;
use think\Controller;
use think\Db;
use \app\index\model\Option;
use \app\index\model\User;
use think\Session;
class Home extends Controller{
public $userObj;
public function _initialize(){
$this->userObj = new User(cookie('user_id'),cookie('login_key'));
if(!$this->userObj->loginStatus){
$this->redirect(url('/Login','',''));
exit();
}
}
public function index(){
$userInfo = $this->userObj->getInfo();
$policyData = $this->userObj->getPolicy();
$groupData = $this->userObj->getGroupData();
$extJson = json_decode($policyData["filetype"],true);
$extLimit="";
foreach ($extJson as $key => $value) {
$extLimit.='{ title : "'.$value["title"].'", extensions : "'.$value["ext"].'" },';
}
$policyData["max_size"] = $policyData["max_size"]/(1024*1024);
return view('home', [
'options' => Option::getValues(['basic','upload']),
'userInfo' => $userInfo,
'extLimit' => $extLimit,
'policyData' => $policyData,
'groupData' => $groupData,
]);
}
public function Album(){
$userInfo = $this->userObj->getInfo();
$list = Db::name("files")->where("upload_user",$this->userObj->uid)
->where(function ($query) {
$query->where('orign_name', "like","%jpg")
->whereor('orign_name', "like","%png")
->whereor('orign_name', "like","%gif")
->whereor('orign_name', "like","%bmp");
})
->order('id DESC')
->paginate(9);
$pageCount = ceil(Db::name("files")->where("upload_user",$this->userObj->uid)
->where(function ($query) {
$query->where('orign_name', "like","%jpg")
->whereor('orign_name', "like","%png")
->whereor('orign_name', "like","%gif")
->whereor('orign_name', "like","%bmp");
})
->order('id DESC')->count()/9);
$listData = $list->all();
$pageNow = input("?get.page")?input("get.page"):1;
if($pageNow>$pageCount){
$this->error('页面不存在',404,Option::getValues(['basic','group_sell']));
}
return view('album', [
'options' => Option::getValues(['basic','group_sell']),
'userInfo' => $userInfo,
'list' => $listData,
'listOrigin' => $list,
'pageCount' => $pageCount,
'page' => $pageNow,
]);
}
}
-27
View File
@@ -1,27 +0,0 @@
<?php
namespace app\index\controller;
use think\Controller;
use think\Db;
use \app\index\model\Option;
use \app\index\model\User;
class Index extends Controller{
public $userObj;
public function index(){
$this->userObj = new User(cookie('user_id'),cookie('login_key'));
if($this->userObj->loginStatus){
$this->redirect(url('/Home','',''));
exit();
}
$userInfo = $this->userObj->getInfo();
return view('index', [
'options' => Option::getValues(['basic']),
'userInfo' => $userInfo,
]);
}
}
-300
View File
@@ -1,300 +0,0 @@
<?php
namespace app\index\controller;
use think\Controller;
use app\index\model\User;
use think\Cookie;
use think\Db;
use \app\index\model\Option;
use \app\index\model\Avatar;
use \PHPGangsta_GoogleAuthenticator;
use \app\index\model\TwoFactor;
class Member extends Controller{
public $userObj;
/**
* [index description]
* @return [type] [description]
*/
public function index(){
echo "hello";
}
/**
* [Register description]
*/
public function Register(){
if(input('?post.username-reg') && input('?post.password-reg')){
$regAction = User::register(input('post.username-reg'),input('post.password-reg'),input('post.captchaCode'));
if ($regAction[0]){
return json(['code' => '200','message' => $regAction[1]]);
}else{
return json(['code' => '1','message' => $regAction[1]]);
}
}else{
return json(['code' => '1','message' => "信息不完整"]);
}
}
public function ForgetPwd(){
if(input('?post.regEmail') && !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();
}
}
}
-80
View File
@@ -1,80 +0,0 @@
<?php
namespace app\index\controller;
use think\Controller;
use app\index\model\User;
use think\Cookie;
use think\Db;
use \app\index\model\Option;
class Profile extends Controller{
public $visitorObj;
public $userObj;
public $siteOptions;
public function _initialize(){
$this->siteOptions = Option::getValues(["basic"]);
}
public function index(){
$this->visitorObj = new User(cookie('user_id'),cookie('login_key'));
$userId = (string)input("param.uid");
$userData = Db::name("users")->where("id",$userId)->find();
if (empty($userId) || empty($userData) || $userData["profile"] == 0){
$this->error('用户主页不存或者用户关闭了个人主页',404,$this->siteOptions);
}
$groupData = Db::name("groups")->where("id",$userData["user_group"])->find();
$shareCount = Db::name('shares')
->where('owner',$userId)
->where('type',"public")
->count();
$regDays = (int)((time()-strtotime($userData["user_date"]))/86400);
switch (input("get.type")) {
case 'all':
$list = Db::name('shares')
->where('owner',$userId)
->where('type',"public")
->order('id DESC')
->paginate(10);
break;
case 'hot':
$num = Option::getValue("hot_share_num");
$list = Db::name('shares')
->where('owner',$userId)
->where('type',"public")
->paginate($num);
break;
default:
$list = Db::name('shares')
->where('owner',$userId)
->where('type',"public")
->order('id DESC')
->paginate(10);
break;
}
$listData = $list->all();
foreach ($listData as $key => $value) {
if($value["source_type"]=="file"){
$listData[$key]["fileData"] = Db::name('files')->where('id',$value["source_name"])->find()["orign_name"];
}else{
$pathDir = explode("/",$value["source_name"]);
$listData[$key]["fileData"] = end($pathDir);
}
}
return view("profile",[
"options" => $this->siteOptions,
'loginStatus' => $this->visitorObj->loginStatus,
'userInfo' => $userData,
'userData' => $this->visitorObj->userSQLData,
'groupData' => $groupData,
'list' => $listData,
'listOrigin' => $list,
'type' => input("get.type"),
'shareCount' => $shareCount,
'regDays' => $regDays,
]);
}
}
-185
View File
@@ -1,185 +0,0 @@
<?php
namespace app\index\controller;
use think\Controller;
use think\Db;
use \app\index\model\Option;
use \app\index\model\User;
use \app\index\model\ShareHandler;
use think\Session;
use think\Request;
class Share extends Controller{
public $userObj;
public $siteOptions;
public function _initialize(){
$this->userObj = new User(cookie('user_id'),cookie('login_key'));
$this->siteOptions = Option::getValues(["basic"]);
}
public function index(){
$shareKey = input('param.key');
$shareObj = new ShareHandler($shareKey);
if(!$shareObj->querryStatus){
header('HTTP/1.1 404 Not Found');
$this->error('当前分享不存在或者已经失效',404,$this->siteOptions);
}
if(!$shareObj->lockStatus){
$shareObj->numIncrease("view_num");
if($shareObj->shareData["source_type"] == "dir"){
return view('share_dir', [
'options' => Option::getValues(['basic','share']),
'userInfo' => $shareObj->shareOwner->userSQLData,
'dirData' => $shareObj->dirData,
'shareData' => $shareObj->shareData,
'loginStatus' => $this->userObj->loginStatus,
'userData' => $this->userObj->userSQLData,
'groupData' => $shareObj->shareOwner->groupData,
'allowPreview' => Option::getValue("allowdVisitorDownload"),
]);
}else{
return view('share_single', [
'options' => Option::getValues(['basic','share']),
'userInfo' => $shareObj->shareOwner->userSQLData,
'fileData' => $shareObj->fileData,
'shareData' => $shareObj->shareData,
'loginStatus' => $this->userObj->loginStatus,
'userData' => $this->userObj->userSQLData,
'allowPreview' => Option::getValue("allowdVisitorDownload"),
]);
}
}else{
return view('share_lock', [
'options' => Option::getValues(['basic','share']),
'userInfo' => $shareObj->shareOwner->userSQLData,
'fileData' => $shareObj->fileData,
'shareData' => $shareObj->shareData,
'loginStatus' => $this->userObj->loginStatus,
'userData' => $this->userObj->userSQLData,
'pwd' => input("?get.pwd") ? input("get.pwd") : "",
]);
}
}
public function getDownloadUrl(){
$shareId = input('key');
$shareObj = new ShareHandler($shareId,false);
return $shareObj->getDownloadUrl($this->userObj);
}
public function Download(){
$shareId = input('param.key');
$filePath = input('get.path');
$shareObj = new ShareHandler($shareId,false);
if(empty($filePath)){
$DownloadHandler = $shareObj->Download($this->userObj);
}else{
$DownloadHandler = $shareObj->DownloadFolder($this->userObj,$filePath);
}
if($DownloadHandler[0]){
$this->redirect($DownloadHandler[1],302);
}else{
$this->error($DownloadHandler[1],404,$this->siteOptions);
}
}
public function chekPwd(){
$shareId = input('key');
$inputPwd = input('password');
$shareObj = new ShareHandler($shareId,false);
if(!$shareObj->querryStatus){
return array(
"error" => 1,
"msg" => "分享不存在"
);
}
return $shareObj->checkPwd($inputPwd);
}
public function Preview(){
$shareId = input('param.key');
$filePath = input('get.path');
$shareObj = new ShareHandler($shareId,false);
if(empty($filePath)){
$previewHandler = $shareObj->Preview($this->userObj);
}else{
if(!empty(input('get.folder'))){
$previewHandler = $shareObj->PreviewFolder($this->userObj,$filePath,true);
}else{
$previewHandler = $shareObj->PreviewFolder($this->userObj,$filePath);
}
}
if($previewHandler[0]){
$this->redirect($previewHandler[1],302);
}else{
$this->error($previewHandler[1],404,$this->siteOptions);
}
}
public function ListFile(){
$shareId = input('param.key');
$reqPathTo = stripslashes(json_decode(file_get_contents("php://input"),true)['path']);
$shareObj = new ShareHandler($shareId,false);
return $shareObj->ListFile($reqPathTo);
}
public function ListPic(){
$filePath = input('get.path');
$shareId = input('get.id');
$shareObj = new ShareHandler($shareId,false);
return $shareObj->listPic($shareId,$filePath);
}
public function Delete(){
$shareId = input('post.id');
$shareObj = new ShareHandler($shareId,false);
if(!$shareObj->querryStatus){
return array(
"error" => 1,
"msg" => "分享不存在"
);
}
return $shareObj->deleteShare($this->userObj->uid);
}
public function ChangePromission(){
$shareId = input('post.id');
$shareObj = new ShareHandler($shareId,false);
if(!$shareObj->querryStatus){
return array(
"error" => 1,
"msg" => "分享不存在"
);
}
return $shareObj->changePromission($this->userObj->uid);
}
public function My(){
if(!$this->userObj->loginStatus){
$this->redirect(url('/Login','',''));
exit();
}
$userInfo = $this->userObj->getInfo();
$groupData = $this->userObj->getGroupData();
$list = Db::name('shares')->where('owner',$this->userObj->uid)->paginate(10);
$listData = $list->all();
foreach ($listData as $key => $value) {
if($value["source_type"]=="file"){
$listData[$key]["fileData"] = Db::name('files')->where('id',$value["source_name"])->find()["orign_name"];
}else{
$listData[$key]["fileData"] = $value["source_name"];
}
}
return view('share_home', [
'options' => Option::getValues(['basic','share']),
'userInfo' => $userInfo,
'groupData' => $groupData,
'list' => $listData,
'listOrigin' => $list
]);
}
}
-78
View File
@@ -1,78 +0,0 @@
<?php
namespace app\index\controller;
use think\Controller;
use think\Db;
use think\Request;
use \app\index\model\Option;
use \app\index\model\User;
use \app\index\model\UploadHandler;
use think\Session;
class Upload extends Controller{
public $userObj;
public function _initialize(){
$this->userObj = new User(cookie('user_id'),cookie('login_key'));
if(!$this->userObj->loginStatus){
echo "Bad request";
exit();
}
}
public function index(){
ob_end_clean();
$file = request()->file('file');
$fileInfo = Request::instance()->request();
$UploadHandler = new UploadHandler($this->userObj->groupData['policy_name'],$this->userObj->uid);
return $UploadHandler->fileReceive($file,$fileInfo);
}
public function Token(){
$uploadObj = new UploadHandler($this->userObj->groupData['policy_name'],$this->userObj->uid);
$upToken = $uploadObj->getToken();
if(!empty($uploadObj->upyunPolicy)){
return json([
"token" => $upToken,
"policy" => $uploadObj->upyunPolicy,
]);
}
if(!empty($uploadObj->s3Policy)){
return json([
"policy" => $uploadObj->s3Policy,
"sign" => $uploadObj->s3Sign,
"key" => $uploadObj->dirName,
"credential" => $uploadObj->s3Credential,
"x_amz_date" => $uploadObj->x_amz_date,
"siteUrl"=>$uploadObj->siteUrl,
"callBackKey" => $uploadObj->callBackKey,
]);
}
if(!$uploadObj->getToken()){
return json([
"uptoken" => $uploadObj->ossToken,
"sign" => $uploadObj->ossSign,
"id" => $uploadObj->ossAccessId,
"key" => $uploadObj->ossFileName,
"callback" => $uploadObj->ossCallBack,
]);
}
return json(["uptoken" => $uploadObj->getToken()]);
}
public function chunk(){
$file = file_get_contents('php://input');
$uploadObj = new UploadHandler($this->userObj->groupData['policy_name'],$this->userObj->uid);
$uploadObj->setChunk(input('param.chunk'),input('param.chunks'),$file);
}
public function mkFile(){
$ctx = file_get_contents('php://input');
$originName = UploadHandler::b64Decode(input('param.fname'));
$filePath = UploadHandler::b64Decode(input('param.path'));
$uploadObj = new UploadHandler($this->userObj->groupData['policy_name'],$this->userObj->uid);
$uploadObj->generateFile($ctx,$originName,$filePath);
}
}
-45
View File
@@ -1,45 +0,0 @@
<?php
namespace app\index\controller;
use think\Controller;
use think\Db;
use \app\index\model\Option;
use \app\index\model\User;
use \app\index\model\Directory;
use \app\index\model\Objects;
use \app\index\model\DavAuth;
use \app\index\model\BasicCallBack;
use Sabre\DAV;
use Sabre\DAV\Auth;
class WebDav extends Controller{
public $userObj;
public $uid;
public function index(){
}
public function Api(){
$this->uid = input("param.uid");
$publicDir = new Directory($this->uid."/");
$server = new DAV\Server($publicDir);
$server->setBaseUri('/WebDav/Api/uid/'.$this->uid);
$lockBackend = new DAV\Locks\Backend\File(ROOT_PATH.'public/locks');
$lockPlugin = new DAV\Locks\Plugin($lockBackend);
$server->addPlugin($lockPlugin);
$check = new DavAuth($this->uid);
$callBack = new BasicCallBack($check);
$authPlugin = new Auth\Plugin($callBack);
$server->addPlugin($authPlugin);
$server->addPlugin(new DAV\Browser\Plugin());
$server->addPlugin(new \Sabre\DAV\Browser\GuessContentType());
ob_end_clean();
$server->exec();
}
}
-668
View File
@@ -1,668 +0,0 @@
<?php
namespace app\index\model;
use think\Model;
use think\Db;
use \app\index\model\Mail;
use \app\index\model\FileManage;
class AdminHandler extends Model{
public $siteOptions;
public $pageData;
public $listData;
public $pageNow;
public $pageTotal;
public $dataTotal;
public $dbVerInfo;
public function __construct($options){
$this->siteOptions = $options;
}
public function checkDbVersion(){
$versionInfo = json_decode(@file_get_contents(ROOT_PATH. "application/version.json"),true);
$dbVerNow = Option::getValue("database_version");
if(!isset($versionInfo["db_version"]) || $dbVerNow < (int)$versionInfo["db_version"]){
$this->dbVerInfo = array('now' => $dbVerNow, 'require' => $versionInfo["db_version"]);
return true;
}
return false;
}
public function 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 = !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 = !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 = !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 =!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"=>"设置已保存"];
}
}
?>
-146
View File
@@ -1,146 +0,0 @@
<?php
namespace app\index\model;
use think\Model;
use think\Db;
use \app\index\model\Option;
use \app\index\model\FileManage;
class Avatar extends Model{
public $avatarObj;
public $errorMsg;
public $fileName;
public $avatarKey;
public $userData;
public $avatarType;
public function __construct($new=false,$obj){
$this->avatarObj = $obj;
if(!$new){
$userData = Db::name("users")->where('id',$obj)->find();
$this->userData = $userData;
if($userData["avatar"] == "default"){
$this->avatarType = "default";
}else{
$avatarPrarm = explode(".",$userData["avatar"]);
$this->avatarType = $avatarPrarm[0];
$this->fileName = ltrim(ltrim($userData["avatar"],"g."),"f.");
}
}
}
public function SaveAvatar(){
$info = $this->avatarObj->validate(['size'=>2097152,'ext'=>'jpg,png,gif.bmp'])->rule('uniqid')->move(ROOT_PATH . 'public' . DS . 'avatars');
if($info){
$_path = ROOT_PATH.'public/avatars/'.$info->getSaveName();
$_img = new Image($_path);
$_img->thumb(200, 200);
$_img->output();
$_img = new Image($_path);
$_img->thumb(130, 130);
$_img->output("_130");
$_img = new Image($_path);
$_img->thumb(50, 50);
$_img->output("_50");
$this->fileName = $info->getSaveName();
return true;
}else{
$this->errorMsg=["result"=>"error","msg"=>$this->avatarObj->getError()];
return false;
}
}
public function bindUser($uid){
$this->avatarKey = "f.".$this->fileName;
Db::name("users")->where('id',$uid)->update(["avatar" => $this->avatarKey]);
}
public function Out($size){
switch ($this->avatarType) {
case 'f':
$this->outPutFile($size);
exit();
break;
case 'default':
$this->defaultAvatar($size);
exit();
break;
case 'g':
return $this->outGravatar($size);
break;
default:
# code...
break;
}
}
public function outPutFile($size){
switch ($size) {
case 's':
$siezSuffix = "_50";
break;
case 'm':
$siezSuffix = "_130";
break;
default:
$siezSuffix = "";
break;
}
$filePath = ROOT_PATH . 'public/avatars/' . $this->fileName.$siezSuffix;
if(file_exists($filePath)){
ob_end_clean();
header('Content-Type: '.FileManage::getMimetype($filePath));
$fileObj = fopen($filePath,"r");
while(!feof($fileObj)){
echo fread($fileObj,2097152);
}
}else{
$this->defaultAvatar($siezSuffix);
}
}
public function outGravatar($size){
switch ($size) {
case 's':
$siezSuffix = "50";
break;
case 'm':
$siezSuffix = "130";
break;
default:
$siezSuffix = "200";
break;
}
ob_end_clean();
$gravatarServer = Option::getValue("gravatar_server");
return $gravatarServer.$this->fileName."?d=mm&s=".$siezSuffix;
}
public function defaultAvatar($size){
switch ($size) {
case 's':
$siezSuffix = "_50";
break;
case 'm':
$siezSuffix = "_130";
break;
default:
$siezSuffix = "";
break;
}
ob_end_clean();
$filePath = ROOT_PATH . 'static/img/default.png' .$siezSuffix;
header('Content-Type: '.FileManage::getMimetype($filePath));
$fileObj = fopen($filePath,"r");
while(!feof($fileObj)){
echo fread($fileObj,2097152);
}
}
public function setGravatar(){
$this->avatarKey="g.".md5($this->userData["user_email"]);
Db::name("users")->where('id',$this->userData["id"])->update(["avatar" => $this->avatarKey]);
}
}
-72
View File
@@ -1,72 +0,0 @@
<?php
namespace app\index\model;
use think\Model;
use think\Db;
use \app\index\model\Option;
class B2 extends Model{
public $policy;
private $ak;
public function __construct($policy){
$this->policy = $policy;
$akInfo = explode(":",$this->policy["ak"]);
$this->ak = $akInfo[0];
if(time()-$akInfo[1]>=86000){
$this->updateAuth();
}
}
private function updateAuth(){
$credentials = base64_encode($this->ak . ":" . $this->policy["sk"]);
$url = "https://api.backblazeb2.com/b2api/v1/b2_authorize_account";
$session = curl_init($url);
$headers = array();
$headers[] = "Accept: application/json";
$headers[] = "Authorization: Basic " . $credentials;
curl_setopt($session, CURLOPT_HTTPHEADER, $headers);
curl_setopt($session, CURLOPT_HTTPGET, true);
curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
curl_setopt($session, CURLOPT_SSL_VERIFYPEER, false); //不验证证书
curl_setopt($session, CURLOPT_SSL_VERIFYHOST, false); //不验证证书
$server_output = curl_exec($session);
curl_close ($session);
$authInfo = json_decode($server_output,true);
Db::name("policy")->where("id",$this->policy["id"])
->update([
"ak" => $this->ak . ":" . time(),
"op_name" => $authInfo["apiUrl"],
"url" => $authInfo["downloadUrl"],
"op_pwd" => $authInfo["authorizationToken"],
]);
$this->policy = Db::name("policy")->where("id",$this->policy["id"])->find();
$this->updateUploadAuth();
}
private function updateUploadAuth(){
$session = curl_init($this->policy["op_name"] . "/b2api/v1/b2_get_upload_url");
$data = array("bucketId" => $this->policy["bucketname"]);
$post_fields = json_encode($data);
curl_setopt($session, CURLOPT_POSTFIELDS, $post_fields);
$headers = array();
$headers[] = "Authorization: " . $this->policy["op_pwd"];
curl_setopt($session, CURLOPT_HTTPHEADER, $headers);
curl_setopt($session, CURLOPT_SSL_VERIFYPEER, false); //不验证证书
curl_setopt($session, CURLOPT_SSL_VERIFYHOST, false); //不验证证书
curl_setopt($session, CURLOPT_POST, true);
curl_setopt($session, CURLOPT_RETURNTRANSFER, true);
$server_output = curl_exec($session);
curl_close ($session);
$authInfo = json_decode($server_output,true);
Db::name("policy")->where("id",$this->policy["id"])
->update([
"server" => $authInfo["uploadUrl"] . "|" . $authInfo["authorizationToken"],
]);
$this->policy = Db::name("policy")->where("id",$this->policy["id"])->find();
die("");
}
}
?>
-39
View File
@@ -1,39 +0,0 @@
<?php
namespace app\index\model;
use think\Model;
use Sabre\DAV;
use Sabre\DAV\Auth\Backend;
class BasicCallBack extends \Sabre\DAV\Auth\Backend\AbstractDigest {
/**
* Callback
*
* @var callable
*/
protected $callBack;
/**
* Creates the backend.
*
* A callback must be provided to handle checking the username and
* password.
*
* @param callable $callBack
* @return void
*/
function __construct(callable $callBack) {
$this->callBack = $callBack;
$this->realm = 'CloudreveWebDav';
}
public function getDigestHash($realm, $username){
$cb = $this->callBack;
return $cb($realm,$username);
}
}
-233
View File
@@ -1,233 +0,0 @@
<?php
namespace app\index\model;
require_once 'extend/Qiniu/functions.php';
use think\Model;
use think\Db;
use Qiniu\Auth;
use \app\index\model\Option;
use \app\index\model\FileManage;
use \app\index\model\UploadHandler;
class CallbackHandler extends Model{
public $CallbackData;
public $policyData;
public $userData;
public function __construct($data){
$this->CallbackData = $data;
}
public function remoteHandler($header){
$jsonData = json_decode(base64_decode($this->CallbackData),true);
$CallbackSqlData = Db::name('callback')->where('callback_key',$jsonData['callbackkey'])->find();
$this->policyData = Db::name('policy')->where('id',$CallbackSqlData['pid'])->find();
if(!$this->IsRemoteCallback($header)){
$this->setError("Undelegated Request");
}
if($this->policyData == null){
$this->setError("CallbackKey Not Exist.");
}
if(!FileManage::sotrageCheck($CallbackSqlData["uid"],$jsonData["fsize"])){
$this->setError("空间容量不足",true);
}
$picInfo = $jsonData["picinfo"];
$addAction = FileManage::addFile($jsonData,$this->policyData,$CallbackSqlData["uid"],$picInfo);
if(!$addAction[0]){
$this->setError($addAction[1],true);
}
FileManage::storageCheckOut($CallbackSqlData["uid"],$jsonData["fsize"]);
$this->setSuccess($jsonData['fname']);
}
public function qiniuHandler($header){
$jsonData = json_decode($this->CallbackData,true);
$CallbackSqlData = Db::name('callback')->where('callback_key',$jsonData['callbackkey'])->find();
$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;
}
}
private function IsRemoteCallback($header){
$signKey = hash_hmac("sha256",$this->CallbackData,$this->policyData["sk"]);
return ($signKey == $header);
}
public function IsOssCallback($auth,$pubKey){
if (empty($auth) || empty($pubKey)){
header("http/1.1 403 Forbidden");
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;
}
}
}
?>
-73
View File
@@ -1,73 +0,0 @@
<?php
namespace app\index\model;
use think\Model;
use think\Db;
use \think\Session;
use \app\index\model\FileManage;
use \app\index\model\Option;
use \app\index\model\Mail;
class CronHandler extends Model{
public $cornTasks;
public $timeNow;
public $notifiedUid = [];
public function __construct(){
$this->cornTasks = Db::name('corn')->where('enable',1)->order('rank desc')->select();
$this->timeNow = time();
}
public function checkInterval($interval,$last){
return ($last+$interval)<= $this->timeNow ? true : false;
}
public function setComplete($name){
Db::name('corn')->where('name', $name)->update(['last_excute' => $this->timeNow]);
}
public function Doit(){
foreach ($this->cornTasks as $key => $value) {
switch ($value["name"]) {
case 'delete_unseful_chunks':
if($this->checkInterval($value["interval_s"],$value["last_excute"])){
$this->deleteUnsefulChunks($value["interval_s"]);
}
break;
case 'delete_callback_data':
if($this->checkInterval($value["interval_s"],$value["last_excute"])){
$this->deleteCallbackData($value["interval_s"]);
}
break;
default:
# code...
break;
}
}
}
private function deleteUnsefulChunks($interval){
echo("deleteUnsefulChunks...");
$chunkInfo = Db::name('chunks')->whereTime('time', '<', date('Y-m-d', time()-86400))->select();
$deleteList=[];
foreach ($chunkInfo as $key => $value) {
$fileSize = @filesize(ROOT_PATH . 'public/uploads/chunks/'.$value["obj_name"].".chunk");
@unlink(ROOT_PATH . 'public/uploads/chunks/'.$value["obj_name"].".chunk");
FileManage::storageGiveBack($value["user"],$fileSize?$fileSize:0);
$deleteList["$key"] = $value["id"];
}
Db::name('chunks')->where(['id' => ["in",$deleteList],])->delete();
$this->setComplete("delete_unseful_chunks");
echo("Complete<br>");
}
private function deleteCallbackData($interval){
echo("deleteCallbackData...");
Db::name("callback")->delete(true);
echo("Complete<br>");
$this->setComplete("delete_callback_data");
}
}
?>
-30
View File
@@ -1,30 +0,0 @@
<?php
namespace app\index\model;
use think\Model;
use think\Db;
use app\index\model\User;
class DavAuth extends Model{
public $uid;
function __construct($id) {
$this->uid = $id;
}
public function __invoke($realm,$um){
$userData = Db::name("users")->where("id",$this->uid)->find();
if(empty($userData) || $userData["user_email"] != $um){
return null;
}
$userGroup = Db::name("groups")->where("id",$userData["user_group"])->find();
if(!$userGroup["webdav"]){
return null;
}
return $userData["webdav_key"];
}
}
?>
-186
View File
@@ -1,186 +0,0 @@
<?php
namespace app\index\model;
use think\Model;
use think\Db;
use Sabre\DAV;
use \app\index\model\FileManage;
use \app\index\model\User;
use \app\index\model\UploadHandler;
class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota{
private $myPath;
public $uid;
public $userObj;
function __construct($path) {
$ex = explode("/",$path);
$this->uid = $ex[0];
if(empty($this->uid)){
return false;
}
$t = strpos($path,$this->uid);
if($t == 0){
$this->myPath = substr($path,$t+strlen($this->uid));
}else{
$this->myPath = $path;
}
$this->myPath = empty($this->myPath) ? "/" : $this->myPath;
}
function createFile($name, $data = NULL){
$userData = Db::name("users")->where("id",$this->uid)->find();
$groupData = Db::name("groups")->where("id",$userData["user_group"])->find();
$policyData = Db::name("policy")->where("id",$groupData["policy_name"])->find();
$uploadHandle = new UploadHandler($groupData["policy_name"],$this->uid);
$allowedExt = UploadHandler::getAllowedExt(json_decode($policyData["filetype"],true));
if(!empty($allowedExt)){
$ex = explode(".",$name);
$fileSuffix = end($ex);
if(!in_array($fileSuffix, explode(",",$allowedExt))){
throw new DAV\Exception\InvalidResourceType('File type not allowed');
}
}
if($policyData["policy_type"] !="local"){
throw new DAV\Exception\Forbidden('Poliyc not supported yet');
}
$fileSize = fstat($data)["size"];
if(empty($fileSize)){
$fileSize = 0;
}
if($fileSize>$policyData["max_size"]){
throw new DAV\Exception\InsufficientStorage('File is to large');
}
if(!FileManage::sotrageCheck($this->uid,$fileSize)){
throw new DAV\Exception\InsufficientStorage('Quota is not enough');
}
if($policyData['autoname']){
$fileName = $uploadHandle->getObjName($policyData['namerule'],"local",$name);
}else{
$fileName = $name;
}
$generatePath = $uploadHandle->getDirName($policyData['dirrule']);
$savePath = ROOT_PATH . 'public/uploads/'.$generatePath;
if(!file_exists($savePath)){
mkdir($savePath,0777,true);
}
file_put_contents($savePath."/".$fileName, $data);
$jsonData = array(
"path" => str_replace("/",",",ltrim($this->myPath,"/")),
"fname" => $name,
"objname" => $generatePath."/".$fileName,
"fsize" => $fileSize,
);
@list($width, $height, $type, $attr) = getimagesize(rtrim($savePath, DS).DS.$fileName);
$picInfo = empty($width)?" ":$width.",".$height;
$addAction = FileManage::addFile($jsonData,$policyData,$this->uid,$picInfo);
if(!$addAction[0]){
unlink($savePath."/".$fileName);
throw new DAV\Exception\Conflict($addAction[1]);
}
FileManage::storageCheckOut($this->uid,$jsonData["fsize"]);
//echo json_encode(array("key" => $info["name"]));
}
function getQuotaInfo() {
$this->userObj = new User($this->uid,"",true);
$quotaInfo = json_decode($this->userObj->getMemory(true),true);
return [
$quotaInfo["used"],
$quotaInfo["total"]
];
}
function setName($name){
$reqPath = $this->myPath;
$ex = explode("/",$reqPath);
$newPath = rtrim(dirname($reqPath) == "\\" ?"/":dirname($reqPath),"/")."/".$name;
$renameAction = json_decode(FileManage::RenameHandler($reqPath,$newPath,$this->uid,true),true);
if(!$renameAction["result"]["success"]){
throw new DAV\Exception\InvalidResourceType($renameAction["result"]["error"]);
}
}
function getChildren() {
$children = array();
$fileList = Db::name('files')->where('upload_user',$this->uid)->where('dir',$this->myPath)->select();
$dirList = Db::name('folders')->where('owner',$this->uid)->where('position',$this->myPath)->select();
foreach($fileList as $node) {
// Ignoring files staring with .
$children[] = $this->getChildFile($node,false);
}
foreach($dirList as $node) {
// Ignoring files staring with .
$children[] = $this->getChildDir($node,true);
}
return $children;
}
function getChildFile($name){
$path = $this->uid.rtrim($this->myPath,"/") . '/' . $name["orign_name"];
return new Objects($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 Objects($path);
}
}
function childExists($name) {
$fileObj = new Objects($this->uid.rtrim($this->myPath,"/") . '/' . $name);
if($this->findDir(rtrim($this->myPath,"/") . '/' . $name) || $fileObj->isExist){
return true;
}
return false;
}
public function findDir($path){
if($path == "/"){
return true;
}
$explode = explode("/",$path);
$dirName = end($explode);
$rootPath = rtrim($path,"/".$dirName);
$rootPath = empty($rootPath) ? "/" : $rootPath;
$dirData = Db::name('folders')->where('owner',$this->uid)->where('position',dirname($path) == "\\" ?"/":dirname($path))->where("folder_name",basename($path))->find();
if(empty($dirData)){
return false;
}
return true;
}
function getName() {
$explode = explode("/", $this->myPath);
return end($explode);
}
function createDirectory($name) {
$createAction = FileManage::createFolder($name,$this->myPath,$this->uid);
if(!$createAction["result"]["success"]){
die($this->myPath);
throw new DAV\Exception\InvalidResourceType($createAction["result"]["error"]);
}
}
}
?>
File diff suppressed because it is too large Load Diff
-89
View File
@@ -1,89 +0,0 @@
<?php
namespace app\index\model;
use think\Model;
class Image extends Model{
private $file; //图片地址
private $width; //图片长度
private $height; //图片长度
private $itype; //图片类型
private $img; //原图的资源句柄
private $new; //新图的资源句柄
//构造方法,初始化
public function __construct($_file) {
$this->file = $_file;
list($this->width, $this->height, $this->itype) = getimagesize($this->file);
$this->img = $this->getFromImg($this->file, $this->itype);
}
//缩略图(固定长高容器,图像等比例,扩容填充,裁剪)[固定了大小,不失真,不变形]
public function thumb($new_width = 0,$new_height = 0) {
if (empty($new_width) && empty($new_height)) {
$new_width = $this->width;
$new_height = $this->height;
}
if (!is_numeric($new_width) || !is_numeric($new_height)) {
$new_width = $this->width;
$new_height = $this->height;
}
//创建一个容器
$_n_w = $new_width;
$_n_h = $new_height;
//创建裁剪点
$_cut_width = 0;
$_cut_height = 0;
if ($this->width < $this->height) {
$new_width = ($new_height / $this->height) * $this->width;
} else {
$new_height = ($new_width / $this->width) * $this->height;
}
if ($new_width < $_n_w) { //如果新高度小于新容器高度
$r = $_n_w / $new_width; //按长度求出等比例因子
$new_width *= $r; //扩展填充后的长度
$new_height *= $r; //扩展填充后的高度
$_cut_height = ($new_height - $_n_h) / 2; //求出裁剪点的高度
}
if ($new_height < $_n_h) { //如果新高度小于容器高度
$r = $_n_h / $new_height; //按高度求出等比例因子
$new_width *= $r; //扩展填充后的长度
$new_height *= $r; //扩展填充后的高度
$_cut_width = ($new_width - $_n_w) / 2; //求出裁剪点的长度
}
$this->new = imagecreatetruecolor($_n_w,$_n_h);
imagecopyresampled($this->new,$this->img,0,0,$_cut_width,$_cut_height,$new_width,$new_height,$this->width,$this->height);
}
//加载图片,各种类型,返回图片的资源句柄
public function getFromImg($_file, $_type) {
switch ($_type) {
case 1 :
$img = imagecreatefromgif($_file);
break;
case 2 :
$img = imagecreatefromjpeg($_file);
break;
case 3 :
$img = imagecreatefrompng($_file);
break;
default:
$img = '';
}
return $img;
}
//图像输出
public function output($name = "") {
imagepng($this->new,$this->file.$name);//第二个参数为新生成的图片名
imagedestroy($this->img);
imagedestroy($this->new);
}
}
?>
-60
View File
@@ -1,60 +0,0 @@
<?php
namespace app\index\model;
use think\Model;
use think\Db;
use \app\index\model\Option;
use \PHPMailer\PHPMailer\PHPMailer;
use \PHPMailer\PHPMailer\Exception;
class Mail extends Model{
public $fromName;
public $fromAdress;
public $smtpHost;
public $smtpPort;
public $replyTo;
public $smtpUser;
public $smtpPass;
public $encriptionType;
public $errorMsg;
public function __construct(){
$mailOptions = Option::getValues(["mail"]);
$this->fromName = $mailOptions["fromName"];
$this->fromAdress = $mailOptions["fromAdress"];
$this->smtpHost = $mailOptions["smtpHost"];
$this->smtpPort = $mailOptions["smtpPort"];
$this->replyTo = $mailOptions["replyTo"];
$this->smtpUser = $mailOptions["smtpUser"];
$this->smtpPass = $mailOptions["smtpPass"];
$this->encriptionType = $mailOptions["encriptionType"];
}
public function Send($to,$name,$title,$content){
$mail = new PHPMailer();
$mail->isSMTP();
$mail->SMTPAuth=true;
$mail->Host = $this->smtpHost;
if(!empty($this->encriptionType) && $this->encriptionType != "no"){
$mail->SMTPSecure = $this->encriptionType;
}
$mail->Port = $this->smtpPort;
$mail->CharSet = 'UTF-8';
$mail->FromName = $this->fromName;
$mail->Username =$this->smtpUser;
$mail->Password = $this->smtpPass;
$mail->From = $this->fromAdress;
$mail->isHTML(true);
$mail->addAddress($to,$name);
$mail->Subject = $title;
$mail->Body = $content;
$status = $mail->send();
if(!$status){
$this->errorMsg = $mail->ErrorInfo;
return false;
}
return true;
}
}
?>
-95
View File
@@ -1,95 +0,0 @@
<?php
namespace app\index\model;
use think\Model;
use think\Db;
use Sabre\DAV;
use \app\index\model\FileManage;
class Objects extends DAV\File{
private $myPath;
public $id;
public $fileData;
public $uid;
public $fileName;
public $dir;
public $actualPath;
public $isExist;
function __construct($path) {
$ex = explode("/",$path);
$this->uid = $ex[0];
$t = strpos($path,$this->uid);
if($t == 0){
$this->myPath = substr($path,$t+strlen($this->uid));
}else{
$this->myPath = $path;
}
$this->fileName = end($ex);
$this->dir = dirname($this->myPath) == "\\" ? "/" :dirname($this->myPath);
$this->fileData = Db::name('files')->where('upload_user',$this->uid)->where('dir',$this->dir)->where('orign_name',$this->fileName)->find();
if(empty($this->fileData)){
$this->isExist = false;
}else{
$this->isExist = true;
}
$this->actualPath = ROOT_PATH . 'public/uploads/'.$this->fileData["pre_name"];
}
function getName() {
return $this->fileName;
}
function get() {
return fopen($this->actualPath, 'r');
}
function getSize() {
return $this->fileData["size"];
}
function setName($name){
$reqPath = $this->myPath;
$ex = explode("/",$reqPath);
$newPath = rtrim($reqPath,end($ex)).$name;
$renameAction = json_decode(FileManage::RenameHandler($reqPath,$newPath,$this->uid,true),true);
if(!$renameAction["result"]["success"]){
throw new DAV\Exception\Forbidden($renameAction["result"]["error"]);
}
}
function getContentType() {
return null;
}
function put($data){
$fileSize = (int)$_SERVER['CONTENT_LENGTH'];
if(!FileManage::sotrageCheck($this->uid,$fileSize)){
throw new DAV\Exception\InsufficientStorage("Quota is not enough");
}
$filePath = ROOT_PATH . 'public/uploads/' . $this->fileData["pre_name"];
file_put_contents($filePath, "");
file_put_contents($filePath, $data);
FileManage::storageGiveBack($this->uid,$this->fileData["size"]);
FileManage::storageCheckOut($this->uid,$fileSize);
@list($width, $height, $type, $attr) = getimagesize($filePath);
$picInfo = empty($width)?" ":$width.",".$height;
Db::name('files')->where('id', $this->fileData["id"])->update(['size' => $fileSize,'pic_info' => $picInfo]);
}
function delete(){
FileManage::DeleteHandler([0=>$this->myPath],$this->uid);
}
function getETag() {
return '"' . sha1(
fileinode($this->actualPath) .
filesize($this->actualPath) .
filemtime($this->actualPath)
) . '"';
}
}
?>
-16
View File
@@ -1,16 +0,0 @@
<?php
namespace app\index\model;
use think\Model;
use think\Db;
class Option extends Model{
static function getValues($groups = ['basic']){
$t = Db::name('options')->where('option_type','in',$groups)->column('option_value','option_name');
return $t;
}
static function getValue($optionName){
return Db::name('options')->where('option_name',$optionName)->value('option_value');
}
}
?>
-73
View File
@@ -1,73 +0,0 @@
<?php
namespace app\index\model;
use think\Model;
use think\Db;
use \app\index\model\Option;
class Remote extends Model{
public $sk;
private $policy;
private $serverOutput;
private $httpCode;
public function __construct($policy){
$this->policy = $policy;
}
public function remove($fileList){
$signKey = $this->sign($fileList,"DELETE");
$this->send("manager.php",$signKey,"DELETE",base64_encode(json_encode($fileList)));
}
public function preview($fname){
return $this->signUrl($this->policy["url"]."object.php?action=preview&name=".urlencode($fname)."&expires=".(time()+(int)Option::getValue("timeout")));
}
public function clean(){
return $this->signUrl($this->policy["url"]."object.php?action=clean&expires=".(time()+(int)Option::getValue("timeout")));
}
public function download($fname,$attnanme){
return $this->signUrl($this->policy["url"]."object.php?action=download&name=".urlencode($fname)."&attaname=".urlencode($attnanme)."&expires=".(time()+(int)Option::getValue("timeout")));
}
public function thumb($fname,$picInfo){
return $this->signUrl($this->policy["url"]."object.php?action=thumb&name=".urlencode($fname)."&expires=".(time()+(int)Option::getValue("timeout"))."&w=".$picInfo[0]."&h=".$picInfo[1]);
}
public function signUrl($url){
$signKey = hash_hmac("sha256",$url,"GET".$this->policy["sk"]);
return $url."&auth=".$signKey;
}
public function updateContent($fname,$content){
$object = ["fname"=>$fname,"content"=>$content];
$signKey = $this->sign($object,"UPDATE");
$this->send("manager.php",$signKey,"UPDATE",base64_encode(json_encode($object)));
}
public function send($target,$auth,$action,$object){
$session = curl_init($this->policy["server"].$target);
$postData = array(
"action" => $action,
"auth" => $auth,
"object" => $object,
);
curl_setopt($session, CURLOPT_POST, 1);
curl_setopt($session, CURLOPT_POSTFIELDS, $postData);
curl_setopt($session, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($session, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($session, CURLOPT_SSL_VERIFYHOST, false);
$this->serverOutput = curl_exec($session);
$this->httpCode = curl_getinfo($session,CURLINFO_HTTP_CODE);
echo $this->serverOutput;
}
public function sign($content,$method = null){
return hash_hmac("sha256",base64_encode(json_encode($content)),$method.$this->policy["sk"]);
}
}
?>
-308
View File
@@ -1,308 +0,0 @@
<?php
namespace app\index\model;
use think\Model;
use think\Db;
use \think\Session;
use \app\index\model\FileManage;
use \app\index\model\Option;
use \app\index\model\User;
class ShareHandler extends Model{
public $shareData;
public $querryStatus = true;
public $shareOwner;
public $fileData;
public $dirData;
public $lockStatus = false;
public function __construct($key,$notExist=true){
$this->shareData = Db::name('shares')->where('share_key',$key)->find();
if(empty($this->shareData)){
$this->querryStatus = false;
}else{
if($notExist){
if($this->shareData["source_type"] == "file"){
$this->fileShareHandler();
}else{
$this->dirShareHandler();
}
}
}
if($this->shareData["type"] == "private"){
$this->lockStatus = Session::has("share".$this->shareData["id"])?false:true;
}
}
public function deleteShare($uid){
if($this->shareData["owner"] != $uid){
return array(
"error" => 1,
"msg" => "无权操作"
);
}
Db::name('shares')->where('share_key',$this->shareData["share_key"])->delete();
return array(
"error" => 0,
"msg" => "分享取消成功"
);
}
public function changePromission($uid,$ignore=false){
if($this->shareData["owner"] != $uid && $ignore == false){
return array(
"error" => 1,
"msg" => "无权操作"
);
}
Db::name('shares')->where('share_key',$this->shareData["share_key"])->update([
'type' => $this->shareData["type"] == "public"?"private":"public",
'share_pwd' => self::getRandomKey(6)
]);
return array(
"error" =>0,
"msg" => "更改成功"
);
}
public function checkPwd($pwd){
if($pwd == $this->shareData["share_pwd"]){
Session::set("share".$this->shareData["id"],"1");
return array(
"error" =>0,
);
}else{
return array(
"error" =>1,
"msg" => "密码错误"
);
}
}
public function checkSession($user){
if($this->lockStatus){
return [false,"会话过期,请刷新页面"];
}
if(Option::getValue("allowdVisitorDownload") == "false" && !$user->loginStatus){
return [false,"未登录用户禁止下载,请先登录"];
}
if(!$this->querryStatus){
return [false,"分享不存在,请检查链接是否正确"];
}
return[true,null];
}
public function Download($user){
$checkStatus = $this->checkSession($user);
if(!$checkStatus[0]){
return [$checkStatus[0],$checkStatus[1]];
}
$reqPath = Db::name('files')->where('id',$this->shareData["source_name"])->find();
if($reqPath["dir"] == "/"){
$reqPath["dir"] = $reqPath["dir"].$reqPath["orign_name"];
}else{
$reqPath["dir"] = $reqPath["dir"]."/".$reqPath["orign_name"];
}
$fileObj = new FileManage($reqPath["dir"],$this->shareData["owner"]);
$FileHandler = $fileObj->Download();
return $FileHandler;
}
public function DownloadFolder($user,$path){
$checkStatus = $this->checkSession($user);
if(!$checkStatus[0]){
return [$checkStatus[0],$checkStatus[1]];
}
$reqPath = Db::name('folders')->where('position_absolute',$this->shareData["source_name"])->find();
$path = $path == "/"?"":$path;
$fileObj = new FileManage($reqPath["position_absolute"].$path,$this->shareData["owner"]);
$this->numIncrease("download_num");
$FileHandler = $fileObj->Download();
return $FileHandler;
}
public function ListFile($path){
if($this->lockStatus){
die('{ "result": { "success": false, "error": "会话过期,请重新登陆" } }');
}
if(!$this->querryStatus){
return [false,"分享不存在,请检查链接是否正确"];
}
$reqPath = Db::name('folders')->where('position_absolute',$this->shareData["source_name"])->find();
$path = $path == "/"?"":$path;
return FileManage::ListFile($this->shareData["source_name"].$path,$this->shareData["owner"]);
}
public function Preview($user){
$checkStatus = $this->checkSession($user);
if(!$checkStatus[0]){
return [$checkStatus[0],$checkStatus[1]];
}
$reqPath = Db::name('files')->where('id',$this->shareData["source_name"])->find();
if($reqPath["dir"] == "/"){
$reqPath["dir"] = $reqPath["dir"].$reqPath["orign_name"];
}else{
$reqPath["dir"] = $reqPath["dir"]."/".$reqPath["orign_name"];
}
$fileObj = new FileManage($reqPath["dir"],$this->shareData["owner"]);
return $fileObj->PreviewHandler();
}
public function PreviewFolder($user,$path,$folder=false){
$checkStatus = $this->checkSession($user);
if(!$checkStatus[0]){
return [$checkStatus[0],$checkStatus[1]];
}
$reqPath = Db::name('folders')->where('position_absolute',$this->shareData["source_name"])->find();
if($folder){
$fileObj = new FileManage($path,$this->shareData["owner"]);
}else{
$fileObj = new FileManage($reqPath["position_absolute"].$path,$this->shareData["owner"]);
}
return $fileObj->PreviewHandler();
}
public function listPic($id,$path){
if($this->lockStatus){
die('{ "result": { "success": false, "error": "会话过期,请重新登陆" } }');
}
if(!$this->querryStatus){
return [false,"分享不存在,请检查链接是否正确"];
}
$reqPath = Db::name('folders')->where('position_absolute',$this->shareData["source_name"])->find();
$path = $path == "/"?"":$path;
return FileManage::listPic($this->shareData["source_name"].$path,$this->shareData["owner"],"/Share/Preview/".$this->shareData["share_key"]."?folder=true");
}
public function numIncrease($name){
Db::name('shares')->where('share_key',$this->shareData["share_key"])->setInc($name);
}
public function getDownloadUrl($user){
if(Option::getValue("allowdVisitorDownload") == "false" && !$user->loginStatus){
return array(
"error" => 1,
"msg" => "未登录用户禁止下载,请先登录",
);
}else{
$this->numIncrease("download_num");
return array(
"error" => 0,
"result" => "/Share/Download/".$this->shareData["share_key"],
);
}
}
public function fileShareHandler(){
$this->shareOwner = new User($this->shareData["owner"],null,true);
$this->fileData = Db::name('files')
->where('upload_user',$this->shareData["owner"])
->where('id',(int)$this->shareData["source_name"])
->find();
if(!$this->shareOwner->loginStatus || empty($this->fileData)){
$this->querryStatus = false;
}else{
$this->querryStatus = true;
}
}
public function dirShareHandler(){
$this->shareOwner = new User($this->shareData["owner"],null,true);
$this->dirData = Db::name('folders')
->where('owner',$this->shareData["owner"])
->where('position_absolute',$this->shareData["source_name"])
->find();
if(!$this->shareOwner->loginStatus || empty($this->dirData)){
$this->querryStatus = false;
}else{
$this->querryStatus = true;
}
}
static function createShare($fname,$type,$user,$group){
if(!$group["allow_share"]){
self::setError("您当前的用户组无权分享文件");
}
$path = FileManage::getFileName($fname)[1];
$fnameTmp = FileManage::getFileName($fname)[0];
$fileRecord = Db::name('files')->where('upload_user',$user["id"])->where('orign_name',$fnameTmp)->where('dir',$path)->find();
if(empty($fileRecord)){
self::createDirShare($fname,$type,$user,$group);
}else{
self::createFileShare($fileRecord,$type,$user,$group);
}
}
static function setError($text){
die('{ "result": { "success": false, "error": "'.$text.'" } }');
}
static function setSuccess($text){
die('{ "result": "'.$text.'" }');
}
static function createDirShare($fname,$type,$user,$group){
$dirRecord = Db::name('folders')->where('owner',$user["id"])->where('position_absolute',$fname)->find();
if(empty($dirRecord)){
self::setError("目录不存在");
}
$shareKey = self::getRandomKey(8);
$sharePwd = $type=="public" ? "0" : self::getRandomKey(6);
$SQLData = [
'type' => $type=="public" ? "public" : "private",
'share_time' => date("Y-m-d H:i:s"),
'owner' => $user["id"],
'source_name' => $fname,
'origin_name' => $fname,
'download_num' => 0,
'view_num' => 0,
'source_type' => "dir",
'share_key' => $shareKey,
'share_pwd' => $sharePwd,
];
if(Db::name('shares')->insert($SQLData)){
if($sharePwd == "0"){
self::setSuccess(Option::getValue("siteURL")."s/".$shareKey);
}else{
self::setSuccess("链接:".Option::getValue("siteURL")."s/".$shareKey." 密码:".$sharePwd);
}
}
}
static function createFileShare($file,$type,$user,$group){
$shareKey = self::getRandomKey(8);
$sharePwd = $type=="public" ? "0" : self::getRandomKey(6);
$SQLData = [
'type' => $type=="public" ? "public" : "private",
'share_time' => date("Y-m-d H:i:s"),
'owner' => $user["id"],
'source_name' => $file["id"],
'origin_name' => $file["orign_name"],
'download_num' => 0,
'view_num' => 0,
'source_type' => "file",
'share_key' => $shareKey,
'share_pwd' => $sharePwd,
];
if(Db::name('shares')->insert($SQLData)){
if($sharePwd == "0"){
self::setSuccess(Option::getValue("siteURL")."s/".$shareKey);
}else{
self::setSuccess("链接:".Option::getValue("siteURL")."s/".$shareKey." 密码:".$sharePwd);
}
}
}
static function getRandomKey($length = 16){
$charTable = 'abcdefghijklmnopqrstuvwxyz0123456789';
$result = "";
for ( $i = 0; $i < $length; $i++ ){
$result .= $charTable[ mt_rand(0, strlen($charTable) - 1) ];
}
return $result;
}
}
?>
-91
View File
@@ -1,91 +0,0 @@
<?php
namespace app\index\model;
use think\Model;
use think\Db;
class Thumb extends Model{
private $file; //图片地址
private $width; //图片长度
private $height; //图片长度
private $img_type; //图片类型
private $img; //原图的资源句柄
private $new; //新图的资源句柄
//构造方法,初始化
public function __construct($_file) {
$this->file = $_file;
list($this->width, $this->height, $this->img_type) = getimagesize($this->file);
$this->img = $this->getFromImg($this->file, $this->img_type);
}
//缩略图(固定长高容器,图像等比例,扩容填充,裁剪)[固定了大小,不失真,不变形]
public function thumb($new_width = 0,$new_height = 0) {
if (empty($new_width) && empty($new_height)) {
$new_width = $this->width;
$new_height = $this->height;
}
if (!is_numeric($new_width) || !is_numeric($new_height)) {
$new_width = $this->width;
$new_height = $this->height;
}
//创建一个容器
$_n_w = $new_width;
$_n_h = $new_height;
//创建裁剪点
$_cut_width = 0;
$_cut_height = 0;
if ($this->width < $this->height) {
$new_width = ($new_height / $this->height) * $this->width;
} else {
$new_height = ($new_width / $this->width) * $this->height;
}
if ($new_width < $_n_w) { //如果新高度小于新容器高度
$r = $_n_w / $new_width; //按长度求出等比例因子
$new_width *= $r; //扩展填充后的长度
$new_height *= $r; //扩展填充后的高度
$_cut_height = ($new_height - $_n_h) / 2; //求出裁剪点的高度
}
if ($new_height < $_n_h) { //如果新高度小于容器高度
$r = $_n_h / $new_height; //按高度求出等比例因子
$new_width *= $r; //扩展填充后的长度
$new_height *= $r; //扩展填充后的高度
$_cut_width = ($new_width - $_n_w) / 2; //求出裁剪点的长度
}
$this->new = imagecreatetruecolor($_n_w,$_n_h);
imagecopyresampled($this->new,$this->img,0,0,$_cut_width,$_cut_height,$new_width,$new_height,$this->width,$this->height);
}
//加载图片,各种类型,返回图片的资源句柄
private function getFromImg($_file, $_type) {
switch ($_type) {
case 1 :
$img = imagecreatefromgif($_file);
break;
case 2 :
$img = imagecreatefromjpeg($_file);
break;
case 3 :
$img = imagecreatefrompng($_file);
break;
default:
$img = '';
}
return $img;
}
//图像输出
public function out($name) {
imagepng($this->new,$name);//第二个参数为新生成的图片名
imagedestroy($this->img);
imagedestroy($this->new);
}
}
?>
-54
View File
@@ -1,54 +0,0 @@
<?php
namespace app\index\model;
use think\Model;
use think\Db;
use \think\Session;
use \PHPGangsta_GoogleAuthenticator;
use \Endroid\QrCode\QrCode;
use \app\index\model\Option;
class TwoFactor extends Model{
public $ga;
public $secretKey;
public $checkResult;
public function __construct(){
$this->ga = new PHPGangsta_GoogleAuthenticator();
}
public function qrcodeRender(){
ob_end_clean();
$this->secretKey = $this->ga->createSecret();
session("two_factor_enable",$this->secretKey);
$qrCode = new QrCode(urldecode(str_replace("https://chart.googleapis.com/chart?chs=200x200&chld=M|0&cht=qr&chl=","",$this->ga->getQRCodeGoogleUrl(Option::getValue("siteName"), $this->secretKey))));
$qrCode->setSize(165);
$qrCode->setMargin(0);
header('Content-Type: '.$qrCode->getContentType());
echo $qrCode->writeString();
}
public function confirmCode($key,$code){
$this->secretKey = $key;
if(empty($code)){
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]);
}
}
?>
-484
View File
@@ -1,484 +0,0 @@
<?php
namespace app\index\model;
require_once 'extend/Qiniu/functions.php';
use think\Model;
use think\Db;
use Qiniu\Auth;
use \app\index\model\Option;
use \app\index\model\FileManage;
class UploadHandler extends Model{
public $policyId;
public $policyContent;
public $userId;
public $chunkData;
public $fileSizeTmp;
public $ossToken;
public $ossSign;
public $ossCallback;
public $ossAccessId;
public $ossFileName;
public $ossCallBack;
public $upyunPolicy;
public $s3Policy;
public $s3Sign;
public $dirName;
public $s3Credential;
public $siteUrl;
public $callBackKey;
public function __construct($id,$uid){
$this->policyId = $id;
$this->userId = $uid;
$this->policyContent = Db::name('policy')->where('id',$id)->find();
}
public function setChunk($chunkId,$chunkSum,$file){
$sqlData = [
'user' => $this->userId,
'ctx' => self::getRandomKey(),
'obj_name' => self::getRandomKey(8),
'time' => date("Y-m-d H:i:s"),
'chunk_id' => $chunkId,
'sum' => $chunkSum,
];
$this->chunkData = $sqlData;
Db::name('chunks')->insert($sqlData);
$this->saveChunk($file);
$this->chunkInfo();
}
public function saveChunk($file){
$chunkSize = strlen($file);
if(!FileManage::sotrageCheck($this->userId,$chunkSize)){
$this->setError("空间容量不足",false);
}
FileManage::storageCheckOut($this->userId,$chunkSize);
if($chunkSize >=4195304){
$this->setError("分片错误",false);
}
$chunkObj=fopen (ROOT_PATH . 'public/uploads/chunks/'.$this->chunkData["obj_name"].".chunk","w+");
$chunkObjWrite = fwrite ($chunkObj,$file);
if(!$chunkObj || !$chunkObjWrite){
$this->setError("分片创建错误",false);
}
}
public function chunkInfo(){
$returnJson = array(
"ctx" => $this->chunkData["ctx"],
);
echo json_encode($returnJson);
return 0;
}
public function generateFile($ctx,$fname,$path){
$ctxTmp = explode(",",$ctx);
$chunks = Db::name('chunks')->where([
'ctx' => ["in",$ctxTmp],
])->order('id asc')->select();
$file = $this->combineChunks($chunks);
$this->filterCheck($file,$fname);
$suffixTmp = explode('.', $fname);
$fileSuffix = array_pop($suffixTmp);
if($this->policyContent['autoname']){
$fileName = $this->getObjName($this->policyContent['namerule'],"local",$fname).".".$fileSuffix;
}else{
$fileName = $fname;
}
$generatePath = $this->getDirName($this->policyContent['dirrule']);
$savePath = ROOT_PATH . 'public/uploads/'.$generatePath;
is_dir($savePath)? :mkdir($savePath,0777,true);
if(file_exists($savePath.DS.$fileName)){
$this->setError("文件重名",true,$file,ROOT_PATH . 'public/uploads/chunks/');
}
if(!@rename(ROOT_PATH . 'public/uploads/chunks/'.$file,$savePath.DS.$fileName)){
$this->setError("文件创建失败",true,$file,ROOT_PATH . 'public/uploads/chunks/');
}else{
if($path == "ROOTDIR"){
$path = "";
}
$jsonData = array(
"path" => $path,
"fname" => $fname,
"objname" => $generatePath."/".$fileName,
"fsize" => $this->fileSizeTmp,
);
$addAction = FileManage::addFile($jsonData,$this->policyContent,$this->userId);
if(!$addAction[0]){
$this->setError($addAction[1],true,$fileName,$savePath);
}
echo json_encode(array("key" => $fname));
}
}
public function filterCheck($file,$fname){
$fileSize = filesize(ROOT_PATH . 'public/uploads/chunks/'.$file);
$suffixTmp = explode('.', $fname);
$fileSuffix = array_pop($suffixTmp);
$allowedSuffix = explode(',', self::getAllowedExt(json_decode($this->policyContent["filetype"],true)));
$sufficCheck = !in_array($fileSuffix,$allowedSuffix);
if(empty(self::getAllowedExt(json_decode($this->policyContent["filetype"],true)))){
$sufficCheck = false;
}
if(($fileSize >= (int)$this->policyContent["max_size"]) || $sufficCheck){
FileManage::storageGiveBack($this->userId,$fileSize);
$this->setError("文件效验失败",true,$file,ROOT_PATH . 'public/uploads/chunks/');
}
$this->fileSizeTmp = $fileSize;
}
public function combineChunks($fname){
$fileName = "file_".self::getRandomKey(8);
$fileObj=fopen (ROOT_PATH . 'public/uploads/chunks/'.$fileName,"a+");
$deleteList=[];
foreach ($fname as $key => $value) {
$chunkObj = fopen(ROOT_PATH . 'public/uploads/chunks/'.$value["obj_name"].".chunk", "rb");
if(!$fileObj || !$chunkObj){
$this->setError("文件创建失败",false);
}
$content = fread($chunkObj, 4195304);
fwrite($fileObj, $content, 4195304);
unset($content);
fclose($chunkObj);
unlink(ROOT_PATH . 'public/uploads/chunks/'.$value["obj_name"].".chunk");
array_push($deleteList, $value["id"]);
}
$chunks = Db::name('chunks')->where([
'id' => ["in",$deleteList],
])->delete();
return $fileName;
}
public function fileReceive($file,$info){
$allowedExt = self::getAllowedExt(json_decode($this->policyContent["filetype"],true));
$filter = array('size'=>(int)$this->policyContent["max_size"]);
if(!empty($allowedExt)){
$filter = array_merge($filter,array("ext" => $allowedExt));
}
if(!FileManage::sotrageCheck($this->userId,$file->getInfo('size'))){
$this->setError("空间容量不足",false);
}
if($this->policyContent['autoname']){
$fileName = $this->getObjName($this->policyContent['namerule'],"local",$file->getInfo('name'));
}else{
$fileName = $file->getInfo('name');
}
$generatePath = $this->getDirName($this->policyContent['dirrule']);
$savePath = ROOT_PATH . 'public/uploads/'.$generatePath;
$Uploadinfo = $file
->validate($filter)
->move($savePath,$fileName,false);
if($Uploadinfo){
$jsonData = array(
"path" => $info["path"],
"fname" => $info["name"],
"objname" => $generatePath."/".$Uploadinfo->getSaveName(),
"fsize" => $Uploadinfo->getSize(),
);
@list($width, $height, $type, $attr) = getimagesize(rtrim($savePath, DS).DS.$Uploadinfo->getSaveName());
$picInfo = empty($width)?" ":$width.",".$height;
$addAction = FileManage::addFile($jsonData,$this->policyContent,$this->userId,$picInfo);
if(!$addAction[0]){
$tmpFileName = $Uploadinfo->getSaveName();
unset($Uploadinfo);
$this->setError($addAction[1],true,$tmpFileName,$savePath);
}
FileManage::storageCheckOut($this->userId,$jsonData["fsize"],$Uploadinfo->getInfo('size'));
echo json_encode(array("key" => $info["name"]));
}else{
header("HTTP/1.1 401 Unauthorized");
echo json_encode(array("error" => $file->getError()));
}
}
public function setError($text,$delete = false,$fname="",$path=""){
header("HTTP/1.1 401 Unauthorized");
if($delete){
unlink(rtrim($path, DS).DS.$fname);
}
die(json_encode(["error"=> $text]));
}
static function getAllowedExt($ext){
$returnValue = "";
foreach ($ext as $key => $value) {
$returnValue .= $value["ext"].",";
}
return rtrim($returnValue, ",");
}
public function getToken(){
switch ($this->policyContent['policy_type']) {
case 'qiniu':
return $this->getQiniuToken();
break;
case 'local':
return $this->getLocalToken();
break;
case 'oss':
return $this->getOssToken();
break;
case 'upyun':
return $this->getUpyunToken();
break;
case 's3':
return $this->getS3Token();
break;
case 'remote':
return $this->getRemoteToken();
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;
}
private function getRemoteToken(){
$callbackKey = $this->getRandomKey();
$sqlData = [
'callback_key' => $callbackKey,
'pid' => $this->policyId,
'uid' => $this->userId
];
Db::name('callback')->insert($sqlData);
$policy = array(
'callbackUrl' =>Option::getValue("siteURL").'Callback/Remote',
'callbackKey' => $callbackKey,
'callbackBodyType' => 'application/json',
'fsizeLimit' => (int)$this->policyContent['max_size'],
'uid' => $this->userId,
);
$dirName = $this->getObjName($this->policyContent['dirrule']);
if($this->policyContent["autoname"]){
$policy = array_merge($policy,array("saveKey" => $dirName.(empty($dirName)?"":"/").$this->getObjName($this->policyContent['namerule'])));
}else{
$policy = array_merge($policy,array("saveKey" => $dirName.(empty($dirName)?"":"/")."$(fname)"));
}
if(!empty($this->policyContent['mimetype'])){
$policy = array_merge($policy,array("mimeLimit" => $this->policyContent['mimetype']));
}
$signingKey = hash_hmac("sha256",json_encode($policy),"UPLOAD".$this->policyContent['sk']);
$token = $signingKey. ":" .base64_encode(json_encode($policy));
return $token;
}
static function upyunSign($key, $secret, $method, $uri, $date, $policy=null, $md5=null){
$elems = array();
foreach (array($method, $uri, $date, $policy, $md5) as $v){
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);
}
}
?>
-375
View File
@@ -1,375 +0,0 @@
<?php
namespace app\index\model;
use think\Model;
use think\Db;
use \think\Session;
use \think\Cookie;
use \app\index\model\Option;
use \app\index\model\Mail;
use think\Validate;
class User extends Model{
public $uid;
public $varifyKey;
public $groupId;
public $regDate;
public $loginStatus = false;
public $userNick;
public $userMail;
public $groupData;
public $userSQLData;
/**
* [__construct description]
* @param [type] $userId [description]
* @param [type] $userKey [description]
*/
public function __construct($userId,$userKey,$ignoreLogin = false){
$userData = Db::name('users')->where('id',$userId)->where('user_status',0)->find();
if(empty($userData)){
$this->loginStatus = false;
$this->setUser();
return false;
}
if(!$ignoreLogin){
if(md5($userData['user_email'].$userData['user_pass'].config('salt')) != $userKey){
$this->loginStatus = false;
$this->setUser();
return false;
}
}
$this->groupData = Db::name('groups')->where('id',$userData['user_group'])->find();
$this->loginStatus = true;
$this->uid = $userId;
$this->groupId = $userData['user_group'];
$this->regDate = $userData['user_date'];
$this->userNick = $userData['user_nick'];
$this->userMail = $userData['user_email'];
$this->varifyKey = $userKey;
$this->userSQLData = $userData;
}
public function setUser(){
$this->groupData = Db::name('groups')->where('id',2)->find();
$this->uid = -1;
}
static function resetPwd($key,$pwd){
$key = explode("_",$key);
$resetKey = $key[0]."_".$key[1];
$userId = $key[2];
$keyCheck = self::resetUser($resetKey,$userId);
if(!$keyCheck[0]){
return $keyCheck;
}else{
if ((mb_strlen($pwd,'UTF8')>64) || (mb_strlen($pwd,'UTF8')<4)){
return [false,"密码不符合规范"];
}
self::Reset($userId,$pwd);
return [true,"密码重设成功"];
}
}
static function Reset($uid,$pwd){
Db::name('users')->where('id',$uid)
->update([
'user_pass' => md5(config('salt').$pwd),
]);
}
/**
* [register description]
* @param [type] $userEmail [description]
* @param [type] $userPass [description]
* @return [type] [description]
*/
static function register($userEmail,$userPass,$captchaCode){
if(Option::getValue("reg_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("forget_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($usedMemory);
$returnData["total"] = self::countSize($groupStorage+$packetStorage);
$returnData["rate"] = floor($usedMemory/($groupStorage+$packetStorage)*100);
$returnData["basic"] = self::countSize($groupStorage);
$returnData["pack"] = self::countSize($packetStorage);
if($usedMemory > $groupStorage){
$returnData["r1"] = floor($usedMemory/($groupStorage+$packetStorage)*100);
$returnData["r2"] = 0;
$returnData["r3"] = 100-$returnData["r1"];
}else{
$returnData["r1"] = floor($usedMemory/($groupStorage+$packetStorage)*100);
$returnData["r2"] = floor(($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];
}
}
?>
-72
View File
@@ -1,72 +0,0 @@
{extend name="header_admin" /}
{block name="title"}基础设置- {$options.siteName}{/block}
{block name="content"}
<div class="content-wrapper">
<div class="container-fluid">
<!-- Breadcrumbs-->
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="/Admin">管理面板</a>
</li>
<li class="breadcrumb-item active">其他</li>
<li class="breadcrumb-item active">关于</li>
</ol>
<!-- Area Chart Example-->
<div class="row">
<div class="col-12">
<h2>关于</h2>
<br>
<div class="row">
<div class="col">
<div class="card">
<div class="card-header" >
<i class="fa fa-eye fa-fw" aria-hidden="true"></i>
系统信息
</div>
<div class="card-body">
<ul>
<li>服务器信息:{:$_SERVER ['SERVER_SOFTWARE']}</li>
<li>服务端系统:{:PHP_OS}</li>
<li>最大上传限制:{:get_cfg_var ("upload_max_filesize")?get_cfg_var ("upload_max_filesize"):"不允许上传"}</li>
<li>脚本最大执行时间:{:get_cfg_var("max_execution_time")."s "}</li>
<li>脚本最大内存:{:get_cfg_var ("memory_limit")?get_cfg_var("memory_limit"):"无"}</li>
<li>PHP扩展:curl{eq name=":extension_loaded('curl')" value="true"}√{else/}×{/eq} openssl{eq name=":extension_loaded('openssl')" value="true"}√{else/}×{/eq} GD{eq name=":extension_loaded('gd')" value="true"}√{else/}×{/eq} fileinfo{eq name=":extension_loaded('fileinfo')" value="true"}√{else/}×{/eq}</li>
</ul>
</div>
</div>
</div>
<div class="col">
<div class="card" style="min-height: 269px;">
<div class="card-header">
<i class="fa fa-cloud fa-fw" aria-hidden="true"></i>
关于Cloudreve
</div>
<div class="card-body">
<h5 class="card-title">Cloudreve {$programVersion.type} {$programVersion.version}</h5>
<ul>
<li>主页:<a href="https://cloudreve.org" target="_blank">https://cloudreve.org</a></li>
<li>Github<a href="https://github.com/HFO4/Cloudreve" target="_blank">https://github.com/HFO4/Cloudreve</a></li>
<li>许可证:<a href="https://github.com/HFO4/Cloudreve/LICENSE" target="_blank">GPL V3</a>(社区版)</li>
<li>其他链接:<a href="https://github.com/HFO4/Cloudreve/graphs/contributors" target="_blank">代码贡献者</a> <a href="https://cloudreve.org/joingroup" target="_blank">Telegram群组</a> <a href="https://forum.cloudreve.org" target="_blank">社区</a></li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Example DataTables Card-->
</div>
<!-- /.container-fluid-->
</div>
{/block}
{block name="js"}
<script type="text/javascript">
</script>
{/block}
-164
View File
@@ -1,164 +0,0 @@
{extend name="header_admin" /}
{block name="title"}注册访问- {$options.siteName}{/block}
{block name="content"}
<div class="content-wrapper">
<div class="container-fluid">
<!-- Breadcrumbs-->
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="/Admin">管理面板</a>
</li>
<li class="breadcrumb-item active">用户组</li>
<li class="breadcrumb-item active">添加用户组</li>
</ol>
<!-- Area Chart Example-->
<div class="row">
<div class="col-12">
<h2>添加用户组</h2>
<br>
<form id="addGroup">
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="colFormLabelSm" class="col-form-label col-form-label-sm">用户组名</label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="group_name" required></div>
<div class="col-md-4 option-des"> 用户组的名称</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="colFormLabelSm" class="col-form-label col-form-label-sm">上传策略</label>
</div>
<div class="col-md-4">
<select name="policy_name" required class="form-control">
{volist name="policy" id="p"}
<option value="{$p.id}">{$p.policy_name}</option>
{/volist}
</select>
</div>
<div class="col-md-4 option-des"> 为该用户组绑定一个上传策略</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="colFormLabelSm" class="col-form-label col-form-label-sm">初始容量</label>
</div>
<div class="col-md-4 input-group mb-3">
<input type="number" class="form-control" name="max_storage" spellcheck="false" min="0" value="10" required>
<div class="input-group-append">
<span class="input-group-text" id="basic-addon2">
<select name="sizeTimes" class="selectIn">
<option value="1">B</option>
<option value="1024">KB</option>
<option value="1048576" selected>MB</option>
<option value="1073741824">GB</option>
</select>
</span>
</div>
</div>
<div class="col-md-4 option-des"> 该用户组初始最大可用容量</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="colFormLabelSm" class="col-form-label col-form-label-sm">下载限速</label>
</div>
<div class="col-md-4 input-group mb-3">
<input type="number" class="form-control" name="speed" spellcheck="false" min="0" placeholder="留空表示不限速,0表示禁止下载">
<div class="input-group-append">
<span class="input-group-text" id="basic-addon2">
Kb/s
</span>
</div>
</div>
<div class="col-md-4 option-des"> 限制该用户组下的用户上传的文件的下载速度,<strong>此设置仅对本地上传方案有效</strong></div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="colFormLabelSm" class="col-form-label col-form-label-sm">断点续传及多线程下载</label>
</div>
<div class="col-md-4"> <input class="" type="radio" name="range_transfer" value="1" id="allow_range_1" checked>
<label class="" for="allow_range_1" >允许</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="range_transfer" id="allow_range_0" value="0" >
<label class="" for="allow_range_0">禁止</label></div>
<div class="col-md-4 option-des"> 是否断点续传及多线程下载,关闭后预览视频不支持拖拽播放,<strong>此设置仅对本地上传方案有效</strong></div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="colFormLabelSm" class="col-form-label col-form-label-sm">创建分享</label>
</div>
<div class="col-md-4"> <input class="" type="radio" name="allow_share" value="1" id="allow_share_1" checked>
<label class="" for="allow_share_1" >允许</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="allow_share" id="allow_share_0" value="0" >
<label class="" for="allow_share_0">禁止</label></div>
<div class="col-md-4 option-des"> 是否允许创建文件分享链接</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="colFormLabelSm" class="col-form-label col-form-label-sm">WebDAV支持</label>
</div>
<div class="col-md-4"> <input class="" type="radio" name="webdav" value="1" id="webdav1" checked>
<label class="" for="webdav1" >允许</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="webdav" id="webdav0" value="0" >
<label class="" for="webdav0">禁止</label></div>
<div class="col-md-4 option-des"> 是否允许用户使用WebDAV协议同步文件。目前此功能仅支持本地上传方案</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="colFormLabelSm" class="col-form-label col-form-label-sm">用户组标志色</label>
</div>
<div class="col-md-4">
<input class="" type="radio" name="color" value="default" id="default" checked>
<label class="" for="default" ><span class="badge badge-primary">蓝色</span></label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="color" value="primary" id="primary">
<label class="" for="primary" ><span class="badge badge-secondary">灰色</span></label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="color" value="success" id="success">
<label class="" for="success" ><span class="badge badge-success">绿色</span></label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="color" value="danger" id="danger">
<label class="" for="danger" ><span class="badge badge-danger">红色</span></label>
<br>
<input class="" type="radio" name="color" value="warning" id="warning">
<label class="" for="warning" ><span class="badge badge-warning">黄色</span></label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="color" value="info" id="info">
<label class="" for="info" ><span class="badge badge-info">浅蓝色</span></label>
&nbsp;&nbsp;&nbsp;
</div>
<div class="col-md-4 option-des"> 用户个人主页展示用户组时的徽章颜色</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
</div>
<div class="col-md-4"> <button type="submit" class="btn btn-primary" id="saveGroup">添加</button></div>
<div class="col-md-4 option-des"> </div>
<br><br><br>
</div>
</form>
</div>
</div>
<!-- Example DataTables Card-->
</div>
<!-- /.container-fluid-->
</div>
<!-- /.content-wrapper-->
{/block}
{block name="js"}
<script src="/static/js/admin/add_group.js"></script>
<script type="text/javascript">
</script>
{/block}
@@ -1,825 +0,0 @@
{extend name="header_admin" /}
{block name="title"}添加上传策略- {$options.siteName}{/block}
{block name="content"}
<div class="content-wrapper">
<div class="container-fluid">
<!-- Breadcrumbs-->
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="/Admin">管理面板</a>
</li>
<li class="breadcrumb-item">
<a href="/Admin/PolicyAdd">上传策略</a>
</li>
<li class="breadcrumb-item active">添加</li>
</ol>
<!-- Area Chart Example-->
<div class="row">
<div class="col-12">
<h2>添加上传策略</h2>
<br>
<div id="choose">
<div class="row">
<div class="col-md-3 md-2 mt-2">
<div class="card cloud">
<img class="card-img-top" src="/static/img/local.png" alt="Card image cap">
<div class="card-body">
<h5 class="card-title">本地服务器</h5>
<p class="card-text">将文件存放在Cloudreve主程序的同一个服务器上</p>
<a href="javascript:void()" class="btn btn-primary" id="addLocal">添加</a>
</div>
</div>
</div>
<div class="col-md-3 md-2 mt-2">
<div class="card cloud">
<img class="card-img-top" src="/static/img/qiniu.png" alt="Card image cap">
<div class="card-body">
<h5 class="card-title">七牛云存储</h5>
<p class="card-text">使用<a href="https://www.qiniu.com/" target="_blank">七牛云</a>提供的云存储及CDN服务</p>
<a href="javascript:void();" class="btn btn-primary" id="addQiniu">添加</a>
</div>
</div>
</div>
<div class="col-md-3 md-2 mt-2">
<div class="card cloud">
<img class="card-img-top" src="/static/img/oss.png" alt="Card image cap">
<div class="card-body">
<h5 class="card-title">阿里云OSS</h5>
<p class="card-text">使用<a href="https://www.aliyun.com/product/oss?spm=5176.doc54464.765261.286.v2y7Hk" target="_blank">OSS对象存储</a>存放文件,推荐配合阿里云CDN使用</p>
<a href="javascript:void()" class="btn btn-primary" id="addOss">添加</a>
</div>
</div>
</div>
<div class="col-md-3 md-2 mt-2">
<div class="card cloud">
<img class="card-img-top" src="/static/img/upyun.png" alt="Card image cap">
<div class="card-body">
<h5 class="card-title">又拍云</h5>
<p class="card-text">使用<a href="https://console.upyun.com/register/?invite=ryPX265PW" target="_blank">又拍云存储</a>提供的服务,每月有一定免费额度</p>
<a href="javascript:void()" class="btn btn-primary" id="addUpyun">添加</a>
</div>
</div>
</div>
<div class="col-md-3 mt-2 md-2">
<div class="card cloud">
<img class="card-img-top" src="/static/img/s3.png" alt="Card image cap">
<div class="card-body">
<h5 class="card-title">Amazon S3</h5>
<p class="card-text"><a href="https://aws.amazon.com/cn/s3/?nc1=h_ls" target="_blank">Amazon S3</a>专为数据而构建的对象存储</p>
<a href="/Admin/PolicyAddS3" class="btn btn-primary">添加</a>
</div>
</div>
</div>
<div class="col-md-3 mt-2 md-2">
<div class="card cloud">
<img class="card-img-top" src="/static/img/remote.png" alt="Card image cap">
<div class="card-body">
<h5 class="card-title">远程服务器</h5>
<p class="card-text">你可以将文件存放在不同于主程序的服务器上。<a href="https://github.com/HFO4/Cloudreve/wiki/%E8%BF%9C%E7%A8%8B%E5%AD%98%E5%82%A8%E6%9C%8D%E5%8A%A1%E7%AB%AF%E6%90%AD%E5%BB%BA">配置说明</a></p>
<a href="/Admin/PolicyAddRemote" class="btn btn-primary">添加</a>
</div>
</div>
</div>
</div>
</div>
<div class="card" id="local" style="display: none">
<div class="card-header">
添加本地上传策略
</div>
<div class="card-body">
<form id="localPolicy">
<input type="text" class="form-control" name="policy_type" value="local" style="display: none">
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="policy_name" class="col-form-label col-form-label-sm">上传策略名称</label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="policy_name" required></div>
<div class="col-md-4 option-des"> 上传策略的名称,用于区别不同策略</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="policy_name" class="col-form-label col-form-label-sm">允许获取外链</label>
</div>
<div class="col-md-4">
<input class="" type="radio" name="origin_link" id="local_allowd_origin1" value="1" >
<label class="" for="local_allowd_origin1" >允许</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="origin_link" id="local_allowd_origin2" value="0" checked>
<label class="" for="local_allowd_origin2">禁止</label>
</div>
<div class="col-md-4 option-des"> 是否允许获取文件的源URL,推荐禁止</div>
</div>
<div class="row form-setting" id="localOrigin" style="display: none">
<div class="col-md-1 form-label ">
<label for="url" class="col-form-label col-form-label-sm">外链根URL</label>
</div>
<div class="col-md-4">
<input type="text" class="form-control" name="url" value="{$options.siteURL}public/uploads/">
</div>
<div class="col-md-4 option-des"> 一般保持默认。如果你设置了融合CDN等产品,这里可以填写CDN域名,结尾要加"/"</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="filetype" class="col-form-label col-form-label-sm">允许的文件后缀</label>
</div>
<div class="col-md-4">
<input type="text" class="form-control" name="filetype" value="image/*,jpg,png,gif,bmp,mp4,mp3,txt" spellcheck="false">
</div>
<div class="col-md-4 option-des"> 多个请以半角逗号","隔开,留空表示不限制。如果允许图片类型文件,除了图片类型后缀外,请额外添加一项"image/*"</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="filetype" class="col-form-label col-form-label-sm">单文件最大大小</label>
</div>
<div class="col-md-4 input-group mb-3">
<input type="number" class="form-control" name="max_size" spellcheck="false" min="0" value="10" required>
<div class="input-group-append">
<span class="input-group-text" id="basic-addon2">
<select name="sizeTimes" class="selectIn">
<option value="1">B</option>
<option value="1024">KB</option>
<option value="1048576" selected>MB</option>
<option value="1073741824">GB</option>
</select>
</span>
</div>
</div>
<div class="col-md-4 option-des"> 允许上传的单个文件的最大尺寸</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="filetype" class="col-form-label col-form-label-sm">文件重命名</label>
</div>
<div class="col-md-4">
<input class="" type="radio" name="autoname" id="autoname1" value="1" checked>
<label class="" for="autoname1" >开启</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="autoname" id="autoname2" value="0" >
<label class="" for="autoname2">关闭</label>
</div>
<div class="col-md-4 option-des"> 是否对存储的文件自动重命名。推荐开启,重命名不会影响用户端文件名展示,开启后可以避免文件重名</div>
</div>
<div class="row form-setting" id="autoname_form" >
<div class="col-md-1 form-label ">
<label for="url" class="col-form-label col-form-label-sm">重命名规则</label>
</div>
<div class="col-md-4">
<input type="text" class="form-control" name="namerule" value="{uid}_{randomkey8}_{originname}" spellcheck="false" required>
</div>
<div class="col-md-4 option-des"> 你可以使用<a href="javascript:void()" data-toggle="modal" data-target="#varTable">变量对照表</a>中的字段填写</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="filetype" class="col-form-label col-form-label-sm">存储目录</label>
</div>
<div class="col-md-4 input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="basic-addon2">
/public/uploads/
</span>
</div>
<input type="text" class="form-control" name="dirrule" spellcheck="false" value="{date}/{uid}" required>
</div>
<div class="col-md-4 option-des"> 文件存放的目录,你可以使用<a href="javascript:void()" data-toggle="modal" data-target="#varTableFolder">目录变量对照表</a>中的字段填写</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
</div>
<div class="col-md-4"> <button type="submit" class="btn btn-primary" id="savePolicy">保存设置</button></div>
<div class="col-md-4 option-des"> </div>
<br> <br>
</div>
</form>
</div>
<bn>
</div>
<div class="card" id="qiniu" style="display: none">
<div class="card-header">
添加七牛上传策略
</div>
<div class="card-body">
<form id="qiniuPolicy">
<input type="text" class="form-control" name="policy_type" value="qiniu" style="display: none">
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="policy_name" class="col-form-label col-form-label-sm">上传策略名称</label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="policy_name" required></div>
<div class="col-md-4 option-des"> 上传策略的名称,用于区别不同策略</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="ak" class="col-form-label col-form-label-sm">AccessKey </label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="ak" required></div>
<div class="col-md-4 option-des"> 七牛账号的AccessKey,请在七牛控制面板查看</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="sk" class="col-form-label col-form-label-sm">SecretKey </label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="sk" required></div>
<div class="col-md-4 option-des"> 七牛账号的SecretKey,请在七牛控制面板查看</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="bucketname" class="col-form-label col-form-label-sm">存储空间名称 </label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="bucketname" required></div>
<div class="col-md-4 option-des"> 创建空间时填写的空间名</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="policy_name" class="col-form-label col-form-label-sm">空间属性</label>
</div>
<div class="col-md-4">
<input class="" type="radio" name="bucket_private" id="bucket_private_1" value="1" checked>
<label class="" for="bucket_private_1" >私有空间</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="bucket_private" id="bucket_private_0" value="0">
<label class="" for="bucket_private_0">公开空间</label>
</div>
<div class="col-md-4 option-des"> 与七牛空间访问控制设置保持一致,推荐设置为私有空间</div>
</div>
<div class="row form-setting" id="outlink" style="display: none">
<div class="col-md-1 form-label ">
<label for="policy_name" class="col-form-label col-form-label-sm">允许获取外链</label>
</div>
<div class="col-md-4">
<input class="" type="radio" name="origin_link" id="qiniu_allowd_origin1" value="1" >
<label class="" for="qiniu_allowd_origin1" >允许</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="origin_link" id="qiniu_allowd_origin2" value="0" checked>
<label class="" for="qiniu_allowd_origin2">禁止</label>
</div>
<div class="col-md-4 option-des"> 是否允许获取文件的源URL,推荐禁止</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="url" class="col-form-label col-form-label-sm">空间域名</label>
</div>
<div class="col-md-4">
<input type="text" class="form-control" name="url" required>
</div>
<div class="col-md-4 option-des"> 七牛空间绑定的域名,结尾要加"/"</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="filetype" class="col-form-label col-form-label-sm">允许的文件后缀</label>
</div>
<div class="col-md-4">
<input type="text" class="form-control" name="filetype" value="image/*,jpg,png,gif,bmp,mp4,mp3,txt" spellcheck="false">
</div>
<div class="col-md-4 option-des"> 多个请以半角逗号","隔开,留空表示不限制。如果允许图片类型文件,除了图片类型后缀外,请额外添加一项"image/*"</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="mimetype" class="col-form-label col-form-label-sm">允许的mimeType</label>
</div>
<div class="col-md-4">
<input type="text" class="form-control" name="mimetype" spellcheck="false">
</div>
<div class="col-md-4 option-des"> 多个请以半角分号";"隔开,留空表示不限制。示例:image/*表示只允许上传图片类型,image/jpeg;image/png表示只允许上传jpg和png类型的图片,!application/json;text/plain表示禁止上传json文本和纯文本。注意最前面的感叹号!</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="filetype" class="col-form-label col-form-label-sm">单文件最大大小</label>
</div>
<div class="col-md-4 input-group mb-3">
<input type="number" class="form-control" name="max_size" spellcheck="false" min="0" value="10" required>
<div class="input-group-append">
<span class="input-group-text" id="basic-addon2">
<select name="sizeTimes" class="selectIn">
<option value="1">B</option>
<option value="1024">KB</option>
<option value="1048576" selected>MB</option>
<option value="1073741824">GB</option>
</select>
</span>
</div>
</div>
<div class="col-md-4 option-des"> 允许上传的单个文件的最大尺寸</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="filetype" class="col-form-label col-form-label-sm">文件重命名</label>
</div>
<div class="col-md-4">
<input class="" type="radio" name="autoname" id="qiniu_autoname1" value="1" checked>
<label class="" for="qiniu_autoname1" >开启</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="autoname" id="qiniu_autoname2" value="0" >
<label class="" for="qiniu_autoname2">关闭</label>
</div>
<div class="col-md-4 option-des"> 是否对存储的文件自动重命名。推荐开启,重命名不会影响用户端文件名展示,开启后可以避免文件重名</div>
</div>
<div class="row form-setting" id="qiniu_autoname_form" >
<div class="col-md-1 form-label ">
<label for="url" class="col-form-label col-form-label-sm">重命名规则</label>
</div>
<div class="col-md-4">
<input type="text" class="form-control" name="namerule" value="{uid}_{randomkey8}_{originname}" spellcheck="false" required>
</div>
<div class="col-md-4 option-des"> 你可以使用<a href="javascript:void()" data-toggle="modal" data-target="#varTable">变量对照表</a>中的字段填写</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="filetype" class="col-form-label col-form-label-sm">存储目录</label>
</div>
<div class="col-md-4 input-group mb-3">
<input type="text" class="form-control" name="dirrule" spellcheck="false" value="{date}/{uid}" required>
</div>
<div class="col-md-4 option-des"> 文件存放的目录,你可以使用<a href="javascript:void()" data-toggle="modal" data-target="#varTableFolder">目录变量对照表</a>中的字段填写</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
</div>
<div class="col-md-4"> <button type="submit" class="btn btn-primary" id="saveQiniu">保存设置</button></div>
<div class="col-md-4 option-des"> </div>
<br> <br>
</div>
</form>
</div>
<bn>
</div>
<div id="oss" style="display: none">
<div class="alert alert-primary" role="alert">
阿里云OSS创建空间后请进行如下操作,否则无法正常上传。
<ul>
<li>转到 空间管理 - 基础设置 - 跨域设置;</li>
<li>创建规则,其中来源填写“*”,允许 Methods全部勾选,允许 Headers填写“*”,其他保持默认,点击确定保存.</li>
</ul>
</div>
<div class="card" >
<div class="card-header">
添加阿里云OSS上传策略
</div>
<div class="card-body">
<form id="ossPolicy">
<input type="text" class="form-control" name="policy_type" value="oss" style="display: none">
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="policy_name" class="col-form-label col-form-label-sm">上传策略名称</label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="policy_name" required></div>
<div class="col-md-4 option-des"> 上传策略的名称,用于区别不同策略</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="ak" class="col-form-label col-form-label-sm">Access Key ID </label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="ak" pattern="[^\s]+" title="请不要包含空格" required></div>
<div class="col-md-4 option-des"> 阿里云账号的Access Key ID,请在阿里云控制面板-Access Key管理中创建或查看</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="sk" class="col-form-label col-form-label-sm"> Access Key Secret </label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="sk" pattern="[^\s]+" title="请不要包含空格" required></div>
<div class="col-md-4 option-des"> 获取方法同上一项</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="bucketname" class="col-form-label col-form-label-sm">Bucket名称 </label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="bucketname" required></div>
<div class="col-md-4 option-des"> 创建空间时填写的Bucket名</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="policy_name" class="col-form-label col-form-label-sm">读写权限</label>
</div>
<div class="col-md-4">
<input class="" type="radio" name="bucket_private" id="oss_private_1" value="1" checked>
<label class="" for="oss_private_1" >私有</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="bucket_private" id="oss_private_0" value="0">
<label class="" for="oss_private_0">公共读</label>
</div>
<div class="col-md-4 option-des"> 与OSS空间访问控制设置保持一致,推荐设置为私有空间</div>
</div>
<div class="row form-setting" id="oss_outlink" style="display: none">
<div class="col-md-1 form-label ">
<label for="policy_name" class="col-form-label col-form-label-sm">允许获取外链</label>
</div>
<div class="col-md-4">
<input class="" type="radio" name="origin_link" id="oss_allowd_origin1" value="1" >
<label class="" for="oss_allowd_origin1" >允许</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="origin_link" id="oss_allowd_origin2" value="0" checked>
<label class="" for="oss_allowd_origin2">禁止</label>
</div>
<div class="col-md-4 option-des"> 是否允许获取文件的源URL,推荐禁止</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="url" class="col-form-label col-form-label-sm">空间域名</label>
</div>
<div class="col-md-4">
<input type="text" class="form-control" name="url" value="http(s)://" required>
</div>
<div class="col-md-4 option-des"> OSS空间绑定的域名,用于文件下载、访问,结尾要加"/"(推荐配合阿里云CDN使用,此处填写CDN域名)</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="server" class="col-form-label col-form-label-sm">上传域名</label>
</div>
<div class="col-md-4">
<input type="text" class="form-control" name="server" value="http(s)://" required>
</div>
<div class="col-md-4 option-des"> OSS空间的域名,一般与上一项保持一致。(如果上一项填写的是CDN域名,则此处与上一项不应相同)</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="filetype" class="col-form-label col-form-label-sm">允许的文件后缀</label>
</div>
<div class="col-md-4">
<input type="text" class="form-control" name="filetype" value="image/*,jpg,png,gif,bmp,mp4,mp3,txt" spellcheck="false">
</div>
<div class="col-md-4 option-des"> 多个请以半角逗号","隔开,留空表示不限制。如果允许图片类型文件,除了图片类型后缀外,请额外添加一项"image/*"</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="filetype" class="col-form-label col-form-label-sm">单文件最大大小</label>
</div>
<div class="col-md-4 input-group mb-3">
<input type="number" class="form-control" name="max_size" spellcheck="false" min="0" value="10" required>
<div class="input-group-append">
<span class="input-group-text" id="basic-addon2">
<select name="sizeTimes" class="selectIn">
<option value="1">B</option>
<option value="1024">KB</option>
<option value="1048576" selected>MB</option>
<option value="1073741824">GB</option>
</select>
</span>
</div>
</div>
<div class="col-md-4 option-des"> 允许上传的单个文件的最大尺寸</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="filetype" class="col-form-label col-form-label-sm">文件重命名</label>
</div>
<div class="col-md-4">
<input class="" type="radio" name="autoname" id="oss_autoname1" value="1" checked>
<label class="" for="oss_autoname1" >开启</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="autoname" id="oss_autoname2" value="0" >
<label class="" for="oss_autoname2">关闭</label>
</div>
<div class="col-md-4 option-des"> 是否对存储的文件自动重命名。推荐开启,重命名不会影响用户端文件名展示,开启后可以避免文件重名</div>
</div>
<div class="row form-setting" id="oss_autoname_form" >
<div class="col-md-1 form-label ">
<label for="url" class="col-form-label col-form-label-sm">重命名规则</label>
</div>
<div class="col-md-4">
<input type="text" class="form-control" name="namerule" value="{uid}_{randomkey8}_{originname}" spellcheck="false" required>
</div>
<div class="col-md-4 option-des"> 你可以使用<a href="javascript:void()" data-toggle="modal" data-target="#varTable">变量对照表</a>中的字段填写</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="filetype" class="col-form-label col-form-label-sm">存储目录</label>
</div>
<div class="col-md-4 input-group mb-3">
<input type="text" class="form-control" name="dirrule" spellcheck="false" value="{date}/{uid}" required>
</div>
<div class="col-md-4 option-des"> 文件存放的目录,你可以使用<a href="javascript:void()" data-toggle="modal" data-target="#varTableFolder">目录变量对照表</a>中的字段填写</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
</div>
<div class="col-md-4"> <button type="submit" class="btn btn-primary" id="saveOss">保存设置</button></div>
<div class="col-md-4 option-des"> </div>
<br> <br>
</div>
</form>
</div>
<bn>
</div>
</div>
<div class="card" id="upyun" style="display: none">
<div class="card-header">
又拍云
</div>
<div class="card-body">
<form id="upyunPolicy">
<input type="text" class="form-control" name="policy_type" value="upyun" style="display: none">
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="policy_name" class="col-form-label col-form-label-sm">上传策略名称</label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="policy_name" required></div>
<div class="col-md-4 option-des"> 上传策略的名称,用于区别不同策略</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="ak" class="col-form-label col-form-label-sm">操作员名称 </label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="op_name" required></div>
<div class="col-md-4 option-des"> 创建存储服务时授权的操作员名称</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="sk" class="col-form-label col-form-label-sm">操作员密码 </label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="op_pwd" required></div>
<div class="col-md-4 option-des"> 创建存储服务时授权的操作员密码</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="bucketname" class="col-form-label col-form-label-sm">存储服务名 </label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="bucketname" required></div>
<div class="col-md-4 option-des"> 创建存储服务时填写的名称</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="policy_name" class="col-form-label col-form-label-sm">Token 防盗链</label>
</div>
<div class="col-md-4">
<input class="" type="radio" name="bucket_private" id="upyun_bucket_private_1" value="1" checked>
<label class="" for="upyun_bucket_private_1" >开启</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="bucket_private" id="upyun_bucket_private_0" value="0">
<label class="" for="upyun_bucket_private_0">关闭</label>
</div>
<div class="col-md-4 option-des"> 与 功能配置-访问配置-Token 防盗链 保持一致,推荐设置为开启</div>
</div>
<div class="row form-setting" id="upyun_token" style="">
<div class="col-md-1 form-label ">
<label for="policy_name" class="col-form-label col-form-label-sm">防盗链密钥</label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="sk"></div>
<div class="col-md-4 option-des"> 与 功能配置-访问配置-Token防盗链 中的密钥保持一致</div>
</div>
<div class="row form-setting" id="upyun_outlink" style="display: none">
<div class="col-md-1 form-label ">
<label for="policy_name" class="col-form-label col-form-label-sm">允许获取外链</label>
</div>
<div class="col-md-4">
<input class="" type="radio" name="origin_link" id="upyun_allowd_origin1" value="1" >
<label class="" for="upyun_allowd_origin1" >允许</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="origin_link" id="upyun_allowd_origin2" value="0" checked>
<label class="" for="upyun_allowd_origin2">禁止</label>
</div>
<div class="col-md-4 option-des"> 是否允许获取文件的源URL,推荐禁止</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="url" class="col-form-label col-form-label-sm">空间域名</label>
</div>
<div class="col-md-4">
<input type="text" class="form-control" name="url" required>
</div>
<div class="col-md-4 option-des"> 绑定的域名,开头要加http(s)://结尾要加"/"</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="filetype" class="col-form-label col-form-label-sm">允许的文件后缀</label>
</div>
<div class="col-md-4">
<input type="text" class="form-control" name="filetype" value="image/*,jpg,png,gif,bmp,mp4,mp3,txt" spellcheck="false">
</div>
<div class="col-md-4 option-des"> 多个请以半角逗号","隔开,留空表示不限制。如果允许图片类型文件,除了图片类型后缀外,请额外添加一项"image/*"</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="filetype" class="col-form-label col-form-label-sm">单文件最大大小</label>
</div>
<div class="col-md-4 input-group mb-3">
<input type="number" class="form-control" name="max_size" spellcheck="false" min="0" value="10" required>
<div class="input-group-append">
<span class="input-group-text" id="basic-addon2">
<select name="sizeTimes" class="selectIn">
<option value="1">B</option>
<option value="1024">KB</option>
<option value="1048576" selected>MB</option>
<option value="1073741824">GB</option>
</select>
</span>
</div>
</div>
<div class="col-md-4 option-des"> 允许上传的单个文件的最大尺寸</div>
</div>
<input type="text" name="autoname" value="1" style="display: none">
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="filetype" class="col-form-label col-form-label-sm">存储目录</label>
</div>
<div class="col-md-4 input-group mb-3">
<input type="text" class="form-control" name="dirrule" spellcheck="false" value="{date}/{uid}" required>
</div>
<div class="col-md-4 option-des"> 文件存放的目录,你可以使用<a href="javascript:void()" data-toggle="modal" data-target="#varTableFolder">目录变量对照表</a>中的字段填写</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
</div>
<div class="col-md-4"> <button type="submit" class="btn btn-primary" id="saveUpyun">保存设置</button></div>
<div class="col-md-4 option-des"> </div>
<br> <br>
</div>
</form>
</div>
<bn>
</div>
<br>
</div>
</div>
<!-- Example DataTables Card-->
</div>
<!-- /.container-fluid-->
</div>
<!-- /.content-wrapper-->
<div class="modal fade" tabindex="-1" role="dialog" id="varTable">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">自动重命名变量对照表</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th >变量字段</th>
<th >说明</th>
<th >示例</th>
<th >适用范围</th>
</tr>
</thead>
<tbody>
<tr>
<td >{date}</td>
<td>上传日期</td>
<td>20180118</td>
<td>全部</td>
</tr>
<tr>
<td >{datetime}</td>
<td>上传日期时间</td>
<td>20180118121049</td>
<td>全部</td>
</tr>
<tr>
<td >{uid}</td>
<td>上传者UID</td>
<td>154</td>
<td>全部</td>
</tr>
<tr>
<td >{timestamp}</td>
<td>时间戳</td>
<td>1516277624</td>
<td>全部</td>
</tr>
<tr>
<td >{randomkey16}</td>
<td>16位随机字符</td>
<td>16D8lhjErTDWAQjW</td>
<td>全部</td>
</tr>
<tr>
<td >{randomkey8}</td>
<td>8位随机字符</td>
<td>hM4Tpdh6</td>
<td>全部</td>
</tr>
<tr>
<td >{originname}</td>
<td>原始文件名</td>
<td>plus1s.jpg</td>
<td>全部</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
</div>
</div>
</div>
</div>
<div class="modal fade" tabindex="-1" role="dialog" id="varTableFolder">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">目录变量对照表</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th >变量字段</th>
<th >说明</th>
<th >示例</th>
<th >适用范围</th>
</tr>
</thead>
<tbody>
<tr>
<td >{date}</td>
<td>上传日期</td>
<td>20180118</td>
<td>全部</td>
</tr>
<tr>
<td >{datetime}</td>
<td>上传日期时间</td>
<td>20180118121049</td>
<td>全部</td>
</tr>
<tr>
<td >{uid}</td>
<td>上传者UID</td>
<td>154</td>
<td>全部</td>
</tr>
<tr>
<td >{timestamp}</td>
<td>时间戳</td>
<td>1516277624</td>
<td>全部</td>
</tr>
<tr>
<td >{randomkey16}</td>
<td>16位随机字符</td>
<td>16D8lhjErTDWAQjW</td>
<td>全部</td>
</tr>
<tr>
<td >{randomkey8}</td>
<td>8位随机字符</td>
<td>hM4Tpdh6</td>
<td>全部</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
</div>
</div>
</div>
</div>
{/block}
{block name="js"}
<script src="/static/js/admin/add_policy.js"></script>
<script type="text/javascript">
</script>
{/block}
@@ -1,170 +0,0 @@
{extend name="header_admin" /}
{block name="title"}添加上传策略- {$options.siteName}{/block}
{block name="content"}
<div class="content-wrapper">
<div class="container-fluid">
<!-- Breadcrumbs-->
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="/Admin">管理面板</a>
</li>
<li class="breadcrumb-item">
<a href="/Admin/PolicyAdd">上传策略</a>
</li>
<li class="breadcrumb-item active">添加</li>
</ol>
<!-- Area Chart Example-->
<div class="row">
<div class="col-12">
<h2>添加上传策略</h2>
<br>
<div class="card" id="s3" >
<div class="card-header">
添加远程上传策略
</div>
<div class="card-body">
<form id="qiniuPolicy">
<input type="text" class="form-control" name="policy_type" value="remote" style="display: none">
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="policy_name" class="col-form-label col-form-label-sm">上传策略名称</label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="policy_name" required></div>
<div class="col-md-4 option-des"> 上传策略的名称,用于区别不同策略</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="ak" class="col-form-label col-form-label-sm">AccessToken </label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="sk" required></div>
<div class="col-md-4 option-des"> 默认随机生成,请与远程服务端配置文件中保持一致</div>
</div>
<input type="text" class="form-control" name="ak" value="0" style="display: none" required>
<input type="text" name="bucket_private" value="1" style="display: none">
<input type="text" name="origin_link" value="0" style="display: none">
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="url" class="col-form-label col-form-label-sm">服务端URL</label>
</div>
<div class="col-md-4">
<input type="text" class="form-control" name="server" required>
</div>
<div class="col-md-4 option-des"> 结尾要加"/"</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="url" class="col-form-label col-form-label-sm">下载根URL</label>
</div>
<div class="col-md-4">
<input type="text" class="form-control" name="url" required>
</div>
<div class="col-md-4 option-des"> 一般与上一步保持一致,结尾要加"/"</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="filetype" class="col-form-label col-form-label-sm">单文件最大大小</label>
</div>
<div class="col-md-4 input-group mb-3">
<input type="number" class="form-control" name="max_size" spellcheck="false" min="0" value="10" required>
<div class="input-group-append">
<span class="input-group-text" id="basic-addon2">
<select name="sizeTimes" class="selectIn">
<option value="1">B</option>
<option value="1024">KB</option>
<option value="1048576" selected>MB</option>
<option value="1073741824">GB</option>
</select>
</span>
</div>
</div>
<div class="col-md-4 option-des"> 允许上传的单个文件的最大尺寸</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="filetype" class="col-form-label col-form-label-sm">文件重命名</label>
</div>
<div class="col-md-4">
<input class="" type="radio" name="autoname" id="autoname1" value="1" checked>
<label class="" for="autoname1" >开启</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="autoname" id="autoname2" value="0" >
<label class="" for="autoname2">关闭</label>
</div>
<div class="col-md-4 option-des"> 是否对存储的文件自动重命名。推荐开启,重命名不会影响用户端文件名展示,开启后可以避免文件重名</div>
</div>
<div class="row form-setting" id="autoname_form" >
<div class="col-md-1 form-label ">
<label for="url" class="col-form-label col-form-label-sm">重命名规则</label>
</div>
<div class="col-md-4">
<input type="text" class="form-control" name="namerule" value="{uid}_{randomkey8}_{originname}" spellcheck="false" required>
</div>
<div class="col-md-4 option-des"> 你可以使用变量对照表中的字段填写</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="filetype" class="col-form-label col-form-label-sm">存储目录</label>
</div>
<div class="col-md-4 input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="basic-addon2">
/public/uploads/
</span>
</div>
<input type="text" class="form-control" name="dirrule" spellcheck="false" value="{date}/{uid}" required>
</div>
<div class="col-md-4 option-des"> 文件存放的目录,你可以使用目录变量对照表中的字段填写</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
</div>
<div class="col-md-4"> <button type="submit" class="btn btn-primary" id="saveQiniu">保存设置</button></div>
<div class="col-md-4 option-des"> </div>
<br> <br>
</div>
</form>
</div>
<bn>
</div>
<br>
</div>
</div>
<!-- Example DataTables Card-->
</div>
<!-- /.container-fluid-->
</div>
{/block}
{block name="js"}
<script src="/static/js/admin/add_policy.js"></script>
<script type="text/javascript">
function randomString(len) {
  len = len || 32;
  var $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
  var maxPos = $chars.length;
  var pwd = '';
  for (i = 0; i < len; i++) {
    pwd += $chars.charAt(Math.floor(Math.random() * maxPos));
  }
  return pwd;
}
$("[name='sk']").val(randomString(32));
</script>
{/block}
@@ -1,175 +0,0 @@
{extend name="header_admin" /}
{block name="title"}添加上传策略- {$options.siteName}{/block}
{block name="content"}
<div class="content-wrapper">
<div class="container-fluid">
<!-- Breadcrumbs-->
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="/Admin">管理面板</a>
</li>
<li class="breadcrumb-item">
<a href="/Admin/PolicyAdd">上传策略</a>
</li>
<li class="breadcrumb-item active">添加</li>
</ol>
<!-- Area Chart Example-->
<div class="row">
<div class="col-12">
<h2>添加上传策略</h2>
<br>
<div class="alert alert-primary" role="alert">
创建储存桶后请在储存桶控制面板添加CORS跨域规则,允许本站的POST请求。请确保您的服务器和用户可以正常连接到AWS服务器。
</ul>
</div>
<div class="card" id="s3" >
<div class="card-header">
添加S3上传策略
</div>
<div class="card-body">
<form id="qiniuPolicy">
<input type="text" class="form-control" name="policy_type" value="s3" style="display: none">
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="policy_name" class="col-form-label col-form-label-sm">上传策略名称</label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="policy_name" required></div>
<div class="col-md-4 option-des"> 上传策略的名称,用于区别不同策略</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="ak" class="col-form-label col-form-label-sm">AWSAccessKeyId </label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="ak" required></div>
<div class="col-md-4 option-des"> AWS账户的访问秘钥信息,请在 控制面板 - 您的安全凭证 中创建</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="sk" class="col-form-label col-form-label-sm">AWSSecretKey </label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="sk" required></div>
<div class="col-md-4 option-des"> 同上一项获取</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="bucketname" class="col-form-label col-form-label-sm">存储桶名称 </label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="bucketname" required></div>
<div class="col-md-4 option-des"> 创建桶时填写的名称</div>
</div>
<input type="text" name="bucket_private" value="1" style="display: none">
<input type="text" name="origin_link" value="0" style="display: none">
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="url" class="col-form-label col-form-label-sm">下载根URL</label>
</div>
<div class="col-md-4">
<input type="text" class="form-control" name="url" required>
</div>
<div class="col-md-4 option-des"> 一般格式为:https://s3-分区名.amazonaws.com/储存桶名/ 结尾要加"/"</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="url" class="col-form-label col-form-label-sm">上传服务器URL</label>
</div>
<div class="col-md-4">
<input type="text" class="form-control" name="server" required>
</div>
<div class="col-md-4 option-des"> 一般格式为:https://储存桶名.s3-分区代号.amazonaws.com/</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="url" class="col-form-label col-form-label-sm">储存区域</label>
</div>
<div class="col-md-4">
<input type="text" class="form-control" name="op_name" required>
</div>
<div class="col-md-4 option-des"> 例如:ap-southeast-1</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="url" class="col-form-label col-form-label-sm">EndPoint</label>
</div>
<div class="col-md-4">
<input type="text" class="form-control" name="op_name" required>
</div>
<div class="col-md-4 option-des"> 一般格式为:s3-储存区域.amazonaws.com,只填写域名部分</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="filetype" class="col-form-label col-form-label-sm">允许的文件后缀</label>
</div>
<div class="col-md-4">
<input type="text" class="form-control" name="filetype" value="image/*,jpg,png,gif,bmp,mp4,mp3,txt" spellcheck="false">
</div>
<div class="col-md-4 option-des"> 多个请以半角逗号","隔开,留空表示不限制。如果允许图片类型文件,除了图片类型后缀外,请额外添加一项"image/*"</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="filetype" class="col-form-label col-form-label-sm">单文件最大大小</label>
</div>
<div class="col-md-4 input-group mb-3">
<input type="number" class="form-control" name="max_size" spellcheck="false" min="0" value="10" required>
<div class="input-group-append">
<span class="input-group-text" id="basic-addon2">
<select name="sizeTimes" class="selectIn">
<option value="1">B</option>
<option value="1024">KB</option>
<option value="1048576" selected>MB</option>
<option value="1073741824">GB</option>
</select>
</span>
</div>
</div>
<div class="col-md-4 option-des"> 允许上传的单个文件的最大尺寸</div>
</div>
<input type="text" name="autoname" value="0" style="display: none">
<input type="text" class="form-control" name="dirrule" spellcheck="false" value="{uid}" style="display: none" required>
<div class="row form-setting">
<div class="col-md-1 form-label ">
</div>
<div class="col-md-4"> <button type="submit" class="btn btn-primary" id="saveQiniu">保存设置</button></div>
<div class="col-md-4 option-des"> </div>
<br> <br>
</div>
</form>
</div>
<bn>
</div>
<br>
</div>
</div>
<!-- Example DataTables Card-->
</div>
<!-- /.container-fluid-->
</div>
{/block}
{block name="js"}
<script src="/static/js/admin/add_policy.js"></script>
<script type="text/javascript">
</script>
{/block}
@@ -1,229 +0,0 @@
{extend name="header_admin" /}
{block name="title"}管理面板- {$options.siteName}{/block}
{block name="content"}
<div class="content-wrapper">
<div class="container-fluid">
<!-- Breadcrumbs-->
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="#">管理面板</a>
</li>
<li class="breadcrumb-item active">数据概况</li>
</ol>
<!-- Icon Cards-->
<div class="row">
<div class="col-xl-3 col-sm-6 mb-3">
<div class="card text-white bg-primary o-hidden h-100">
<div class="card-body">
<div class="card-body-icon">
<i class="fa fa-fw fa-users"></i>
</div>
<div class="mr-5">{$statics.userNum} 位用户</div>
</div>
<a class="card-footer text-white clearfix small z-1" href="/Admin/Users">
<span class="float-left">查看详情</span>
<span class="float-right">
<i class="fa fa-angle-right"></i>
</span>
</a>
</div>
</div>
<div class="col-xl-3 col-sm-6 mb-3">
<div class="card text-white bg-warning o-hidden h-100">
<div class="card-body">
<div class="card-body-icon">
<i class="fa fa-fw fa-file"></i>
</div>
<div class="mr-5">{$statics.fileNum} 个文件</div>
</div>
<a class="card-footer text-white clearfix small z-1" href="/Admin/Files">
<span class="float-left">查看详情</span>
<span class="float-right">
<i class="fa fa-angle-right"></i>
</span>
</a>
</div>
</div>
<div class="col-xl-3 col-sm-6 mb-3">
<div class="card text-white bg-success o-hidden h-100">
<div class="card-body">
<div class="card-body-icon">
<i class="fa fa-fw fa-share-alt"></i>
</div>
<div class="mr-5">{$statics.publicShareNum} 个公开分享</div>
</div>
<a class="card-footer text-white clearfix small z-1" href="/Admin/Shares">
<span class="float-left">查看详情</span>
<span class="float-right">
<i class="fa fa-angle-right"></i>
</span>
</a>
</div>
</div>
<div class="col-xl-3 col-sm-6 mb-3">
<div class="card text-white bg-danger o-hidden h-100">
<div class="card-body">
<div class="card-body-icon">
<i class="fa fa-fw fa-lock"></i>
</div>
<div class="mr-5">{$statics.privateShareNum} 个私密分享</div>
</div>
<a class="card-footer text-white clearfix small z-1" href="/Admin/Shares">
<span class="float-left">查看详情</span>
<span class="float-right">
<i class="fa fa-angle-right"></i>
</span>
</a>
</div>
</div>
</div>
<!-- Area Chart Example-->
<div class="card mb-3">
<div class="card-header">
<i class="fa fa-area-chart"></i> 近期趋势</div>
<div class="card-body">
<canvas id="myAreaChart" width="100%" height="30"></canvas>
</div>
</div>
<div class="row">
<div class="col-lg-8">
<!-- Example Bar Chart Card-->
<div class="card mb-3">
<div class="card-header">
<i class="fa fa-bell-o"></i> 订阅新闻</div>
<div class="list-group list-group-flush small" id="news">
</div>
</div>
<!-- Card Columns Example Social Feed-->
<!-- /Card Columns-->
</div>
<div class="col-lg-4">
<!-- Example Pie Chart Card-->
<div class="card mb-3">
<div class="card-header">
<i class="fa fa-pie-chart"></i> 文件组成</div>
<div class="card-body">
<canvas id="myPieChart" width="100%" height="80"></canvas>
</div>
<div class="card-footer small text-muted">*此结果仅供参考</div>
</div>
<!-- Example Notifications Card-->
</div>
</div>
<!-- Example DataTables Card-->
</div>
<!-- /.container-fluid-->
<!-- /.content-wrapper-->
<footer class="sticky-footer">
<div class="container">
<div class="text-center">
<small>Copyright © Cloudreve {php}echo date("Y");{/php} </small>
</div>
</div>
</footer>
<!-- Scroll to Top Button-->
<a class="scroll-to-top rounded" href="#page-top">
<i class="fa fa-angle-up"></i>
</a>
<!-- Logout Modal-->
<!-- Bootstrap core JavaScript-->
{/block}
{block name="js"}
<script type="text/javascript">
$(document).ready(function() {
$.getJSON("https://cloudreve.org/api/notice/?callback=?", function(data){
$("#news").html(data[0]);
})
})
Chart.defaults.global.defaultFontFamily = '-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif',
Chart.defaults.global.defaultFontColor = "#292b2c";
var ctx = document.getElementById("myAreaChart"),
myLineChart = new Chart(ctx, {
type: "line",
data: {
labels: [{$statics.trendDate}],
datasets: [{
label: "上传文件",
lineTension: .3,
backgroundColor: "rgba(2,117,216,0.2)",
borderColor: "rgba(2,117,216,1)",
pointRadius: 5,
pointBackgroundColor: "rgba(2,117,216,1)",
pointBorderColor: "rgba(255,255,255,0.8)",
pointHoverRadius: 5,
pointHoverBackgroundColor: "rgba(2,117,216,1)",
pointHitRadius: 20,
pointBorderWidth: 2,
data: [{$statics.trendFile}]
},{
label: "注册用户",
lineTension: .3,
backgroundColor: "rgba(83, 216, 2, 0.2)",
borderColor: "#4CAF50",
pointRadius: 5,
pointBackgroundColor: "#4CAF50",
pointBorderColor: "rgba(255,255,255,0.8)",
pointHoverRadius: 5,
pointHoverBackgroundColor: "#4CAF50",
pointHitRadius: 20,
pointBorderWidth: 2,
data: [{$statics.trendUser}]
},
]
},
options: {
scales: {
xAxes: [{
time: {
unit: "date"
},
gridLines: {
display: !1
},
ticks: {
maxTicksLimit: 7
}
}],
yAxes: [{
ticks: {
maxTicksLimit: 5
},
gridLines: {
color: "rgba(0, 0, 0, .125)"
}
}]
},
legend: {
display: !1
}
}
}),
ctx = document.getElementById("myPieChart"),
myPieChart = new Chart(ctx, {
type: "pie",
data: {
labels: ["其他", "图片", "音频", "视频"],
datasets: [{
data: [{$statics.otherRate}, {$statics.imgRate}, {$statics.audioRate}, {$statics.videoRate}],
backgroundColor: ["#007bff", "#dc3545", "#ffc107", "#28a745"]
}]
}
});
</script>
{/block}
@@ -1,83 +0,0 @@
{extend name="header_admin" /}
{block name="title"}基础设置- {$options.siteName}{/block}
{block name="content"}
<div class="content-wrapper">
<div class="container-fluid">
<!-- Breadcrumbs-->
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="/Admin">管理面板</a>
</li>
<li class="breadcrumb-item active">设置</li>
<li class="breadcrumb-item active">基础设置</li>
</ol>
<!-- Area Chart Example-->
<div class="row">
<div class="col-12">
<h2>基础设置</h2>
<br>
<form id="basicOptionsForm">
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="colFormLabelSm" class="col-form-label col-form-label-sm">站点主标题</label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="siteName" value="{$options.siteName}"></div>
<div class="col-md-4 option-des"> 站点的主标题,将会展示在个页面的标题尾部、邮件中。</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="colFormLabelSm" class="col-form-label col-form-label-sm">站点副标题</label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="siteTitle" value="{$options.siteTitle}"></div>
<div class="col-md-4 option-des"> 只会展示在首页的副标题。</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="colFormLabelSm" class="col-form-label col-form-label-sm">站点URL</label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="siteURL" value="{$options.siteURL}" spellcheck="false"></div>
<div class="col-md-4 option-des"> 站点的URL,此设置很重要,请如实填写,否则会影响系统正常工作.</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="colFormLabelSm" class="col-form-label col-form-label-sm">站点关键词</label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="siteKeywords" value="{$options.siteKeywords}"></div>
<div class="col-md-4 option-des"> 位于首页meta标签内的站点关键词</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="colFormLabelSm" class="col-form-label col-form-label-sm">站点描述</label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="siteDes" value="{$options.siteDes}"></div>
<div class="col-md-4 option-des"> 位于首页meta标签内的站点描述</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="colFormLabelSm" class="col-form-label col-form-label-sm">页脚代码</label>
</div>
<div class="col-md-4"> <textarea class="form-control" name="js_code" rows="4" spellcheck="false">{$options.js_code}</textarea></div>
<div class="col-md-4 option-des"> 位于前台页面底部的页脚代码,你可以在此放置统计代码。</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
</div>
<div class="col-md-4"> <button type="button" class="btn btn-primary" id="saveBasic">保存设置</button></div>
<div class="col-md-4 option-des"> </div>
<br> <br>
</div>
</form>
</div>
</div>
<!-- Example DataTables Card-->
</div>
<!-- /.container-fluid-->
</div>
{/block}
{block name="js"}
<script src="/static/js/admin/setting.js"></script>
<script type="text/javascript">
</script>
{/block}
@@ -1,51 +0,0 @@
{extend name="header_admin" /}
{block name="title"}基础设置- {$options.siteName}{/block}
{block name="content"}
<div class="content-wrapper">
<div class="container-fluid">
<!-- Breadcrumbs-->
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="/Admin">管理面板</a>
</li>
<li class="breadcrumb-item active">设置</li>
<li class="breadcrumb-item active">配置文件</li>
</ol>
<!-- Area Chart Example-->
<div class="row">
<div class="col-12">
<h2>配置文件</h2>
{$path}
<br> <br>
<div class="row">
<div class="col-md-9">
<input type="text" id="configType" value="{$type}" style="display: none">
<textarea rows="15" class="form-control" spellcheck="false">{$content}</textarea>
<br>
<button class="btn btn-primary" id="save">保存</button>
<br><br>
</div>
<div class="col-md-3">
<div class="nav flex-column nav-pills" id="v-pills-tab" role="tablist" aria-orientation="vertical">
<a class="nav-link" id="v-pills-home-tab" href="/Admin/Config/type/common" role="tab" data-type="common">系统公共配置</a>
<a class="nav-link" id="v-pills-profile-tab" href="/Admin/Config/type/database" role="tab" data-type="database">数据库</a>
<a class="nav-link" id="v-pills-messages-tab" href="/Admin/Config/type/route" role="tab" data-type="route">路由</a>
<a class="nav-link" id="v-pills-settings-tab" href="/Admin/Config/type/tags" role="tab" data-type="tags">行为扩展</a>
</div>
</div>
</div>
</div>
</div>
<!-- Example DataTables Card-->
</div>
<!-- /.container-fluid-->
</div>
{/block}
{block name="js"}
<script src="/static/js/admin/config.js"></script>
<script type="text/javascript">
</script>
{/block}
@@ -1,84 +0,0 @@
{extend name="header_admin" /}
{block name="title"}基础设置- {$options.siteName}{/block}
{block name="content"}
<div class="content-wrapper">
<div class="container-fluid">
<!-- Breadcrumbs-->
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="/Admin">管理面板</a>
</li>
<li class="breadcrumb-item active">其他</li>
<li class="breadcrumb-item active">定时任务</li>
</ol>
<!-- Area Chart Example-->
<div class="row">
<div class="col-12">
<h2>定时任务</h2>
<br>
{eq name="neverExcute" value="true"}
<div class="alert alert-warning" role="alert">
定时任务从未执行!请将 {$options.siteURL}Cron 加入到您的定时任务列队中(如Crontab)。
</div>
{/eq}
{volist name="cron" id="c"}
<div class="card">
<div class="card-header">
{$c.name}
</div>
<div class="card-body">
<blockquote class="blockquote mb-0">
<p>{$c.des}</p>
</blockquote><form id="cronForm" method="post" action="/Admin/SaveCron">
<div class="row">
<input type="text" name="id" value="{$c.id}" style="display: none;">
<div class="col-md-4">
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="basic-addon1">优先级</span>
</div>
<input type="number" min="0" class="form-control" name="rank" placeholder="值越高越优先" value="{$c.rank}">
</div>
</div>
<div class="col-md-4">
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="basic-addon1">执行间隔(s)</span>
</div>
<input type="number" min="1" class="form-control" name="interval_s" value="{$c.interval_s}">
</div>
</div>
<div class="col-md-4">
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="basic-addon1">启用</span>
</div>
<input type="number" min="0" max="1" class="form-control" name="enable" value="{$c.enable}">
</div>
</div>
</div>
<input type="submit" class="btn btn-primary" value="保存">
</form>
</div>
<div class="card-footer text-muted">
上次执行:{eq name="c.last_excute" value="0"}从未执行{else/}{:date("Y-m-d H:i:s",$c.last_excute)}{/eq}
</div>
</div><br>
{/volist}
</div>
</div>
<!-- Example DataTables Card-->
</div>
<!-- /.container-fluid-->
</div>
{/block}
{block name="js"}
<script type="text/javascript">
</script>
{/block}
@@ -1,171 +0,0 @@
{extend name="header_admin" /}
{block name="title"}注册访问- {$options.siteName}{/block}
{block name="content"}
<div class="content-wrapper">
<div class="container-fluid">
<!-- Breadcrumbs-->
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="/Admin">管理面板</a>
</li>
<li class="breadcrumb-item active">用户组</li>
<li class="breadcrumb-item active">编辑用户组</li>
</ol>
<!-- Area Chart Example-->
<div class="row">
<div class="col-12">
<h2>编辑用户组</h2>
<br>
<form id="editGroup">
<div class="row form-setting">
<div class="col-md-1 form-label ">
<input type="text" name="id" value="{$group.id}" style="display: none">
<label for="colFormLabelSm" class="col-form-label col-form-label-sm">用户组名</label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="group_name" value="{$group.group_name}" required></div>
<div class="col-md-4 option-des"> 用户组的名称</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="colFormLabelSm" class="col-form-label col-form-label-sm">上传策略</label>
</div>
<div class="col-md-4">
<select name="policy_name" required class="form-control" >
{volist name="policy" id="p"}
<option value="{$p.id}">{$p.policy_name}</option>
{/volist}
</select>
</div>
<div class="col-md-4 option-des"> 为该用户组绑定一个上传策略</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="colFormLabelSm" class="col-form-label col-form-label-sm">初始容量</label>
</div>
<div class="col-md-4 input-group mb-3">
<input type="number" class="form-control" name="max_storage" spellcheck="false" min="0" value="{:countSize($group.max_storage,true)[0]}" required>
<div class="input-group-append">
<span class="input-group-text" id="basic-addon2">
<select name="sizeTimes" class="selectIn" data-value="{:countSize($group.max_storage,true)[1]}">
<option value="1">B</option>
<option value="1024">KB</option>
<option value="1048576" selected>MB</option>
<option value="1073741824">GB</option>
</select>
</span>
</div>
</div>
<div class="col-md-4 option-des"> 该用户组初始最大可用容量</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="colFormLabelSm" class="col-form-label col-form-label-sm">下载限速</label>
</div>
<div class="col-md-4 input-group mb-3">
<input type="number" class="form-control" name="speed" spellcheck="false" min="0" placeholder="留空表示不限速,0表示禁止下载" value="{$group.speed}">
<div class="input-group-append">
<span class="input-group-text" id="basic-addon2">
Kb/s
</span>
</div>
</div>
<div class="col-md-4 option-des"> 限制该用户组下的用户上传的文件的下载速度,<strong>此设置仅对本地上传方案有效</strong></div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="colFormLabelSm" class="col-form-label col-form-label-sm">断点续传及多线程下载</label>
</div>
<div class="col-md-4"> <input class="" type="radio" name="range_transfer" value="1" id="allow_range_1">
<label class="" for="allow_range_1" >允许</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="range_transfer" id="allow_range_0" value="0" >
<label class="" for="allow_range_0">禁止</label></div>
<div class="col-md-4 option-des"> 是否断点续传及多线程下载,关闭后预览视频不支持拖拽播放,<strong>此设置仅对本地上传方案有效</strong></div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="colFormLabelSm" class="col-form-label col-form-label-sm">创建分享</label>
</div>
<div class="col-md-4"> <input class="" type="radio" name="allow_share" value="1" id="allow_share_1" checked>
<label class="" for="allow_share_1" >允许</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="allow_share" id="allow_share_0" value="0" >
<label class="" for="allow_share_0">禁止</label></div>
<div class="col-md-4 option-des"> 是否允许创建文件分享链接</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="colFormLabelSm" class="col-form-label col-form-label-sm">WebDAV支持</label>
</div>
<div class="col-md-4"> <input class="" type="radio" name="webdav" value="1" id="webdav1" checked>
<label class="" for="webdav1" >允许</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="webdav" id="webdav0" value="0" >
<label class="" for="webdav0">禁止</label></div>
<div class="col-md-4 option-des"> 是否允许用户使用WebDAV协议同步文件。目前此功能仅支持本地上传方案</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="colFormLabelSm" class="col-form-label col-form-label-sm">用户组标志色</label>
</div>
<div class="col-md-4">
<input class="" type="radio" name="color" value="default" id="default" checked>
<label class="" for="default" ><span class="badge badge-primary">蓝色</span></label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="color" value="primary" id="primary">
<label class="" for="primary" ><span class="badge badge-secondary">灰色</span></label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="color" value="success" id="success">
<label class="" for="success" ><span class="badge badge-success">绿色</span></label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="color" value="danger" id="danger">
<label class="" for="danger" ><span class="badge badge-danger">红色</span></label>
<br>
<input class="" type="radio" name="color" value="warning" id="warning">
<label class="" for="warning" ><span class="badge badge-warning">黄色</span></label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="color" value="info" id="info">
<label class="" for="info" ><span class="badge badge-info">浅蓝色</span></label>
&nbsp;&nbsp;&nbsp;
</div>
<div class="col-md-4 option-des"> 用户个人主页展示用户组时的徽章颜色</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
</div>
<div class="col-md-4"> <button type="submit" class="btn btn-primary" id="saveGroup">保存</button></div>
<div class="col-md-4 option-des"> </div>
<br><br><br>
</div>
</form>
</div>
</div>
<!-- Example DataTables Card-->
</div>
<!-- /.container-fluid-->
</div>
<!-- /.content-wrapper-->
{/block}
{block name="js"}
<script src="/static/js/admin/add_group.js"></script>
<script type="text/javascript">
$("option[value='{$group.policy_name}']").attr("selected",true);
$("option[value='{$group.max_storage}']").attr("selected",true);
$("input[name='range_transfer'][value='{$group.range_transfer}']").attr("checked",true);
$("input[name='allow_share'][value='{$group.allow_share}']").attr("checked",true);
$("input[name='color'][value='{$group.color}']").attr("checked",true);
$("input[name='webdav'][value='{$group.webdav}']").attr("checked",true);
</script>
{/block}
File diff suppressed because it is too large Load Diff
-194
View File
@@ -1,194 +0,0 @@
{extend name="header_admin" /}
{block name="title"}文件列表- {$options.siteName}{/block}
{block name="content"}
<div class="content-wrapper">
<div class="container-fluid">
<!-- Breadcrumbs-->
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="/Admin">管理面板</a>
</li>
<li class="breadcrumb-item active">文件</li>
</ol>
<div class="row">
<div class="col-12">
<h2>文件</h2>
<br>
<div class="card mb-3">
<div class="card-header">
<i class="fa fa-tags"></i> 条件检索</div>
<div class="card-body">
<div class="row">
<div class="col-1 form-label-search mb-2">排序方式</div>
<div class="col-md-10">
<ul class="nav nav-pills" id="order">
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-method="id DESC">日期</a>
</li>
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-method="orign_name ASC">文件名</a>
</li>
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-method="size DESC">大小</a>
</li>
</ul>
</div>
</div>
<div class="row">
<div class="col-1 form-label-search mb-2">上传策略</div>
<div class="col-md-10">
<ul class="nav nav-pills" id="policy_select">
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-policy="">全部</a>
</li>
{volist name="policy" id="policy"}
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-policy="{$policy.id}">{$policy.policy_name}</a>
</li>
{/volist}
</ul>
</div>
</div>
<div class="row" style="margin-top: 5px;">
<div class="col-1 form-label-search mb-2">高级检索</div>
<div class="col-md-10">
<div class="row">
<div class="col-md-2">
<select class="form-control form-control-sm" id="searchCol">
<option value="id" selected>ID</option>
<option value="orign_name">文件名</option>
<option value="pre_name">实际文件名</option>
<option value="upload_user">上传者UID</option>
<option value="upload_date">上传日期</option>
<option value="pic_info">图像尺寸</option>
<option value="parent_folder">所属目录ID</option>
<option value="policy_id">上传策略ID</option>
<option value="dir">目录路径</option>
</select>
</div>
<div class="col-md-2">
<input type="text" class="form-control form-control-sm" placeholder="检索表达式" id="searchValue">
</div>
<div class="col-md-1">
<button type="button" class="btn btn-primary btn-sm" id="applySearch">应用</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="card mb-3">
<div class="card-header">
<i class="fa fa-table"></i> 文件列表</div>
<div class="card-body">
<div class="table-responsive">
<div id="dataTable_wrapper" class="dataTables_wrapper container-fluid dt-bootstrap4"><div class="row"><div class="col-sm-12 col-md-6"><div class="dataTables_length" ><label>每页展示 <select id="dataTable_length" aria-controls="dataTable" class="form-control form-control-sm"><option value="10">10</option><option value="25">25</option><option value="50">50</option><option value="100">100</option></select></label></div></div><div class="col-sm-12 col-md-6"><div id="dataTable_filter" class="dataTables_filter"><label>搜索:<input type="search" class="form-control form-control-sm" placeholder="" id="searchFrom"></label></div></div></div><div class="row"><div class="col-sm-12">
<div class="table-responsive">
<table class="table table-bordered dataTable" id="dataTable" width="100%" cellspacing="0" role="grid" aria-describedby="dataTable_info" style="width: 100%;">
<thead>
<tr role="row" class="textCenter"><th><input type="checkbox" data-type="all"></th><th>文件名</th><th class="textCenter">大小</th><th class="textCenter">上传者</th><th class="textCenter">日期</th><th class="textCenter">操作</th></tr>
</thead>
<tfoot>
<tr><th rowspan="1" colspan="1" class="textCenter"><input type="checkbox" data-type="all"></th><th rowspan="1" colspan="1">文件名</th><th rowspan="1" colspan="1" class="textCenter">大小</th><th rowspan="1" colspan="1" class="textCenter">上传者</th><th rowspan="1" colspan="1" class="textCenter">日期</th><th rowspan="1" colspan="1" class="textCenter">操作</th></tr>
</tfoot>
<tbody>
<tr role="row" class="odd" id="fileList">
{volist name='list' id='file'}
<tr role="row" class="odd">
<td class="sorting_1 textCenter"><input type="checkbox" data-type="mark" data-path="{:rtrim($file.dir,'/')}/{$file.orign_name}" data-uid="{$file.upload_user}"></td>
<td>
{eq name=":isPreview($file.orign_name)" value="yes"}
<a href="/Admin/Preview/id/{$file.id}" class="noAColor" target="_blank">{$file.orign_name|htmlspecialchars=ENT_NOQUOTES}</a>
{else}
<a href="/Admin/Download/id/{$file.id}" class="noAColor" target="_blank">{$file.orign_name|htmlspecialchars=ENT_NOQUOTES}</a>
{/eq}
</td>
<td class="textCenter">{:countSize($file.size)}</td>
<td class="textCenter">{$originList[$key]["user"]["user_nick"]}</td>
<td class="textCenter">{$file.upload_date}</td>
<td class="textCenter"><button type="button" class="btn btn-secondary fix" data-toggle="tooltip" data-placement="top" title="删除" data-action="delete" data-id="{$file.id}"><i class="fa fa-trash" aria-hidden="true"></i></button>
<button type="button" class="btn btn-secondary fix" data-toggle="tooltip" data-placement="top" title="下载" data-action="download" data-id="{$file.id}"><i class="fa fa-download" aria-hidden="true"></i></button>
<button type="button" class="btn btn-secondary fix" data-toggle="tooltip" data-placement="top" title="详情" data-action="info" data-id="{$file.id}"><i class="fa fa-info-circle" aria-hidden="true"></i></button>
</td>
</tr>
{/volist}
</tbody>
</table>
</div>
<div class="col-md-5 mb-2 mt-2" style="display: none" id="del">
<button type="button" class="btn btn-danger" id="delAll"><i class="fa fa-trash" aria-hidden="true"></i> 删除选中文件</button>
</div>
</div></div><div class="row"><div class="col-sm-12 col-md-5"><div class="dataTables_info" id="dataTable_info" role="status" aria-live="polite">展示第 {$pageNow} 页,共 {$pageTotal} 页 {$dataTotal} 条数据</div></div><div class="col-sm-12 col-md-7">
<div class="dataTables_paginate paging_simple_numbers" id="dataTable_paginate">
{$list->render()}
</div></div></div></div>
</div>
</div>
</div>
</div>
</div>
<!-- Example DataTables Card-->
</div>
<!-- /.container-fluid-->
</div>
<div class="modal fade bd-example-modal-sm" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true" id="fileInfo">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">文件详情</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="row">
<div class="col-md-12"><strong>ID:</strong></div>
<div class="col-md-12 break" id="fileId">12</div>
</div>
<div class="row">
<div class="col-md-12"><strong>文件名:</strong></div>
<div class="col-md-12 break" id="fileName">5c06e532e7afdb4389e4ae846ea7876c_w - 副本 - 副本.jpg</div>
</div>
<div class="row">
<div class="col-md-12"><strong>源文件名:</strong></div>
<div class="col-md-12 break" id="fileOrigin">5c06e532e7afdb4389e4ae846ea7876c_w - 副本 - 副本.jpg</div>
</div>
<div class="row">
<div class="col-md-12"><strong>上传者UID:</strong></div>
<div class="col-md-12 break" id="fileUID">17</div>
</div>
<div class="row">
<div class="col-md-12"><strong>大小(字节):</strong></div>
<div class="col-md-12 break" id="fileSize">7481817</div>
</div>
<div class="row">
<div class="col-md-12"><strong>图像尺寸:</strong></div>
<div class="col-md-12 break" id="filePic">147,445</div>
</div>
<div class="row">
<div class="col-md-12"><strong>上传策略:</strong></div>
<div class="col-md-12 break" id="filePolicy">147,445</div>
</div>
<div class="row">
<div class="col-md-12"><strong>所属目录:</strong></div>
<div class="col-md-12 break" id="fileDir">147,445</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
</div>
</div>
</div>
</div>
<!-- /.content-wrapper-->
{/block}
{block name="js"}
<script src="/static/js/admin/files.js"></script>
<script type="text/javascript">
</script>
{/block}
@@ -1,131 +0,0 @@
{extend name="header_admin" /}
{block name="title"}上传策略- {$options.siteName}{/block}
{block name="content"}
<div class="content-wrapper">
<div class="container-fluid">
<!-- Breadcrumbs-->
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="/Admin">管理面板</a>
</li>
<li class="breadcrumb-item active">用户组</li>
</ol>
<!-- Area Chart Example-->
<div class="row">
<div class="col-12">
<h2>用户组</h2>
<br>
<div class="card mb-3">
<div class="card-header">
<i class="fa fa-table"></i> 用户组列表</div>
<div class="card-body">
<div class="table-responsive">
<div id="dataTable_wrapper" class="dataTables_wrapper container-fluid dt-bootstrap4"><div class="row"><div class="col-sm-12 col-md-6"><div class="dataTables_length" ><label>每页展示 <select id="dataTable_length" aria-controls="dataTable" class="form-control form-control-sm"><option value="10">10</option><option value="25">25</option><option value="50">50</option><option value="100">100</option></select></label></div></div></div><div class="row"><div class="col-sm-12">
<div class="table-responsive">
<table class="table table-bordered dataTable" id="dataTable" width="100%" cellspacing="0" role="grid" aria-describedby="dataTable_info" style="width: 100%;">
<thead>
<tr role="row" class="textCenter"><th>#</th><th>名称</th><th class="textCenter">上传策略</th><th class="textCenter">最大容量</th><th class="textCenter">下属用户数</th><th class="textCenter">操作</th></tr>
</thead>
<tfoot>
<tr><th rowspan="1" colspan="1" class="textCenter">#</th><th rowspan="1" colspan="1">名称</th><th rowspan="1" colspan="1" class="textCenter">上传策略</th><th rowspan="1" colspan="1" class="textCenter">最大容量</th><th rowspan="1" colspan="1" class="textCenter">下属用户数</th><th rowspan="1" colspan="1" class="textCenter">操作</th></tr>
</tfoot>
<tbody>
<tr role="row" class="odd" id="fileList">
{volist name='list' id='group'}
<tr role="row" class="odd">
<td class="sorting_1 textCenter">{$group.id}</td>
<td>
{$group.group_name}
</td>
<td class="textCenter">
{$originList[$key]["policy"]["policy_name"]}
</td>
<td class="textCenter">{:countSize($group["max_storage"])}</td>
<td class="textCenter">{$originList[$key]["user_num"]}</td>
<td class="textCenter"><button type="button" class="btn btn-secondary fix" data-toggle="tooltip" data-placement="top" title="删除" data-action="delete" data-id="{$group.id}" data-unable="{eq name="$originList[$key]['user_num']" value="0"}0{else}1{/eq}"><i class="fa fa-trash" aria-hidden="true"></i></button>
<button type="button" class="btn btn-secondary fix" data-toggle="tooltip" data-placement="top" title="编辑" data-action="edit" data-id="{$group.id}"><i class="fa fa-edit" aria-hidden="true"></i></button>
</td>
</tr>
{/volist}
</tbody>
</table>
</div>
<div class="col-md-5 mb-2 mt-2" style="display: none" id="del">
<button type="button" class="btn btn-danger" id="delAll"><i class="fa fa-trash" aria-hidden="true"></i> 删除选中文件</button>
</div>
</div></div><div class="row"><div class="col-sm-12 col-md-5"><div class="dataTables_info" id="dataTable_info" role="status" aria-live="polite">展示第 {$pageNow} 页,共 {$pageTotal} 页 {$dataTotal} 条数据</div></div><div class="col-sm-12 col-md-7">
<div class="dataTables_paginate paging_simple_numbers" id="dataTable_paginate">
{$list->render()}
</div></div></div></div>
</div>
</div>
</div>
</div>
</div>
<!-- Example DataTables Card-->
</div>
<!-- /.container-fluid-->
</div>
<div class="modal fade bd-example-modal-sm" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true" id="fileInfo">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">文件详情</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="row">
<div class="col-md-12"><strong>ID:</strong></div>
<div class="col-md-12 break" id="fileId">12</div>
</div>
<div class="row">
<div class="col-md-12"><strong>文件名:</strong></div>
<div class="col-md-12 break" id="fileName">5c06e532e7afdb4389e4ae846ea7876c_w - 副本 - 副本.jpg</div>
</div>
<div class="row">
<div class="col-md-12"><strong>源文件名:</strong></div>
<div class="col-md-12 break" id="fileOrigin">5c06e532e7afdb4389e4ae846ea7876c_w - 副本 - 副本.jpg</div>
</div>
<div class="row">
<div class="col-md-12"><strong>上传者UID:</strong></div>
<div class="col-md-12 break" id="fileUID">17</div>
</div>
<div class="row">
<div class="col-md-12"><strong>大小(字节):</strong></div>
<div class="col-md-12 break" id="fileSize">7481817</div>
</div>
<div class="row">
<div class="col-md-12"><strong>图像尺寸:</strong></div>
<div class="col-md-12 break" id="filePic">147,445</div>
</div>
<div class="row">
<div class="col-md-12"><strong>上传策略:</strong></div>
<div class="col-md-12 break" id="filePolicy">147,445</div>
</div>
<div class="row">
<div class="col-md-12"><strong>所属目录:</strong></div>
<div class="col-md-12 break" id="fileDir">147,445</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
</div>
</div>
</div>
</div>
<!-- /.content-wrapper-->
{/block}
{block name="js"}
<script src="/static/js/admin/group_list.js"></script>
<script type="text/javascript">
</script>
{/block}
@@ -1,206 +0,0 @@
{extend name="header_admin" /}
{block name="title"}邮件收发- {$options.siteName}{/block}
{block name="content"}
<link href="/static/css/admin/summernote.css" rel="stylesheet">
<div class="content-wrapper">
<div class="container-fluid">
<!-- Breadcrumbs-->
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="/Admin">管理面板</a>
</li>
<li class="breadcrumb-item active">设置</li>
<li class="breadcrumb-item active">邮件设置</li>
</ol>
<!-- Area Chart Example-->
<div class="row">
<div class="col-12">
<h2>邮件收发</h2>
<br>
<ul class="nav nav-pills mb-3" id="pills-tab" role="tablist">
<li class="nav-item">
<a class="nav-link active" id="pills-home-tab" data-toggle="pill" href="#basic" role="tab" aria-controls="pills-home" aria-selected="true">基本设置</a>
</li>
<li class="nav-item">
<a class="nav-link" id="pills-profile-tab" data-toggle="pill" href="#test" role="tab" aria-controls="pills-profile" aria-selected="false">发信测试</a>
</li>
<li class="nav-item">
<a class="nav-link" id="pills-contact-tab" data-toggle="pill" href="#template" role="tab" aria-controls="pills-contact" aria-selected="false">邮件模板</a>
</li>
</ul>
<div class="tab-content" >
<div class="tab-pane fade show active" id="basic" role="tabpanel" aria-labelledby="pills-home-tab">
<form id="basicOptionsForm">
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="fromName" class="col-form-label col-form-label-sm">发件人姓名</label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="fromName" value="{$optionsForSet.fromName}" spellcheck="false"></div>
<div class="col-md-4 option-des"> 显示在邮件发件邮箱旁的发件人姓名</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="fromAdress" class="col-form-label col-form-label-sm">发件人邮箱</label>
</div>
<div class="col-md-4"> <input type="email" class="form-control" name="fromAdress" value="{$optionsForSet.fromAdress}" spellcheck="false"></div>
<div class="col-md-4 option-des"> 发件邮箱的地址</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="smtpHost" class="col-form-label col-form-label-sm">SMTP服务器</label>
</div>
<div class="col-md-4"> <input type="email" class="form-control" name="smtpHost" value="{$optionsForSet.smtpHost}" spellcheck="false"></div>
<div class="col-md-4 option-des"> 发信邮箱的SMTP服务器地址</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="smtpPort" class="col-form-label col-form-label-sm">端口</label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="smtpPort" value="{$optionsForSet.smtpPort}" spellcheck="false"></div>
<div class="col-md-4 option-des"> 发信邮箱SMTP服务器的端口</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="smtpPort" class="col-form-label col-form-label-sm">加密方式</label>
</div>
<div class="col-md-4">
<select class="form-control" name="encriptionType">
<option value="no" {eq name="$optionsForSet.encriptionType" value="no"}selected{/eq}>不启用</option>
<option value="tls" {eq name="$optionsForSet.encriptionType" value="tls"}selected{/eq}>TLS</option>
<option value="ssl" {eq name="$optionsForSet.encriptionType" value="ssl"}selected{/eq}>SSL</option>
</select>
</div>
<div class="col-md-4 option-des"> </div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="smtpUser" class="col-form-label col-form-label-sm">用户名</label>
</div>
<div class="col-md-4"> <input type="email" class="form-control" name="smtpUser" value="{$optionsForSet.smtpUser}" spellcheck="false"></div>
<div class="col-md-4 option-des"> 发信邮箱用户名,一般与邮箱相同</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="smtpPass" class="col-form-label col-form-label-sm">密码</label>
</div>
<div class="col-md-4"> <input type="password" class="form-control" name="smtpPass" value="{$optionsForSet.smtpPass}" spellcheck="false"></div>
<div class="col-md-4 option-des"> 发信邮箱密码</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="replyTo" class="col-form-label col-form-label-sm">回信邮箱</label>
</div>
<div class="col-md-4"> <input type="email" class="form-control" name="replyTo" value="{$optionsForSet.replyTo}" spellcheck="false"></div>
<div class="col-md-4 option-des"> 用户回复系统发送的邮件时,用于接收回信的邮箱</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
</div>
<div class="col-md-4"> <button type="button" class="btn btn-primary" id="saveMail">保存设置</button></div>
<div class="col-md-4 option-des"> </div>
<br><br><br>
</div>
</form>
</div>
<div class="tab-pane fade" id="test" role="tabpanel" aria-labelledby="pills-profile-tab">
<form id="testMail">
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="fromName" class="col-form-label col-form-label-sm">收件人邮箱</label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="receiveMail" spellcheck="false"></div>
<div class="col-md-4 option-des"> 接受测试邮件的收件人邮箱</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="fromName" class="col-form-label col-form-label-sm">主题</label>
</div>
<div class="col-md-4"> <input type="text" class="form-control" name="subject" spellcheck="false" value="这是一封测试邮件"></div>
<div class="col-md-4 option-des"> 测试邮件的主题</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="fromName" class="col-form-label col-form-label-sm">正文</label>
</div>
<div class="col-md-8"> <textarea class="form-control" name="content" spellcheck="false" id="content" > 这是一封由Cloudreve发出的测试邮件,用于测试邮件设置是否正常工作。</textarea></div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
</div>
<div class="col-md-4"> <button type="button" class="btn btn-primary" id="sendMail">发送测试邮件</button></div>
<div class="col-md-4 option-des"> </div>
<br><br><br>
</div>
</form>
</div>
<div class="tab-pane fade" id="template" role="tabpanel" aria-labelledby="pills-profile-tab">
<form id="mailTemplate">
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="fromName" class="col-form-label col-form-label-sm">账户激活</label>
</div>
<div class="col-md-8"> <textarea class="form-control textEdit" name="mail_activation_template" spellcheck="false" > {$optionsForSet.mail_activation_template}</textarea>
</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="fromName" class="col-form-label col-form-label-sm">重设密码</label>
</div>
<div class="col-md-8"> <textarea class="form-control textEdit" name="mail_reset_pwd_template" spellcheck="false" > {$optionsForSet.mail_reset_pwd_template}</textarea>
</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
</div>
<div class="col-md-4"> <button type="button" class="btn btn-primary" id="saveTemplate">保存设置</button></div>
<div class="col-md-4 option-des"> </div>
<br><br><br>
</div>
</form>
</div>
</div>
</div>
</div>
<!-- Example DataTables Card-->
</div>
<!-- /.container-fluid-->
</div>
{/block}
{block name="js"}
<script src="/static/js/admin/summernote.min.js"></script>
<script src="/static/js/admin/summernote-zh-CN.min.js"></script>
<script src="/static/js/admin/setting.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$('#content').summernote({
lang:"zh-CN",
height: 150,
});
});
$(document).ready(function() {
$('.textEdit').summernote({
lang:"zh-CN",
height: 300,
});
});
</script>
{/block}
@@ -1,127 +0,0 @@
{extend name="header_admin" /}
{block name="title"}注册访问- {$options.siteName}{/block}
{block name="content"}
<div class="content-wrapper">
<div class="container-fluid">
<!-- Breadcrumbs-->
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="/Admin">管理面板</a>
</li>
<li class="breadcrumb-item active">设置</li>
<li class="breadcrumb-item active">杂项</li>
</ol>
<!-- Area Chart Example-->
<div class="row">
<div class="col-12">
<h2>杂项设置</h2>
<br>
<form id="mailTemplate">
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="maxEditSize" class="col-form-label col-form-label-sm">文本编辑大小限制</label>
</div>
<div class="col-md-4"> <input type="email" class="form-control" name="maxEditSize" value="{$optionsForSet.maxEditSize}" spellcheck="false"></div>
<div class="col-md-4 option-des"> 用户可在线编辑的文本类文件的最大尺寸。单位:字节</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="maxEditSize" class="col-form-label col-form-label-sm">允许游客下载</label>
</div>
<div class="col-md-4">
{eq name="$optionsForSet.allowdVisitorDownload" value="true"}
<input class="" type="radio" name="allowdVisitorDownload" id="inlineRadio1" value="true" checked>
<label class="" for="inlineRadio1" >允许</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="allowdVisitorDownload" id="inlineRadio2" value="false">
<label class="" for="inlineRadio2">拒绝</label>
{else}
<input class="" type="radio" name="allowdVisitorDownload" id="inlineRadio1" value="true">
<label class="" for="inlineRadio1" >允许</label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="allowdVisitorDownload" id="inlineRadio2" value="false" checked>
<label class="" for="inlineRadio2">拒绝</label>
{/eq}
</div>
<div class="col-md-4 option-des"> 是否允许未登录用户下载被分享的文件</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="hot_share_num" class="col-form-label col-form-label-sm">热门分享展示数量</label>
</div>
<div class="col-md-4"> <input type="email" class="form-control" name="hot_share_num" value="{$optionsForSet.hot_share_num}" spellcheck="false"></div>
<div class="col-md-4 option-des"> 在用户个人主页展示的热门分享的个数</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="gravatar_server" class="col-form-label col-form-label-sm">Gravatar服务器</label>
</div>
<div class="col-md-4"> <input type="email" class="form-control" name="gravatar_server" value="{$optionsForSet.gravatar_server}" spellcheck="false"></div>
<div class="col-md-4 option-des"> 用于展示用户头像的Gravatar服务器地址</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="gravatar_server" class="col-form-label col-form-label-sm">文件数据发送模式</label>
</div>
<div class="col-md-4">
<select class="form-control" name="sendfile">
<option value="0">传统</option>
<option value="1" {eq name="optionsForSet.sendfile" value="1"}selected{/eq}>X-Sendfile</option>
</select>
</div>
<div class="col-md-4 option-des"> 推荐使用X-Sendfile以获得高效的文件传输,启用前请确保服务器安装X-Sendfile模块并在站点配置文件中启用。</div>
</div>
<div class="row form-setting" style="{eq name="optionsForSet.sendfile" value="0"}display:none{/eq}" id="sendfile_header">
<div class="col-md-1 form-label ">
<label for="gravatar_server" class="col-form-label col-form-label-sm">Sendfile Header</label>
</div>
<div class="col-md-4">
<select class="form-control" name="header">
<option value="X-Sendfile" {eq name="optionsForSet.header" value="X-Sendfile"}selected{/eq}>X-Sendfile [Apache,Lighttpd v1.5,Cherokee]</option>
<option value="X-LIGHTTPD-send-file" {eq name="optionsForSet.header" value="X-LIGHTTPD-send-file"}selected{/eq}>X-LIGHTTPD-send-file [Lighttpd v1.4]</option>
<option value="X-Accel-Redirect" {eq name="optionsForSet.header" value="X-Accel-Redirect"}selected{/eq}>X-Accel-Redirect [Nginx,Cherokee]</option>
</select>
</div>
<div class="col-md-4 option-des"> 请根据你所使用的服务器软件选择合适的header</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
</div>
<div class="col-md-4"> <button type="button" class="btn btn-primary" id="saveTemplate">保存设置</button></div>
<div class="col-md-4 option-des"> </div>
<br><br><br>
</div>
</form>
</div>
</div>
<!-- Example DataTables Card-->
</div>
<!-- /.container-fluid-->
</div>
<!-- /.content-wrapper-->
{/block}
{block name="js"}
<script src="/static/js/admin/setting.js"></script>
<script type="text/javascript">
</script>
{/block}
@@ -1,172 +0,0 @@
{extend name="header_admin" /}
{block name="title"}上传策略- {$options.siteName}{/block}
{block name="content"}
<div class="content-wrapper">
<div class="container-fluid">
<!-- Breadcrumbs-->
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="/Admin">管理面板</a>
</li>
<li class="breadcrumb-item active">上传策略</li>
</ol>
<!-- Area Chart Example-->
<div class="row">
<div class="col-12">
<h2>上传策略</h2>
<br>
<div class="card mb-3">
<div class="card-header">
<i class="fa fa-tags"></i> 条件检索</div>
<div class="card-body">
<div class="row">
<div class="col-1 form-label-search mb-2">类型</div>
<div class="col-md-10">
<ul class="nav nav-pills" id="policyType">
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-policy="">全部</a>
</li>
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-policy="local">本地</a>
</li>
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-policy="qiniu">七牛</a>
</li>
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-policy="oss">OSS</a>
</li>
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-policy="upyun">又拍云</a>
</li>
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-policy="s3">S3</a>
</li>
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-policy="remote">远程</a>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="card mb-3">
<div class="card-header">
<i class="fa fa-table"></i> 上传策略列表</div>
<div class="card-body">
<div class="table-responsive">
<div id="dataTable_wrapper" class="dataTables_wrapper container-fluid dt-bootstrap4"><div class="row"><div class="col-sm-12 col-md-6"><div class="dataTables_length" ><label>每页展示 <select id="dataTable_length" aria-controls="dataTable" class="form-control form-control-sm"><option value="10">10</option><option value="25">25</option><option value="50">50</option><option value="100">100</option></select></label></div></div><div class="col-sm-12 col-md-6"><div id="dataTable_filter" class="dataTables_filter"><label>搜索:<input type="search" class="form-control form-control-sm" placeholder="" id="searchFrom"></label></div></div></div><div class="row"><div class="col-sm-12">
<div class="table-responsive">
<table class="table table-bordered dataTable" id="dataTable" width="100%" cellspacing="0" role="grid" aria-describedby="dataTable_info" style="width: 100%;">
<thead>
<tr role="row" class="textCenter"><th>#</th><th>名称</th><th class="textCenter">类型</th><th class="textCenter">下属文件数</th><th class="textCenter">数据量</th><th class="textCenter">操作</th></tr>
</thead>
<tfoot>
<tr><th rowspan="1" colspan="1" class="textCenter">#</th><th rowspan="1" colspan="1">名称</th><th rowspan="1" colspan="1" class="textCenter">类型</th><th rowspan="1" colspan="1" class="textCenter">下属文件数</th><th rowspan="1" colspan="1" class="textCenter">数据量</th><th rowspan="1" colspan="1" class="textCenter">操作</th></tr>
</tfoot>
<tbody>
<tr role="row" class="odd" id="fileList">
{volist name='list' id='policy'}
<tr role="row" class="odd">
<td class="sorting_1 textCenter">{$policy.id}</td>
<td>
{$policy.policy_name}
</td>
<td class="textCenter">
{switch name="policy.policy_type"}
{case value="local"}本地{/case}
{case value="qiniu"}七牛{/case}
{case value="oss"}OSS{/case}
{case value="upyun"}又拍云{/case}
{case value="s3"}Amazon S3{/case}
{case value="remote"}远程{/case}
{default /}其他
{/switch}
</td>
<td class="textCenter">{$originList[$key]["file_num"]}</td>
<td class="textCenter">{:countSize($originList[$key]["file_size"])}</td>
<td class="textCenter"><button type="button" class="btn btn-secondary fix" data-toggle="tooltip" data-placement="top" title="删除" data-action="delete" data-id="{$policy.id}" data-unable="{eq name="$originList[$key]['file_num']" value="0"}0{else}1{/eq}"><i class="fa fa-trash" aria-hidden="true"></i></button>
<button type="button" class="btn btn-secondary fix" data-toggle="tooltip" data-placement="top" title="编辑" data-action="edit" data-id="{$policy.id}"><i class="fa fa-edit" aria-hidden="true"></i></button>
</td>
</tr>
{/volist}
</tbody>
</table>
</div>
<div class="col-md-5 mb-2 mt-2" style="display: none" id="del">
<button type="button" class="btn btn-danger" id="delAll"><i class="fa fa-trash" aria-hidden="true"></i> 删除选中文件</button>
</div>
</div></div><div class="row"><div class="col-sm-12 col-md-5"><div class="dataTables_info" id="dataTable_info" role="status" aria-live="polite">展示第 {$pageNow} 页,共 {$pageTotal} 页 {$dataTotal} 条数据</div></div><div class="col-sm-12 col-md-7">
<div class="dataTables_paginate paging_simple_numbers" id="dataTable_paginate">
{$list->render()}
</div></div></div></div>
</div>
</div>
</div>
</div>
</div>
<!-- Example DataTables Card-->
</div>
<!-- /.container-fluid-->
</div>
<div class="modal fade bd-example-modal-sm" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true" id="fileInfo">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">文件详情</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="row">
<div class="col-md-12"><strong>ID:</strong></div>
<div class="col-md-12 break" id="fileId">12</div>
</div>
<div class="row">
<div class="col-md-12"><strong>文件名:</strong></div>
<div class="col-md-12 break" id="fileName">5c06e532e7afdb4389e4ae846ea7876c_w - 副本 - 副本.jpg</div>
</div>
<div class="row">
<div class="col-md-12"><strong>源文件名:</strong></div>
<div class="col-md-12 break" id="fileOrigin">5c06e532e7afdb4389e4ae846ea7876c_w - 副本 - 副本.jpg</div>
</div>
<div class="row">
<div class="col-md-12"><strong>上传者UID:</strong></div>
<div class="col-md-12 break" id="fileUID">17</div>
</div>
<div class="row">
<div class="col-md-12"><strong>大小(字节):</strong></div>
<div class="col-md-12 break" id="fileSize">7481817</div>
</div>
<div class="row">
<div class="col-md-12"><strong>图像尺寸:</strong></div>
<div class="col-md-12 break" id="filePic">147,445</div>
</div>
<div class="row">
<div class="col-md-12"><strong>上传策略:</strong></div>
<div class="col-md-12 break" id="filePolicy">147,445</div>
</div>
<div class="row">
<div class="col-md-12"><strong>所属目录:</strong></div>
<div class="col-md-12 break" id="fileDir">147,445</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
</div>
</div>
</div>
</div>
<!-- /.content-wrapper-->
{/block}
{block name="js"}
<script src="/static/js/admin/policy.js"></script>
<script type="text/javascript">
</script>
{/block}
@@ -1,134 +0,0 @@
{extend name="header_admin" /}
{block name="title"}注册访问- {$options.siteName}{/block}
{block name="content"}
<div class="content-wrapper">
<div class="container-fluid">
<!-- Breadcrumbs-->
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="/Admin">管理面板</a>
</li>
<li class="breadcrumb-item active">设置</li>
<li class="breadcrumb-item active">注册访问</li>
</ol>
<!-- Area Chart Example-->
<div class="row">
<div class="col-12">
<h2>注册与访问</h2>
<br>
<form id="basicOptionsForm">
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="colFormLabelSm" class="col-form-label col-form-label-sm">允许注册</label>
</div>
<div class="col-md-4">
{eq name="$optionsForSet.regStatus" value="0"}
<input class="" type="radio" name="regStatus" id="inlineRadio1" value="0"checked>
<label class="" for="inlineRadio1" ></label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="regStatus" id="inlineRadio2" value="1">
<label class="" for="inlineRadio2"></label>
{else}
<input class="" type="radio" name="regStatus" id="inlineRadio1" value="0">
<label class="" for="inlineRadio1" ></label>
&nbsp;&nbsp;&nbsp;
<input class="" type="radio" name="regStatus" id="inlineRadio2" value="1" checked>
<label class="" for="inlineRadio2"></label>
{/eq}
</div>
<div class="col-md-4 option-des"> 是否允许新用户注册</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="colFormLabelSm" class="col-form-label col-form-label-sm">默认用户组</label>
</div>
<div class="col-md-4">
<select class="form-control" name="defaultGroup">
{volist name="groups" id="group"}
{eq name="$group.id" value="$optionsForSet.defaultGroup"}
<option value="{$group.id}" selected>{$group.group_name}</option>
{else}
<option value="{$group.id}">{$group.group_name}</option>
{/eq}
{/volist}
</select>
</div>
<div class="col-md-4 option-des"> 用户注册后默认属于的用户组</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="colFormLabelSm" class="col-form-label col-form-label-sm">邮件激活</label>
</div>
<div class="col-md-4">
<input type="checkbox" id="inlineCheckbox3" name="email_active" value="1" {eq name="$optionsForSet.email_active" value="1" }checked{/eq}>
<label for="inlineCheckbox3">启用</label>
</div>
<div class="col-md-4 option-des"> 启用后,新用户注册需要点击邮件中的激活链接才能完成。请确认邮件发送设置是否正确,否则激活邮件无法送达</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="colFormLabelSm" class="col-form-label col-form-label-sm">登录验证码</label>
</div>
<div class="col-md-4"> <input type="checkbox" id="login_captcha" name="login_captcha" value="1" {eq name="$optionsForSet.login_captcha" value="1" }checked{/eq}>
<label for="login_captcha">启用</label>
</div>
<div class="col-md-4 option-des"> 是否启用登录表单验证码</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="colFormLabelSm" class="col-form-label col-form-label-sm">注册验证码</label>
</div>
<div class="col-md-4"> <input type="checkbox" id="reg_captcha" name="reg_captcha" value="1" {eq name="$optionsForSet.reg_captcha" value="1" }checked{/eq}>
<label for="reg_captcha">启用</label>
</div>
<div class="col-md-4 option-des"> 是否启用注册表单验证码</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
<label for="colFormLabelSm" class="col-form-label col-form-label-sm">找回密码验证码</label>
</div>
<div class="col-md-4"> <input type="checkbox" id="forget_captcha" name="forget_captcha" value="1" {eq name="$optionsForSet.forget_captcha" value="1" }checked{/eq}>
<label for="forget_captcha">启用</label>
</div>
<div class="col-md-4 option-des"> 是否启用找回密码表单验证码</div>
</div>
<div class="row form-setting">
<div class="col-md-1 form-label ">
</div>
<div class="col-md-4"> <button type="button" class="btn btn-primary" id="saveReg">保存设置</button></div>
<div class="col-md-4 option-des"> </div>
<br><br><br>
</div>
</form>
</div>
</div>
<!-- Example DataTables Card-->
</div>
<!-- /.container-fluid-->
</div>
<!-- /.content-wrapper-->
{/block}
{block name="js"}
<script src="/static/js/admin/setting.js"></script>
<script type="text/javascript">
</script>
{/block}
@@ -1,110 +0,0 @@
{extend name="header_admin" /}
{block name="title"}文件列表- {$options.siteName}{/block}
{block name="content"}
<div class="content-wrapper">
<div class="container-fluid">
<!-- Breadcrumbs-->
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="/Admin">管理面板</a>
</li>
<li class="breadcrumb-item active">分享</li>
</ol>
<!-- Area Chart Example-->
<div class="row">
<div class="col-12">
<h2>分享</h2>
<br>
<div class="card mb-3">
<div class="card-header">
<i class="fa fa-tags"></i> 条件检索</div>
<div class="card-body">
<div class="row">
<div class="col-1 form-label-search mb-2">排序方式</div>
<div class="col-md-10">
<ul class="nav nav-pills" id="order">
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-method="id DESC">日期</a>
</li>
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-method="download_num DESC">下载次数</a>
</li>
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-method="view_num DESC">浏览次数</a>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="card mb-3">
<div class="card-header">
<i class="fa fa-table"></i> 分享列表</div>
<div class="card-body">
<div class="table-responsive">
<div id="dataTable_wrapper" class="dataTables_wrapper container-fluid dt-bootstrap4"><div class="row"><div class="col-sm-12 col-md-6"><div class="dataTables_length" ><label>每页展示 <select id="dataTable_length" aria-controls="dataTable" class="form-control form-control-sm"><option value="10">10</option><option value="25">25</option><option value="50">50</option><option value="100">100</option></select></label></div></div><div class="col-sm-12 col-md-6"><div id="dataTable_filter" class="dataTables_filter"><label>搜索:<input type="search" class="form-control form-control-sm" placeholder="" id="searchFrom"></label></div></div></div><div class="row"><div class="col-sm-12">
<div class="table-responsive">
<table class="table table-bordered dataTable" id="dataTable" width="100%" cellspacing="0" role="grid" aria-describedby="dataTable_info" style="width: 100%;">
<thead>
<tr role="row" class="textCenter"><th><input type="checkbox" data-type="all"></th><th>分享名称</th><th class="textCenter">分享者</th><th class="textCenter">类型</th><th class="textCenter">日期</th><th class="textCenter">浏览次数</th><th class="textCenter">下载次数</th><th class="textCenter">操作</th></tr>
</thead>
<tfoot>
<tr><th rowspan="1" colspan="1" class="textCenter"><input type="checkbox" data-type="all"></th><th rowspan="1" colspan="1" class="textCenter">分享名称</th><th rowspan="1" colspan="1" class="textCenter">分享者</th><th rowspan="1" colspan="1" class="textCenter">类型</th><th rowspan="1" colspan="1" class="textCenter">日期</th><th rowspan="1" colspan="1" class="textCenter">浏览次数</th><th rowspan="1" colspan="1" class="textCenter">下载次数</th><th rowspan="1" colspan="1" class="textCenter">操作</th></tr>
</tfoot>
<tbody>
<tr role="row" class="odd" id="fileList">
{volist name='list' id='share'}
<tr role="row" class="odd">
<td class="sorting_1 textCenter"><input type="checkbox" data-type="mark" data-id="{$share.id}"></td>
<td>
{eq name="$share.source_type" value="dir"}
<i class="fa fa-folder-open-o" aria-hidden="true"></i> <a href="/S/{$share.share_key}?pwd={$share.share_pwd}" class="noAColor" target="_blank">{:htmlspecialchars(getDirName($share.source_name),ENT_NOQUOTES)}</a>
{else}
<i class="fa fa-file" aria-hidden="true"></i> <a href="/S/{$share.share_key}?pwd={$share.share_pwd}" class="noAColor" target="_blank">{$share.origin_name|htmlspecialchars=ENT_NOQUOTES}</a>
{/eq}
</td>
<td class="textCenter">{$originList[$key]["user"]["user_nick"]}</td>
<td class="textCenter">
{eq name="share.type" value="public"}
<i class="fa fa-eye" aria-hidden="true"></i> 公开
{else/}
<i class="fa fa-lock" aria-hidden="true"></i> 私密
{/eq}
</td>
<td class="textCenter">{$share.share_time}</td>
<td class="textCenter">{$share.view_num}</td>
<td class="textCenter">{$share.download_num}</td>
<td class="textCenter"><button type="button" class="btn btn-secondary fix" data-toggle="tooltip" data-placement="top" title="删除" data-action="delete" data-id="{$share.id}"><i class="fa fa-trash" aria-hidden="true"></i></button> <button type="button" class="btn btn-secondary fix" data-toggle="tooltip" data-placement="top" title="变更分享类型" data-action="change" data-id="{$share.share_key}"><i class="fa fa-lock" aria-hidden="true"></i></button></td>
</tr>
{/volist}
</tbody>
</table>
</div>
<div class="col-md-5 mb-2 mt-2" style="display: none" id="del">
<button type="button" class="btn btn-danger" id="delAll"><i class="fa fa-trash" aria-hidden="true"></i> 删除选中文件</button>
</div>
</div></div><div class="row"><div class="col-sm-12 col-md-5"><div class="dataTables_info" id="dataTable_info" role="status" aria-live="polite">展示第 {$pageNow} 页,共 {$pageTotal} 页 {$dataTotal} 条数据</div></div><div class="col-sm-12 col-md-7">
<div class="dataTables_paginate paging_simple_numbers" id="dataTable_paginate">
{$list->render()}
</div></div></div></div>
</div>
</div>
</div>
</div>
</div>
<!-- Example DataTables Card-->
</div>
<!-- /.container-fluid-->
</div>
<!-- /.content-wrapper-->
{/block}
{block name="js"}
<script src="/static/js/admin/shares.js"></script>
<script type="text/javascript">
</script>
{/block}
-51
View File
@@ -1,51 +0,0 @@
{extend name="header_admin" /}
{block name="title"}基础设置- {$options.siteName}{/block}
{block name="content"}
<div class="content-wrapper">
<div class="container-fluid">
<!-- Breadcrumbs-->
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="/Admin">管理面板</a>
</li>
<li class="breadcrumb-item active">模板</li>
</ol>
<!-- Area Chart Example-->
<div class="row">
<div class="col-12">
<h2>编辑模板</h2>
application/index/view/{:rtrim($path,"/")}/{$name}.html
<br> <br>
<div class="row">
<div class="col-md-9">
<input type="text" id="fileName" value="{$name}" style="display: none">
<textarea rows="15" class="form-control" spellcheck="false" style=" font-family: 'Courier New';">{:htmlspecialchars($content)}</textarea>
<br>
<button class="btn btn-primary" id="saveTheme">保存</button>
<br><br>
</div>
<div class="col-md-3">
<div class="file_side">
<div class="nav flex-column nav-pills" id="v-pills-tab" role="tablist" aria-orientation="vertical">
{volist name="list" id="file"}
<a class="nav-link" id="v-pills-home-tab" href="/Admin/Theme/name/{:str_replace(".html","",$file)}" role="tab" data-name="{:str_replace(".html","",$file)}">{$file}</a>
{/volist}
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Example DataTables Card-->
</div>
<!-- /.container-fluid-->
</div>
{/block}
{block name="js"}
<script src="/static/js/admin/config.js"></script>
<script type="text/javascript">
</script>
{/block}
-298
View File
@@ -1,298 +0,0 @@
{extend name="header_admin" /}
{block name="title"}文件列表- {$options.siteName}{/block}
{block name="content"}
<div class="content-wrapper">
<div class="container-fluid">
<!-- Breadcrumbs-->
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="/Admin">管理面板</a>
</li>
<li class="breadcrumb-item active">用户</li>
</ol>
<!-- Area Chart Example-->
<div class="row">
<div class="col-12">
<h2>用户 <button class="btn btn-secondary btn-sm" data-toggle="modal" data-target="#addUser"><li class="fa fa-plus"></li></button></h2>
<br>
<div class="card mb-3">
<div class="card-header">
<i class="fa fa-tags"></i> 条件检索</div>
<div class="card-body">
<div class="row">
<div class="col-1 form-label-search mb-2">排序方式</div>
<div class="col-md-10">
<ul class="nav nav-pills" id="order">
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-method="user_nick ASC">用户名</a>
</li>
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-method="id DESC">注册日期</a>
</li>
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-method="used_storage DESC">已用空间</a>
</li>
</ul>
</div>
</div>
<div class="row">
<div class="col-1 form-label-search mb-2">用户组</div>
<div class="col-md-10">
<ul class="nav nav-pills" id="groupS">
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-group="">全部</a>
</li>
{volist name="group" id="group"}
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-group="{$group.id}">{$group.group_name}</a>
</li>
{/volist}
</ul>
</div>
</div>
<div class="row">
<div class="col-1 form-label-search mb-2">用户状态</div>
<div class="col-md-10">
<ul class="nav nav-pills" id="status">
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-status="">全部</a>
</li>
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-status="1">正常</a>
</li>
<li class="nav-item">
<a class="nav-link selectLab" href="javascript:void()" data-status="2">封禁/未激活</a>
</li>
</ul>
</div>
</div>
<div class="row" style="margin-top: 5px;">
<div class="col-1 form-label-search mb-2">高级检索</div>
<div class="col-md-10">
<div class="row">
<div class="col-md-2">
<select class="form-control form-control-sm" id="searchColUser">
<option value="id">用户UID</option>
<option value="user_nick">用户昵称</option>
<option value="user_date">注册日期</option>
<option value="user_email">邮箱</option>
<option value="group_primary">初始用户组</option>
<option value="user_activation_key">邮箱激活密钥</option>
<option value="used_storage">已用空间</option>
<option value="delay_time">用户组过期日期</option>
<option value="avatar">头像标识</option>
<option value="profile">个人主页状态</option>
</select>
</div>
<div class="col-md-2">
<input type="text" class="form-control form-control-sm" placeholder="检索表达式" id="searchValueUser">
</div>
<div class="col-md-1">
<button type="button" class="btn btn-primary btn-sm" id="applySearch">应用</button>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="card mb-3">
<div class="card-header">
<i class="fa fa-table"></i> 用户列表 </div>
<div class="card-body">
<div class="table-responsive">
<div id="dataTable_wrapper" class="dataTables_wrapper container-fluid dt-bootstrap4"><div class="row"><div class="col-sm-12 col-md-6"><div class="dataTables_length" ><label>每页展示 <select id="dataTable_length" aria-controls="dataTable" class="form-control form-control-sm"><option value="10">10</option><option value="25">25</option><option value="50">50</option><option value="100">100</option></select></label></div></div><div class="col-sm-12 col-md-6"><div id="dataTable_filter" class="dataTables_filter"><label>搜索:<input type="search" class="form-control form-control-sm" placeholder="" id="searchFrom"></label></div></div></div><div class="row"><div class="col-sm-12">
<div class="table-responsive">
<table class="table table-bordered dataTable" id="dataTable" width="100%" cellspacing="0" role="grid" aria-describedby="dataTable_info" style="width: 100%;">
<thead>
<tr role="row" class="textCenter"><th><input type="checkbox" data-type="all"></th><th>UID</th><th>昵称</th><th class="textCenter">邮箱</th><th class="textCenter">用户组</th><th class="textCenter">空间用量</th><th class="textCenter">状态</th><th class="textCenter">操作</th></tr>
</thead>
<tfoot>
<tr><th rowspan="1" colspan="1" class="textCenter"><input type="checkbox" data-type="all"></th><th rowspan="1" colspan="1" class="textCenter">UID</th><th rowspan="1" colspan="1" class="textCenter">昵称</th><th rowspan="1" colspan="1" class="textCenter">邮箱</th><th rowspan="1" colspan="1" class="textCenter">用户组</th><th rowspan="1" colspan="1" class="textCenter">空间用量</th><th rowspan="1" colspan="1" class="textCenter">状态</th><th rowspan="1" colspan="1" class="textCenter">操作</th></tr>
</tfoot>
<tbody>
<tr role="row" class="odd" id="userList">
{volist name='list' id='user'}
<tr role="row" class="odd">
<td class="sorting_1 textCenter"><input type="checkbox" data-type="mark" data-id="{$user.id}"></td>
<td class="textCenter">{$user.id}</td>
<td class="textCenter">{$user.user_nick}</td>
<td class="textCenter">{$user.user_email}</td>
<td class="textCenter">{:$originList[$key]["group"]["group_name"]}</td>
<td class="textCenter">{:countSize($user.used_storage)}</td>
<td class="textCenter">
{eq name="user.user_status" value="0"}
<span class="order_success">正常</span>
{else/}
<span class="order_warning">封禁/未激活</span>
{/eq}
</td>
<td class="textCenter">
<button type="button" class="btn btn-secondary fix" data-toggle="tooltip" data-placement="top" title="删除" data-action="delete" data-id="{$user.id}" data-unable="{eq name="user.used_storage" value="0"}0{else/}1{/eq}"><i class="fa fa-trash" aria-hidden="true"></i></button>
<button type="button" class="btn btn-secondary fix" data-toggle="tooltip" data-placement="top" title="编辑" data-action="edit" data-id="{$user.id}"><i class="fa fa-id-card" aria-hidden="true"></i></button>
<button type="button" class="btn btn-secondary fix" data-toggle="tooltip" data-placement="top" title="封号/解封" data-action="ban" data-id="{$user.id}"><i class="fa fa-ban" aria-hidden="true"></i></button>
</td>
</tr>
{/volist}
</tbody>
</table>
</div>
<div class="col-md-5 mb-2 mt-2" style="display: none" id="del">
<button type="button" class="btn btn-danger" id="delAll"><i class="fa fa-trash" aria-hidden="true"></i> 删除选中用户</button>
</div>
</div></div><div class="row"><div class="col-sm-12 col-md-5"><div class="dataTables_info" id="dataTable_info" role="status" aria-live="polite">展示第 {$pageNow} 页,共 {$pageTotal} 页 {$dataTotal} 条数据</div></div><div class="col-sm-12 col-md-7">
<div class="dataTables_paginate paging_simple_numbers" id="dataTable_paginate">
{$list->render()}
</div></div></div></div>
</div>
</div>
</div>
</div>
</div>
<!-- Example DataTables Card-->
</div>
<!-- /.container-fluid-->
</div>
<div class="modal fade bd-example-modal-sm" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true" id="editUser">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">用户详情</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<form id="editUserForm">
<div class="form-group">
<label>
头像
</label>
<img src="" id="user_avatar">
</div>
<div class="form-group">
<label for="name">UID</label>
<input type="text" name="uid" id="uid" style="display: none;">
<input class="form-control" id="id" type="text" value="17" readonly>
</div>
<div class="form-group">
<label for="lovelyname">昵称</label>
<input type="text " class="form-control" id="user_nick" name="user_nick" required>
</div>
<div class="form-group">
<label for="InputPassword1">密码</label>
<input type="password" class="form-control" id="user_pass" name="user_pass" placeholder="如果不修改密码则留空" >
</div>
<div class="form-group">
<label for="InputEmail1">邮箱</label>
<input type="email" class="form-control" id="user_email" name="user_email" placeholder="Email" required>
</div>
<div class="form-group">
<label for="date">注册日期</label>
<input class="form-control" id="user_date" type="text" value="2017.12.31" readonly>
</div>
<div class="form-group">
<label for="space">已用空间</label>
<input class="form-control" id="used_storage" type="text" value="500M" readonly>
</div>
<div class="form-group">
<label for="openid">二步验证秘钥</label>
<input type="text " class="form-control" id="two_step" name="two_step" placeholder="取消二步验证请填写0" required="">
</div>
<div class="form-group">
<label for="inputState">用户状态</label>
<select class="form-control" id="user_status" name="user_status">
<option value="0">正常</option>
<option value="1">封禁/未激活</option>
</select>
</div>
<div class="form-group">
<label for="inputState">用户组</label>
<select id="user_group" class="form-control" name="user_group">
{foreach $groups as $g}
<option value="{$g.id}">{$g.group_name}</option>
{/foreach}
</select>
</div>
<div class="form-group">
<label for="inputState">个人主页状态</label>
<div class="radio">
<label>
<input type="radio" name="profile" id="profile1" value="1">
开启
</label>
<label>
<input type="radio" name="profile" id="profile0" value="0">
关闭
</label>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
<button type="submit" class="btn btn-primary" id="editUserSubmit">保存</button>
</div></form>
</div>
</div>
</div>
<div class="modal fade bd-example-modal-sm" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true" id="addUser">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">添加用户</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<form id="addUserForm">
<div class="form-group">
<label for="lovelyname">昵称</label>
<input type="text " class="form-control" id="user_nick" name="user_nick" required>
</div>
<div class="form-group">
<label for="InputPassword1">密码</label>
<input type="password" class="form-control" id="user_pass" name="user_pass" required>
</div>
<div class="form-group">
<label for="InputEmail1">邮箱</label>
<input type="email" class="form-control" id="user_email" name="user_email" placeholder="Email" required>
</div>
<div class="form-group">
<label for="inputState">用户状态</label>
<select class="form-control" name="user_status">
<option value="0">正常</option>
<option value="1">封禁/未激活</option>
</select>
</div>
<div class="form-group">
<label for="inputState">用户组</label>
<select class="form-control" name="user_group">
{foreach $groups as $g}
<option value="{$g.id}">{$g.group_name}</option>
{/foreach}
</select>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
<button type="submit" class="btn btn-primary" id="addUserSubmit">保存</button>
</div></form>
</div>
</div>
</div>
<!-- /.content-wrapper-->
{/block}
{block name="js"}
<script src="/static/js/admin/users.js"></script>
<script type="text/javascript">
</script>
{/block}
@@ -1,23 +0,0 @@
{extend name="header_public" /}
{block name="title"}支付成功 - {$options.siteName}{/block}
{block name="content"}
<link rel="stylesheet" href="/static/css/error.css" />
</head>
<body data-ma-header="teal">
<div class="container" align="center">
<header align="left">
<br>
<img src="/img/logo_s.png" style="width:192px;">
</header>
<div class="error_content" >
<div class="jumbotron animated bounce" style="padding-left:30px;">
<h1>支付成功</h1>
<br>
<p> 付款成功,您所购买的服务已开通。</p>
<p><a class="btn btn-primary btn-lg" href="/Home/Quota">查看详情</a></p>
</div>
</div>
</div>
</body>
{/block}
-24
View File
@@ -1,24 +0,0 @@
{extend name="header_public" /}
{block name="title"}错误提示 - {$options.siteName}{/block}
{block name="content"}
<link rel="stylesheet" href="/static/css/error.css" />
</head>
<body data-ma-header="teal">
<div class="container" align="center">
<header align="left">
<br>
<img src="/static/img/logo_s.png" style="width:192px;">
</header>
<div class="error_content" >
<div class="jumbotron animated bounce" style="padding-left:30px;">
<h1>发生错误</h1>
<br>
<p> {$msg}</p>
<p><a class="btn btn-primary btn-lg" onclick="history.go(-1);"><< 返回</a></p>
</div>
</div>
</div>
{$options.js_code}
</body>
{/block}
-24
View File
@@ -1,24 +0,0 @@
{extend name="header_public" /}
{block name="title"}错误提示 - {$options.siteName}{/block}
{block name="content"}
<link rel="stylesheet" href="/static/css/error.css" />
</head>
<body data-ma-header="teal">
<div class="container" align="center">
<header align="left">
<br>
<img src="/static/img/logo_s.png" style="width:192px;">
</header>
<div class="error_content" >
<div class="jumbotron animated bounce" style="padding-left:30px;">
<h1>发生错误</h1>
<br>
<p> {$msg}</p>
<p><a class="btn btn-primary btn-lg" onclick="history.go(-1);"><< 返回</a></p>
</div>
</div>
</div>
{$options.js_code}
</body>
{/block}
@@ -1,76 +0,0 @@
{extend name="header_public" /}
{block name="title"}“{$keyWords}”搜索结果 - {$options.siteName}{/block}
{block name="content"}
<link rel="stylesheet" href="/static/css/search.css" />
</head>
<body data-ma-header="teal">
<nav class="navbar navbar-inverse" >
<div class="container-fluid">
<div class="container" >
{include file="navbar_public" /}
<div class="header-panel shadow-z-2">
<div class="container-fluid">
<div class="row">
</div>
</div>
</div>
<div class="container main-h">
<div class="col-md-12">
<h1>搜索分享</h1>
<input type="text" placeholder="请输入关键词,回车键发起搜索" value="{$keyWords}" autofocus="true"><br><br>
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th width="50%">文件名 </th>
<th class="cent">分享日期</th>
<th class="cent">下载次数</th>
<th class="cent">浏览次数</th>
</tr>
</thead>
<tbody>{volist name='list' id='shares'}
<tr>
<td >{switch $shares.source_type}
{case file}<i class="fa fa-file" aria-hidden="true"></i> {/case}
{case dir}<i class="fa fa-folder-open blue" aria-hidden="true"></i> {/case}
{/switch} <a href="/s/{$shares.share_key}" class="notWave" target="_blank">{$shares.fileData|htmlspecialchars=ENT_NOQUOTES}</a></td>
<td class="cent">{$shares.share_time}</td>
<td align="center">{$shares.download_num}</td>
<td align="center">{$shares.view_num}</td>
</tr>
{/volist}
</tbody>
</table>
</div>
{$listOrigin->render()}
</div>
</div>
</div>
</body>
<script type="text/javascript">
</script>
<script src="/static/js/material.js"></script>
<script >
$.material.init();
document.onkeydown=function(){
if (event.keyCode == 13){
keyWords = $("input").val();
if(keyWords ==""){
toastr["warning"]("关键字不能为空");
}else{
window.location="/Explore/S/"+keyWords;
}
}
else{
}
}
</script>
{$options.js_code}
{/block}
@@ -1,47 +0,0 @@
{extend name="header_public" /}
{block name="title"}用户主页 - {$options.siteName}{/block}
{block name="content"}
<link rel="stylesheet" href="/static/css/search.css" />
</head>
<body data-ma-header="teal">
<nav class="navbar navbar-inverse" >
<div class="container-fluid">
<div class="container" >
{include file="navbar_public" /}
<div class="header-panel shadow-z-2">
<div class="container-fluid">
<div class="row">
</div>
</div>
</div>
<div class="container main-h">
<div class="col-md-12">
<h1>搜索分享</h1>
<input type="text" placeholder="请输入关键词,回车键发起搜索" autofocus="true">
</div>
</div>
</div>
</body>
<script type="text/javascript">
</script>
<script src="/static/js/material.js"></script>
<script >
document.onkeydown=function(){
if (event.keyCode == 13){
keyWords = $("input").val();
if(keyWords ==""){
toastr["warning"]("关键字不能为空");
}else{
window.location="/Explore/S/"+keyWords;
}
}
else{
}
}
</script>
{$options.js_code}
{/block}
@@ -1,5 +0,0 @@
下载已开始...
<a href="{$url}" download="" id="downloadA">手动下载</a>
<script type="text/javascript">
document.getElementById("downloadA").click();
</script>
-37
View File
@@ -1,37 +0,0 @@
<!DOCTYPE html>
<html class="full-height">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<meta name="keywords" content="{$options.siteKeywords}"/>
<meta name="description" content="{$options.siteDes}"/>
<meta name="theme-color" content="#4e64d9"/>
<title>{$options.siteName} - {$options.siteTitle}</title>
<!-- Font Awesome -->
<link rel="stylesheet" href="/static/css/font-awesome.min.css">
<!-- Bootstrap core CSS -->
<link href="/static/css/bootstrap4/bootstrap.min.css" rel="stylesheet">
<!-- Material Design Bootstrap -->
<link href="/static/css/mdb.css" rel="stylesheet">
</head>
<body class="grey-skin intro-page creative-lp">
<!--Navigation & Intro-->
<header>
<!--Navbar-->
<nav class="navbar fixed-top navbar-dark ">
<div class="container">
<a class="navbar-brand" href="#">
<img src="static/img/logo_s.png" style=" width: 192px;">
</a>
</div>
</nav>
<!--/Navbar-->
-194
View File
@@ -1,194 +0,0 @@
<!DOCTYPE html>
<html lang="zh_cn">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>{block name="title"}{/block}</title>
<!-- Bootstrap core CSS-->
<link href="/static/css/bootstrap4/bootstrap.min.css" rel="stylesheet">
<!-- Custom fonts for this template-->
<link href="/static/css/font-awesome.min.css" rel="stylesheet" type="text/css">
<!-- Page level plugin CSS-->
<link href="/static/css/datatables/dataTables.bootstrap4.css" rel="stylesheet">
<link href="/static/css/toastr.min.css" rel="stylesheet">
<!-- Custom styles for this template-->
<link href="/static/css/sb-admin.css" rel="stylesheet">
</head>
<body class="{$options.admin_color_body}" id="page-top">
<!-- Navigation-->
<nav class="{$options.admin_color_nav}" id="mainNav">
<a class="navbar-brand" href="index.html">Cloudreve</a>
<button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarResponsive">
<ul class="navbar-nav navbar-sidenav" id="exampleAccordion">
<li class="nav-item" data-toggle="tooltip" data-placement="right" title="面板首页">
<a class="nav-link" href="/Admin">
<i class="fa fa-fw fa-dashboard"></i>
<span class="nav-link-text">面板首页</span>
</a>
</li>
<li class="nav-item" data-toggle="tooltip" data-placement="right" title="设置">
<a class="nav-link nav-link-collapse collapsed" data-toggle="collapse" href="#collapseComponents" data-parent="#exampleAccordion">
<i class="fa fa-fw fa-wrench"></i>
<span class="nav-link-text">设置</span>
</a>
<ul class="sidenav-second-level collapse" id="collapseComponents">
<li>
<a href="/Admin/Setting">基础设置</a>
</li>
<li>
<a href="/Admin/SettingReg">注册访问</a>
</li>
<li>
<a href="/Admin/SettingMail">邮件发送</a>
</li>
<li>
<a href="/Admin/Config">配置文件</a>
</li>
<li>
<a href="/Admin/SettingOther">杂项</a>
</li>
</ul>
</li>
<li class="nav-item" data-toggle="tooltip" data-placement="right" title="模板">
<a class="nav-link" href="/Admin/Theme">
<i class="fa fa-fw fa-paint-brush"></i>
<span class="nav-link-text">模板</span>
</a>
</li>
<li class="nav-item" data-toggle="tooltip" data-placement="right" title="文件">
<a class="nav-link" href="/Admin/Files">
<i class="fa fa-fw fa-folder"></i>
<span class="nav-link-text">文件</span>
</a>
</li>
<li class="nav-item" data-toggle="tooltip" data-placement="right" title="分享">
<a class="nav-link" href="/Admin/Shares">
<i class="fa fa-fw fa-send"></i>
<span class="nav-link-text">分享</span>
</a>
</li>
<li class="nav-item" data-toggle="tooltip" data-placement="right" title="用户">
<a class="nav-link" href="/Admin/Users" data-parent="#user">
<i class="fa fa-fw fa-user"></i>
<span class="nav-link-text">用户</span>
</a>
</li>
<li class="nav-item" data-toggle="tooltip" data-placement="right" title="用户组">
<a class="nav-link nav-link-collapse collapsed" data-toggle="collapse" href="#group" data-parent="#group">
<i class="fa fa-fw fa-users"></i>
<span class="nav-link-text">用户组</span>
</a>
<ul class="sidenav-second-level collapse" id="group">
<li>
<a href="/Admin/GroupList">管理</a>
</li>
<li>
<a href="/Admin/GroupAdd">添加</a>
</li>
</ul>
</li>
<li class="nav-item" data-toggle="tooltip" data-placement="right" title="上传策略">
<a class="nav-link nav-link-collapse collapsed" data-toggle="collapse" href="#policy" data-parent="#policy">
<i class="fa fa-fw fa-upload"></i>
<span class="nav-link-text">上传策略</span>
</a>
<ul class="sidenav-second-level collapse" id="policy">
<li>
<a href="/Admin/PolicyList">管理</a>
</li>
<li>
<a href="/Admin/PolicyAdd">添加</a>
</li>
</ul>
</li>
<li class="nav-item" data-toggle="tooltip" data-placement="right" title="其他">
<a class="nav-link nav-link-collapse collapsed" data-toggle="collapse" href="#else" data-parent="#else">
<i class="fa fa-fw fa-ellipsis-h"></i>
<span class="nav-link-text">其他</span>
</a>
<ul class="sidenav-second-level collapse" id="else">
<li>
<a href="/Admin/Cron">定时任务</a>
</li>
<li>
<a href="/Admin/About">关于</a>
</li>
</ul>
</li>
</ul>
<ul class="navbar-nav sidenav-toggler">
<li class="nav-item">
<a class="nav-link text-center" id="sidenavToggler">
<i class="fa fa-fw fa-angle-left"></i>
</a>
</li>
</ul>
<ul class="navbar-nav ml-auto">
<li class="nav-item">
<a class="nav-link" href="javascript:void" id="toggleNavColor">
<i class="fa fa-fw fa-toggle-on" aria-hidden="true"></i>切换配色</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/">
<i class="fa fa-fw fa-home"></i>返回首页</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="modal" data-target="#exampleModal">
<i class="fa fa-fw fa-sign-out"></i>登出</a>
</li>
</ul>
</div>
</nav>
{block name="content"}{/block}
<footer class="sticky-footer">
<div class="container">
<div class="text-center">
<small>Copyright © Cloudreve {php}echo date("Y");{/php} </small>
</div>
</div>
</footer>
<!-- Scroll to Top Button-->
<a class="scroll-to-top rounded" href="#page-top">
<i class="fa fa-angle-up"></i>
</a>
<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">确认</h5>
<button class="close" type="button" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">点击“登出”按钮退出当前账户。</div>
<div class="modal-footer">
<button class="btn btn-secondary" type="button" data-dismiss="modal">取消</button>
<a class="btn btn-primary" href="/Member/LogOut">登出</a>
</div>
</div>
</div>
</div>
<script src="/static/js/jquery.min.js"></script>
<script src="/static/js/bootstrap4/bootstrap.bundle.min.js"></script>
<!-- Core plugin JavaScript-->
<script src="/static/js/chart.js/Chart.min.js"></script>
<!-- Custom scripts for all pages-->
<script src="/static/js/sb-admin.min.js"></script>
<script type="text/javascript" src="/static/js/toastr.min.js"></script>
{block name="js"}
{/block}
</div>
</body>
</html>
@@ -1,15 +0,0 @@
<html lang="zh-cn" data-ng-app="FileManagerApp">
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<title>{block name="title"}{/block}</title>
<!-- third party -->
<link rel="stylesheet" href="/static/css/bootstrap.min.css" />
<link rel="stylesheet" href="/static/css/material.css" />
<link rel="stylesheet" href="/static/css/animate.css" />
<link rel="stylesheet" href="/static/css/font-awesome.min.css">
<!-- /third party -->
<!-- Comment if you need to use raw source code -->
<link href="/static/css/toastr.min.css" rel="stylesheet">
<!-- /Comment if you need to use raw source code -->
{block name="content"}{/block}
-18
View File
@@ -1,18 +0,0 @@
<!doctype html>
<html lang="zh-cn" data-ng-app="FileManagerApp">
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<meta name="theme-color" content="#4e64d9"/>
<title>{block name="title"}{/block}</title>
<script src="/static/js/jquery.min.js"></script>
<link rel="stylesheet" href="/static/css/bootstrap.min.css" />
<link rel="stylesheet" href="/static/css/material.css" />
<script src="/static/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="/static/css/font-awesome.min.css">
<link href="/static/css/angular-filemanager.min.css" rel="stylesheet">
<link href="/static/css/toastr.min.css" rel="stylesheet">
<script type="text/javascript" src="/static/js/toastr.min.js"></script>
<script type="text/javascript">
</script>
{block name="content"}{/block}
-20
View File
@@ -1,20 +0,0 @@
<html lang="zh-cn" data-ng-app="FileManagerApp">
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<meta name="theme-color" content="#4e64d9"/>
<title>{block name="title"}{/block}</title>
<!-- third party -->
<script src="/static/js/jquery.min.js"></script>
<link rel="stylesheet" href="/static/css/bootstrap.min.css" />
<link rel="stylesheet" href="/static/css/material.css" />
<link rel="stylesheet" href="/static/css/animate.css" />
<script src="/static/js/material.js"></script>
<script src="/static/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="/static/css/font-awesome.min.css">
<!-- /third party -->
<!-- Comment if you need to use raw source code -->
<link href="/static/css/toastr.min.css" rel="stylesheet">
<script type="text/javascript" src="/static/js/toastr.min.js"></script>
<!-- /Comment if you need to use raw source code -->
{block name="content"}{/block}
-82
View File
@@ -1,82 +0,0 @@
<!DOCTYPE HTML>
<!--
Multiverse by HTML5 UP
html5up.net | @ajlkn
Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
-->
<html>
<head>
<title>图片集 - {$options.siteName}</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<!--[if lte IE 8]><script src="https://file.aoaoao.me/content/themes/material/pages/js/ie/html5shiv.js"></script><![endif]-->
<link rel="stylesheet" href="/static/css/main.css" />
<link href="/static/css/font-awesome.min.css" rel="stylesheet">
<!--[if lte IE 9]><link rel="stylesheet" href="https://file.aoaoao.me/content/themes/material/pages/css/ie9.css" /><![endif]-->
<!--[if lte IE 8]><link rel="stylesheet" href="https://file.aoaoao.me/content/themes/material/pages/css/ie8.css" /><![endif]-->
<style type="text/css">
body{
font-family: "微软雅黑","黑体";
}
</style>
</head>
<body>
<!-- Wrapper -->
<div id="wrapper">
<!-- Header -->
<div id="main">
{volist name='list' id='pic'}
<article class="thumb">
<a href="/File/Preview?action=preview&path={$pic.dir|urlencode}/{$pic.orign_name|urlencode}" class="image"><img src="/File/Preview?action=preview&path={$pic.dir|urlencode}/{$pic.orign_name|urlencode}" alt="" /></a>
<h2>{$pic.orign_name}</h2>
</article>
{/volist}
</div>
<header id="header">
<h1><a href="/Home"><strong>图片集</strong> {$options.siteName}</a></h1>
<nav>
<ul>
<li><a href="javascript:previous();" class="icon fa-arrow-circle-left">上一页</a></li>
{$page}/{$pageCount} <li><a href="javascript:next();" class="icon fa-arrow-circle-right">下一页</a></li>
</ul>
</nav>
</header>
<!-- Main -->
<!-- Footer -->
</div>
<!-- Scripts -->
<script src = "/static/js/jquery.min.js"></script>
<script src="/static/js/jquery.poptrox.min.js"></script>
<script src="/static/js/skel.min.js"></script>
<script src="/static/js/util.js"></script>
<!--[if lte IE 8]><script src="assets/js/ie/respond.min.js"></script><![endif]-->
<script src="/static/js/album.js"></script>
<script type="text/javascript">
pageNow = {$page};
pageTotal = {$pageCount};
function next(){
if(pageNow == pageTotal){
}else{
window.location.href="/Home/Album?page="+(pageNow+1);
}
}
function previous(){
if(pageNow == 1){
}else{
window.location.href="/Home/Album?page="+(pageNow-1);
}
}
</script>
{$options.js_code}
</body>
</html>
-98
View File
@@ -1,98 +0,0 @@
<!doctype html>
<html lang="zh_cn" data-ng-app="FileManagerApp">
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<meta name="theme-color" content="#4e64d9"/>
<title>我的文件 - {$options.siteName}</title>
<script src="/static/js/angular.min.js"></script>
<script src="/static/js/angular-translate.min.js"></script>
<script src="/static/js/jquery.min.js"></script>
<link rel="stylesheet" href="/static/css/bootstrap.min.css" />
<link rel="stylesheet" href="/static/css/material.css" />
<script src="/static/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="/static/css/font-awesome.min.css">
<link href="/static/css/angular-filemanager.min.css" rel="stylesheet">
<link href="/static/css/toastr.min.css" rel="stylesheet">
<script type="text/javascript" src="/static/js/toastr.min.js"></script>
<script src="/static/js/angular-filemanager.min.js"></script>
<link rel="stylesheet" href="/static/css/photoswipe.css">
<link rel="stylesheet" href="/static/css/default-skin/default-skin.css">
<script type="text/javascript">
uploadConfig={
saveType : "{$policyData.policy_type}",
maxSize : "{$policyData.max_size}mb",
allowedType: [
{$extLimit}
],
allowSource : "{$policyData.origin_link}",
upUrl : "{$policyData.server}",
allowShare:"{$groupData.allow_share}",
};
</script>
<script src="/static/js/home.js"></script>
</head>
<body class="ng-cloak">
<div id="container">
{include file="navbar_home" /}
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
<!-- Background of PhotoSwipe.
It's a separate element, as animating opacity is faster than rgba(). -->
<div class="pswp__bg"></div>
<!-- Slides wrapper with overflow:hidden. -->
<div class="pswp__scroll-wrap">
<!-- Container that holds slides. PhotoSwipe keeps only 3 slides in DOM to save memory. -->
<div class="pswp__container">
<!-- don't modify these 3 pswp__item elements, data is added later on -->
<div class="pswp__item"></div>
<div class="pswp__item"></div>
<div class="pswp__item"></div>
</div>
<!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->
<div class="pswp__ui pswp__ui--hidden">
<div class="pswp__top-bar">
<!-- Controls are self-explanatory. Order can be changed. -->
<div class="pswp__counter"></div>
<button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
<button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
<button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>
<!-- Preloader demo https://codepen.io/dimsemenov/pen/yyBWoR -->
<!-- element will get class pswp__preloader--active when preloader is running -->
<div class="pswp__preloader">
<div class="pswp__preloader__icn">
<div class="pswp__preloader__cut">
<div class="pswp__preloader__donut"></div>
</div>
</div>
</div>
</div>
<div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
<div class="pswp__share-tooltip"></div>
</div>
<button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
</button>
<button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
</button>
<div class="pswp__caption">
<div class="pswp__caption__center"></div>
</div>
</div>
</div>
</div>
<div class="col-md-10 max_height">
<angular-filemanager></angular-filemanager>
</div>
</div>
</body>
<script src="/static/js/material.js"></script>
<script type="text/javascript">
upload_load=0;
</script>
{$options.js_code}
</html>
-49
View File
@@ -1,49 +0,0 @@
{include file="header" /}
<!--Video-->
<div class="intro-video view" id="home">
<div class="hm-gradient">
<div class="full-bg-img flex-center">
<div class="container smooth-scroll">
<div class="row">
<div class="col-md-12 white-text text-center smooth-scroll">
<div class="fadeInDown" data-wow-delay="0.2s">
<h3 class="brand-name font-bold white-text mb-2">开始云上之旅</h3>
<hr class="hr-light">
<h4 class="subtext-header mt-2 mb-2">只需十秒钟,注册后即可开始使用免费高速的云存储服务</h4>
</div>
<a href="/Login" class="btn btn-rounded btn-light-green-2" ><i class="fa fa-paper-plane-o"></i> 注册</a>
<a href="/Home" class="btn btn-rounded btn-light-green-2" ><i class="fa fa-sign-in"></i> 登录</a>
</div>
</div>
</div>
</div>
</div>
</div>
<!--/Video-->
</header>
<!--/.Content-->
</div>
</div>
<!-- JQuery -->
<script type="text/javascript" src="/static/js/jquery.min.js"></script>
<script>
</script>
</body>
</html>
@@ -1,59 +0,0 @@
{extend name="header_public" /}
{block name="title"}注册成功- {$options.siteName}{/block}
{block name="content"}
<link rel="stylesheet" href="/static/css/login.css" />
<link rel="stylesheet" href="/static/css/photoswipe.css">
<link rel="stylesheet" href="/static/css/default-skin/default-skin.css">
<script src="/static/js/jquery.color.js"></script>
</head>
<body data-ma-header="teal">
<nav class="navbar navbar-inverse" >
<div class="container-fluid">
<div class="container" >
{include file="navbar_public" loginStatus=$loginStatus userData=$userData /}
<div class="header-panel shadow-z-2">
<div class="container-fluid">
<div class="row">
</div>
</div>
</div>
<div class="container main" >
<div class="col-md-4"></div>
<div class="col-md-4">
<div class="jumbotron" >
<div class="card_top">
<div class="row top-color">
<div class="card-top-row">
<div class="login-icon"><i class="fa fa-check" aria-hidden="true"></i></div>
<div class="login-text">注册成功</div>
</div>
</div>
</div>
<div class="card_botom">
<div class="row bottom-width">
<br>
您已成功激活账号。<br><br>
<a class="btn btn-raised btn-primary" href="/Login">立即登录</a>
</div>
</div>
</div>
</div>
</div></div>
<div class="col-md-4"></div>
</div>
</div>
</body>
<script type="text/javascript">
</script>
<script src="/static/js/two_step.js"> </script>
{$options.js_code}
{/block}
-185
View File
@@ -1,185 +0,0 @@
{extend name="header_public" /}
{block name="title"}登录- {$options.siteName}{/block}
{block name="content"}
<link rel="stylesheet" href="/static/css/login.css" />
<link rel="stylesheet" href="/static/css/photoswipe.css">
<link rel="stylesheet" href="/static/css/default-skin/default-skin.css">
<script src="/static/js/jquery.color.js"></script>
</head>
<body data-ma-header="teal">
<nav class="navbar navbar-inverse" >
<div class="container-fluid">
<div class="container" >
{include file="navbar_public" loginStatus=$loginStatus userData=$userData /}
<div class="header-panel shadow-z-2">
<div class="container-fluid">
<div class="row">
</div>
</div>
</div>
<div class="container main" >
<div class="col-md-4"></div>
<div class="col-md-4">
<div class="jumbotron" id="logForm">
<div class="card_top">
<div class="row top-color">
<div class="card-top-row">
<div class="login-icon"><i class="fa fa-user-circle-o" aria-hidden="true"></i></div>
<div class="login-text">登录后方可享用精彩内容</div>
</div>
</div>
</div>
<div class="card_botom">
<div class="row bottom-width">
<form id="loginForm">
<div class="form-group label-floating">
<label class="control-label" for="inputEmail">Email 电子邮箱</label>
<input type="text" class="form-control" id="inputEmail" name="userMail">
</div>
<div class="form-group label-floating">
<label class="control-label" for="inputPwd">密码</label>
<input type="password" class="form-control" id="inputPwd" name="userPass">
</div>
{eq name="$RegOptions.login_captcha" value="1"}
<div class="input-group form-group label-floating">
<label class="control-label" for="captcha">验证码</label>
<input type="text" id="captcha" class="form-control" name="captchaCode">
<span class="input-group-btn">
<div class="captcha_img">{:captcha_img()}</div>
</span>
</div>
{else/}
{/eq}
</form> <button class="btn btn-raised btn-primary" id="loginButton">登录</button>
<div class="link-group">
<a href="javascript:void" class="noWave" id="create" data-change="true">创建一个账户</a><br>
<a href="javascript:void" class="noWave" id="forgetSwitch2" data-change="true">忘记密码?</a>
</div>
</div>
</div>
</div>
<div class="jumbotron" id="regForm" style="display: none;">
<div class="card_top">
<div class="row top-color">
<div class="card-top-row">
<div class="login-icon"><i class="fa fa-sign-in" aria-hidden="true"></i></div>
<div class="login-text">注册账户</div>
</div>
</div>
</div>
<div class="card_botom">
<div class="row bottom-width">
<form id="registerForm">
<div class="form-group label-floating">
<label class="control-label" for="inputEmail">Email 电子邮箱</label>
<input type="text" class="form-control" id="inputEmail" name="username-reg">
</div>
<div class="form-group label-floating">
<label class="control-label" for="inputPwd">密码</label>
<input type="password" class="form-control" id="inputPwd" name="password-reg">
</div>
<div class="form-group label-floating">
<label class="control-label" for="inputPwd">重复密码</label>
<input type="password" class="form-control" id="inputPwd" name="password-check">
</div>
{eq name="$RegOptions.reg_captcha" value="1"}
<div class="input-group form-group label-floating">
<label class="control-label" for="captcha">验证码</label>
<input type="text" id="captcha" class="form-control" name="captchaCode">
<span class="input-group-btn">
<div class="captcha_img">{:captcha_img()}</div>
</span>
</div>
{else/}
{/eq}
</form> <button class="btn btn-raised btn-primary" id="regButton">注册</button> <div class="link-group">
<a href="javascript:void" class="noWave" id="loginSwitch3" data-change="true">已有账号?立即登录</a><br>
<a href="javascript:void" class="noWave" id="forgetSwitch" data-change="true">忘记密码?</a>
</div>
</div>
</div>
</div>
<div class="jumbotron" id="emailCheck" style="display: none;">
<div class="card_top">
<div class="row top-color">
<div class="card-top-row">
<div class="login-icon"><i class="fa fa-envelope" aria-hidden="true"></i></div>
<div class="login-text">激活账户</div>
</div>
</div>
</div>
<div class="card_botom">
<div class="row bottom-width"><br>
我们已经向您的注册邮箱发送了一封确认邮件,请访问邮件中的激活链接以完成注册。如果未收到邮件,请检查您的垃圾邮件。<br><br>如果还仍无法接受邮件,请尝试更换注册邮箱或联系站点管理员。
</div>
</div>
</div>
<div class="jumbotron" id="forgetForm" style="display: none;">
<div class="card_top">
<div class="row top-color">
<div class="card-top-row">
<div class="login-icon"><i class="fa fa-question-circle-o" aria-hidden="true"></i></div>
<div class="login-text">找回密码</div>
</div>
</div>
</div>
<div class="card_botom">
<div class="row bottom-width">
<form id="forgetPwdForm">
<div class="form-group label-floating">
<label class="control-label" for="inputEmail">请填写注册时绑定的邮箱</label>
<input type="text" class="form-control" id="regEmail" name="regEmail">
</div>
{eq name="$RegOptions.forget_captcha" value="1"}
<div class="input-group form-group label-floating">
<label class="control-label" for="captcha">验证码</label>
<input type="text" id="captcha" class="form-control" name="captchaCode">
<span class="input-group-btn">
<div class="captcha_img">{:captcha_img()}</div>
</span>
</div>
{else/}
{/eq}
</form> <button class="btn btn-raised btn-primary" id="findMyFuckingPwd">找回密码</button> <div class="link-group">
<a href="javascript:void" class="noWave" id="loginSwitch2" data-change="true">返回登录</a><br>
</div>
</div>
</div>
</div>
</div></div>
<div class="col-md-4"></div>
</div>
</div>
</body>
<script type="text/javascript">
</script>
<script src="/static/js/login.js"> </script>
{$options.js_code}
{/block}
@@ -1,122 +0,0 @@
{extend name="header_public" /}
{block name="title"}登录- {$options.siteName}{/block}
{block name="content"}
<link rel="stylesheet" href="/static/css/login.css" />
<link rel="stylesheet" href="/static/css/photoswipe.css">
<link rel="stylesheet" href="/static/css/default-skin/default-skin.css">
<script src="/static/js/jquery.color.js"></script>
</head>
<body data-ma-header="teal">
<nav class="navbar navbar-inverse" >
<div class="container-fluid">
<div class="container" >
{include file="navbar_public" loginStatus=$loginStatus userData=$userData /}
<div class="header-panel shadow-z-2">
<div class="container-fluid">
<div class="row">
</div>
</div>
</div>
<div class="container main" >
<div class="col-md-4"></div>
<div class="col-md-4">
<div class="jumbotron" id="logForm">
<div class="card_top">
<div class="row top-color">
<div class="card-top-row">
<div class="login-icon"><i class="fa fa-user-circle-o" aria-hidden="true"></i></div>
<div class="login-text">登录后方可享用精彩内容</div>
</div>
</div>
</div>
<div class="card_botom">
<div class="row bottom-width">
<form id="loginForm">
<div class="form-group label-floating">
<label class="control-label" for="inputEmail">Email 电子邮箱</label>
<input type="text" class="form-control" id="inputEmail" name="userMail">
</div>
<div class="form-group label-floating">
<label class="control-label" for="inputPwd">密码</label>
<input type="password" class="form-control" id="inputPwd" name="userPass">
</div>
{eq name="$RegOptions.login_captcha" value="1"}
<div class="input-group form-group label-floating">
<label class="control-label" for="captcha">验证码</label>
<input type="text" id="captcha" class="form-control" name="captchaCode">
<span class="input-group-btn">
<div class="captcha_img">{:captcha_img()}</div>
</span>
</div>
{else/}
{/eq}
</form> <button class="btn btn-raised btn-primary" id="loginButton">登录</button> <button class="btn btn-raised btn-info" ><i class="fa fa-qq" aria-hidden="true"></i> 使用QQ账号登录</button><div class="link-group">
<a href="#" class="noWave">创建一个账户</a><br>
<a href="#" class="noWave">忘记密码?</a>
</div>
</div>
</div>
</div>
<div class="jumbotron" id="regForm">
<div class="card_top">
<div class="row top-color">
<div class="card-top-row">
<div class="login-icon"><i class="fa fa-user-circle-o" aria-hidden="true"></i></div>
<div class="login-text">登录后方可享用精彩内容</div>
</div>
</div>
</div>
<div class="card_botom">
<div class="row bottom-width">
<form id="loginForm">
<div class="form-group label-floating">
<label class="control-label" for="inputEmail">Email 电子邮箱</label>
<input type="text" class="form-control" id="inputEmail" name="userMail">
</div>
<div class="form-group label-floating">
<label class="control-label" for="inputPwd">密码</label>
<input type="password" class="form-control" id="inputPwd" name="userPass">
</div>
{eq name="$RegOptions.login_captcha" value="1"}
<div class="input-group form-group label-floating">
<label class="control-label" for="captcha">验证码</label>
<input type="text" id="captcha" class="form-control" name="captchaCode">
<span class="input-group-btn">
<div class="captcha_img">{:captcha_img()}</div>
</span>
</div>
{else/}
{/eq}
</form> <button class="btn btn-raised btn-primary" id="loginButton">登录</button> <button class="btn btn-raised btn-info" ><i class="fa fa-qq" aria-hidden="true"></i> 使用QQ账号登录</button><div class="link-group">
<a href="#" class="noWave">创建一个账户</a><br>
<a href="#" class="noWave">忘记密码?</a>
</div>
</div>
</div>
</div>
</div></div>
<div class="col-md-4"></div>
</div>
</div>
</body>
<script type="text/javascript">
</script>
<script src="/static/js/login_bind.js"> </script>
{$options.js_code}
{/block}
@@ -1,70 +0,0 @@
{extend name="header_public" /}
{block name="title"}密码重置- {$options.siteName}{/block}
{block name="content"}
<link rel="stylesheet" href="/static/css/login.css" />
<link rel="stylesheet" href="/static/css/photoswipe.css">
<link rel="stylesheet" href="/static/css/default-skin/default-skin.css">
<script src="/static/js/jquery.color.js"></script>
</head>
<body data-ma-header="teal">
<nav class="navbar navbar-inverse" >
<div class="container-fluid">
<div class="container" >
{include file="navbar_public" loginStatus=$loginStatus userData=$userData /}
<div class="header-panel shadow-z-2">
<div class="container-fluid">
<div class="row">
</div>
</div>
</div>
<div class="container main" >
<div class="col-md-4"></div>
<div class="col-md-4">
<div class="jumbotron" >
<div class="card_top">
<div class="row top-color">
<div class="card-top-row">
<div class="login-icon"><i class="fa fa-id-card-o" aria-hidden="true"></i></div>
<div class="login-text">密码重置</div>
</div>
</div>
</div>
<div class="card_botom">
<div class="row bottom-width">
<form id="resetForm">
<div class="form-group label-floating">
<label class="control-label" for="inputPwd">请输入新密码</label>
<input type="password" class="form-control" id="inputPwd" name="password-reg">
</div>
<div class="form-group label-floating">
<label class="control-label" for="inputPwd">重复密码</label>
<input type="password" class="form-control" id="inputPwd" name="password-check">
</div>
<input type="text" style="display:none" class="form-control" id="resetKey" name="key" value="{$key}">
</form> <button class="btn btn-raised btn-primary" id="regButton">重设密码</button>
</div>
</div>
</div>
</div>
</div></div>
<div class="col-md-4"></div>
</div>
</div>
</body>
<script type="text/javascript">
</script>
<script src="/static/js/reset.js"> </script>
{$options.js_code}
{/block}
-265
View File
@@ -1,265 +0,0 @@
{extend name="header_home" /}
{block name="title"}用户设置- {$options.siteName}{/block}
{block name="content"}
<link rel="stylesheet" href="/static/css/setting.css" />
<style type="text/css">
.col-md-3{
padding-right: 15px;
padding-left: 15px;
}
</style>
</head>
<body >
<div id="container">
{include file="navbar_home" /}
<div class="col-md-10 quota_content">
<h1>用户设置</h1>
<br>
<div class="fix_side">
<div class="fix">
<div class="col-md-9">
<ul class="nav nav-tabs" >
<li class="active"><a href="#home" data-toggle="tab" aria-expanded="true">基本信息<div class="ripple-container"></div></a></li>
<li class=""><a href="#security" data-toggle="tab" aria-expanded="false">安全隐私<div class="ripple-container"></div></a></li>
<li class=""><a href="#password" data-toggle="tab" aria-expanded="false">修改密码<div class="ripple-container"></div></a></li>
<li class=""><a href="#webdav" data-toggle="tab" aria-expanded="false">WebDAV<div class="ripple-container"></div></a></li>
</ul>
<div id="myTabContent" class="tab-content">
<div class="tab-pane fade active in" id="home">
<div class="panel panel-default">
<div class="panel-body" id="packs">
<div class="col-md-8">
<div class="row fix">
<div class="col-md-3 option_name"><label for="uid">UID</label></div>
<div class="col-md-9">
<div class="non_input">{$userInfo.uid}</div>
</div>
</div>
<div class="row fix">
<div class="col-md-3 option_name"><label for="nick">昵称:</label></div>
<div class="col-md-6">
<input type="text" class="form-control" id="nick" value="{$userInfo.userNick}" >
</div>
</div>
<div class="row fix">
<div class="col-md-3 option_name"><label for="email">Email</label></div>
<div class="col-md-9">
<input type="email" class="form-control" id="email" value="{$userInfo.userMail}" disabled>
</div>
</div>
<div class="row fix">
<div class="col-md-3 option_name"><label for="inputEmail">用户组:</label></div>
<div class="col-md-9">
<div class="non_input group">{$groupData.group_name} </div>
</div>
</div>
<div class="row fix">
<div class="col-md-3 option_name"><label for="inputEmail">注册日期:</label></div>
<div class="col-md-9">
<div class="non_input ">{$userInfo.regDate}</div>
</div>
</div>
<div class="row fix">
<div class="col-md-3 option_name"><label for="inputEmail"></label></div>
<div class="col-md-9">
<div class="non_input "><button class="btn btn-raised btn-primary" id="saveNick">保存更改</button></div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="avatar">
<img src="/Member/Avatar/{$userInfo.uid}/l?cache=no" class="img-circle avatar-img"><br>
<button class="btn btn-primary" data-toggle="modal" data-target="#avatar_modal"><i class="fa fa-pencil-square-o" aria-hidden="true"></i> 修改头像</button>
</div>
</div>
</div>
</div>
</div>
<div class="tab-pane fade" id="security">
<div class="panel panel-default">
<div class="panel-body" >
<div class="row fix">
<div class="col-md-3 option_name"><label for="inputEmail">个人主页:</label></div>
<div class="col-md-9">
<div ><div class="togglebutton">
<label>
<input type="checkbox" id="homePage" {eq name="$userSQL.profile" value="1"}checked{else}{/eq}>
</label>
</div></div>
</div>
</div>
<div class="row fix">
<div class="col-md-3 option_name" style="margin-top: 10px;"><label for="inputEmail">二步验证:</label></div>
<div class="col-md-9">
{eq name="$userSQL.two_step" value="0"}
<button class="btn btn-primary btn-raised" id="twoStep"><i class="fa fa-lock" aria-hidden="true"></i> 开启二步验证</button>
{else}
<button class="btn btn-primary btn-raised"><i class="fa fa-check" aria-hidden="true"></i> 已开启</button>
{/eq}
</div>
</div>
</div>
</div>
</div>
<div class="tab-pane fade" id="password">
<div class="panel panel-default">
<div class="panel-body" >
<div class="row fix">
<div class="col-md-3 option_name"><label for="inputEmail">原密码:</label></div>
<div class="col-md-6">
<input type="password" class="form-control" id="passOrigin" >
</div>
</div>
<div class="row fix">
<div class="col-md-3 option_name"><label for="inputEmail">新密码:</label></div>
<div class="col-md-6">
<input type="password" class="form-control" id="passNew" >
</div>
</div>
<div class="row fix">
<div class="col-md-3 option_name"><label for="inputEmail">确认新密码:</label></div>
<div class="col-md-6">
<input type="password" class="form-control" id="passNewRepet" >
</div>
</div>
<div class="row fix">
<div class="col-md-3 option_name"><label for="inputEmail"></label></div>
<div class="col-md-9">
<div class="non_input "><button class="btn btn-raised btn-primary waves-effect" id="savePwd">保存更改</button></div>
</div>
</div>
</div>
</div>
</div>
<div class="tab-pane fade" id="webdav">
<div class="panel panel-default">
<div class="panel-body" >
{eq name="groupData.webdav" value="0"}
<div class="alert alert-warning" role="alert">
您当前的用户组不支持WebDAV
</div>
{else/}
<div class="row fix">
<div class="col-md-3 option_name"><label for="inputEmail">连接地址:</label></div>
<div class="col-md-6">
<input type="text" class="form-control" id="webdavUrl" value="{$options.siteURL}WebDav/Api/uid/{$userInfo.uid}" spellcheck="false" readonly>
</div>
</div>
<div class="row fix">
<div class="col-md-3 option_name"><label for="inputEmail">用户名:</label></div>
<div class="col-md-6">
<input type="text" class="form-control" id="webdavUsername" value="{$userInfo.userMail}" spellcheck="false" readonly>
</div>
</div>
<div class="row fix">
<div class="col-md-3 option_name" style="margin-top: 10px;"><label for="inputEmail">登录密码:</label></div>
<div class="col-md-9">
<button class="btn btn-primary btn-raised" id="setWebdavPwd"><i class="fa fa-lock" aria-hidden="true"></i> 设置/更改密码</button>
</div>
</div>
{/eq}<br>
<p>你可以使用任何支持WebDAV协议的文件管理工具或操作系统将网盘映射到本地,方便多端同步管理。初次使用请先设置WebDAV登录密码,此密码默认与登录密码不相同。</p>
</div>
</div>
</div>
</div>
</div>
<div class="col-md-3"><div class="panel panel-default">
<div class="panel-heading">公告</div>
<div class="panel-body">
公告内容
</div>
</div></div>
</div>
</div>
<br>
<div class="fix_side">
<div class="fix">
</div>
</div>
</div>
<div class="modal fade" tabindex="-1" role="dialog" id="avatar_modal">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">修改头像</h4>
</div>
<div class="modal-body">
<div class="row fix">
<div class="col-md-4"><div class="avatar"><img src="/Member/Avatar/{$userInfo.uid}/l?cache=no" class="img-circle avatar-img"><br></div></div>
<div class="col-md-8">
<span class="btn btn-raised btn-info fileinput-button" id="uploadAvatar">
<span id="upload-text">上传头像</span>
<input type="file" accept="image/*" id="avatar_file" name="avatar">
</span>
<br><button class="btn btn-raised btn-info" id="useGravatar">使用Gravatar头像</button>
<br>修改头像后请清理浏览器缓存
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-primary " data-dismiss="modal">取消</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<div class="modal fade" tabindex="-1" role="dialog" id="two_step_modal">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">开启二步验证</h4>
</div>
<div class="modal-body">
<div class="row fix">
<div class="col-md-4"><img id="qrcode"></div>
<div class="col-md-8">
<div class="alert alert-success" role="alert">请使用任意二步验证APP或者支持二步验证的密码管理软件扫描左侧二维码添加本站。扫描完成后请填写二步验证APP给出的6位验证码以开启二步验证。</div>
<input type="number" class="form-control" placeholder="请输入6位验证码" id="vCode">
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-info " id="confirm">确认开启</button>
<button class="btn btn-primary " data-dismiss="modal">取消</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<div class="modal fade" tabindex="-1" role="dialog" id="set_webdav_pwd">
<div class="modal-dialog modal-sm" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">设置WebDAV认证密码</h4>
</div>
<div class="modal-body">
<div class="row fix">
<label>请输入密码:</label>
<input type="password" id="webdav_pwd" class="form-control" autocomplete="false">
</div>
</div>
<div class="modal-footer">
<button class="btn btn-info " id="confirmWebdav">保存</button>
<button class="btn btn-primary " data-dismiss="modal">取消</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
</body>
<script src="/static/js/material.js"></script>
<script src="/static/js/uploader.min.js"></script>
<script type="text/javascript">
upload_load=0;
</script>
<script src="/static/js/setting.js"></script>
{$options.js_code}
</html>
{/block}
@@ -1,66 +0,0 @@
{extend name="header_public" /}
{block name="title"}两步验证- {$options.siteName}{/block}
{block name="content"}
<link rel="stylesheet" href="/static/css/login.css" />
<link rel="stylesheet" href="/static/css/photoswipe.css">
<link rel="stylesheet" href="/static/css/default-skin/default-skin.css">
<script src="/static/js/jquery.color.js"></script>
</head>
<body data-ma-header="teal">
<nav class="navbar navbar-inverse" >
<div class="container-fluid">
<div class="container" >
{include file="navbar_public" loginStatus=$loginStatus userData=$userData /}
<div class="header-panel shadow-z-2">
<div class="container-fluid">
<div class="row">
</div>
</div>
</div>
<div class="container main" >
<div class="col-md-4"></div>
<div class="col-md-4">
<div class="jumbotron" >
<div class="card_top">
<div class="row top-color">
<div class="card-top-row">
<div class="login-icon"><i class="fa fa-lock" aria-hidden="true"></i></div>
<div class="login-text">由于您开启了两步验证,请输入您的两步验证APP上显示的验证码</div>
</div>
</div>
</div>
<div class="card_botom">
<div class="row bottom-width">
<form id="loginForm">
<div class="form-group label-floating">
<label class="control-label" for="inputEmail">验证码</label>
<input type="text" class="form-control" id="inputEmail" name="code">
</div>
</form> <button class="btn btn-raised btn-primary" id="loginButton">继续登录</button>
<br>如果您丢失了两步验证秘钥,请联系站点管理员核验身份后取消二步验证。
</div>
</div>
</div>
</div>
</div></div>
<div class="col-md-4"></div>
</div>
</div>
</body>
<script type="text/javascript">
</script>
<script src="/static/js/two_step.js"> </script>
{$options.js_code}
{/block}
-140
View File
@@ -1,140 +0,0 @@
<nav class="navbar navbar-inverse" >
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<a class="navbar-brand" href="/">
</a>
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right">
<li class="dropdown">
<a href="#" class="dropdown-toggle avatar-a" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><img src="/Member/Avatar/{$userInfo.uid}/s" class="img-circle avatar-s"> {$userInfo.userNick} <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="/Profile/{$userInfo.uid}">个人主页</a></li>
<li><a href="/Member/Setting">设置</a></li>
<li role="separator" class="divider"></li>
<li><a href="/Member/LogOut">退出登录</a></li>
</ul>
</li>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
<!-- Modal -->
<div class="modal fade" id="upload_modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" onclick = "closeUpload()" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
<span class="sr-only">Close</span>
</button>
<h4 class="modal-title" id="myModalLabel">上传文件</h4>
</div>
<div class="modal-body">
<div class="row" style="margin-top: 20px;">
<input type="hidden" id="domain" value="http://7xocov.com1.z0.glb.clouddn.com/">
<input type="hidden" id="uptoken_url" value="uptoken">
<div class="up_button col-md-4">
<div id="container">
<button class="btn btn-raised btn-info btn-lg upload_button" id="pickfiles" >
<i class="glyphicon glyphicon-plus"></i>
<span id="up_text"></span>
</button>
</div>
</div>
<div style="display:none" id="success" class="indo col-md-8">
<div class="alert alert-success">
队列全部文件处理完毕
</div>
</div>
<div class="col-md-12 " align="center">
<div class="info_box" id="info_box">
<br>
<div class="drag_info">
<span class="info_icon"><i class="glyphicon glyphicon-inbox"></i></span>
<div class="info_text">拖动文件至此开始上传</div>
</div>
</div>
<div class="upload_box" style="display:none;" id="upload_box">
<table class="table table-striped table-hover text-left" style="display:none;">
<thead>
<tr>
<th class="col-md-4">文件名</th>
<th class="col-md-2">大小</th>
<th class="col-md-6">进度</th>
</tr>
</thead>
<tbody id="fsUploadProgress">
</tbody>
</table>
</div>
</div>
<div class="container" style="display: none;">
<div class="body">
</div>
</div>
</div>
<div class="modal-footer">
</div>
</div>
</div>
</div>
</div>
<div class="col-md-2 s" id="side">
<div class="list-group" id="b">
<a href="/Home" class="list-group-item">
<i class="fa fa-file" aria-hidden="true"></i>&nbsp;&nbsp;&nbsp; 我的文件
</a>
<a href="/Share/My" class="list-group-item"> <i class="fa fa-share-alt" aria-hidden="true"></i>&nbsp;&nbsp;&nbsp; 我的分享
</a>
<a href="/Explore/Search" class="list-group-item">
<i class="fa fa-search" aria-hidden="true"></i>&nbsp;&nbsp;&nbsp; 搜索分享
</a>
<a href="/Home/Album" class="list-group-item">
<i class="fa fa-picture-o" aria-hidden="true"></i>&nbsp;&nbsp;&nbsp; 图片集
</a>
</div>
<div clss="usage" style=" visibility: visible;
position: absolute;
width: 100%;
height: 100px;
top: auto;
bottom: 0px;
background-color: #f9f9f9;padding: 15px">
<div class="usage-title">容量使用:</div>
<div class="usage-bar">
<div class="progress progress-striped active">
<div class="progress-bar" id="memory_bar"></div>
</div>
</div>
<div class="usage-text"><span id="used">--</span>/<span id="total">--</span></div>
</div>
</div>
-42
View File
@@ -1,42 +0,0 @@
<div class="navbar-header">
<div >
<a class="navbar-brand" href="/">
</a>
</div>
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right">
{eq name="$loginStatus" value="1"}
<li class="dropdown">
<a href="#" class="dropdown-toggle avatar-a" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><img src="/Member/Avatar/{$userData.id}/s" class="img-circle avatar-s"> {$userData.user_nick} <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="/Home">我的文件</a></li>
<li><a href="/Profile/{$userData.id}">个人主页</a></li>
<li><a href="/Member/Setting">设置</a></li>
<li role="separator" class="divider"></li>
<li><a href="/Member/LogOut">退出登录</a></li>
</ul>
</li>
{else/}
<li >
<a href="/Login" class="dropdown-toggle" role="button" aria-haspopup="true" aria-expanded="false"><i class="fa fa-user mr-1"></i> 登录/注册 </a>
</li>
{/eq}
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</div>
</nav>
-115
View File
@@ -1,115 +0,0 @@
{extend name="header_public" /}
{block name="title"}用户主页 - {$options.siteName}{/block}
{block name="content"}
<link rel="stylesheet" href="/static/css/profile.css" />
</head>
<body data-ma-header="teal">
<nav class="navbar navbar-inverse" >
<div class="container-fluid">
<div class="container" >
{include file="navbar_public" /}
<div class="header-panel shadow-z-2">
<div class="container-fluid">
<div class="row">
</div>
</div>
</div>
<div class="container main-h">
<div class="col-md-3">
<div class="card type--profile">
<header class="card-heading card-background" id="card_img_02">
<img src="/Member/Avatar/{$userInfo.id}/l" alt="" class="img-circle">
<ul class="card-actions icons right-top">
<li class="dropdown" style="display: none;">
<a href="javascript:void(0)" data-toggle="dropdown" aria-expanded="false">
<i class="zmdi zmdi-more-vert text-white"></i>
</a>
<ul class="dropdown-menu dropdown-menu-right">
<li>
<a href="javascript:void(0)">Option One</a>
</li>
<li>
<a href="javascript:void(0)">Option Two</a>
</li>
<li>
<a href="javascript:void(0)">Option Three</a>
</li>
</ul>
</li>
</ul>
</header>
<div class="card-body">
<h3 class="name">{$userInfo.user_nick|htmlspecialchars=ENT_NOQUOTES}</h3>
<span class="title span-fix"><span class="label span-fix label-{$groupData.color}">{$groupData.group_name}</span></span>
</div>
<footer class="card-footer border-top">
<div class="row row p-t-10 p-b-10">
<div class="col-xs-4"><span class="count">{$shareCount}</span><span>公开分享</span></div>
<div class="col-xs-4"><span class="count">{$regDays}</span><span>注册天数</span></div>
<div class="col-xs-4"><span class="count">{$userInfo.id}</span><span>用户编号</span></div>
</div>
</footer>
</div>
</div>
<div class="col-md-9">
<div class="jumbotron">
<div class="card_botom">
<div class="row bottom-width">
<ul class="nav nav-tabs" >
<li id="all"><a href="?page=1" aria-expanded="true">全部分享<div class="ripple-container"></div></a></li>
<li id="hot"><a href="?type=hot" aria-expanded="false">热门分享<div class="ripple-container"></div></a></li>
</ul>
<div id="myTabContent" class="tab-content">
<div class="tab-pane fade active in">
<div class="panel panel-default">
<div class="panel-body" >
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th width="50%">文件名 </th>
<th class="cent">分享日期</th>
<th class="cent">下载次数</th>
<th class="cent">浏览次数</th>
</tr>
</thead>
<tbody>{volist name='list' id='shares'}
<tr>
<td >{switch $shares.source_type}
{case file}<i class="fa fa-file" aria-hidden="true"></i> {/case}
{case dir}<i class="fa fa-folder-open blue" aria-hidden="true"></i> {/case}
{/switch} <a href="/s/{$shares.share_key}" class="fname" target="_blank">{$shares.fileData|htmlspecialchars=ENT_NOQUOTES}</a></td>
<td class="cent">{$shares.share_time}</td>
<td align="center">{$shares.download_num}</td>
<td align="center">{$shares.view_num}</td>
</tr>
{/volist}
</tbody>
</table>
</div>
<div class="navi">
{eq name="$type" value="hot"}
{else/}
{$listOrigin->render()}
{/eq}
</div>
</div></div></div></div>
</div>
</div>
</div></div>
</div>
</div>
</body>
<script type="text/javascript">
</script>
<script src="/static/js/material.js"></script>
<script src="/static/js/profile.js"> </script>
{$options.js_code}
{/block}

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