Compare commits
224 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
aa94de4945 | ||
|
d99a14eaa9 | ||
|
7d914d45fb | ||
|
2243f2e6a5 | ||
|
4b6c8d796a | ||
|
d257b79067 | ||
|
6b147c7bfb | ||
|
0f2c9d095d | ||
|
184e01c0a6 | ||
|
136c654432 | ||
|
c122d5e44a | ||
|
d81d8a9298 | ||
|
a556a2be50 | ||
|
6ef253e44a | ||
|
252ffc5cb9 | ||
|
70e112a43a | ||
|
e8434f5d89 | ||
|
984aca0093 | ||
|
673ee7ccc7 | ||
|
059b2e16ed | ||
|
84d84e163b | ||
|
6da08269d8 | ||
|
ce939c3115 | ||
|
8889ac4e2e | ||
|
2a3f860473 | ||
|
5e72d0f6a3 | ||
|
bc4f964b24 | ||
|
3930e8c204 | ||
|
b1960a0d15 | ||
|
a1bb7552dc | ||
|
324242a584 | ||
|
78d6bf6c27 | ||
|
745985bf18 | ||
|
50167d3382 | ||
|
24d8359a2e | ||
|
869f1f5cda | ||
|
5ffc5cf6fd | ||
|
8966a517c6 | ||
|
a92c44ef0a | ||
|
59a41665b0 | ||
|
f7333eb51c | ||
|
02bf7079dd | ||
|
8a15390694 | ||
|
6f61a12772 | ||
|
566338020a | ||
|
52ff7462a9 | ||
|
427ca82722 | ||
|
c521ecd055 | ||
|
946c862dc4 | ||
|
2d371d112d | ||
|
77d6f4af7f | ||
|
e2a743bca5 | ||
|
ab4fa886c3 | ||
|
4b08092c18 | ||
|
0fd57cad51 | ||
|
db764b6780 | ||
|
44e53ab213 | ||
|
5af71185ff | ||
|
d714ea90fb | ||
|
1e12faa756 | ||
|
85ddff9c2d | ||
|
00232389ad | ||
|
e10fe49cc0 | ||
|
6c52ae659f | ||
|
3c54c1d66c | ||
|
940608d02a | ||
|
b6b8d9f144 | ||
|
c559edc208 | ||
|
4a41994556 | ||
|
d763d6b20a | ||
|
dc2a74d251 | ||
|
fe5ce111af | ||
|
a930f4ce1b | ||
|
dae89ba5d8 | ||
|
78df81266c | ||
|
b261c7e937 | ||
|
f9a7a217f8 | ||
|
4d96cb47ad | ||
|
0f4fe15195 | ||
|
d20d1e8b2c | ||
|
4130f7a6fd | ||
|
4ccd4bb030 | ||
|
16926f821d | ||
|
7b5599e9d1 | ||
|
834f3b5425 | ||
|
f0bee58869 | ||
|
03e89dab5e | ||
|
b7f25c45f2 | ||
|
e5966bc610 | ||
|
78bc1e2a1e | ||
|
0315e29b44 | ||
|
152dcb9b46 | ||
|
3a87b594a6 | ||
|
631a0f7aa3 | ||
|
5564559b7c | ||
|
0e0f06d634 | ||
|
e52b3dd440 | ||
|
c486962ff8 | ||
|
3fe1b2d6f8 | ||
|
691cbce10f | ||
|
4ccab28253 | ||
|
a6994150ca | ||
|
1d4b4b8a02 | ||
|
20e080751d | ||
|
8a4ccd098c | ||
|
9e0b1698fc | ||
|
18dfa1e09f | ||
|
83aad78ab0 | ||
|
9b88cdeb9b | ||
|
11030a17af | ||
|
aa7df50402 | ||
|
2008d0755c | ||
|
c7fdfc27a1 | ||
|
717e046bb9 | ||
|
5bbc88b8e2 | ||
|
babb952485 | ||
|
22b2db8daf | ||
|
8485905901 | ||
|
73e74bb887 | ||
|
a893cb7534 | ||
|
87e5472d42 | ||
|
05194167e1 | ||
|
6dbffb8be1 | ||
|
24945faded | ||
|
3761a40e50 | ||
|
f547d95f30 | ||
|
4a3e8c6734 | ||
|
07ccdbd734 | ||
|
47b46813db | ||
|
82c0ae88f8 | ||
|
749c8b29c9 | ||
|
d0b6197aec | ||
|
3b8edf9ad8 | ||
|
9c4f3111ba | ||
|
901d8c407d | ||
|
6b3ba18da1 | ||
|
cfbae4c5d5 | ||
|
7320592dc2 | ||
|
9234e3f287 | ||
|
95c473a7c7 | ||
|
3e14d7bed4 | ||
|
aebfdeb1cd | ||
|
131d153cf5 | ||
|
a3c9bc9db0 | ||
|
06b4d81a61 | ||
|
d8d7b997b5 | ||
|
26c4d569aa | ||
|
67d9e9794b | ||
|
0b8d7e5343 | ||
|
c3cd171785 | ||
|
171f1c12eb | ||
|
50644c84dc | ||
|
92e8e34a66 | ||
|
804df4c0fb | ||
|
41bb7d76b5 | ||
|
35df02984b | ||
|
e0fc7043b5 | ||
|
628836a201 | ||
|
00f9ee09d3 | ||
|
029d4ed5af | ||
|
cd7c3c3dd4 | ||
|
d5c9668013 | ||
|
2fb7f9129e | ||
|
f6150c58f4 | ||
|
3246525d78 | ||
|
fe9cdbc46b | ||
|
324fceb5c3 | ||
|
8656bdd74e | ||
|
8ef9575e51 | ||
|
1fc72d8473 | ||
|
2153056266 | ||
|
2240bd3ca1 | ||
|
127eaf9aac | ||
|
7d5945d45b | ||
|
1d2c45dc68 | ||
|
2ee4a18e1c | ||
|
f0a9937dc6 | ||
|
3a2e61b163 | ||
|
c4fa90a747 | ||
|
1cba9290b6 | ||
|
58cbad2bfd | ||
|
da9d027fed | ||
|
70d6528190 | ||
|
f7187fb14b | ||
|
7ec2bdf16a | ||
|
c7433b0d14 | ||
|
0179a5044b | ||
|
f37e8e7b89 | ||
|
ba670be7d8 | ||
|
93487de085 | ||
|
a2fb3d952d | ||
|
fada3c1e36 | ||
|
aa87ec15b0 | ||
|
a0db0e0ac3 | ||
|
a790c34a24 | ||
|
38daa4aa1f | ||
|
c92822ba7d | ||
|
18f2c72fd1 | ||
|
d03dc990fa | ||
|
882abd1972 | ||
|
2dd594ba13 | ||
|
8d5473903e | ||
|
69c1ffd92f | ||
|
808e37d034 | ||
|
60ef5ff983 | ||
|
171539643e | ||
|
793bfce202 | ||
|
10d6d2c3c1 | ||
|
51a161eede | ||
|
57b3ee6c2f | ||
|
641d9b3cfa | ||
|
5c2d84aaa9 | ||
|
8157ada8fc | ||
|
8e143a4607 | ||
|
e021862acf | ||
|
ed9f04a372 | ||
|
ca86993091 | ||
|
85bd0abd8d | ||
|
ed1ab4053c | ||
|
6aed4455d3 | ||
|
5f265672ae | ||
|
1653306440 | ||
|
d0fe566f8f | ||
|
11bab8d0a1 |
@@ -12,11 +12,11 @@ insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
|
||||
[{package.json,.travis.yml,.eslintrc,.babelrc}]
|
||||
[{*.json,*.yml}]
|
||||
indent_size = 2
|
||||
|
||||
|
||||
[{*.md,*.jade}]
|
||||
[{*.md,*.pug}]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
|
||||
|
@@ -1,3 +1,3 @@
|
||||
**/build/**
|
||||
**/node_modules/**
|
||||
**/vendor/**
|
||||
/build/
|
||||
/local/
|
||||
/node_modules/
|
||||
|
@@ -1,35 +1,12 @@
|
||||
---
|
||||
root: true
|
||||
|
||||
parser: babel-eslint
|
||||
|
||||
env:
|
||||
es6: true
|
||||
node: true
|
||||
|
||||
ecmaFeatures:
|
||||
arrowFunctions: true
|
||||
binaryLiterals: true
|
||||
blockBindings: true
|
||||
classes: false
|
||||
defaultParams: true
|
||||
destructuring: true
|
||||
forOf: true
|
||||
generators: true
|
||||
globalReturn: true
|
||||
jsx: false
|
||||
modules: true
|
||||
objectLiteralComputedProperties: true
|
||||
objectLiteralDuplicateProperties: true
|
||||
objectLiteralShorthandMethods: true
|
||||
objectLiteralShorthandProperties: true
|
||||
octalLiterals: true
|
||||
regexUFlag: true
|
||||
regexYFlag: true
|
||||
spread: true
|
||||
superInFunctions: false
|
||||
templateStrings: true
|
||||
unicodeCodePointEscapes: true
|
||||
parserOptions:
|
||||
ecmaVersion: 2020
|
||||
|
||||
rules:
|
||||
array-bracket-spacing: [2, never]
|
||||
@@ -41,7 +18,7 @@
|
||||
comma-dangle: [2, never]
|
||||
comma-spacing: [2, {before: false, after: true}]
|
||||
comma-style: [2, last]
|
||||
complexity: [1, 25] ###
|
||||
complexity: [1, 10] ###
|
||||
computed-property-spacing: [2, never]
|
||||
consistent-return: 2
|
||||
consistent-this: [2, self]
|
||||
@@ -59,12 +36,13 @@
|
||||
handle-callback-err: 2
|
||||
indent: [2, 4]
|
||||
key-spacing: [2, {beforeColon: false, afterColon: true}]
|
||||
keyword-spacing: [2, {before: true, after: true}]
|
||||
linebreak-style: [2, unix]
|
||||
max-depth: [1, 4]
|
||||
max-len: [0, 80, 4]
|
||||
max-nested-callbacks: [1, 3]
|
||||
max-params: [1, 5] ###
|
||||
max-statements: [1, 80] ###
|
||||
max-params: [1, 4] ###
|
||||
max-statements: [1, 30] ###
|
||||
new-cap: 0
|
||||
new-parens: 2
|
||||
newline-after-var: 0
|
||||
@@ -90,7 +68,6 @@
|
||||
no-else-return: 1
|
||||
no-empty: 2
|
||||
no-empty-character-class: 2
|
||||
no-empty-label: 2
|
||||
no-empty-pattern: 2
|
||||
no-eq-null: 2
|
||||
no-eval: 2
|
||||
@@ -181,7 +158,7 @@
|
||||
prefer-const: 1
|
||||
prefer-reflect: 1
|
||||
prefer-spread: 2
|
||||
prefer-template: 0 ###
|
||||
prefer-template: 0
|
||||
quote-props: [2, as-needed]
|
||||
quotes: [2, single, avoid-escape]
|
||||
radix: 2
|
||||
@@ -189,12 +166,10 @@
|
||||
semi: 2
|
||||
semi-spacing: [2, {before: false, after: true}]
|
||||
sort-vars: 0
|
||||
space-after-keywords: [2, always]
|
||||
space-before-blocks: [2, always]
|
||||
space-before-function-paren: [2, {anonymous: always, named: never}]
|
||||
space-in-parens: [2, never]
|
||||
space-infix-ops: 2
|
||||
space-return-throw-case: 2
|
||||
space-unary-ops: [2, {words: true, nonwords: false}]
|
||||
spaced-comment: [2, always]
|
||||
strict: [2, never]
|
10
.gitignore
vendored
@@ -1,4 +1,6 @@
|
||||
build
|
||||
local
|
||||
node_modules
|
||||
npm-debug.log
|
||||
/.nyc_output/
|
||||
/build/
|
||||
/coverage/
|
||||
/local/
|
||||
/node_modules/
|
||||
/npm-debug.log
|
||||
|
278
CHANGELOG.md
@@ -1,141 +1,219 @@
|
||||
# Changelog
|
||||
|
||||
|
||||
* now require PHP 7.0.0+
|
||||
* fix archive-single-item problem
|
||||
* add header/footer search stop condition
|
||||
* update languages (`id`, `it`, `pt-br`, `pt-pt`)
|
||||
* add EXIF-based image rotation
|
||||
* add `where` to command detection command list
|
||||
* fix #758
|
||||
* fix #760
|
||||
* add `@babel/core` 7.12.10
|
||||
* add `@babel/preset-env` 7.12.11
|
||||
* remove `babel-loader`
|
||||
* update `eslint` to 7.18.0
|
||||
* update `ghu` to 0.26.0
|
||||
* update `jsdom` to 16.4.0
|
||||
* update `kjua` to 0.9.0
|
||||
* update `lolight` to 1.4.0
|
||||
* update `marked` to 1.2.7
|
||||
* update `null-loader` to 4.0.1
|
||||
* update `scar` to 2.3.0
|
||||
|
||||
|
||||
## v0.29.2 - *2019-03-22*
|
||||
|
||||
* update `babel-loader` to 7.1.1
|
||||
* update `eslint` to 5.15.3
|
||||
* update `ghu` to 0.13.0
|
||||
* update `jsdom` to 14.0.0
|
||||
* update `kjua` to 0.2.0
|
||||
* update `lolight` to 1.0.0
|
||||
* update `scar` to 1.2.0
|
||||
|
||||
|
||||
## v0.29.1 - *2019-01-20*
|
||||
|
||||
* replace `babel-preset-es2015` with `babel-preset-env`
|
||||
* update `eslint` to 5.14.1
|
||||
* update `ghu` to 0.12.0
|
||||
* update `jsdom` to 9.2.0
|
||||
* update `kjua` to 0.1.2
|
||||
* update `lolight` to 0.6.0
|
||||
* update `marked` to 0.6.1
|
||||
* update `normalize.css` to 8.0.1
|
||||
* update `scar` to 1.0.0
|
||||
|
||||
|
||||
## v0.29.0 - *2016-08-12*
|
||||
|
||||
* back to cleaner visual experience
|
||||
* add option to disable sidebar
|
||||
* add options to filter/search ignore case
|
||||
* replace PHP `getenv` calls with `$_SERVER` lookups
|
||||
* add `view.fallbackMode` option to generally serve only fallback mode
|
||||
* serve fallback mode for text browsers (`curl`, `links`, `lynx`, `w3m`)
|
||||
* change type `txt-svg` to `img-svg`, no thumbs but preview
|
||||
* fix a tree indentation glitch
|
||||
* fix shell command detection on Windows
|
||||
* fix Piwik anayltics
|
||||
* fix `.htaccess` auth issues
|
||||
* fix drag-select on scrollable content
|
||||
* fix download-all function
|
||||
* fix audio and video preview loading
|
||||
* fix thumbnail request issues
|
||||
* add `rust` type and icon
|
||||
* add `autoplay` option to audio and video preview
|
||||
* add `--dereference` to `shell-du` to follow sym links
|
||||
* remove *Install* section from `README.md`, causes too much trouble
|
||||
* remove peer5 support
|
||||
* update build process to use `node 6.0+`, no need for babel now
|
||||
* replace `jquery-qrcode` with [`kjua`](https://larsjung.de/kjua/)
|
||||
* replace `prism` with [`lolight`](https://larsjung.de/lolight/)
|
||||
* move deps to `package.json` (`normalize.css`, `kjua`, `lolight` and `marked`)
|
||||
* remove `jQuery`
|
||||
* remove `lodash`
|
||||
* remove [`modulejs`](https://larsjung.de/modulejs/) for now
|
||||
* reduce JS code by 60% (~250kb -> ~100kb)
|
||||
* update languages (`et`, `nl`, `pl`)
|
||||
|
||||
|
||||
## v0.28.0 - *2015-12-19*
|
||||
|
||||
* now requires PHP 5.5.0+
|
||||
* changes index path to `/_h5ai/public/index.php`
|
||||
* now only `/_h5ai/public/` needs to be accessable from web
|
||||
* adds support for custom script and style additions
|
||||
* adds options to set font families
|
||||
* adds search
|
||||
* adds ignorecase sorting option to tree
|
||||
* adds wide links in tree view
|
||||
* adds IE edge mode
|
||||
* adds frontend tests
|
||||
* fixes some styles in IE10
|
||||
* fixes preview bottom bar for small screen widths
|
||||
* now require PHP 5.5.0+
|
||||
* change index path to `/_h5ai/public/index.php`
|
||||
* now only `/_h5ai/public/` needs to be web-accessible
|
||||
* add support for custom script and style additions
|
||||
* add options to set font families
|
||||
* add search
|
||||
* add ignorecase sorting option to tree
|
||||
* add wide links in tree view
|
||||
* add IE edge mode
|
||||
* add frontend tests
|
||||
* fix some styles in IE10
|
||||
* fix preview bottom bar for small screen widths
|
||||
* lots of code cleanup and refactorings
|
||||
* changes API
|
||||
* updates build process, now uses [ghu](https://larsjung.de/ghu/)
|
||||
* switches from jshint and jscs to [eslint](http://eslint.org/)
|
||||
* updates `jQuery` to 2.1.4
|
||||
* updates `lodash` to 3.9.3 (adds debounce and trim)
|
||||
* updates `marked` to 0.3.5
|
||||
* updates `modulejs` to 1.13.0
|
||||
* updates `prism` to 2015-12-19
|
||||
* updates h5bp styles to 5.2.0
|
||||
* updates `normalize.css` to 3.0.3
|
||||
* removes `Moment.js`
|
||||
* change API
|
||||
* update build process, now uses [`ghu`](https://larsjung.de/ghu/)
|
||||
* switch from jshint and jscs to [`eslint`](http://eslint.org/)
|
||||
* update `jQuery` to 2.1.4
|
||||
* update `lodash` to 3.9.3 (add debounce and trim)
|
||||
* update `marked` to 0.3.5
|
||||
* update `modulejs` to 1.13.0
|
||||
* update `prism` to 2015-12-19
|
||||
* update h5bp styles to 5.2.0
|
||||
* update `normalize.css` to 3.0.3
|
||||
* remove `Moment.js`
|
||||
|
||||
|
||||
## v0.27.0 - *2015-04-06*
|
||||
|
||||
* new layout
|
||||
* adds editorconfig
|
||||
* drops support for IE9 (gets fallback)
|
||||
* updates sidebar settings
|
||||
* adds info sidebar
|
||||
* adds opt-out for click'n'drag selection
|
||||
* adds package name option for single selections
|
||||
* adds initial support for Peer5
|
||||
* adds option to down-sample images for preview
|
||||
* adds option for natural sorting in tree sidebar
|
||||
* fixes problems with files/folders named `0`
|
||||
* changes font from `Ubuntu` to `Roboto` (smaller footprint, clearer for small sizes)
|
||||
* switches back to Google Fonts
|
||||
* improves PDF thumbnail quality
|
||||
* improves drag-select
|
||||
* improves image preview
|
||||
* prevents listing `_h5ai` folder and subfolders
|
||||
* updates build process, now uses [mkr](https://larsjung.de/mkr/) and [fQuery](https://larsjung.de/fquery/)
|
||||
* updates `jQuery` to 2.1.3
|
||||
* updates `jQuery.qrcode` to 0.11.0
|
||||
* updates `Lo-Dash` to 3.6.0
|
||||
* updates `Modernizr` to 2.8.3
|
||||
* updates `modulejs` to 1.4.0
|
||||
* updates `Moment.js` to 2.9.0
|
||||
* updates `Prism` to 2015-04-05
|
||||
* removes deprecated Google Analytics code
|
||||
* removes `jQuery.fracs`
|
||||
* removes `jQuery.scrollpanel`
|
||||
* removes `jQuery.mousewheel`
|
||||
* language updates and additions (`af`, `es`, `ja`, `ko`, `ru`, `zh-cn`)
|
||||
* add editorconfig
|
||||
* drop support for IE9 (gets fallback)
|
||||
* update sidebar settings
|
||||
* add info sidebar
|
||||
* add opt-out for click'n'drag selection
|
||||
* add package name option for single selections
|
||||
* add initial support for Peer5
|
||||
* add option to down-sample images for preview
|
||||
* add option for natural sorting in tree sidebar
|
||||
* fix problems with files/folders named `0`
|
||||
* change font from `Ubuntu` to `Roboto` (smaller footprint, clearer for small sizes)
|
||||
* switch back to Google Fonts
|
||||
* improve PDF thumbnail quality
|
||||
* improve drag-select
|
||||
* improve image preview
|
||||
* prevent listing `_h5ai` folder and subfolders
|
||||
* update build process, now uses [`mkr`](https://larsjung.de/mkr/) and [`fQuery`](https://larsjung.de/fquery/)
|
||||
* update `jQuery` to 2.1.3
|
||||
* update `jQuery.qrcode` to 0.11.0
|
||||
* update `Lo-Dash` to 3.6.0
|
||||
* update `Modernizr` to 2.8.3
|
||||
* update `modulejs` to 1.4.0
|
||||
* update `Moment.js` to 2.9.0
|
||||
* update `Prism` to 2015-04-05
|
||||
* remove deprecated Google Analytics code
|
||||
* remove `jQuery.fracs`
|
||||
* remove `jQuery.scrollpanel`
|
||||
* remove `jQuery.mousewheel`
|
||||
* update languages (`af`, `es`, `ja`, `ko`, `ru`, `zh-cn`)
|
||||
|
||||
|
||||
## v0.26.1 - *2014-08-17*
|
||||
|
||||
* fixes links
|
||||
* fix links
|
||||
|
||||
|
||||
## v0.26.0 - *2014-08-16*
|
||||
|
||||
* removes True Type fonts
|
||||
* outsources themes to [h5ai-themes](https://github.com/lrsjng/h5ai-themes)
|
||||
* adds filesize fallback for large files and 32bit PHP
|
||||
* fixes server detection
|
||||
* adds config file tests to info page
|
||||
* removes JSON shim
|
||||
* adds caching of command checks
|
||||
* updates `jQuery.mousewheel` to 3.1.12
|
||||
* updates `jQuery.qrcode` to 0.8.0
|
||||
* replaces `markdown` with [`marked`](https://github.com/chjj/marked) 0.3.2
|
||||
* updates `modulejs` to 0.4.5
|
||||
* updates `Moment.js` to 2.8.1
|
||||
* replaces `underscore` with [`Lo-Dash`](https://github.com/lodash/lodash) 2.4.1
|
||||
* replaces `SyntaxHighlighter` with [`Prism`](http://prismjs.com) 2014-08-04
|
||||
* remove True Type fonts
|
||||
* outsource themes to [h5ai-themes](https://github.com/lrsjng/h5ai-themes)
|
||||
* add filesize fallback for large files and 32bit PHP
|
||||
* fix server detection
|
||||
* add config file tests to info page
|
||||
* remove JSON shim
|
||||
* add caching of command checks
|
||||
* update `jQuery.mousewheel` to 3.1.12
|
||||
* update `jQuery.qrcode` to 0.8.0
|
||||
* replace `markdown` with [`marked`](https://github.com/chjj/marked) 0.3.2
|
||||
* update `modulejs` to 0.4.5
|
||||
* update `Moment.js` to 2.8.1
|
||||
* replace `underscore` with [`Lo-Dash`](https://github.com/lodash/lodash) 2.4.1
|
||||
* replace `SyntaxHighlighter` with [`Prism`](http://prismjs.com) 2014-08-04
|
||||
|
||||
|
||||
## v0.25.2 - *2014-07-01*
|
||||
|
||||
* adds optional info page protection
|
||||
* fixes `short_open_tag` issues for PHP < 5.4.0
|
||||
* fixes default folder download (`alwaysVisible` option)
|
||||
* add optional info page protection
|
||||
* fix `short_open_tag` issues for PHP < 5.4.0
|
||||
* fix default folder download (`alwaysVisible` option)
|
||||
* minor fixes
|
||||
|
||||
|
||||
## v0.25.1 - *2014-06-25*
|
||||
|
||||
* fixes broken paths for filenames containing '+' characters
|
||||
* fixes Google Universal Analytics
|
||||
* fixes file type check
|
||||
* fix broken paths for filenames containing '+' characters
|
||||
* fix Google Universal Analytics
|
||||
* fix file type check
|
||||
|
||||
|
||||
## v0.25.0 - *2014-06-22*
|
||||
|
||||
* adds sidebar
|
||||
* adds initial theme support
|
||||
* adds icons from [Evolvere Icon Theme](http://franksouza183.deviantart.com/art/Evolvere-Icon-theme-440718295)
|
||||
* adds PHP variant to calc folder sizes
|
||||
* adds scroll position reset on location change (issue [#279](https://github.com/lrsjng/h5ai/issues/279))
|
||||
* adds option to hide unreadable files
|
||||
* adds option where to place folders (top, inplace, bottom)
|
||||
* adds markdown support for custom header and footer files
|
||||
* adds video and audio preview via HTML5 elements (no fallback, works best in Chrome)
|
||||
* adds filter reset on location change
|
||||
* adds option to make download button always visible
|
||||
* adds Google UA support
|
||||
* extends selectable icon sizes (adds 128px, 192px, 256px, 384px)
|
||||
* improves preview GUI
|
||||
* add sidebar
|
||||
* add initial theme support
|
||||
* add icons from [Evolvere Icon Theme](http://franksouza183.deviantart.com/art/Evolvere-Icon-theme-440718295)
|
||||
* add PHP variant to calc folder sizes
|
||||
* add scroll position reset on location change (issue [#279](https://github.com/lrsjng/h5ai/issues/279))
|
||||
* add option to hide unreadable files
|
||||
* add option where to place folders (top, inplace, bottom)
|
||||
* add markdown support for custom header and footer files
|
||||
* add video and audio preview via HTML5 elements (no fallback, works best in Chrome)
|
||||
* add filter reset on location change
|
||||
* add option to make download button always visible
|
||||
* add Google UA support
|
||||
* extend selectable icon sizes (add 128px, 192px, 256px, 384px)
|
||||
* improve preview GUI
|
||||
* disable thumbs in `cache` folder
|
||||
* fixes QR code URI origin (issue [#287](https://github.com/lrsjng/h5ai/issues/287))
|
||||
* replaces PHP backtick operator with `exec`
|
||||
* removes server side file manipulation extensions `dropbox`, `delete` and `rename`
|
||||
* updates `H5BP` to 4.3.0
|
||||
* updates `jQuery` to 2.1.1
|
||||
* updates `json2.js` to 2014-02-04
|
||||
* updates `markdown-js` to 0.5.0
|
||||
* updates `Modernizr` to 2.8.2
|
||||
* updates `Moment.js` to 2.6.0
|
||||
* updates `Underscore.js` to 1.6.0
|
||||
* language updates (`bg`, `ko`, `pt`, `sl`, `sv`, `zh-cn`)
|
||||
* fix QR code URI origin (issue [#287](https://github.com/lrsjng/h5ai/issues/287))
|
||||
* replace PHP backtick operator with `exec`
|
||||
* remove server side file manipulation extensions `dropbox`, `delete` and `rename`
|
||||
* update `H5BP` to 4.3.0
|
||||
* update `jQuery` to 2.1.1
|
||||
* update `json2.js` to 2014-02-04
|
||||
* update `markdown-js` to 0.5.0
|
||||
* update `Modernizr` to 2.8.2
|
||||
* update `Moment.js` to 2.6.0
|
||||
* update `Underscore.js` to 1.6.0
|
||||
* update languages (`bg`, `ko`, `pt`, `sl`, `sv`, `zh-cn`)
|
||||
|
||||
|
||||
## v0.24.1 - *2014-04-09*
|
||||
|
||||
* security fixes! (issues [#268](https://github.com/lrsjng/h5ai/issues/268), [#269](https://github.com/lrsjng/h5ai/issues/269))
|
||||
* language updates (`fi`, `fr`, `hi`, `it`, `zh-tw`)
|
||||
* fixes WinOS command detection
|
||||
* fix WinOS command detection
|
||||
* update languages (`fi`, `fr`, `hi`, `it`, `zh-tw`)
|
||||
|
||||
|
||||
## v0.24.0 - *2013-09-04*
|
||||
|
28
README.md
@@ -2,23 +2,16 @@
|
||||
|
||||
[![license][license-img]][github] [![web][web-img]][web] [![github][github-img]][github]
|
||||
|
||||
A modern HTTP web server index for Apache httpd, lighttpd, nginx and Cherokee.
|
||||
For bug reports and feature requests please use [issues][github-issues].
|
||||
A modern HTTP web server index for Apache httpd, lighttpd, and nginx.
|
||||
|
||||
There was a [security flaw][cve] in versions 0.22.0 - 0.24.1 that was fixed in
|
||||
0.25.0. If you are still using one of these versions you are advised to
|
||||
upgrade.
|
||||
|
||||
## Install
|
||||
## Important
|
||||
|
||||
Do **not** install any files from the `src` folder, they need to be
|
||||
preprocessed to work correctly! Find a preprocessed package and detailed
|
||||
install instructions on the [project page][web].
|
||||
|
||||
In short you have to take the following two steps:
|
||||
|
||||
* place folder `_h5ai` in the document root folder of the web server
|
||||
* append `/_h5ai/public/index.php` to the end of the default index-file list
|
||||
* Do **not** install any files from the `src` folder, they need to be
|
||||
preprocessed to work correctly!
|
||||
* Find a preprocessed package and detailed install instructions on the
|
||||
[project page][web].
|
||||
* For bug reports and feature requests please use [issues][github-issues].
|
||||
|
||||
|
||||
## Build
|
||||
@@ -27,7 +20,8 @@ There are installation ready packages for the latest [releases][release] and
|
||||
[dev builds][develop]. But to build **h5ai** yourself either `git clone` or
|
||||
download the repository. From within the root folder run the following
|
||||
commands to find a fresh zipball in folder `build` (tested on linux only,
|
||||
requires [`node 4.0+`][node] to be installed).
|
||||
requires [`node 10.0+`][node] to be installed, might work on other
|
||||
configurations).
|
||||
|
||||
~~~sh
|
||||
> npm install
|
||||
@@ -39,7 +33,7 @@ requires [`node 4.0+`][node] to be installed).
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Lars Jung (https://larsjung.de)
|
||||
Copyright (c) 2020 Lars Jung (https://larsjung.de)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -77,5 +71,3 @@ too. Exceptions are some [Material Design icons][material-design-icons] (CC BY 4
|
||||
[license-img]: https://img.shields.io/badge/license-MIT-a0a060.svg?style=flat-square
|
||||
[web-img]: https://img.shields.io/badge/web-larsjung.de/h5ai-a0a060.svg?style=flat-square
|
||||
[github-img]: https://img.shields.io/badge/github-lrsjng/h5ai-a0a060.svg?style=flat-square
|
||||
|
||||
[cve]: https://larsjung.de/h5ai/cve-2015-3203.txt
|
||||
|
102
ghu.js
@@ -1,8 +1,7 @@
|
||||
const {resolve, join} = require('path');
|
||||
const {
|
||||
ghu,
|
||||
autoprefixer, cssmin, each, ife, includeit, jade, jszip,
|
||||
less, mapfn, newerThan, read, remove, run, uglify, watch, wrap, write
|
||||
ghu, autoprefixer, cssmin, each, ife, includeit, jszip, less, mapfn,
|
||||
pug, read, remove, run, uglify, watch, webpack, wrap, write
|
||||
} = require('ghu');
|
||||
|
||||
const ROOT = resolve(__dirname);
|
||||
@@ -10,7 +9,27 @@ const SRC = join(ROOT, 'src');
|
||||
const TEST = join(ROOT, 'test');
|
||||
const BUILD = join(ROOT, 'build');
|
||||
|
||||
const mapper = mapfn.p(SRC, BUILD).s('.less', '.css').s('.jade', '');
|
||||
const mapper = mapfn.p(SRC, BUILD).s('.less', '.css').s('.pug', '');
|
||||
const WEBPACK_CFG = {
|
||||
mode: 'none',
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
use: {
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
presets: ['@babel/preset-env']
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /jsdom/,
|
||||
use: 'null-loader'
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
ghu.defaults('release');
|
||||
|
||||
@@ -28,9 +47,8 @@ ghu.before(runtime => {
|
||||
}
|
||||
|
||||
runtime.comment = `${runtime.pkg.name} v${runtime.pkg.version} - ${runtime.pkg.homepage}`;
|
||||
runtime.commentJs = `/* ${runtime.comment} */\n`;
|
||||
runtime.commentHtml = `<!-- ${runtime.comment} -->`;
|
||||
|
||||
runtime.comment_js = `/* ${runtime.comment} */\n`;
|
||||
runtime.comment_html = `<!-- ${runtime.comment} -->`;
|
||||
console.log(runtime.comment);
|
||||
});
|
||||
|
||||
@@ -45,88 +63,67 @@ ghu.task('clean', 'delete build folder', () => {
|
||||
return remove(BUILD);
|
||||
});
|
||||
|
||||
ghu.task('lint', 'lint all JavaScript files with eslint', () => {
|
||||
return run('eslint .', {stdio: 'inherit'});
|
||||
});
|
||||
|
||||
ghu.task('build:scripts', runtime => {
|
||||
return read(`${SRC}/_h5ai/public/js/*.js`)
|
||||
.then(newerThan(mapper, `${SRC}/_h5ai/public/js/**`))
|
||||
return read(`${SRC}/_h5ai/public/js/scripts.js`)
|
||||
.then(webpack(WEBPACK_CFG))
|
||||
.then(wrap('\n\n// @include "pre.js"\n\n'))
|
||||
.then(includeit())
|
||||
.then(ife(() => runtime.args.production, uglify()))
|
||||
.then(wrap(runtime.commentJs))
|
||||
.then(wrap(runtime.comment_js))
|
||||
.then(write(mapper, {overwrite: true}));
|
||||
});
|
||||
|
||||
ghu.task('build:styles', runtime => {
|
||||
return read(`${SRC}/_h5ai/public/css/*.less`)
|
||||
.then(newerThan(mapper, `${SRC}/_h5ai/public/css/**`))
|
||||
.then(includeit())
|
||||
.then(less())
|
||||
.then(autoprefixer())
|
||||
.then(ife(() => runtime.args.production, cssmin()))
|
||||
.then(wrap(runtime.commentJs))
|
||||
.then(wrap(runtime.comment_js))
|
||||
.then(write(mapper, {overwrite: true}));
|
||||
});
|
||||
|
||||
ghu.task('build:pages', runtime => {
|
||||
return read(`${SRC}: **/*.jade, ! **/*.tpl.jade`)
|
||||
.then(newerThan(mapper, `${SRC}/**/*.tpl.jade`))
|
||||
.then(jade({pkg: runtime.pkg}))
|
||||
.then(wrap('', runtime.commentHtml))
|
||||
return read(`${SRC}: **/*.pug, ! **/*.tpl.pug`)
|
||||
.then(pug({pkg: runtime.pkg}))
|
||||
.then(wrap('', runtime.comment_html))
|
||||
.then(write(mapper, {overwrite: true}));
|
||||
});
|
||||
|
||||
ghu.task('build:copy', runtime => {
|
||||
const mapperRoot = mapfn.p(ROOT, join(BUILD, '_h5ai'));
|
||||
const mapper_root = mapfn.p(ROOT, join(BUILD, '_h5ai'));
|
||||
|
||||
return Promise.all([
|
||||
read(`${SRC}/**/conf/*.json`)
|
||||
.then(newerThan(mapper))
|
||||
.then(wrap(runtime.commentJs))
|
||||
.then(wrap(runtime.comment_js))
|
||||
.then(write(mapper, {overwrite: true, cluster: true})),
|
||||
|
||||
read(`${SRC}: **, ! **/*.js, ! **/*.less, ! **/*.jade, ! **/conf/*.json`)
|
||||
.then(newerThan(mapper))
|
||||
read(`${SRC}: **, ! **/*.js, ! **/*.less, ! **/*.pug, ! **/conf/*.json`)
|
||||
.then(each(obj => {
|
||||
if (/index\.php$/.test(obj.source)) {
|
||||
if ((/index\.php$/).test(obj.source)) {
|
||||
obj.content = obj.content.replace('{{VERSION}}', runtime.pkg.version);
|
||||
}
|
||||
}))
|
||||
.then(write(mapper, {overwrite: true, cluster: true})),
|
||||
|
||||
read(`${ROOT}/*.md`)
|
||||
.then(newerThan(mapperRoot))
|
||||
.then(write(mapperRoot, {overwrite: true, cluster: true}))
|
||||
.then(write(mapper_root, {overwrite: true, cluster: true}))
|
||||
]);
|
||||
});
|
||||
|
||||
ghu.task('build:tests', ['build:scripts', 'build:styles'], 'build the test suite', runtime => {
|
||||
ghu.task('build:tests', ['build:styles'], 'build the test suite', () => {
|
||||
return Promise.all([
|
||||
read(`${TEST}/scripts.js`)
|
||||
.then(newerThan(`${BUILD}/test/scripts.js`))
|
||||
.then(includeit())
|
||||
.then(write(`${BUILD}/test/scripts.js`, {overwrite: true})),
|
||||
read(`${BUILD}/_h5ai/public/css/styles.css`)
|
||||
.then(write(`${BUILD}/test/h5ai-styles.css`, {overwrite: true})),
|
||||
|
||||
read(`${TEST}/styles.less`)
|
||||
.then(newerThan(`${BUILD}/test/styles.css`))
|
||||
.then(includeit())
|
||||
.then(less())
|
||||
.then(autoprefixer())
|
||||
.then(write(`${BUILD}/test/styles.css`, {overwrite: true})),
|
||||
|
||||
read(`${TEST}/index.html.jade`)
|
||||
.then(newerThan(`${BUILD}/test/index.html`))
|
||||
.then(jade({pkg: runtime.pkg}))
|
||||
read(`${TEST}/index.html`)
|
||||
.then(write(`${BUILD}/test/index.html`, {overwrite: true})),
|
||||
|
||||
read(`${BUILD}/_h5ai/public/js/scripts.js`)
|
||||
.then(newerThan(`${BUILD}/test/h5ai-scripts.js`))
|
||||
.then(write(`${BUILD}/test/h5ai-scripts.js`, {overwrite: true})),
|
||||
|
||||
read(`${BUILD}/_h5ai/public/css/styles.css`)
|
||||
.then(newerThan(`${BUILD}/test/h5ai-styles.css`))
|
||||
.then(write(`${BUILD}/test/h5ai-styles.css`, {overwrite: true}))
|
||||
read(`${TEST}: index.js`)
|
||||
.then(webpack(WEBPACK_CFG))
|
||||
.then(wrap(`\n\n// @include "${SRC}/**/js/pre.js"\n\n`))
|
||||
.then(includeit())
|
||||
.then(write(mapfn.p(TEST, `${BUILD}/test`), {overwrite: true}))
|
||||
]).then(() => {
|
||||
console.log(`browse to file://${BUILD}/test/index.html to run the test suite`);
|
||||
});
|
||||
@@ -141,11 +138,10 @@ ghu.task('deploy', ['build'], 'deploy to a specified path with :dest=/some/path'
|
||||
}
|
||||
console.log(`deploy to ${runtime.args.dest}`);
|
||||
|
||||
const mapperDeploy = mapfn.p(BUILD, resolve(runtime.args.dest));
|
||||
const mapper_deploy = mapfn.p(BUILD, resolve(runtime.args.dest));
|
||||
|
||||
return read(`${BUILD}/_h5ai/**`)
|
||||
.then(newerThan(mapperDeploy))
|
||||
.then(write(mapperDeploy, {overwrite: true, cluster: true}));
|
||||
.then(write(mapper_deploy, {overwrite: true, cluster: true}));
|
||||
});
|
||||
|
||||
ghu.task('watch', runtime => {
|
||||
|
7428
package-lock.json
generated
Normal file
27
package.json
@@ -1,9 +1,8 @@
|
||||
{
|
||||
"name": "h5ai",
|
||||
"version": "0.28.0",
|
||||
"version": "0.30.0",
|
||||
"description": "Modern HTTP web server index.",
|
||||
"homepage": "https://larsjung.de/h5ai/",
|
||||
"bugs": "https://github.com/lrsjng/h5ai/issues",
|
||||
"author": "Lars Jung <lrsjng@gmail.com> (https://larsjung.de)",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
@@ -12,17 +11,21 @@
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint .",
|
||||
"ghu": "node -r babel-core/register ghu.js",
|
||||
"build": "npm run -s ghu release"
|
||||
"test": "node test",
|
||||
"build": "node ghu release",
|
||||
"precommit": "npm run -s lint && npm run -s test"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-core": "6.3.21",
|
||||
"babel-eslint": "5.0.0-beta6",
|
||||
"babel-preset-es2015": "6.3.13",
|
||||
"eslint": "1.10.3",
|
||||
"ghu": "0.4.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4.0.0"
|
||||
"@babel/core": "7.12.10",
|
||||
"@babel/preset-env": "7.12.11",
|
||||
"eslint": "7.18.0",
|
||||
"ghu": "0.26.0",
|
||||
"jsdom": "16.4.0",
|
||||
"kjua": "0.9.0",
|
||||
"lolight": "1.4.0",
|
||||
"marked": "1.2.7",
|
||||
"normalize.css": "8.0.1",
|
||||
"null-loader": "4.0.1",
|
||||
"scar": "2.3.0"
|
||||
}
|
||||
}
|
||||
|
@@ -1,43 +1,4 @@
|
||||
---
|
||||
env:
|
||||
es6: false
|
||||
node: false
|
||||
browser: true
|
||||
mocha: false
|
||||
|
||||
globals:
|
||||
modulejs: false
|
||||
|
||||
ecmaFeatures:
|
||||
arrowFunctions: false
|
||||
binaryLiterals: false
|
||||
blockBindings: false
|
||||
classes: false
|
||||
defaultParams: false
|
||||
destructuring: false
|
||||
forOf: false
|
||||
generators: false
|
||||
globalReturn: false
|
||||
jsx: false
|
||||
modules: false
|
||||
objectLiteralComputedProperties: false
|
||||
objectLiteralDuplicateProperties: false
|
||||
objectLiteralShorthandMethods: false
|
||||
objectLiteralShorthandProperties: false
|
||||
octalLiterals: false
|
||||
regexUFlag: false
|
||||
regexYFlag: false
|
||||
spread: false
|
||||
superInFunctions: false
|
||||
templateStrings: false
|
||||
unicodeCodePointEscapes: false
|
||||
|
||||
rules:
|
||||
consistent-this: 0
|
||||
func-names: 0
|
||||
max-params: [1, 10]
|
||||
no-invalid-this: 0
|
||||
no-var: 0
|
||||
object-shorthand: 0
|
||||
prefer-arrow-callback: 0
|
||||
no-console: 1
|
||||
prefer-reflect: 0
|
||||
|
@@ -1,3 +1,165 @@
|
||||
Satisfy all
|
||||
Order deny,allow
|
||||
Deny from all
|
||||
## details here: https://github.com/h5bp/server-configs-apache
|
||||
|
||||
|
||||
|
||||
## SECURITY ###################################################################
|
||||
|
||||
DirectoryIndex disabled
|
||||
FileETag None
|
||||
ServerSignature Off
|
||||
|
||||
# Apache < 2.3
|
||||
<IfModule !mod_authz_core.c>
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
Satisfy All
|
||||
</IfModule>
|
||||
|
||||
# Apache ≥ 2.3
|
||||
<IfModule mod_authz_core.c>
|
||||
Require all denied
|
||||
</IfModule>
|
||||
|
||||
<IfModule mod_headers.c>
|
||||
Header set X-Content-Type-Options "nosniff"
|
||||
Header unset ETag
|
||||
Header unset X-Powered-By
|
||||
</IfModule>
|
||||
|
||||
<IfModule mod_autoindex.c>
|
||||
Options -Indexes
|
||||
</IfModule>
|
||||
|
||||
|
||||
|
||||
## COMPAT #####################################################################
|
||||
|
||||
AddDefaultCharset utf-8
|
||||
|
||||
<IfModule mod_mime.c>
|
||||
AddCharset utf-8 .css .html .js .json .php .svg
|
||||
|
||||
AddType application/font-woff woff
|
||||
AddType application/font-woff2 woff2
|
||||
AddType application/json json
|
||||
AddType application/javascript js
|
||||
AddType application/vnd.ms-fontobject eot
|
||||
AddType application/x-font-ttf ttc ttf
|
||||
AddType image/jpeg jpeg jpg
|
||||
AddType image/png png
|
||||
AddType image/svg+xml svg svgz
|
||||
AddType image/x-icon ico
|
||||
AddType font/opentype otf
|
||||
AddType text/css css
|
||||
AddType text/html html
|
||||
</IfModule>
|
||||
|
||||
|
||||
|
||||
## SPEED ######################################################################
|
||||
|
||||
<IfModule mod_expires.c>
|
||||
ExpiresActive on
|
||||
ExpiresDefault "access plus 1 month"
|
||||
|
||||
ExpiresByType application/json "access plus 0 seconds"
|
||||
|
||||
ExpiresByType text/html "access plus 1 minute"
|
||||
|
||||
ExpiresByType image/x-icon "access plus 1 week"
|
||||
|
||||
ExpiresByType application/javascript "access plus 1 year"
|
||||
ExpiresByType image/jpeg "access plus 1 year"
|
||||
ExpiresByType image/png "access plus 1 year"
|
||||
ExpiresByType image/svg+xml "access plus 1 year"
|
||||
ExpiresByType text/css "access plus 1 year"
|
||||
</IfModule>
|
||||
|
||||
<IfModule mod_deflate.c>
|
||||
<IfModule mod_setenvif.c>
|
||||
<IfModule mod_headers.c>
|
||||
SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s*,?\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding
|
||||
RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding
|
||||
</IfModule>
|
||||
</IfModule>
|
||||
|
||||
# Apache ≥ 2.3
|
||||
<IfModule mod_authz_core.c>
|
||||
# mod_filter as module only available for Apache ≥ 2.3.7
|
||||
<IfModule mod_filter.c>
|
||||
AddOutputFilterByType DEFLATE "application/atom+xml" \
|
||||
"application/javascript" \
|
||||
"application/json" \
|
||||
"application/ld+json" \
|
||||
"application/manifest+json" \
|
||||
"application/rdf+xml" \
|
||||
"application/rss+xml" \
|
||||
"application/schema+json" \
|
||||
"application/vnd.geo+json" \
|
||||
"application/vnd.ms-fontobject" \
|
||||
"application/x-font-ttf" \
|
||||
"application/x-javascript" \
|
||||
"application/x-web-app-manifest+json" \
|
||||
"application/xhtml+xml" \
|
||||
"application/xml" \
|
||||
"font/eot" \
|
||||
"font/opentype" \
|
||||
"image/bmp" \
|
||||
"image/svg+xml" \
|
||||
"image/vnd.microsoft.icon" \
|
||||
"image/x-icon" \
|
||||
"text/cache-manifest" \
|
||||
"text/css" \
|
||||
"text/html" \
|
||||
"text/javascript" \
|
||||
"text/plain" \
|
||||
"text/vcard" \
|
||||
"text/vnd.rim.location.xloc" \
|
||||
"text/vtt" \
|
||||
"text/x-component" \
|
||||
"text/x-cross-domain-policy" \
|
||||
"text/xml"
|
||||
</IfModule>
|
||||
</IfModule>
|
||||
|
||||
# Apache < 2.3
|
||||
<IfModule !mod_authz_core.c>
|
||||
AddOutputFilterByType DEFLATE "application/atom+xml" \
|
||||
"application/javascript" \
|
||||
"application/json" \
|
||||
"application/ld+json" \
|
||||
"application/manifest+json" \
|
||||
"application/rdf+xml" \
|
||||
"application/rss+xml" \
|
||||
"application/schema+json" \
|
||||
"application/vnd.geo+json" \
|
||||
"application/vnd.ms-fontobject" \
|
||||
"application/x-font-ttf" \
|
||||
"application/x-javascript" \
|
||||
"application/x-web-app-manifest+json" \
|
||||
"application/xhtml+xml" \
|
||||
"application/xml" \
|
||||
"font/eot" \
|
||||
"font/opentype" \
|
||||
"image/bmp" \
|
||||
"image/svg+xml" \
|
||||
"image/vnd.microsoft.icon" \
|
||||
"image/x-icon" \
|
||||
"text/cache-manifest" \
|
||||
"text/css" \
|
||||
"text/html" \
|
||||
"text/javascript" \
|
||||
"text/plain" \
|
||||
"text/vcard" \
|
||||
"text/vnd.rim.location.xloc" \
|
||||
"text/vtt" \
|
||||
"text/x-component" \
|
||||
"text/x-cross-domain-policy" \
|
||||
"text/xml"
|
||||
</IfModule>
|
||||
|
||||
<IfModule mod_mime.c>
|
||||
AddEncoding gzip gz
|
||||
AddEncoding gzip svgz
|
||||
</IfModule>
|
||||
</IfModule>
|
||||
|
@@ -1,3 +0,0 @@
|
||||
Satisfy all
|
||||
Order deny,allow
|
||||
Deny from all
|
@@ -6,13 +6,17 @@
|
||||
"download": "Descargar",
|
||||
"empty": "vacío",
|
||||
"files": "Archivos",
|
||||
"filter": "Filtar",
|
||||
"filter": "Filtrar",
|
||||
"folders": "Directorios",
|
||||
"grid": "Cuadrícula",
|
||||
"icons": "Íconos",
|
||||
"language": "Idioma",
|
||||
"lastModified": "Última modificación",
|
||||
"name": "Nombre",
|
||||
"noMatch": "Sin coincidencias",
|
||||
"parentDirectory": "Directorio superior",
|
||||
"size": "Tamaño"
|
||||
"search": "buscar",
|
||||
"size": "Tamaño",
|
||||
"tree": "Arbol",
|
||||
"view": "Vista"
|
||||
}
|
||||
|
22
src/_h5ai/private/conf/l10n/et.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"lang": "estonian",
|
||||
|
||||
"dateFormat": "DD-MM-YYYY HH.mm",
|
||||
"details": "täpsem info",
|
||||
"download": "laadi alla",
|
||||
"empty": "tühi",
|
||||
"files": "failid",
|
||||
"filter": "filter",
|
||||
"folders": "kataloogid",
|
||||
"grid": "võre",
|
||||
"icons": "ikoonid",
|
||||
"language": "Keel",
|
||||
"lastModified": "Viimati muudetud",
|
||||
"name": "Nimi",
|
||||
"noMatch": "ei leitud sobivat",
|
||||
"parentDirectory": "Emakataloog",
|
||||
"search": "otsi",
|
||||
"size": "Suurus",
|
||||
"tree": "Puu",
|
||||
"view": "Vaade"
|
||||
}
|
@@ -6,13 +6,17 @@
|
||||
"download": "télécharger",
|
||||
"empty": "vide",
|
||||
"files": "Fichiers",
|
||||
"filter": "filtre",
|
||||
"filter": "filtrer",
|
||||
"folders": "Répertoires",
|
||||
"grid": "grille",
|
||||
"icons": "icônes",
|
||||
"language": "Langue",
|
||||
"lastModified": "Dernière modification",
|
||||
"name": "Nom",
|
||||
"noMatch": "rien trouvé",
|
||||
"parentDirectory": "Dossier parent",
|
||||
"size": "Taille"
|
||||
"search": "rechercher",
|
||||
"size": "Taille",
|
||||
"tree": "Arborescence",
|
||||
"view": "Disposition"
|
||||
}
|
||||
|
22
src/_h5ai/private/conf/l10n/id.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"lang": "Bahasa Indonesia",
|
||||
|
||||
"dateFormat": "DD-MM-YYYY HH:mm",
|
||||
"details": "rincian",
|
||||
"download": "unduh",
|
||||
"empty": "kosong",
|
||||
"files": "berkas",
|
||||
"filter": "saring",
|
||||
"folders": "pelipat",
|
||||
"grid": "jaring",
|
||||
"icons": "ikon",
|
||||
"language": "Bahasa",
|
||||
"lastModified": "Di modifikasi",
|
||||
"name": "Nama",
|
||||
"noMatch": "tidak cocok",
|
||||
"parentDirectory": "Direktori induk",
|
||||
"search": "cari",
|
||||
"size": "Ukuran",
|
||||
"tree": "Pohon",
|
||||
"view": "Tampil"
|
||||
}
|
@@ -10,9 +10,13 @@
|
||||
"folders": "cartelle",
|
||||
"grid": "griglia",
|
||||
"icons": "icone",
|
||||
"language": "Linugua",
|
||||
"lastModified": "Ultima modifica",
|
||||
"name": "Nome",
|
||||
"noMatch": "nessun risultato",
|
||||
"parentDirectory": "Cartella Superiore",
|
||||
"size": "Dimensione"
|
||||
"search": "cerca",
|
||||
"size": "Dimensione",
|
||||
"tree": "Albero",
|
||||
"view": "Vista"
|
||||
}
|
||||
|
@@ -1,11 +1,22 @@
|
||||
{
|
||||
"lang": "nederlands",
|
||||
|
||||
"dateFormat": "YYYY-MM-DD HH:mm",
|
||||
"details": "details",
|
||||
"empty": "lege",
|
||||
"download": "download",
|
||||
"empty": "leeg",
|
||||
"files": "bestanden",
|
||||
"filter": "filter",
|
||||
"folders": "mappen",
|
||||
"grid": "grid",
|
||||
"icons": "iconen",
|
||||
"language": "Taal",
|
||||
"lastModified": "Laatste wijziging",
|
||||
"name": "Naam",
|
||||
"noMatch": "geen overeenkomst",
|
||||
"parentDirectory": "Bovenliggende map",
|
||||
"size": "Grootte"
|
||||
"search": "zoeken",
|
||||
"size": "Grootte",
|
||||
"tree": "Boom",
|
||||
"view": "Bekijk"
|
||||
}
|
||||
|
@@ -10,9 +10,13 @@
|
||||
"folders": "folderów",
|
||||
"grid": "kafelki",
|
||||
"icons": "ikony",
|
||||
"language": "Język",
|
||||
"lastModified": "Ostatnia modyfikacja",
|
||||
"name": "Nazwa",
|
||||
"noMatch": "nie znaleziono",
|
||||
"parentDirectory": "Katalog nadrzędny",
|
||||
"size": "Rozmiar"
|
||||
"search": "szukaj",
|
||||
"size": "Rozmiar",
|
||||
"tree": "Drzewo",
|
||||
"view": "Układ"
|
||||
}
|
||||
|
22
src/_h5ai/private/conf/l10n/pt-br.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"lang": "português do Brasil",
|
||||
|
||||
"dateFormat": "DD-MM-YYYY HH:mm",
|
||||
"details": "detalhes",
|
||||
"download": "download",
|
||||
"empty": "vazio",
|
||||
"files": "arquivos",
|
||||
"filter": "filtro",
|
||||
"folders": "pastas",
|
||||
"grid": "grade",
|
||||
"icons": "ícones",
|
||||
"language": "Idioma",
|
||||
"lastModified": "Última modificação",
|
||||
"name": "Nome",
|
||||
"noMatch": "sem resultados",
|
||||
"parentDirectory": "Diretório acima",
|
||||
"search": "pesquisa",
|
||||
"size": "Tamanho",
|
||||
"tree": "Árvore",
|
||||
"view": "Visualização"
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"lang": "português",
|
||||
"lang": "português de Portugal",
|
||||
|
||||
"dateFormat": "DD-MM-YYYY HH:mm",
|
||||
"details": "detalhes",
|
||||
@@ -10,9 +10,13 @@
|
||||
"folders": "pastas",
|
||||
"grid": "grelha",
|
||||
"icons": "ícones",
|
||||
"language": "Idioma",
|
||||
"lastModified": "última modificação",
|
||||
"name": "Nome",
|
||||
"noMatch": "sem resultados",
|
||||
"parentDirectory": "diretório acima",
|
||||
"size": "Tamanho"
|
||||
"parentDirectory": "Diretório acima",
|
||||
"search": "pesquisa",
|
||||
"size": "Tamanho",
|
||||
"tree": "Árvore",
|
||||
"view": "Visualização"
|
||||
}
|
@@ -6,7 +6,7 @@
|
||||
"download": "下载",
|
||||
"empty": "空文件夹",
|
||||
"files": "文件",
|
||||
"filter": "查找",
|
||||
"filter": "过滤",
|
||||
"folders": "文件夹",
|
||||
"grid": "网格",
|
||||
"icons": "图标",
|
||||
@@ -15,6 +15,9 @@
|
||||
"name": "文件名",
|
||||
"noMatch": "无匹配项",
|
||||
"parentDirectory": "父文件夹",
|
||||
"search": "搜索",
|
||||
"size": "大小",
|
||||
"view": "视图"
|
||||
"tree": "树形目录",
|
||||
"view": "视图",
|
||||
"info": "信息"
|
||||
}
|
||||
|
@@ -10,9 +10,14 @@
|
||||
"folders": "資料夾",
|
||||
"grid": "網格",
|
||||
"icons": "圖示",
|
||||
"language": "語言",
|
||||
"lastModified": "上次修改",
|
||||
"name": "檔名",
|
||||
"noMatch": "沒有符合的檔案",
|
||||
"parentDirectory": "上層目錄",
|
||||
"size": "大小"
|
||||
"search": "搜尋",
|
||||
"size": "大小",
|
||||
"tree": "樹形目錄",
|
||||
"view": "檢視",
|
||||
"info": "資訊"
|
||||
}
|
||||
|
@@ -32,6 +32,8 @@
|
||||
General view options.
|
||||
|
||||
- binaryPrefix: boolean, set to true uses 1024B=1KiB when formatting file sizes (see http://en.wikipedia.org/wiki/Binary_prefix)
|
||||
- disableSidebar: boolean, hides sidebar and toggle button
|
||||
- fallbackMode: boolean, serve fallback mode
|
||||
- fastBrowsing: boolean, use History API if available (no need to reload the whole page)
|
||||
- fonts: array of strings, fonts to use in regular context
|
||||
- fontsMono: array of strings, fonts to use in monopspaced context
|
||||
@@ -52,12 +54,14 @@
|
||||
is given the view size is fixed and the selector buttons are hidden.
|
||||
The user selected view size is also stored local in modern browsers
|
||||
so that it will be persistent.
|
||||
- theme: string, name of one of the folders in "_h5ai/images/themes", defaults to "default"
|
||||
- theme: string, name of one of the folders in "_h5ai/public/images/themes", defaults to "default"
|
||||
- unmanaged: array of strings, don't manage folders containing one of those files
|
||||
- unmanagedInNewWindow: boolean, open unmanaged links in new window/tab
|
||||
*/
|
||||
"view": {
|
||||
"binaryPrefix": false,
|
||||
"disableSidebar": false,
|
||||
"fallbackMode": false,
|
||||
"fastBrowsing": true,
|
||||
"fonts": ["Ubuntu", "Roboto", "Helvetica", "Arial", "sans-serif"],
|
||||
"fontsMono": ["Ubuntu Mono", "Monaco", "Lucida Sans Typewriter", "monospace"],
|
||||
@@ -89,13 +93,6 @@
|
||||
"interval": 5000
|
||||
},
|
||||
|
||||
/*
|
||||
Enable a context menu (right-click) on some elements.
|
||||
*/
|
||||
"contextmenu": {
|
||||
"enabled": false
|
||||
},
|
||||
|
||||
/*
|
||||
Show a clickable breadcrumb.
|
||||
*/
|
||||
@@ -111,9 +108,14 @@
|
||||
Note the different filenames: "header" (only current) - "headers" (current and sub directories)!
|
||||
The file's content will be placed inside a <div/> tag above/below the main content.
|
||||
If a file's extension is ".md" instead of ".html" its content will be interpreted as markdown.
|
||||
|
||||
- stopSearchingAtRoot: boolean, only search for header and footer files until the web root
|
||||
directory. if `false`, will search for header/footer up the entire directory structure,
|
||||
even above the web root
|
||||
*/
|
||||
"custom": {
|
||||
"enabled": true
|
||||
"enabled": true,
|
||||
"stopSearchingAtRoot": true
|
||||
},
|
||||
|
||||
/*
|
||||
@@ -142,11 +144,13 @@
|
||||
|
||||
- advanced: boolean, use advanced pattern parsing
|
||||
- debounceTime: number, debounce wait time in milliseconds
|
||||
- ignorecase: boolean, ignore case
|
||||
*/
|
||||
"filter": {
|
||||
"enabled": false,
|
||||
"advanced": true,
|
||||
"debounceTime": 100
|
||||
"debounceTime": 100,
|
||||
"ignorecase": true
|
||||
},
|
||||
|
||||
/*
|
||||
@@ -158,7 +162,7 @@
|
||||
- type: string, "php" (sloooow) or "shell-du" (sloow)
|
||||
*/
|
||||
"foldersize": {
|
||||
"enabled": false,
|
||||
"enabled": true,
|
||||
"type": "php"
|
||||
},
|
||||
|
||||
@@ -184,7 +188,8 @@
|
||||
"enabled": true,
|
||||
"show": false,
|
||||
"qrcode": true,
|
||||
"qrColor": "#999"
|
||||
"qrFill": "#999",
|
||||
"qrBack": "#fff"
|
||||
},
|
||||
|
||||
/*
|
||||
@@ -201,16 +206,6 @@
|
||||
"useBrowserLang": true
|
||||
},
|
||||
|
||||
/*
|
||||
Adds peer5 p2p downloader which is based on webrtc (see peer5.com).
|
||||
|
||||
- id: string, the API key
|
||||
*/
|
||||
"peer5": {
|
||||
"enabled": false,
|
||||
"id": "z142i5n5qypq4cxr"
|
||||
},
|
||||
|
||||
/*
|
||||
Adds Piwik tracker javascript code.
|
||||
|
||||
@@ -226,10 +221,12 @@
|
||||
/*
|
||||
Play a audio preview on click.
|
||||
|
||||
- autoplay: start playing as soon as ready
|
||||
- types: array of strings
|
||||
*/
|
||||
"preview-aud": {
|
||||
"enabled": true,
|
||||
"autoplay": true,
|
||||
"types": ["aud"]
|
||||
},
|
||||
|
||||
@@ -242,59 +239,59 @@
|
||||
"preview-img": {
|
||||
"enabled": true,
|
||||
"size": false,
|
||||
"types": ["img", "img-bmp", "img-gif", "img-ico", "img-jpg", "img-png", "img-raw"]
|
||||
"types": ["img", "img-bmp", "img-gif", "img-ico", "img-jpg", "img-png", "img-raw", "img-svg"]
|
||||
},
|
||||
|
||||
/*
|
||||
Show text file preview on click.
|
||||
"types" maps file types to http://prismjs.com languages.
|
||||
|
||||
Additional type are:
|
||||
- "markdown" to render Markdown text
|
||||
- "none" for floating text
|
||||
- "fixed" for fixed width text
|
||||
Available styles are:
|
||||
0: floating text
|
||||
1: fixed width text
|
||||
2: markdown
|
||||
3: syntax highlighting
|
||||
|
||||
- types: dict string to string, maps types to languages
|
||||
- styles: dict string to int, maps types to styles
|
||||
*/
|
||||
"preview-txt": {
|
||||
"enabled": true,
|
||||
"types": {
|
||||
"txt": "fixed",
|
||||
"txt-authors": "fixed",
|
||||
"txt-c": "c",
|
||||
"txt-cpp": "cpp",
|
||||
"txt-css": "css",
|
||||
"txt-diff": "fixed",
|
||||
"txt-go": "go",
|
||||
"txt-h": "c",
|
||||
"txt-hpp": "cpp",
|
||||
"txt-install": "fixed",
|
||||
"txt-java": "java",
|
||||
"txt-js": "javascript",
|
||||
"txt-json": "javascript",
|
||||
"txt-less": "css",
|
||||
"txt-license": "fixed",
|
||||
"txt-log": "fixed",
|
||||
"txt-makefile": "fixed",
|
||||
"txt-md": "markdown",
|
||||
// "txt-php": "php",
|
||||
"txt-py": "python",
|
||||
"txt-rb": "ruby",
|
||||
"txt-readme": "fixed",
|
||||
"txt-rtf": "fixed",
|
||||
"txt-scala": "scala",
|
||||
"txt-script": "bash",
|
||||
"txt-xml": "fixed"
|
||||
"styles": {
|
||||
"txt": 1,
|
||||
"txt-authors": 1,
|
||||
"txt-c": 3,
|
||||
"txt-cpp": 3,
|
||||
"txt-css": 3,
|
||||
"txt-diff": 1,
|
||||
"txt-go": 3,
|
||||
"txt-h": 3,
|
||||
"txt-hpp": 3,
|
||||
"txt-install": 1,
|
||||
"txt-js": 3,
|
||||
"txt-json": 3,
|
||||
"txt-less": 3,
|
||||
"txt-license": 1,
|
||||
"txt-log": 1,
|
||||
"txt-makefile": 1,
|
||||
"txt-md": 2,
|
||||
"txt-py": 3,
|
||||
"txt-rb": 3,
|
||||
"txt-readme": 1,
|
||||
"txt-rtf": 1,
|
||||
"txt-rust": 3,
|
||||
"txt-script": 3,
|
||||
"txt-xml": 1
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
Play a video preview on click.
|
||||
|
||||
- autoplay: start playing as soon as ready
|
||||
- types: array of strings
|
||||
*/
|
||||
"preview-vid": {
|
||||
"enabled": true,
|
||||
"autoplay": true,
|
||||
"types": ["vid-avi", "vid-flv", "vid-mkv", "vid-mov", "vid-mp4", "vid-mpg", "vid-webm"]
|
||||
},
|
||||
|
||||
@@ -309,11 +306,13 @@
|
||||
|
||||
- advanced: boolean, use advanced pattern parsing
|
||||
- debounceTime: number, debounce wait time in milliseconds
|
||||
- ignorecase: boolean, ignore case
|
||||
*/
|
||||
"search": {
|
||||
"enabled": true,
|
||||
"enabled": false,
|
||||
"advanced": true,
|
||||
"debounceTime": 300
|
||||
"debounceTime": 300,
|
||||
"ignorecase": true
|
||||
},
|
||||
|
||||
/*
|
||||
@@ -344,12 +343,12 @@
|
||||
"column": 0,
|
||||
"reverse": false,
|
||||
"ignorecase": true,
|
||||
"natural": false,
|
||||
"natural": true,
|
||||
"folders": 0
|
||||
},
|
||||
|
||||
/*
|
||||
Show thumbnails for image files. Needs the "/_h5ai/cache" folder to be
|
||||
Show thumbnails for image files. Needs the "/_h5ai/public/cache" folder to be
|
||||
writable for the web Server.
|
||||
|
||||
- img: array of strings
|
||||
@@ -358,6 +357,7 @@
|
||||
- delay: number, delay in milliseconds after "dom-ready" before thumb-requesting starts
|
||||
- size: number, size in pixel of the generated thumbnails
|
||||
- exif: boolean, use included EXIF thumbs if possible
|
||||
- chunksize: int, number of thumbs per request
|
||||
*/
|
||||
"thumbnails": {
|
||||
"enabled": true,
|
||||
@@ -366,7 +366,8 @@
|
||||
"doc": ["x-pdf", "x-ps"],
|
||||
"delay": 1,
|
||||
"size": 240,
|
||||
"exif": false
|
||||
"exif": false,
|
||||
"chunksize": 20
|
||||
},
|
||||
|
||||
/*
|
||||
@@ -389,7 +390,7 @@
|
||||
"enabled": true,
|
||||
"show": true,
|
||||
"maxSubfolders": 50,
|
||||
"naturalSort": false,
|
||||
"naturalSort": true,
|
||||
"ignorecase": true
|
||||
}
|
||||
}
|
||||
|
@@ -18,6 +18,7 @@
|
||||
"img-jpg": ["*.jpg", "*.jpeg"],
|
||||
"img-png": ["*.png"],
|
||||
"img-raw": ["*.cr2", "*.nef"],
|
||||
"img-svg": ["*.svg"],
|
||||
"img-tiff": ["*.tiff"],
|
||||
"txt": ["*.text", "*.txt"],
|
||||
"txt-build": ["*.pom", "build.xml", "pom.xml"],
|
||||
@@ -41,9 +42,9 @@
|
||||
"txt-rb": ["*.rb"],
|
||||
"txt-rss": ["*.rss"],
|
||||
"txt-rtf": ["*.rtf"],
|
||||
"txt-rust": ["*.rs", "*.rlib"],
|
||||
"txt-script": ["*.conf", "*.bsh", "*.csh", "*.ini", "*.ksh", "*.sh", "*.shar", "*.tcl", "*.zsh"],
|
||||
"txt-source": [],
|
||||
"txt-svg": ["*.svg"],
|
||||
"txt-tex": ["*.tex"],
|
||||
"txt-vcal": ["*.vcal"],
|
||||
"txt-xml": ["*.xml"],
|
||||
|
@@ -1,11 +1,9 @@
|
||||
<?php
|
||||
|
||||
class Bootstrap {
|
||||
|
||||
private static $autopaths = ['core', 'ext'];
|
||||
|
||||
public static function run() {
|
||||
|
||||
spl_autoload_register(['Bootstrap', 'autoload']);
|
||||
putenv('LANG=en_US.UTF-8');
|
||||
setlocale(LC_CTYPE, 'en_US.UTF-8');
|
||||
@@ -13,26 +11,27 @@ class Bootstrap {
|
||||
session_start();
|
||||
|
||||
$session = new Session($_SESSION);
|
||||
$request = new Request($_REQUEST);
|
||||
$request = new Request($_REQUEST, file_get_contents('php://input'));
|
||||
$setup = new Setup($request->query_boolean('refresh', false));
|
||||
$context = new Context($session, $request, $setup);
|
||||
|
||||
if ($context->is_api_request()) {
|
||||
(new Api($context))->apply();
|
||||
} else if ($context->is_info_request()) {
|
||||
} elseif ($context->is_info_request()) {
|
||||
$public_href = $setup->get('PUBLIC_HREF');
|
||||
$x_head_tags = $context->get_x_head_html();
|
||||
$fallback_mode = false;
|
||||
require __DIR__ . '/pages/info.php';
|
||||
} else {
|
||||
$public_href = $setup->get('PUBLIC_HREF');
|
||||
$x_head_tags = $context->get_x_head_html();
|
||||
$fallback_mode = $context->is_fallback_mode();
|
||||
$fallback_html = (new Fallback($context))->get_html();
|
||||
require __DIR__ . '/pages/index.php';
|
||||
}
|
||||
}
|
||||
|
||||
public static function autoload($class_name) {
|
||||
|
||||
$filename = 'class-' . strtolower($class_name) . '.php';
|
||||
|
||||
foreach (Bootstrap::$autopaths as $path) {
|
||||
|
@@ -1,20 +1,17 @@
|
||||
<?php
|
||||
|
||||
class Api {
|
||||
|
||||
private $context;
|
||||
private $request;
|
||||
private $setup;
|
||||
|
||||
public function __construct($context) {
|
||||
|
||||
$this->context = $context;
|
||||
$this->request = $context->get_request();
|
||||
$this->setup = $context->get_setup();
|
||||
}
|
||||
|
||||
public function apply() {
|
||||
|
||||
$action = $this->request->query('action');
|
||||
$supported = ['download', 'get', 'login', 'logout'];
|
||||
Util::json_fail(Util::ERR_UNSUPPORTED, 'unsupported action', !in_array($action, $supported));
|
||||
@@ -24,17 +21,17 @@ class Api {
|
||||
}
|
||||
|
||||
private function on_download() {
|
||||
|
||||
Util::json_fail(Util::ERR_DISABLED, 'download disabled', !$this->context->query_option('download.enabled', false));
|
||||
|
||||
$as = $this->request->query('as');
|
||||
$type = $this->request->query('type');
|
||||
$base_href = $this->request->query('baseHref');
|
||||
$hrefs = $this->request->query('hrefs');
|
||||
$hrefs = $this->request->query('hrefs', '');
|
||||
|
||||
$archive = new Archive($this->context);
|
||||
|
||||
set_time_limit(0);
|
||||
session_write_close();
|
||||
header('Content-Type: application/octet-stream');
|
||||
header('Content-Disposition: attachment; filename="' . $as . '"');
|
||||
header('Connection: close');
|
||||
@@ -45,70 +42,57 @@ class Api {
|
||||
}
|
||||
|
||||
private function on_get() {
|
||||
|
||||
$response = [];
|
||||
|
||||
foreach (['langs', 'options', 'types'] as $name) {
|
||||
if ($this->request->query_boolean($name, false)) {
|
||||
|
||||
$methodname = 'get_' . $name;
|
||||
$response[$name] = $this->context->$methodname();
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->request->query_boolean('setup', false)) {
|
||||
|
||||
$response['setup'] = $this->setup->to_jsono($this->context->is_admin());
|
||||
}
|
||||
|
||||
if ($this->request->query_boolean('theme', false)) {
|
||||
|
||||
$theme = new Theme($this->context);
|
||||
$response['theme'] = $theme->get_icons();
|
||||
}
|
||||
|
||||
if ($this->request->query('items', false)) {
|
||||
|
||||
$href = $this->request->query('items.href');
|
||||
$what = $this->request->query_numeric('items.what');
|
||||
|
||||
$response['items'] = $this->context->get_items($href, $what);
|
||||
}
|
||||
|
||||
if ($this->request->query('custom', false)) {
|
||||
|
||||
Util::json_fail(Util::ERR_DISABLED, 'custom disabled', !$this->context->query_option('custom.enabled', false));
|
||||
$href = $this->request->query('custom');
|
||||
|
||||
$custom = new Custom($this->context);
|
||||
$response['custom'] = $custom->get_customizations($href);
|
||||
}
|
||||
|
||||
if ($this->request->query('l10n', false)) {
|
||||
|
||||
Util::json_fail(Util::ERR_DISABLED, 'l10n disabled', !$this->context->query_option('l10n.enabled', false));
|
||||
$iso_codes = $this->request->query_array('l10n');
|
||||
|
||||
$iso_codes = array_filter($iso_codes);
|
||||
$response['l10n'] = $this->context->get_l10n($iso_codes);
|
||||
}
|
||||
|
||||
if ($this->request->query('search', false)) {
|
||||
|
||||
Util::json_fail(Util::ERR_DISABLED, 'search disabled', !$this->context->query_option('search.enabled', false));
|
||||
$href = $this->request->query('search.href');
|
||||
$pattern = $this->request->query('search.pattern');
|
||||
|
||||
$ignorecase = $this->request->query_boolean('search.ignorecase', false);
|
||||
$search = new Search($this->context);
|
||||
$response['search'] = $search->get_items($href, $pattern);
|
||||
$response['search'] = $search->get_items($href, $pattern, $ignorecase);
|
||||
}
|
||||
|
||||
if ($this->request->query('thumbs', false)) {
|
||||
|
||||
Util::json_fail(Util::ERR_DISABLED, 'thumbnails disabled', !$this->context->query_option('thumbnails.enabled', false));
|
||||
Util::json_fail(Util::ERR_UNSUPPORTED, 'thumbnails not supported', !$this->setup->get('HAS_PHP_JPEG'));
|
||||
$thumbs = $this->request->query_array('thumbs');
|
||||
|
||||
$response['thumbs'] = $this->context->get_thumbs($thumbs);
|
||||
}
|
||||
|
||||
@@ -116,13 +100,11 @@ class Api {
|
||||
}
|
||||
|
||||
private function on_login() {
|
||||
|
||||
$pass = $this->request->query('pass');
|
||||
Util::json_exit(['asAdmin' => $this->context->login_admin($pass)]);
|
||||
}
|
||||
|
||||
private function on_logout() {
|
||||
|
||||
Util::json_exit(['asAdmin' => $this->context->logout_admin()]);
|
||||
}
|
||||
}
|
||||
|
@@ -1,9 +1,14 @@
|
||||
<?php
|
||||
|
||||
class Context {
|
||||
|
||||
private static $DEFAULT_PASSHASH = 'cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e';
|
||||
private static $AS_ADMIN_SESSION_KEY = 'AS_ADMIN';
|
||||
private static $L10N_ISO_CODES = array(
|
||||
'af', 'bg', 'cs', 'da', 'de', 'el', 'en', 'es', 'et', 'fi', 'fr', 'he',
|
||||
'hi', 'hr', 'hu', 'id', 'it', 'ja','ko', 'lv', 'nb', 'nl', 'pl',
|
||||
'pt-br', 'pt-pt', 'ro', 'ru', 'sk', 'sl', 'sr', 'sv', 'tr', 'uk',
|
||||
'zh-cn', 'zh-tw'
|
||||
);
|
||||
|
||||
private $session;
|
||||
private $request;
|
||||
@@ -12,7 +17,6 @@ class Context {
|
||||
private $passhash;
|
||||
|
||||
public function __construct($session, $request, $setup) {
|
||||
|
||||
$this->session = $session;
|
||||
$this->request = $request;
|
||||
$this->setup = $setup;
|
||||
@@ -25,64 +29,60 @@ class Context {
|
||||
}
|
||||
|
||||
public function get_session() {
|
||||
|
||||
return $this->session;
|
||||
}
|
||||
|
||||
public function get_request() {
|
||||
|
||||
return $this->request;
|
||||
}
|
||||
|
||||
public function get_setup() {
|
||||
|
||||
return $this->setup;
|
||||
}
|
||||
|
||||
public function get_options() {
|
||||
|
||||
return $this->options;
|
||||
}
|
||||
|
||||
public function query_option($keypath = '', $default = null) {
|
||||
|
||||
return Util::array_query($this->options, $keypath, $default);
|
||||
}
|
||||
|
||||
public function get_types() {
|
||||
|
||||
return Json::load($this->setup->get('CONF_PATH') . '/types.json');
|
||||
}
|
||||
|
||||
public function login_admin($pass) {
|
||||
|
||||
$this->session->set(Context::$AS_ADMIN_SESSION_KEY, strcasecmp(hash('sha512', $pass), $this->passhash) === 0);
|
||||
return $this->session->get(Context::$AS_ADMIN_SESSION_KEY);
|
||||
}
|
||||
|
||||
public function logout_admin() {
|
||||
|
||||
$this->session->set(Context::$AS_ADMIN_SESSION_KEY, false);
|
||||
return $this->session->get(Context::$AS_ADMIN_SESSION_KEY);
|
||||
}
|
||||
|
||||
public function is_admin() {
|
||||
|
||||
return $this->session->get(Context::$AS_ADMIN_SESSION_KEY);
|
||||
}
|
||||
|
||||
public function is_api_request() {
|
||||
|
||||
return strtolower($this->setup->get('REQUEST_METHOD')) === 'post';
|
||||
}
|
||||
|
||||
public function is_info_request() {
|
||||
|
||||
return Util::starts_with($this->setup->get('REQUEST_HREF') . '/', $this->setup->get('PUBLIC_HREF'));
|
||||
}
|
||||
|
||||
public function to_href($path, $trailing_slash = true) {
|
||||
public function is_text_browser() {
|
||||
return preg_match('/curl|links|lynx|w3m/i', $this->setup->get('HTTP_USER_AGENT')) === 1;
|
||||
}
|
||||
|
||||
public function is_fallback_mode() {
|
||||
return $this->query_option('view.fallbackMode', false) || $this->is_text_browser();
|
||||
}
|
||||
|
||||
public function to_href($path, $trailing_slash = true) {
|
||||
$rel_path = substr($path, strlen($this->setup->get('ROOT_PATH')));
|
||||
$parts = explode('/', $rel_path);
|
||||
$encoded_parts = [];
|
||||
@@ -96,13 +96,11 @@ class Context {
|
||||
}
|
||||
|
||||
public function to_path($href) {
|
||||
|
||||
$rel_href = substr($href, strlen($this->setup->get('ROOT_HREF')));
|
||||
return Util::normalize_path($this->setup->get('ROOT_PATH') . '/' . rawurldecode($rel_href));
|
||||
}
|
||||
|
||||
public function is_hidden($name) {
|
||||
|
||||
// always hide
|
||||
if ($name === '.' || $name === '..') {
|
||||
return true;
|
||||
@@ -119,7 +117,6 @@ class Context {
|
||||
}
|
||||
|
||||
public function read_dir($path) {
|
||||
|
||||
$names = [];
|
||||
if (is_dir($path)) {
|
||||
foreach (scandir($path) as $name) {
|
||||
@@ -137,12 +134,10 @@ class Context {
|
||||
}
|
||||
|
||||
public function is_managed_href($href) {
|
||||
|
||||
return $this->is_managed_path($this->to_path($href));
|
||||
}
|
||||
|
||||
public function is_managed_path($path) {
|
||||
|
||||
if (!is_dir($path) || strpos($path, '../') !== false || strpos($path, '/..') !== false || $path === '..') {
|
||||
return false;
|
||||
}
|
||||
@@ -175,7 +170,6 @@ class Context {
|
||||
}
|
||||
|
||||
public function get_current_path() {
|
||||
|
||||
$current_href = Util::normalize_path($this->setup->get('REQUEST_HREF'), true);
|
||||
$current_path = $this->to_path($current_href);
|
||||
|
||||
@@ -187,7 +181,6 @@ class Context {
|
||||
}
|
||||
|
||||
public function get_items($href, $what) {
|
||||
|
||||
if (!$this->is_managed_href($href)) {
|
||||
return [];
|
||||
}
|
||||
@@ -219,7 +212,6 @@ class Context {
|
||||
}
|
||||
|
||||
public function get_langs() {
|
||||
|
||||
$langs = [];
|
||||
$l10n_path = $this->setup->get('CONF_PATH') . '/l10n';
|
||||
if (is_dir($l10n_path)) {
|
||||
@@ -238,10 +230,13 @@ class Context {
|
||||
}
|
||||
|
||||
public function get_l10n($iso_codes) {
|
||||
|
||||
$results = [];
|
||||
|
||||
foreach ($iso_codes as $iso_code) {
|
||||
if (!in_array($iso_code, Context::$L10N_ISO_CODES)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$file = $this->setup->get('CONF_PATH') . '/l10n/' . $iso_code . '.json';
|
||||
$results[$iso_code] = Json::load($file);
|
||||
$results[$iso_code]['isoCode'] = $iso_code;
|
||||
@@ -251,7 +246,6 @@ class Context {
|
||||
}
|
||||
|
||||
public function get_thumbs($requests) {
|
||||
|
||||
$hrefs = [];
|
||||
|
||||
foreach ($requests as $req) {
|
||||
@@ -263,7 +257,6 @@ class Context {
|
||||
}
|
||||
|
||||
private function prefix_x_head_href($href) {
|
||||
|
||||
if (preg_match('@^(https?://|/)@i', $href)) {
|
||||
return $href;
|
||||
}
|
||||
@@ -272,7 +265,6 @@ class Context {
|
||||
}
|
||||
|
||||
private function get_fonts_html() {
|
||||
|
||||
$fonts = $this->query_option('view.fonts', []);
|
||||
$fonts_mono = $this->query_option('view.fontsMono', []);
|
||||
|
||||
@@ -292,7 +284,6 @@ class Context {
|
||||
}
|
||||
|
||||
public function get_x_head_html() {
|
||||
|
||||
$scripts = $this->query_option('resources.scripts', []);
|
||||
$styles = $this->query_option('resources.styles', []);
|
||||
|
||||
|
@@ -1,16 +1,13 @@
|
||||
<?php
|
||||
|
||||
class Fallback {
|
||||
|
||||
private $context;
|
||||
|
||||
public function __construct($context) {
|
||||
|
||||
$this->context = $context;
|
||||
}
|
||||
|
||||
public function get_html($path = null) {
|
||||
|
||||
if (!$path) {
|
||||
$path = $this->context->get_current_path();
|
||||
}
|
||||
|
@@ -1,47 +1,28 @@
|
||||
<?php
|
||||
|
||||
class Filesize {
|
||||
private static $cache = [];
|
||||
|
||||
private $cache = [];
|
||||
|
||||
public function __construct() {
|
||||
|
||||
public static function getSize($path, $withFoldersize, $withDu) {
|
||||
$fs = new Filesize();
|
||||
return $fs->size($path, $withFoldersize, $withDu);
|
||||
}
|
||||
|
||||
public function fseek($path) {
|
||||
|
||||
$size = 0;
|
||||
$step = 1073741824;
|
||||
|
||||
$handle = fopen($path, 'r');
|
||||
fseek($handle, 0, SEEK_SET);
|
||||
|
||||
while ($step > 1) {
|
||||
fseek($handle, $step, SEEK_CUR);
|
||||
if (fgetc($handle) !== false) {
|
||||
$size += $step + 1;
|
||||
} else {
|
||||
fseek($handle, -$step, SEEK_CUR);
|
||||
$step = intval($step / 2, 10);
|
||||
}
|
||||
public static function getCachedSize($path, $withFoldersize, $withDu) {
|
||||
if (array_key_exists($path, Filesize::$cache)) {
|
||||
return Filesize::$cache[$path];
|
||||
}
|
||||
|
||||
while (fgetc($handle) !== false) {
|
||||
$size += 1;
|
||||
}
|
||||
|
||||
fclose($handle);
|
||||
$size = Filesize::getSize($path, $withFoldersize, $withDu);
|
||||
|
||||
Filesize::$cache[$path] = $size;
|
||||
return $size;
|
||||
}
|
||||
|
||||
public function filesize($path) {
|
||||
|
||||
return @filesize($path);
|
||||
}
|
||||
private function __construct() {}
|
||||
|
||||
private function read_dir($path) {
|
||||
|
||||
$paths = [];
|
||||
if (is_dir($path)) {
|
||||
foreach (scandir($path) as $name) {
|
||||
@@ -53,8 +34,23 @@ class Filesize {
|
||||
return $paths;
|
||||
}
|
||||
|
||||
private function exec($cmdv) {
|
||||
private function php_filesize($path, $recursive = false) {
|
||||
// if (PHP_INT_SIZE < 8) {
|
||||
// }
|
||||
$size = @filesize($path);
|
||||
|
||||
if (!is_dir($path) || !$recursive) {
|
||||
return $size;
|
||||
}
|
||||
|
||||
foreach ($this->read_dir($path) as $p) {
|
||||
$size += $this->php_filesize($p, true);
|
||||
}
|
||||
return $size;
|
||||
}
|
||||
|
||||
|
||||
private function exec($cmdv) {
|
||||
$cmd = implode(' ', array_map('escapeshellarg', $cmdv));
|
||||
$lines = [];
|
||||
$rc = null;
|
||||
@@ -62,38 +58,39 @@ class Filesize {
|
||||
return $lines;
|
||||
}
|
||||
|
||||
public function du_paths($paths) {
|
||||
|
||||
$cmdv = array_merge(['du', '-sk'], $paths);
|
||||
private function exec_du_all($paths) {
|
||||
$cmdv = array_merge(['du', '-sbL'], $paths);
|
||||
$lines = $this->exec($cmdv);
|
||||
|
||||
$sizes = [];
|
||||
foreach ($lines as $line) {
|
||||
$parts = preg_split('/[\s]+/', $line, 2);
|
||||
$size = intval($parts[0], 10) * 1024;
|
||||
$size = intval($parts[0], 10);
|
||||
$path = $parts[1];
|
||||
$sizes[$path] = $size;
|
||||
}
|
||||
return $sizes;
|
||||
}
|
||||
|
||||
public function du_dir($path) {
|
||||
|
||||
return $this->du_paths($this->read_dir($path));
|
||||
}
|
||||
|
||||
public function du_path($path) {
|
||||
|
||||
$sizes = $this->du_paths([$path]);
|
||||
private function exec_du($path) {
|
||||
$sizes = $this->exec_du_all([$path]);
|
||||
return $sizes[$path];
|
||||
}
|
||||
|
||||
public function add($path) {
|
||||
|
||||
$size = 0;
|
||||
foreach ($this->read_dir($path) as $p) {
|
||||
$size += $this->filesize($p);
|
||||
private function size($path, $withFoldersize = false, $withDu = false) {
|
||||
if (is_file($path)) {
|
||||
return $this->php_filesize($path);
|
||||
}
|
||||
return $size;
|
||||
|
||||
if (is_dir($path) && $withFoldersize) {
|
||||
if ($withDu) {
|
||||
return $this->exec_du($path);
|
||||
}
|
||||
|
||||
return $this->php_filesize($path, true);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@@ -1,9 +1,7 @@
|
||||
<?php
|
||||
|
||||
class Item {
|
||||
|
||||
public static function cmp($item1, $item2) {
|
||||
|
||||
if ($item1->is_folder && !$item2->is_folder) {
|
||||
return -1;
|
||||
}
|
||||
@@ -15,7 +13,6 @@ class Item {
|
||||
}
|
||||
|
||||
public static function get($context, $path, &$cache) {
|
||||
|
||||
if (!Util::starts_with($path, $context->get_setup()->get('ROOT_PATH'))) {
|
||||
return null;
|
||||
}
|
||||
@@ -41,7 +38,6 @@ class Item {
|
||||
public $is_content_fetched;
|
||||
|
||||
private function __construct($context, $path) {
|
||||
|
||||
$this->context = $context;
|
||||
|
||||
$this->path = Util::normalize_path($path, false);
|
||||
@@ -53,7 +49,6 @@ class Item {
|
||||
}
|
||||
|
||||
public function to_json_object() {
|
||||
|
||||
$obj = [
|
||||
'href' => $this->href,
|
||||
'time' => $this->date * 1000, // seconds (PHP) to milliseconds (JavaScript)
|
||||
@@ -69,7 +64,6 @@ class Item {
|
||||
}
|
||||
|
||||
public function get_parent(&$cache) {
|
||||
|
||||
$parent_path = Util::normalize_path(dirname($this->path), false);
|
||||
if ($parent_path !== $this->path && Util::starts_with($parent_path, $this->context->get_setup()->get('ROOT_PATH'))) {
|
||||
return Item::get($this->context, $parent_path, $cache);
|
||||
@@ -78,7 +72,6 @@ class Item {
|
||||
}
|
||||
|
||||
public function get_content(&$cache) {
|
||||
|
||||
$items = [];
|
||||
|
||||
if (!$this->context->is_managed_href($this->href)) {
|
||||
|
@@ -1,12 +1,10 @@
|
||||
<?php
|
||||
|
||||
class Json {
|
||||
|
||||
const SINGLE = 1;
|
||||
const MULTI = 2;
|
||||
|
||||
public static function load($path) {
|
||||
|
||||
if (!is_readable($path)) {
|
||||
return [];
|
||||
}
|
||||
@@ -16,25 +14,21 @@ class Json {
|
||||
}
|
||||
|
||||
public static function save($path, $obj) {
|
||||
|
||||
$json = json_encode($obj);
|
||||
return file_put_contents($path, $json) !== false;
|
||||
}
|
||||
|
||||
public static function decode($json) {
|
||||
|
||||
private static function decode($json) {
|
||||
$json = Json::strip($json);
|
||||
return json_decode($json, true);
|
||||
}
|
||||
|
||||
public static function strip($commented_json) {
|
||||
|
||||
private static function strip($commented_json) {
|
||||
$insideString = false;
|
||||
$insideComment = false;
|
||||
$json = '';
|
||||
|
||||
for ($i = 0; $i < strlen($commented_json); $i += 1) {
|
||||
|
||||
for ($i = 0, $len = strlen($commented_json); $i < $len; $i += 1) {
|
||||
$char = $commented_json[$i];
|
||||
$charchar = $char . @$commented_json[$i + 1];
|
||||
$prevChar = @$commented_json[$i - 1];
|
||||
@@ -45,22 +39,22 @@ class Json {
|
||||
|
||||
if ($insideString) {
|
||||
$json .= $char;
|
||||
} else if (!$insideComment && $charchar === '//') {
|
||||
} elseif (!$insideComment && $charchar === '//') {
|
||||
$insideComment = Json::SINGLE;
|
||||
$i += 1;
|
||||
} else if (!$insideComment && $charchar === '/*') {
|
||||
} elseif (!$insideComment && $charchar === '/*') {
|
||||
$insideComment = Json::MULTI;
|
||||
$i += 1;
|
||||
} else if (!$insideComment) {
|
||||
} elseif (!$insideComment) {
|
||||
$json .= $char;
|
||||
} else if ($insideComment === Json::SINGLE && $charchar === "\r\n") {
|
||||
} elseif ($insideComment === Json::SINGLE && $charchar === "\r\n") {
|
||||
$insideComment = false;
|
||||
$json .= $charchar;
|
||||
$i += 1;
|
||||
} else if ($insideComment === Json::SINGLE && $char === "\n") {
|
||||
} elseif ($insideComment === Json::SINGLE && $char === "\n") {
|
||||
$insideComment = false;
|
||||
$json .= $char;
|
||||
} else if ($insideComment === Json::MULTI && $charchar === '*/') {
|
||||
} elseif ($insideComment === Json::MULTI && $charchar === '*/') {
|
||||
$insideComment = false;
|
||||
$i += 1;
|
||||
}
|
||||
|
@@ -1,25 +1,21 @@
|
||||
<?php
|
||||
|
||||
class Logger {
|
||||
|
||||
private static $start;
|
||||
private static $prev;
|
||||
|
||||
public static function init() {
|
||||
private static function time() {
|
||||
return microtime(true) * 1000; // sec * 1000 = ms
|
||||
}
|
||||
|
||||
public static function init() {
|
||||
self::$start = self::time();
|
||||
self::$prev = self::$start;
|
||||
register_shutdown_function(function () { Logger::log('shutdown'); });
|
||||
Logger::log('--------------------------------');
|
||||
}
|
||||
|
||||
private static function time() {
|
||||
|
||||
return microtime(true) * 1000; // sec * 1000 = ms
|
||||
}
|
||||
|
||||
public static function log($message=null, $obj=null) {
|
||||
|
||||
$now = self::time();
|
||||
$message = number_format($now - self::$start, 3) . ' ' . number_format($now - self::$prev, 3) . ' ' . $message;
|
||||
|
||||
@@ -28,4 +24,5 @@ class Logger {
|
||||
self::$prev = $now;
|
||||
}
|
||||
}
|
||||
|
||||
Logger::init();
|
||||
|
@@ -1,16 +1,14 @@
|
||||
<?php
|
||||
|
||||
class Request {
|
||||
|
||||
private $params;
|
||||
|
||||
public function __construct($params) {
|
||||
|
||||
$this->params = $params;
|
||||
public function __construct($params, $body) {
|
||||
$data = json_decode($body, true);
|
||||
$this->params = $data !== null ? $data : $params;
|
||||
}
|
||||
|
||||
public function query($keypath = '', $default = Util::NO_DEFAULT) {
|
||||
|
||||
$value = Util::array_query($this->params, $keypath, Util::NO_DEFAULT);
|
||||
|
||||
if ($value === Util::NO_DEFAULT) {
|
||||
@@ -22,20 +20,17 @@ class Request {
|
||||
}
|
||||
|
||||
public function query_boolean($keypath = '', $default = Util::NO_DEFAULT) {
|
||||
|
||||
$value = $this->query($keypath, $default);
|
||||
return filter_var($value, FILTER_VALIDATE_BOOLEAN);
|
||||
}
|
||||
|
||||
public function query_numeric($keypath = '', $default = Util::NO_DEFAULT) {
|
||||
|
||||
$value = $this->query($keypath, $default);
|
||||
Util::json_fail(Util::ERR_ILLIGAL_PARAM, 'parameter \'' . $keypath . '\' is not numeric', !is_numeric($value));
|
||||
return intval($value, 10);
|
||||
}
|
||||
|
||||
public function query_array($keypath = '', $default = Util::NO_DEFAULT) {
|
||||
|
||||
$value = $this->query($keypath, $default);
|
||||
Util::json_fail(Util::ERR_ILLIGAL_PARAM, 'parameter \'' . $keypath . '\' is no array', !is_array($value));
|
||||
return $value;
|
||||
|
@@ -1,24 +1,19 @@
|
||||
<?php
|
||||
|
||||
class Session {
|
||||
|
||||
private static $KEY_PREFIX = '__H5AI__';
|
||||
|
||||
private $store;
|
||||
|
||||
public function __construct(&$store) {
|
||||
|
||||
$this->store = &$store;
|
||||
}
|
||||
|
||||
public function set($key, $value) {
|
||||
|
||||
$key = Session::$KEY_PREFIX . $key;
|
||||
$this->store[$key] = $value;
|
||||
}
|
||||
|
||||
public function get($key, $default = null) {
|
||||
|
||||
$key = Session::$KEY_PREFIX . $key;
|
||||
return array_key_exists($key, $this->store) ? $this->store[$key] : $default;
|
||||
}
|
||||
|
@@ -1,12 +1,10 @@
|
||||
<?php
|
||||
|
||||
class Setup {
|
||||
|
||||
private $store;
|
||||
private $refresh;
|
||||
|
||||
public function __construct($refresh = false) {
|
||||
|
||||
$this->store = [];
|
||||
$this->refresh = $refresh;
|
||||
|
||||
@@ -19,7 +17,6 @@ class Setup {
|
||||
}
|
||||
|
||||
private function set($key, $value) {
|
||||
|
||||
if (array_key_exists($key, $this->store)) {
|
||||
Logger::log('setup key already taken', [
|
||||
'key' => $key,
|
||||
@@ -40,7 +37,6 @@ class Setup {
|
||||
}
|
||||
|
||||
public function get($key) {
|
||||
|
||||
if (!array_key_exists($key, $this->store)) {
|
||||
Logger::log('setup key not found', ['key' => $key]);
|
||||
exit;
|
||||
@@ -50,18 +46,18 @@ class Setup {
|
||||
}
|
||||
|
||||
private function add_globals_and_envs() {
|
||||
|
||||
$this->set('PHP_VERSION', PHP_VERSION);
|
||||
$this->set('MIN_PHP_VERSION', MIN_PHP_VERSION);
|
||||
$this->set('PHP_ARCH', (PHP_INT_SIZE * 8) . '-bit');
|
||||
|
||||
$this->set('REQUEST_METHOD', getenv('REQUEST_METHOD'));
|
||||
$this->set('REQUEST_HREF', parse_url(getenv('REQUEST_URI'), PHP_URL_PATH));
|
||||
$this->set('SCRIPT_NAME', getenv('SCRIPT_NAME'));
|
||||
$this->set('SERVER_SOFTWARE', getenv('SERVER_SOFTWARE'));
|
||||
$this->set('REQUEST_METHOD', $_SERVER['REQUEST_METHOD']);
|
||||
$this->set('REQUEST_HREF', parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH));
|
||||
$this->set('SCRIPT_NAME', $_SERVER['SCRIPT_NAME']);
|
||||
$this->set('SERVER_SOFTWARE', $_SERVER['SERVER_SOFTWARE']);
|
||||
$this->set('HTTP_USER_AGENT', $_SERVER['HTTP_USER_AGENT']);
|
||||
}
|
||||
|
||||
private function add_php_checks() {
|
||||
|
||||
$this->set('HAS_PHP_EXIF', function_exists('exif_thumbnail'));
|
||||
|
||||
$has_php_jpeg = false;
|
||||
@@ -73,14 +69,12 @@ class Setup {
|
||||
}
|
||||
|
||||
private function add_app_metadata() {
|
||||
|
||||
$this->set('NAME', 'h5ai');
|
||||
$this->set('VERSION', H5AI_VERSION);
|
||||
$this->set('FILE_PREFIX', '_h5ai');
|
||||
}
|
||||
|
||||
private function add_server_metadata_and_check() {
|
||||
|
||||
$server_software = $this->get('SERVER_SOFTWARE');
|
||||
$server_name = null;
|
||||
$server_version = null;
|
||||
@@ -96,7 +90,6 @@ class Setup {
|
||||
}
|
||||
|
||||
private function add_paths() {
|
||||
|
||||
$script_name = $this->get('SCRIPT_NAME');
|
||||
if ($this->get('SERVER_NAME') === 'lighttpd') {
|
||||
$script_name = preg_replace('#^.*?//#', '/', $script_name);
|
||||
@@ -123,23 +116,25 @@ class Setup {
|
||||
}
|
||||
|
||||
private function add_sys_cmd_checks() {
|
||||
|
||||
$cmds_cache_path = Util::normalize_path($this->get('CACHE_PRV_PATH') . '/cmds.json', false);
|
||||
|
||||
$cmds = Json::load($cmds_cache_path);
|
||||
if (sizeof($cmds) === 0 || $this->refresh) {
|
||||
$cmds['command'] = Util::exec_0('command -v command');
|
||||
$cmds['which'] = Util::exec_0('which which');
|
||||
$cmds['which'] = Util::exec_0('which which') || Util::exec_0('which which.exe');
|
||||
$cmds['where'] = Util::exec_0('where where.exe');
|
||||
|
||||
$cmd = false;
|
||||
if ($cmds['command']) {
|
||||
$cmd = 'command -v';
|
||||
} else if ($cmds['which']) {
|
||||
} elseif ($cmds['which']) {
|
||||
$cmd = 'which';
|
||||
} elseif ($cmds['where']) {
|
||||
$cmd = 'where';
|
||||
}
|
||||
|
||||
foreach (['avconv', 'convert', 'du', 'ffmpeg', 'gm', 'tar', 'zip'] as $c) {
|
||||
$cmds[$c] = ($cmd !== false) && Util::exec_0($cmd . ' ' . $c);
|
||||
$cmds[$c] = ($cmd !== false) && (Util::exec_0($cmd . ' ' . $c) || Util::exec_0($cmd . ' ' . $c . '.exe'));
|
||||
}
|
||||
|
||||
Json::save($cmds_cache_path, $cmds);
|
||||
@@ -150,7 +145,6 @@ class Setup {
|
||||
}
|
||||
|
||||
public function to_jsono($as_admin = false) {
|
||||
|
||||
$keys = [
|
||||
'PUBLIC_HREF',
|
||||
'ROOT_HREF'
|
||||
@@ -162,6 +156,7 @@ class Setup {
|
||||
|
||||
'PHP_VERSION',
|
||||
'MIN_PHP_VERSION',
|
||||
'PHP_ARCH',
|
||||
'HAS_PHP_EXIF',
|
||||
'HAS_PHP_JPEG',
|
||||
|
||||
|
@@ -1,18 +1,14 @@
|
||||
<?php
|
||||
|
||||
class Theme {
|
||||
|
||||
private static $EXTENSIONS = ['svg', 'png', 'jpg'];
|
||||
|
||||
private $context;
|
||||
|
||||
public function __construct($context) {
|
||||
|
||||
$this->context = $context;
|
||||
}
|
||||
|
||||
public function get_icons() {
|
||||
|
||||
$public_path = $this->context->get_setup()->get('PUBLIC_PATH');
|
||||
$theme = $this->context->query_option('view.theme', '-NONE-');
|
||||
$theme_path = $public_path . '/images/themes/' . $theme;
|
||||
|
@@ -1,7 +1,6 @@
|
||||
<?php
|
||||
|
||||
class Util {
|
||||
|
||||
const ERR_MISSING_PARAM = 'ERR_MISSING_PARAM';
|
||||
const ERR_ILLIGAL_PARAM = 'ERR_ILLIGAL_PARAM';
|
||||
const ERR_FAILED = 'ERR_FAILED';
|
||||
@@ -11,27 +10,23 @@ class Util {
|
||||
const RE_DELIMITER = '@';
|
||||
|
||||
public static function normalize_path($path, $trailing_slash = false) {
|
||||
|
||||
$path = preg_replace('#[\\\\/]+#', '/', $path);
|
||||
return preg_match('#^(\w:)?/$#', $path) ? $path : (rtrim($path, '/') . ($trailing_slash ? '/' : ''));
|
||||
}
|
||||
|
||||
public static function json_exit($obj = []) {
|
||||
|
||||
header('Content-type: application/json;charset=utf-8');
|
||||
echo json_encode($obj);
|
||||
exit;
|
||||
}
|
||||
|
||||
public static function json_fail($err, $msg = '', $cond = true) {
|
||||
|
||||
if ($cond) {
|
||||
Util::json_exit(['err' => $err, 'msg' => $msg]);
|
||||
}
|
||||
}
|
||||
|
||||
public static function array_query($array, $keypath = '', $default = Util::NO_DEFAULT) {
|
||||
|
||||
$value = $array;
|
||||
|
||||
$keys = array_filter(explode('.', $keypath));
|
||||
@@ -46,30 +41,25 @@ class Util {
|
||||
}
|
||||
|
||||
public static function starts_with($sequence, $head) {
|
||||
|
||||
return substr($sequence, 0, strlen($head)) === $head;
|
||||
}
|
||||
|
||||
public static function ends_with($sequence, $tail) {
|
||||
|
||||
$len = strlen($tail);
|
||||
return $len === 0 ? true : substr($sequence, -$len) === $tail;
|
||||
}
|
||||
|
||||
public static function wrap_pattern($pattern) {
|
||||
|
||||
return Util::RE_DELIMITER . str_replace(Util::RE_DELIMITER, '\\' . Util::RE_DELIMITER, $pattern) . Util::RE_DELIMITER;
|
||||
}
|
||||
|
||||
public static function passthru_cmd($cmd) {
|
||||
|
||||
$rc = null;
|
||||
passthru($cmd, $rc);
|
||||
return $rc;
|
||||
}
|
||||
|
||||
public static function exec_cmdv($cmdv) {
|
||||
|
||||
if (!is_array($cmdv)) {
|
||||
$cmdv = func_get_args();
|
||||
}
|
||||
@@ -82,7 +72,6 @@ class Util {
|
||||
}
|
||||
|
||||
public static function exec_0($cmd) {
|
||||
|
||||
$lines = [];
|
||||
$rc = null;
|
||||
try {
|
||||
@@ -92,32 +81,9 @@ class Util {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static $size_cache = [];
|
||||
|
||||
public static function filesize($context, $path) {
|
||||
|
||||
if (array_key_exists($path, Util::$size_cache)) {
|
||||
return Util::$size_cache[$path];
|
||||
}
|
||||
$fs = new Filesize();
|
||||
|
||||
$size = null;
|
||||
|
||||
if (is_file($path)) {
|
||||
if (PHP_INT_SIZE < 8) {
|
||||
$size = $fs->fseek($path);
|
||||
} else {
|
||||
$size = $fs->filesize($path);
|
||||
}
|
||||
} else if (is_dir($path) && $context->query_option('foldersize.enabled', false)) {
|
||||
if ($context->get_setup()->get('HAS_CMD_DU') && $context->query_option('foldersize.type', null) === 'shell-du') {
|
||||
$size = $fs->du_path($path);
|
||||
} else {
|
||||
$size = $fs->add($path);
|
||||
}
|
||||
}
|
||||
|
||||
Util::$size_cache[$path] = $size;
|
||||
return $size;
|
||||
$withFoldersize = $context->query_option('foldersize.enabled', false);
|
||||
$withDu = $context->get_setup()->get('HAS_CMD_DU') && $context->query_option('foldersize.type', null) === 'shell-du';
|
||||
return Filesize::getCachedSize($path, $withFoldersize, $withDu);
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,6 @@
|
||||
<?php
|
||||
|
||||
class Archive {
|
||||
|
||||
const NULL_BYTE = "\0";
|
||||
|
||||
private static $SEGMENT_SIZE = 16777216; // 1024 * 1024 * 16 = 16MiB
|
||||
@@ -14,12 +13,10 @@ class Archive {
|
||||
private $files;
|
||||
|
||||
public function __construct($context) {
|
||||
|
||||
$this->context = $context;
|
||||
}
|
||||
|
||||
public function output($type, $base_href, $hrefs) {
|
||||
|
||||
$this->base_path = $this->context->to_path($base_href);
|
||||
if (!$this->context->is_managed_path($this->base_path)) {
|
||||
return false;
|
||||
@@ -39,22 +36,16 @@ class Archive {
|
||||
}
|
||||
|
||||
if ($type === 'php-tar') {
|
||||
|
||||
return $this->php_tar($this->dirs, $this->files);
|
||||
|
||||
} else if ($type === 'shell-tar') {
|
||||
|
||||
} elseif ($type === 'shell-tar') {
|
||||
return $this->shell_cmd(Archive::$TAR_PASSTHRU_CMD);
|
||||
|
||||
} else if ($type === 'shell-zip') {
|
||||
|
||||
} elseif ($type === 'shell-zip') {
|
||||
return $this->shell_cmd(Archive::$ZIP_PASSTHRU_CMD);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private function shell_cmd($cmd) {
|
||||
|
||||
$cmd = str_replace('[ROOTDIR]', escapeshellarg($this->base_path), $cmd);
|
||||
$cmd = str_replace('[DIRS]', count($this->dirs) ? implode(' ', array_map('escapeshellarg', $this->dirs)) : '', $cmd);
|
||||
$cmd = str_replace('[FILES]', count($this->files) ? implode(' ', array_map('escapeshellarg', $this->files)) : '', $cmd);
|
||||
@@ -67,11 +58,9 @@ class Archive {
|
||||
}
|
||||
|
||||
private function php_tar($dirs, $files) {
|
||||
|
||||
$filesizes = [];
|
||||
$total_size = 512 * count($dirs);
|
||||
foreach (array_keys($files) as $real_file) {
|
||||
|
||||
$size = filesize($real_file);
|
||||
|
||||
$filesizes[$real_file] = $size;
|
||||
@@ -84,11 +73,10 @@ class Archive {
|
||||
header('Content-Length: ' . $total_size);
|
||||
|
||||
foreach ($dirs as $real_dir => $archived_dir) {
|
||||
|
||||
echo $this->php_tar_header($archived_dir, 0, @filemtime($real_dir . DIRECTORY_SEPARATOR . "."), 5);
|
||||
echo $this->php_tar_header($archived_dir, 0, @filemtime($real_dir . DIRECTORY_SEPARATOR . '.'), 5);
|
||||
}
|
||||
foreach ($files as $real_file => $archived_file) {
|
||||
|
||||
foreach ($files as $real_file => $archived_file) {
|
||||
$size = $filesizes[$real_file];
|
||||
|
||||
echo $this->php_tar_header($archived_file, $size, @filemtime($real_file), 0);
|
||||
@@ -103,7 +91,6 @@ class Archive {
|
||||
}
|
||||
|
||||
private function php_tar_header($filename, $size, $mtime, $type) {
|
||||
|
||||
$name = substr(basename($filename), -99);
|
||||
$prefix = substr(Util::normalize_path(dirname($filename)), -154);
|
||||
if ($prefix === '.') {
|
||||
@@ -136,7 +123,6 @@ class Archive {
|
||||
}
|
||||
|
||||
private function print_file($file) {
|
||||
|
||||
// Send file content in segments to not hit PHP's memory limit (default: 128M)
|
||||
if ($fd = fopen($file, 'rb')) {
|
||||
while (!feof($fd)) {
|
||||
@@ -149,14 +135,17 @@ class Archive {
|
||||
}
|
||||
|
||||
private function add_hrefs($hrefs) {
|
||||
if (!is_array($hrefs)) {
|
||||
$hrefs = array($hrefs);
|
||||
}
|
||||
|
||||
foreach ($hrefs as $href) {
|
||||
|
||||
if (trim($href) === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$d = Util::normalize_path(dirname($href), true);
|
||||
$href = Util::normalize_path($href, false);
|
||||
$d = dirname($href);
|
||||
$n = basename($href);
|
||||
|
||||
if ($this->context->is_managed_href($d) && !$this->context->is_hidden($n)) {
|
||||
@@ -174,20 +163,17 @@ class Archive {
|
||||
}
|
||||
|
||||
private function add_file($real_file, $archived_file) {
|
||||
|
||||
if (is_readable($real_file)) {
|
||||
$this->files[$real_file] = $archived_file;
|
||||
}
|
||||
}
|
||||
|
||||
private function add_dir($real_dir, $archived_dir) {
|
||||
|
||||
if ($this->context->is_managed_path($real_dir)) {
|
||||
$this->dirs[$real_dir] = $archived_dir;
|
||||
|
||||
$files = $this->context->read_dir($real_dir);
|
||||
foreach ($files as $file) {
|
||||
|
||||
$real_file = $real_dir . '/' . $file;
|
||||
$archived_file = $archived_dir . '/' . $file;
|
||||
|
||||
|
@@ -1,18 +1,14 @@
|
||||
<?php
|
||||
|
||||
class Custom {
|
||||
|
||||
private static $EXTENSIONS = ['html', 'md'];
|
||||
|
||||
private $context;
|
||||
|
||||
public function __construct($context) {
|
||||
|
||||
$this->context = $context;
|
||||
}
|
||||
|
||||
private function read_custom_file($path, $name, &$content, &$type) {
|
||||
|
||||
$file_prefix = $this->context->get_setup()->get('FILE_PREFIX');
|
||||
|
||||
foreach (Custom::$EXTENSIONS as $ext) {
|
||||
@@ -26,7 +22,6 @@ class Custom {
|
||||
}
|
||||
|
||||
public function get_customizations($href) {
|
||||
|
||||
if (!$this->context->query_option('custom.enabled', false)) {
|
||||
return [
|
||||
'header' => ['content' => null, 'type' => null],
|
||||
@@ -46,14 +41,12 @@ class Custom {
|
||||
$this->read_custom_file($path, 'footer', $footer, $footer_type);
|
||||
|
||||
while ($header === null || $footer === null) {
|
||||
|
||||
if ($header === null) {
|
||||
$this->read_custom_file($path, 'headers', $header, $header_type);
|
||||
}
|
||||
if ($footer === null) {
|
||||
$this->read_custom_file($path, 'footers', $footer, $footer_type);
|
||||
}
|
||||
|
||||
if ($path === $root_path) {
|
||||
break;
|
||||
}
|
||||
@@ -61,6 +54,14 @@ class Custom {
|
||||
if ($parent_path === $path) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Stop once we reach the root
|
||||
if (
|
||||
$this->context->query_option('custom.stopSearchingAtRoot', true) &&
|
||||
$path === $this->context->get_setup()->get('ROOT_PATH')
|
||||
) {
|
||||
break;
|
||||
}
|
||||
$path = $parent_path;
|
||||
}
|
||||
|
||||
|
@@ -1,19 +1,19 @@
|
||||
<?php
|
||||
|
||||
class Search {
|
||||
|
||||
private $context;
|
||||
|
||||
public function __construct($context) {
|
||||
|
||||
$this->context = $context;
|
||||
}
|
||||
|
||||
public function get_paths($root, $pattern = null) {
|
||||
|
||||
public function get_paths($root, $pattern = null, $ignorecase = false) {
|
||||
$paths = [];
|
||||
if ($pattern && $this->context->is_managed_path($root)) {
|
||||
$re = Util::wrap_pattern($pattern);
|
||||
if ($ignorecase) {
|
||||
$re .= 'i';
|
||||
}
|
||||
$names = $this->context->read_dir($root);
|
||||
foreach ($names as $name) {
|
||||
$path = $root . '/' . $name;
|
||||
@@ -21,20 +21,18 @@ class Search {
|
||||
$paths[] = $path;
|
||||
}
|
||||
if (@is_dir($path)) {
|
||||
$paths = array_merge($paths, $this->get_paths($path, $pattern));
|
||||
$paths = array_merge($paths, $this->get_paths($path, $pattern, $ignorecase));
|
||||
}
|
||||
}
|
||||
}
|
||||
return $paths;
|
||||
}
|
||||
|
||||
public function get_items($href, $pattern = null) {
|
||||
|
||||
public function get_items($href, $pattern = null, $ignorecase = false) {
|
||||
$cache = [];
|
||||
$root = $this->context->to_path($href);
|
||||
$paths = $this->get_paths($root, $pattern);
|
||||
$paths = $this->get_paths($root, $pattern, $ignorecase);
|
||||
$items = array_map(function ($path) {
|
||||
|
||||
return Item::get($this->context, $path, $cache)->to_json_object();
|
||||
}, $paths);
|
||||
return $items;
|
||||
|
@@ -1,11 +1,10 @@
|
||||
<?php
|
||||
|
||||
class Thumb {
|
||||
|
||||
private static $FFMPEG_CMDV = ['ffmpeg', '-ss', '0:00:10', '-i', '[SRC]', '-an', '-vframes', '1', '[DEST]'];
|
||||
private static $AVCONV_CMDV = ['avconv', '-ss', '0:00:10', '-i', '[SRC]', '-an', '-vframes', '1', '[DEST]'];
|
||||
private static $CONVERT_CMDV = ['convert', '-density', '200', '-quality', '100', '-sharpen', '0x1.0', '-strip', '[SRC][0]', '[DEST]'];
|
||||
private static $GM_CONVERT_CMDV = ['gm', 'convert', '-density', '200', '-quality', '100', '-sharpen', '0x1.0', '[SRC][0]', '[DEST]'];
|
||||
private static $CONVERT_CMDV = ['convert', '-density', '200', '-quality', '100', '-strip', '[SRC][0]', '[DEST]'];
|
||||
private static $GM_CONVERT_CMDV = ['gm', 'convert', '-density', '200', '-quality', '100', '[SRC][0]', '[DEST]'];
|
||||
private static $THUMB_CACHE = 'thumbs';
|
||||
|
||||
private $context;
|
||||
@@ -14,7 +13,6 @@ class Thumb {
|
||||
private $thumbs_href;
|
||||
|
||||
public function __construct($context) {
|
||||
|
||||
$this->context = $context;
|
||||
$this->setup = $context->get_setup();
|
||||
$this->thumbs_path = $this->setup->get('CACHE_PUB_PATH') . '/' . Thumb::$THUMB_CACHE;
|
||||
@@ -26,7 +24,6 @@ class Thumb {
|
||||
}
|
||||
|
||||
public function thumb($type, $source_href, $width, $height) {
|
||||
|
||||
$source_path = $this->context->to_path($source_href);
|
||||
if (!file_exists($source_path) || Util::starts_with($source_path, $this->setup->get('CACHE_PUB_PATH'))) {
|
||||
return null;
|
||||
@@ -35,16 +32,16 @@ class Thumb {
|
||||
$capture_path = $source_path;
|
||||
if ($type === 'img') {
|
||||
$capture_path = $source_path;
|
||||
} else if ($type === 'mov') {
|
||||
} elseif ($type === 'mov') {
|
||||
if ($this->setup->get('HAS_CMD_AVCONV')) {
|
||||
$capture_path = $this->capture(Thumb::$AVCONV_CMDV, $source_path);
|
||||
} else if ($this->setup->get('HAS_CMD_FFMPEG')) {
|
||||
} elseif ($this->setup->get('HAS_CMD_FFMPEG')) {
|
||||
$capture_path = $this->capture(Thumb::$FFMPEG_CMDV, $source_path);
|
||||
}
|
||||
} else if ($type === 'doc') {
|
||||
} elseif ($type === 'doc') {
|
||||
if ($this->setup->get('HAS_CMD_CONVERT')) {
|
||||
$capture_path = $this->capture(Thumb::$CONVERT_CMDV, $source_path);
|
||||
} else if ($this->setup->get('HAS_CMD_GM')) {
|
||||
} elseif ($this->setup->get('HAS_CMD_GM')) {
|
||||
$capture_path = $this->capture(Thumb::$GM_CONVERT_CMDV, $source_path);
|
||||
}
|
||||
}
|
||||
@@ -53,7 +50,6 @@ class Thumb {
|
||||
}
|
||||
|
||||
private function thumb_href($source_path, $width, $height) {
|
||||
|
||||
if (!file_exists($source_path)) {
|
||||
return null;
|
||||
}
|
||||
@@ -63,7 +59,6 @@ class Thumb {
|
||||
$thumb_href = $this->thumbs_href . '/' . $name;
|
||||
|
||||
if (!file_exists($thumb_path) || filemtime($source_path) >= filemtime($thumb_path)) {
|
||||
|
||||
$image = new Image();
|
||||
|
||||
$et = false;
|
||||
@@ -86,7 +81,6 @@ class Thumb {
|
||||
}
|
||||
|
||||
private function capture($cmdv, $source_path) {
|
||||
|
||||
if (!file_exists($source_path)) {
|
||||
return null;
|
||||
}
|
||||
@@ -94,7 +88,6 @@ class Thumb {
|
||||
$capture_path = $this->thumbs_path . '/capture-' . sha1($source_path) . '.jpg';
|
||||
|
||||
if (!file_exists($capture_path) || filemtime($source_path) >= filemtime($capture_path)) {
|
||||
|
||||
foreach ($cmdv as &$arg) {
|
||||
$arg = str_replace('[SRC]', $source_path, $arg);
|
||||
$arg = str_replace('[DEST]', $capture_path, $arg);
|
||||
@@ -108,7 +101,6 @@ class Thumb {
|
||||
}
|
||||
|
||||
class Image {
|
||||
|
||||
private $source_file;
|
||||
private $source;
|
||||
private $width;
|
||||
@@ -117,7 +109,6 @@ class Image {
|
||||
private $dest;
|
||||
|
||||
public function __construct($filename = null) {
|
||||
|
||||
$this->source_file = null;
|
||||
$this->source = null;
|
||||
$this->width = null;
|
||||
@@ -130,13 +121,11 @@ class Image {
|
||||
}
|
||||
|
||||
public function __destruct() {
|
||||
|
||||
$this->release_source();
|
||||
$this->release_dest();
|
||||
}
|
||||
|
||||
public function set_source($filename) {
|
||||
|
||||
$this->release_source();
|
||||
$this->release_dest();
|
||||
|
||||
@@ -160,7 +149,6 @@ class Image {
|
||||
}
|
||||
|
||||
public function save_dest_jpeg($filename, $quality = 80) {
|
||||
|
||||
if (!is_null($this->dest)) {
|
||||
@imagejpeg($this->dest, $filename, $quality);
|
||||
@chmod($filename, 0775);
|
||||
@@ -168,7 +156,6 @@ class Image {
|
||||
}
|
||||
|
||||
public function release_dest() {
|
||||
|
||||
if (!is_null($this->dest)) {
|
||||
@imagedestroy($this->dest);
|
||||
$this->dest = null;
|
||||
@@ -176,7 +163,6 @@ class Image {
|
||||
}
|
||||
|
||||
public function release_source() {
|
||||
|
||||
if (!is_null($this->source)) {
|
||||
@imagedestroy($this->source);
|
||||
$this->source_file = null;
|
||||
@@ -188,7 +174,6 @@ class Image {
|
||||
}
|
||||
|
||||
public function thumb($width, $height) {
|
||||
|
||||
if (is_null($this->source)) {
|
||||
return;
|
||||
}
|
||||
@@ -233,7 +218,6 @@ class Image {
|
||||
}
|
||||
|
||||
public function rotate($angle) {
|
||||
|
||||
if (is_null($this->source) || ($angle !== 90 && $angle !== 180 && $angle !== 270)) {
|
||||
return;
|
||||
}
|
||||
@@ -245,7 +229,6 @@ class Image {
|
||||
}
|
||||
|
||||
public function normalize_exif_orientation($exif_source_file = null) {
|
||||
|
||||
if (is_null($this->source) || !function_exists('exif_read_data')) {
|
||||
return;
|
||||
}
|
||||
@@ -255,7 +238,7 @@ class Image {
|
||||
}
|
||||
|
||||
$exif = exif_read_data($exif_source_file);
|
||||
switch(@$exif['Orientation']) {
|
||||
switch (@$exif['Orientation']) {
|
||||
case 3:
|
||||
$this->rotate(180);
|
||||
break;
|
||||
|
@@ -1,8 +0,0 @@
|
||||
extends ./page.tpl.jade
|
||||
|
||||
block init
|
||||
- var title = 'index - powered by h5ai v' + pkg.version + ' (' + pkg.homepage + ')'
|
||||
- var module = 'index'
|
||||
|
||||
block body
|
||||
div#fallback <?= $fallback_html; ?>
|
8
src/_h5ai/private/php/pages/index.php.pug
Normal file
@@ -0,0 +1,8 @@
|
||||
extends ./page.tpl.pug
|
||||
|
||||
block init
|
||||
- var title = `index - powered by h5ai v${pkg.version} (${pkg.homepage})`
|
||||
- var module = 'index'
|
||||
|
||||
block body
|
||||
div#fallback <?= $fallback_html; ?>
|
@@ -1,10 +0,0 @@
|
||||
extends ./page.tpl.jade
|
||||
|
||||
block init
|
||||
- var title = 'h5ai info page - v' + pkg.version
|
||||
- var module = 'info'
|
||||
|
||||
block body
|
||||
div#content
|
||||
h1#header
|
||||
a(href='#{pkg.homepage}') h5ai
|
10
src/_h5ai/private/php/pages/info.php.pug
Normal file
@@ -0,0 +1,10 @@
|
||||
extends ./page.tpl.pug
|
||||
|
||||
block init
|
||||
- var title = `h5ai info page - v${pkg.version}`
|
||||
- var module = 'info'
|
||||
|
||||
block body
|
||||
div#content
|
||||
h1#header
|
||||
a(href=pkg.homepage) h5ai
|
@@ -5,23 +5,26 @@ doctype html
|
||||
html(class='no-js', lang='en')
|
||||
|
||||
head
|
||||
<!--[if lt IE 10]><meta id='no-browser'><![endif]-->
|
||||
meta(charset='utf-8')
|
||||
meta(http-equiv='x-ua-compatible', content='ie=edge')
|
||||
title #{title}
|
||||
meta(name='description', content='#{title}')
|
||||
meta(name='description', content=title)
|
||||
meta(name='viewport', content='width=device-width, initial-scale=1')
|
||||
link(rel='shortcut icon', href!='<?= $public_href; ?>images/favicon/favicon-16-32.ico')
|
||||
link(rel='apple-touch-icon-precomposed', type='image/png', href!='<?= $public_href; ?>images/favicon/favicon-152.png')
|
||||
link(rel='stylesheet', href!='<?= $public_href; ?>css/styles.css')
|
||||
script(src!='<?= $public_href; ?>js/scripts.js', data-module='#{module}')
|
||||
<?php if (!$fallback_mode) { ?>
|
||||
script(src!='<?= $public_href; ?>js/scripts.js', data-module=module)
|
||||
<?php } ?>
|
||||
<?= $x_head_tags; ?>
|
||||
|
||||
body#root(class='#{module}')
|
||||
body#root(class=module)
|
||||
|
||||
div#fallback-hints
|
||||
<?php if (!$fallback_mode) { ?>
|
||||
span.noJsMsg Works best with JavaScript enabled!
|
||||
span.noBrowserMsg Works best in #[a(href='http://browsehappy.com') modern browsers]!
|
||||
span.backlink #[a(href='#{pkg.homepage}', title='h5ai v#{pkg.version} - #{pkg.description}') powered by h5ai]
|
||||
<?php } ?>
|
||||
span.backlink #[a(href=pkg.homepage, title=`h5ai v${pkg.version} - ${pkg.description}`) powered by h5ai]
|
||||
|
||||
block body
|
@@ -1,27 +1,13 @@
|
||||
Satisfy all
|
||||
Order allow,deny
|
||||
Allow from all
|
||||
## make this folder accessible
|
||||
|
||||
DirectoryIndex disabled
|
||||
|
||||
<IfModule mod_autoindex.c>
|
||||
Options -Indexes
|
||||
# Apache < 2.3
|
||||
<IfModule !mod_authz_core.c>
|
||||
Order allow,deny
|
||||
Allow from all
|
||||
Satisfy All
|
||||
</IfModule>
|
||||
|
||||
AddDefaultCharset utf-8
|
||||
|
||||
<IfModule mod_mime.c>
|
||||
AddCharset utf-8 .css .html .js .json .php .svg
|
||||
</IfModule>
|
||||
|
||||
<IfModule mod_expires.c>
|
||||
ExpiresActive on
|
||||
ExpiresDefault "access plus 1 month"
|
||||
|
||||
ExpiresByType text/html "access plus 0 seconds"
|
||||
ExpiresByType application/json "access plus 0 seconds"
|
||||
|
||||
ExpiresByType text/css "access plus 1 week"
|
||||
ExpiresByType application/javascript "access plus 1 week"
|
||||
ExpiresByType image/x-icon "access plus 1 week"
|
||||
# Apache ≥ 2.3
|
||||
<IfModule mod_authz_core.c>
|
||||
Require all granted
|
||||
</IfModule>
|
||||
|
@@ -27,7 +27,7 @@
|
||||
@col-back-native-selection: @col-pink-a200;
|
||||
|
||||
@col-text: @col-text-primary-black;
|
||||
@col-back: @col-grey-100;
|
||||
@col-back: @col-white;
|
||||
@col-back-paper: @col-white;
|
||||
@col-back-panel: @col-grey-50;
|
||||
@col-text-hover: @col-blue-400;
|
||||
|
@@ -1,5 +1,4 @@
|
||||
#cm-overlay {
|
||||
display: none;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
|
@@ -3,7 +3,6 @@
|
||||
input {
|
||||
display: none;
|
||||
border: none;
|
||||
font-weight: lighter;
|
||||
font-size: 16px;
|
||||
color: @col-text;
|
||||
background: transparent;
|
||||
|
@@ -1,12 +1,9 @@
|
||||
#info {
|
||||
display: none;
|
||||
|
||||
overflow: auto;
|
||||
flex: 0 0 auto;
|
||||
order: 99;
|
||||
|
||||
padding: 16px;
|
||||
border-left: 1px solid @col-border;
|
||||
padding: 32px 32px 32px 48px;
|
||||
white-space: nowrap;
|
||||
overflow-x: hidden;
|
||||
width: 240px;
|
||||
@@ -50,7 +47,7 @@
|
||||
margin: 0 auto;
|
||||
width: 200px;
|
||||
|
||||
canvas {
|
||||
img {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
#pv-aud-audio {
|
||||
#pv-content-aud {
|
||||
.raised;
|
||||
|
||||
position: absolute;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
#pv-img-image {
|
||||
#pv-content-img {
|
||||
.raised;
|
||||
|
||||
@check-white: #f8f8f8;
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
position: absolute;
|
||||
|
||||
image-orientation: from-image;
|
||||
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
|
||||
|
@@ -1,6 +1,7 @@
|
||||
#pv-txt-text {
|
||||
#pv-content-txt {
|
||||
.raised;
|
||||
|
||||
box-sizing: border-box;
|
||||
max-width: 960px;
|
||||
text-align: left;
|
||||
background: @col-back-paper;
|
||||
@@ -8,103 +9,28 @@
|
||||
padding: 8px;
|
||||
overflow: auto;
|
||||
|
||||
&.highlighted {
|
||||
a, a:active, a:visited {
|
||||
color: #2080FF;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
|
||||
code {
|
||||
line-height: 1.2em;
|
||||
}
|
||||
|
||||
a, a:active, a:visited {
|
||||
color: #2080FF;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: #68A9FF;
|
||||
}
|
||||
}
|
||||
|
||||
.token.comment,
|
||||
.token.prolog,
|
||||
.token.doctype,
|
||||
.token.cdata {
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
.token.punctuation {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.namespace {
|
||||
opacity: .7;
|
||||
}
|
||||
|
||||
.token.property,
|
||||
.token.tag,
|
||||
.token.boolean,
|
||||
.token.number,
|
||||
.token.constant,
|
||||
.token.symbol {
|
||||
color: #905;
|
||||
}
|
||||
|
||||
.token.selector,
|
||||
.token.attr-name,
|
||||
.token.string,
|
||||
.token.builtin {
|
||||
color: #690;
|
||||
}
|
||||
|
||||
.token.operator,
|
||||
.token.entity,
|
||||
.token.url,
|
||||
.language-css .token.string,
|
||||
.style .token.string,
|
||||
.token.variable {
|
||||
color: #a67f59;
|
||||
background: hsla(0,0%,100%,.5);
|
||||
}
|
||||
|
||||
.token.atrule,
|
||||
.token.attr-value,
|
||||
.token.keyword {
|
||||
color: #07a;
|
||||
}
|
||||
|
||||
.token.function {
|
||||
color: #DD4A68;
|
||||
}
|
||||
|
||||
.token.regex,
|
||||
.token.important {
|
||||
color: #e90;
|
||||
}
|
||||
|
||||
.token.important {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.token.entity {
|
||||
cursor: help;
|
||||
}
|
||||
}
|
||||
|
||||
&.markdown {
|
||||
font-size: 1.1em;
|
||||
padding: 8px 24px;
|
||||
|
||||
a, a:active, a:visited {
|
||||
color: #2080FF;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: #68A9FF;
|
||||
}
|
||||
}
|
||||
|
||||
code {
|
||||
color: #008200;
|
||||
&:hover {
|
||||
color: #68A9FF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pre#pv-content-txt {
|
||||
code {
|
||||
line-height: 1.2em;
|
||||
}
|
||||
}
|
||||
|
||||
div#pv-content-txt {
|
||||
font-size: 1.1em;
|
||||
padding: 8px 24px;
|
||||
|
||||
code {
|
||||
color: #008200;
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
#pv-vid-video {
|
||||
#pv-content-vid {
|
||||
.raised;
|
||||
|
||||
position: absolute;
|
||||
@@ -7,7 +7,7 @@
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
#pv-vid-video:-webkit-full-screen {
|
||||
#pv-content-vid:-webkit-full-screen {
|
||||
top: auto !important;
|
||||
left: auto !important;
|
||||
}
|
||||
|
@@ -1,5 +1,4 @@
|
||||
#pv-overlay {
|
||||
display: none;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
@@ -17,7 +16,7 @@
|
||||
background: @col-grey-900;
|
||||
}
|
||||
|
||||
#pv-content {
|
||||
#pv-container {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
|
@@ -3,7 +3,6 @@
|
||||
input {
|
||||
display: none;
|
||||
border: none;
|
||||
font-weight: lighter;
|
||||
font-size: 16px;
|
||||
color: @col-text;
|
||||
background: transparent;
|
||||
|
@@ -1,5 +1,4 @@
|
||||
#selection-rect {
|
||||
display: none;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
|
@@ -1,16 +1,12 @@
|
||||
#tree {
|
||||
display: none;
|
||||
|
||||
overflow: auto;
|
||||
flex: 0 0 auto;
|
||||
order: 1;
|
||||
|
||||
padding: 16px 16px 16px 8px;
|
||||
border-right: 1px solid @col-border;
|
||||
padding: 32px 32px 32px 16px;
|
||||
white-space: nowrap;
|
||||
max-width: 250px;
|
||||
overflow-x: hidden;
|
||||
font-weight: lighter;
|
||||
|
||||
a, a:active, a.visited {
|
||||
display: block;
|
||||
@@ -37,23 +33,29 @@
|
||||
cursor: pointer;
|
||||
|
||||
img {
|
||||
.eased-transition;
|
||||
// .eased-transition;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
zoom: 1;
|
||||
}
|
||||
&.open {
|
||||
img {
|
||||
transform: rotate(90deg);
|
||||
zoom: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.item {
|
||||
clear: left;
|
||||
|
||||
&.open > .indicator img {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
&.unknown {
|
||||
&.unknown > .indicator {
|
||||
opacity: 0.3;
|
||||
}
|
||||
&.none {
|
||||
&.none > .indicator {
|
||||
opacity: 0;
|
||||
cursor: inherit;
|
||||
}
|
||||
&.unknown > .content, &.none > .content, &.closed > .content {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.icon {
|
||||
@@ -71,8 +73,12 @@
|
||||
}
|
||||
|
||||
.content {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0 0 0 20px;
|
||||
}
|
||||
|
||||
.summary {
|
||||
color: @col-text-disabled-black;
|
||||
padding: 0 0 0 8px;
|
||||
}
|
||||
}
|
||||
|
@@ -5,7 +5,6 @@
|
||||
order: 50;
|
||||
color: @col-text;
|
||||
text-align: center;
|
||||
font-weight: lighter;
|
||||
}
|
||||
|
||||
code {
|
||||
@@ -67,7 +66,7 @@
|
||||
|
||||
#hint {
|
||||
margin: 12px auto;
|
||||
width: 300px;
|
||||
width: 320px;
|
||||
}
|
||||
|
||||
#tests {
|
||||
@@ -78,11 +77,10 @@
|
||||
padding: 0;
|
||||
|
||||
.test {
|
||||
.card;
|
||||
.rounded;
|
||||
background: @col-back-paper;
|
||||
margin: 12px 0 0 0;
|
||||
padding: 8px 12px 12px 12px;
|
||||
border-bottom: 1px solid @col-border;
|
||||
}
|
||||
.label {
|
||||
display: inline-block;
|
||||
|
@@ -12,3 +12,18 @@
|
||||
*:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
code, pre {
|
||||
font-family: @font-family-mono;
|
||||
font-size: @font-size-mono;
|
||||
font-weight: @font-weight;
|
||||
color: @col-text;
|
||||
}
|
||||
|
||||
audio, canvas, iframe, img, svg, video {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
textarea {
|
||||
resize: vertical;
|
||||
}
|
||||
|
@@ -1,5 +1,18 @@
|
||||
.card {
|
||||
box-shadow: 0 1px 1px 0 rgba(0,0,0,0.2);
|
||||
.hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.invisible {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.clearfix:before,
|
||||
.clearfix:after {
|
||||
content: " ";
|
||||
display: table;
|
||||
}
|
||||
.clearfix:after {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.raised {
|
||||
@@ -43,7 +56,6 @@
|
||||
}
|
||||
|
||||
.el-button {
|
||||
.card;
|
||||
.rounded;
|
||||
.eased-transition;
|
||||
color: @col-text-primary-white;
|
||||
@@ -57,10 +69,11 @@
|
||||
}
|
||||
|
||||
.el-input {
|
||||
.card;
|
||||
.rounded;
|
||||
.clear-appearance;
|
||||
background: @col-back-paper;
|
||||
border: none;
|
||||
outline: none;
|
||||
background: @col-back-panel;
|
||||
border: 1px solid @col-border;
|
||||
}
|
||||
|
@@ -8,12 +8,12 @@
|
||||
}
|
||||
}
|
||||
#view.view-details {
|
||||
.header .label, .item .label {
|
||||
margin-right: 80px !important;
|
||||
}
|
||||
.header .date, .item .date {
|
||||
display: none;
|
||||
}
|
||||
// .header .label, .item .label {
|
||||
// margin-right: 80px !important;
|
||||
// }
|
||||
// .header .date, .item .date {
|
||||
// display: none;
|
||||
// }
|
||||
}
|
||||
#tree, #info {
|
||||
display: none !important;
|
||||
@@ -21,8 +21,15 @@
|
||||
}
|
||||
|
||||
@media print {
|
||||
a[href]:after {
|
||||
content: "" !important;
|
||||
*,
|
||||
*:before,
|
||||
*:after,
|
||||
*:first-letter,
|
||||
*:first-line {
|
||||
background: transparent !important;
|
||||
color: #000 !important;
|
||||
box-shadow: none !important;
|
||||
text-shadow: none !important;
|
||||
}
|
||||
#toolbar, #sidebar, #tree, #info {
|
||||
display: none !important;
|
||||
|
@@ -2,4 +2,5 @@
|
||||
overflow: auto;
|
||||
flex: 1 1 auto;
|
||||
order: 50;
|
||||
position: relative;
|
||||
}
|
||||
|
@@ -5,7 +5,6 @@
|
||||
padding: 32px 16px;
|
||||
|
||||
table {
|
||||
.card;
|
||||
display: block;
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
@@ -15,13 +14,12 @@
|
||||
padding: 6px;
|
||||
text-align: left;
|
||||
border: none;
|
||||
border-bottom: 1px solid #eee;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
th {
|
||||
color: #aaa;
|
||||
font-weight: lighter;
|
||||
font-weight: normal;
|
||||
line-height: 36px;
|
||||
background: @col-back-panel;
|
||||
}
|
||||
td {
|
||||
overflow: hidden;
|
||||
@@ -70,7 +68,7 @@
|
||||
overflow: hidden;
|
||||
text-align: right;
|
||||
background: @col-back-panel;
|
||||
box-shadow: 0 0 8px 0 rgba(0,0,0,0.2);
|
||||
border-bottom: 1px solid @col-border;
|
||||
|
||||
a, a:active, a:visited {
|
||||
.eased-transition;
|
||||
|
@@ -7,6 +7,7 @@
|
||||
bottom: 0;
|
||||
overflow: hidden;
|
||||
background: @col-back;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
#root, input, select {
|
||||
@@ -15,10 +16,3 @@
|
||||
font-weight: @font-weight;
|
||||
color: @col-text;
|
||||
}
|
||||
|
||||
pre, code {
|
||||
font-family: @font-family-mono;
|
||||
font-size: @font-size-mono;
|
||||
font-weight: @font-weight;
|
||||
color: @col-text;
|
||||
}
|
||||
|
@@ -1,13 +1,17 @@
|
||||
#sidebar {
|
||||
display: none;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
flex: 0 0 auto;
|
||||
order: 0;
|
||||
background: @col-back-panel;
|
||||
border-right: 1px solid rgba(0,0,0,0.08);
|
||||
border-right: 1px solid @col-border;
|
||||
padding: 16px;
|
||||
|
||||
position: absolute;
|
||||
top: 48px;
|
||||
min-height: 100%;
|
||||
z-index: 1;
|
||||
|
||||
.block {
|
||||
display: block;
|
||||
margin: 0 0 24px 0;
|
||||
|
@@ -5,7 +5,7 @@
|
||||
order: 1;
|
||||
|
||||
background: @col-back-panel;
|
||||
box-shadow: 0 0 8px 0 rgba(0,0,0,0.2);
|
||||
border-bottom: 1px solid @col-border;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
|
@@ -23,24 +23,19 @@
|
||||
}
|
||||
}
|
||||
|
||||
margin: 16px;
|
||||
|
||||
#items {
|
||||
.rounded;
|
||||
box-shadow: 0 1px 1px 0 rgba(0,0,0,0.2);
|
||||
}
|
||||
margin: 32px;
|
||||
|
||||
.header {
|
||||
position: relative;
|
||||
white-space: nowrap;
|
||||
display: list-item;
|
||||
background: @col-back-panel;
|
||||
border-bottom: 1px solid rgba(0,0,0,0.07);
|
||||
border-radius: 2px 2px 0 0;
|
||||
|
||||
.label, .date, .size {
|
||||
.eased-transition;
|
||||
line-height: 46px;
|
||||
line-height: 24px;
|
||||
padding: 0px 8px 16px 8px;
|
||||
opacity: 0.4;
|
||||
outline: 0;
|
||||
|
||||
@@ -115,3 +110,26 @@
|
||||
|
||||
.view-details-sized(16px)
|
||||
}
|
||||
|
||||
#view.view-details {
|
||||
&.width-0 {
|
||||
.label {
|
||||
margin-right: 4px;
|
||||
}
|
||||
.date {
|
||||
display: none;
|
||||
}
|
||||
.size {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.width-1 {
|
||||
.label {
|
||||
margin-right: 64px;
|
||||
}
|
||||
.date {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -17,10 +17,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
margin: 8px;
|
||||
margin: 28px;
|
||||
|
||||
.item {
|
||||
.card;
|
||||
.rounded;
|
||||
overflow: hidden;
|
||||
float: left;
|
||||
@@ -34,7 +33,6 @@
|
||||
.square {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
background: @col-back-panel;
|
||||
}
|
||||
|
||||
.label {
|
||||
|
@@ -21,10 +21,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
margin: 8px;
|
||||
margin: 28px;
|
||||
|
||||
.item {
|
||||
.card;
|
||||
.rounded;
|
||||
overflow: hidden;
|
||||
float: left;
|
||||
@@ -43,6 +42,7 @@
|
||||
.label {
|
||||
padding: 0 6px;
|
||||
line-height: 24px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.date, .size {
|
||||
|
@@ -1,7 +1,6 @@
|
||||
@charset "utf-8";
|
||||
|
||||
// @include "vendor/normalize.less"
|
||||
// @include "vendor/h5bp-pre.less"
|
||||
// @include "../../../../node_modules/normalize.css/normalize.css"
|
||||
|
||||
// @include "lib/colors.less"
|
||||
// @include "lib/fonts.less"
|
||||
@@ -11,5 +10,3 @@
|
||||
// @include "lib/*/*.less"
|
||||
|
||||
// @include "lib/responsive.less"
|
||||
|
||||
// @include "vendor/h5bp-post.less"
|
||||
|
169
src/_h5ai/public/css/vendor/h5bp-post.less
vendored
@@ -1,169 +0,0 @@
|
||||
/* ==========================================================================
|
||||
Helper classes
|
||||
========================================================================== */
|
||||
|
||||
/*
|
||||
* Hide visually and from screen readers
|
||||
*/
|
||||
|
||||
.hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/*
|
||||
* Hide only visually, but have it available for screen readers:
|
||||
* http://snook.ca/archives/html_and_css/hiding-content-for-accessibility
|
||||
*/
|
||||
|
||||
.visuallyhidden {
|
||||
border: 0;
|
||||
clip: rect(0 0 0 0);
|
||||
height: 1px;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
}
|
||||
|
||||
/*
|
||||
* Extends the .visuallyhidden class to allow the element
|
||||
* to be focusable when navigated to via the keyboard:
|
||||
* https://www.drupal.org/node/897638
|
||||
*/
|
||||
|
||||
.visuallyhidden.focusable:active,
|
||||
.visuallyhidden.focusable:focus {
|
||||
clip: auto;
|
||||
height: auto;
|
||||
margin: 0;
|
||||
overflow: visible;
|
||||
position: static;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
/*
|
||||
* Hide visually and from screen readers, but maintain layout
|
||||
*/
|
||||
|
||||
.invisible {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clearfix: contain floats
|
||||
*
|
||||
* For modern browsers
|
||||
* 1. The space content is one way to avoid an Opera bug when the
|
||||
* `contenteditable` attribute is included anywhere else in the document.
|
||||
* Otherwise it causes space to appear at the top and bottom of elements
|
||||
* that receive the `clearfix` class.
|
||||
* 2. The use of `table` rather than `block` is only necessary if using
|
||||
* `:before` to contain the top-margins of child elements.
|
||||
*/
|
||||
|
||||
.clearfix:before,
|
||||
.clearfix:after {
|
||||
content: " "; /* 1 */
|
||||
display: table; /* 2 */
|
||||
}
|
||||
|
||||
.clearfix:after {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
EXAMPLE Media Queries for Responsive Design.
|
||||
These examples override the primary ('mobile first') styles.
|
||||
Modify as content requires.
|
||||
========================================================================== */
|
||||
|
||||
// @media only screen and (min-width: 35em) {
|
||||
// /* Style adjustments for viewports that meet the condition */
|
||||
// }
|
||||
|
||||
// @media print,
|
||||
// (-webkit-min-device-pixel-ratio: 1.25),
|
||||
// (min-resolution: 1.25dppx),
|
||||
// (min-resolution: 120dpi) {
|
||||
// /* Style adjustments for high resolution devices */
|
||||
// }
|
||||
|
||||
/* ==========================================================================
|
||||
Print styles.
|
||||
Inlined to avoid the additional HTTP request:
|
||||
http://www.phpied.com/delay-loading-your-print-css/
|
||||
========================================================================== */
|
||||
|
||||
@media print {
|
||||
*,
|
||||
*:before,
|
||||
*:after,
|
||||
*:first-letter,
|
||||
*:first-line {
|
||||
background: transparent !important;
|
||||
color: #000 !important; /* Black prints faster:
|
||||
http://www.sanbeiji.com/archives/953 */
|
||||
box-shadow: none !important;
|
||||
text-shadow: none !important;
|
||||
}
|
||||
|
||||
a,
|
||||
a:visited {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
a[href]:after {
|
||||
content: " (" attr(href) ")";
|
||||
}
|
||||
|
||||
abbr[title]:after {
|
||||
content: " (" attr(title) ")";
|
||||
}
|
||||
|
||||
/*
|
||||
* Don't show links that are fragment identifiers,
|
||||
* or use the `javascript:` pseudo protocol
|
||||
*/
|
||||
|
||||
a[href^="#"]:after,
|
||||
a[href^="javascript:"]:after {
|
||||
content: "";
|
||||
}
|
||||
|
||||
pre,
|
||||
blockquote {
|
||||
border: 1px solid #999;
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
|
||||
/*
|
||||
* Printing Tables:
|
||||
* http://css-discuss.incutio.com/wiki/Printing_Tables
|
||||
*/
|
||||
|
||||
thead {
|
||||
display: table-header-group;
|
||||
}
|
||||
|
||||
tr,
|
||||
img {
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100% !important;
|
||||
}
|
||||
|
||||
p,
|
||||
h2,
|
||||
h3 {
|
||||
orphans: 3;
|
||||
widows: 3;
|
||||
}
|
||||
|
||||
h2,
|
||||
h3 {
|
||||
page-break-after: avoid;
|
||||
}
|
||||
}
|
96
src/_h5ai/public/css/vendor/h5bp-pre.less
vendored
@@ -1,96 +0,0 @@
|
||||
/* HTML5 Boilerplate v5.2.0 | MIT License | https://html5boilerplate.com/ */
|
||||
|
||||
/*
|
||||
* What follows is the result of much research on cross-browser styling.
|
||||
* Credit left inline and big thanks to Nicolas Gallagher, Jonathan Neal,
|
||||
* Kroc Camen, and the H5BP dev community and team.
|
||||
*/
|
||||
|
||||
/* ==========================================================================
|
||||
Base styles: opinionated defaults
|
||||
========================================================================== */
|
||||
|
||||
html {
|
||||
color: #222;
|
||||
font-size: 1em;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove text-shadow in selection highlight:
|
||||
* https://twitter.com/miketaylr/status/12228805301
|
||||
*
|
||||
* These selection rule sets have to be separate.
|
||||
* Customize the background color to match your design.
|
||||
*/
|
||||
|
||||
::-moz-selection {
|
||||
background: #b3d4fc;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
::selection {
|
||||
background: #b3d4fc;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
/*
|
||||
* A better looking default horizontal rule
|
||||
*/
|
||||
|
||||
hr {
|
||||
display: block;
|
||||
height: 1px;
|
||||
border: 0;
|
||||
border-top: 1px solid #ccc;
|
||||
margin: 1em 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove the gap between audio, canvas, iframes,
|
||||
* images, videos and the bottom of their containers:
|
||||
* https://github.com/h5bp/html5-boilerplate/issues/440
|
||||
*/
|
||||
|
||||
audio,
|
||||
canvas,
|
||||
iframe,
|
||||
img,
|
||||
svg,
|
||||
video {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove default fieldset styles.
|
||||
*/
|
||||
|
||||
fieldset {
|
||||
border: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Allow only vertical resizing of textareas.
|
||||
*/
|
||||
|
||||
textarea {
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
/* ==========================================================================
|
||||
Browser Upgrade Prompt
|
||||
========================================================================== */
|
||||
|
||||
// .browserupgrade {
|
||||
// margin: 0.2em 0;
|
||||
// background: #ccc;
|
||||
// color: #000;
|
||||
// padding: 0.2em 0;
|
||||
// }
|
||||
|
||||
/* ==========================================================================
|
||||
Author's custom styles
|
||||
========================================================================== */
|
424
src/_h5ai/public/css/vendor/normalize.less
vendored
@@ -1,424 +0,0 @@
|
||||
/* normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */
|
||||
|
||||
/**
|
||||
* 1. Set default font family to sans-serif.
|
||||
* 2. Prevent iOS and IE text size adjust after device orientation change,
|
||||
* without disabling user zoom.
|
||||
*/
|
||||
|
||||
html {
|
||||
font-family: sans-serif; /* 1 */
|
||||
-ms-text-size-adjust: 100%; /* 2 */
|
||||
-webkit-text-size-adjust: 100%; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove default margin.
|
||||
*/
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* HTML5 display definitions
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Correct `block` display not defined for any HTML5 element in IE 8/9.
|
||||
* Correct `block` display not defined for `details` or `summary` in IE 10/11
|
||||
* and Firefox.
|
||||
* Correct `block` display not defined for `main` in IE 11.
|
||||
*/
|
||||
|
||||
article,
|
||||
aside,
|
||||
details,
|
||||
figcaption,
|
||||
figure,
|
||||
footer,
|
||||
header,
|
||||
hgroup,
|
||||
main,
|
||||
menu,
|
||||
nav,
|
||||
section,
|
||||
summary {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct `inline-block` display not defined in IE 8/9.
|
||||
* 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
|
||||
*/
|
||||
|
||||
audio,
|
||||
canvas,
|
||||
progress,
|
||||
video {
|
||||
display: inline-block; /* 1 */
|
||||
vertical-align: baseline; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent modern browsers from displaying `audio` without controls.
|
||||
* Remove excess height in iOS 5 devices.
|
||||
*/
|
||||
|
||||
audio:not([controls]) {
|
||||
display: none;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address `[hidden]` styling not present in IE 8/9/10.
|
||||
* Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22.
|
||||
*/
|
||||
|
||||
[hidden],
|
||||
template {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Links
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove the gray background color from active links in IE 10.
|
||||
*/
|
||||
|
||||
a {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Improve readability of focused elements when they are also in an
|
||||
* active/hover state.
|
||||
*/
|
||||
|
||||
a:active,
|
||||
a:hover {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
/* Text-level semantics
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Address styling not present in IE 8/9/10/11, Safari, and Chrome.
|
||||
*/
|
||||
|
||||
abbr[title] {
|
||||
border-bottom: 1px dotted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
|
||||
*/
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address styling not present in Safari and Chrome.
|
||||
*/
|
||||
|
||||
dfn {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address variable `h1` font-size and margin within `section` and `article`
|
||||
* contexts in Firefox 4+, Safari, and Chrome.
|
||||
*/
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address styling not present in IE 8/9.
|
||||
*/
|
||||
|
||||
mark {
|
||||
background: #ff0;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address inconsistent and variable font size in all browsers.
|
||||
*/
|
||||
|
||||
small {
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent `sub` and `sup` affecting `line-height` in all browsers.
|
||||
*/
|
||||
|
||||
sub,
|
||||
sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
/* Embedded content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove border when inside `a` element in IE 8/9/10.
|
||||
*/
|
||||
|
||||
img {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct overflow not hidden in IE 9/10/11.
|
||||
*/
|
||||
|
||||
svg:not(:root) {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Grouping content
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Address margin not present in IE 8/9 and Safari.
|
||||
*/
|
||||
|
||||
figure {
|
||||
margin: 1em 40px;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address differences between Firefox and other browsers.
|
||||
*/
|
||||
|
||||
hr {
|
||||
box-sizing: content-box;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Contain overflow in all browsers.
|
||||
*/
|
||||
|
||||
pre {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address odd `em`-unit font size rendering in all browsers.
|
||||
*/
|
||||
|
||||
code,
|
||||
kbd,
|
||||
pre,
|
||||
samp {
|
||||
font-family: monospace, monospace;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
/* Forms
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Known limitation: by default, Chrome and Safari on OS X allow very limited
|
||||
* styling of `select`, unless a `border` property is set.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 1. Correct color not being inherited.
|
||||
* Known issue: affects color of disabled elements.
|
||||
* 2. Correct font properties not being inherited.
|
||||
* 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
|
||||
*/
|
||||
|
||||
button,
|
||||
input,
|
||||
optgroup,
|
||||
select,
|
||||
textarea {
|
||||
color: inherit; /* 1 */
|
||||
font: inherit; /* 2 */
|
||||
margin: 0; /* 3 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Address `overflow` set to `hidden` in IE 8/9/10/11.
|
||||
*/
|
||||
|
||||
button {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address inconsistent `text-transform` inheritance for `button` and `select`.
|
||||
* All other form control elements do not inherit `text-transform` values.
|
||||
* Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
|
||||
* Correct `select` style inheritance in Firefox.
|
||||
*/
|
||||
|
||||
button,
|
||||
select {
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
|
||||
* and `video` controls.
|
||||
* 2. Correct inability to style clickable `input` types in iOS.
|
||||
* 3. Improve usability and consistency of cursor style between image-type
|
||||
* `input` and others.
|
||||
*/
|
||||
|
||||
button,
|
||||
html input[type="button"], /* 1 */
|
||||
input[type="reset"],
|
||||
input[type="submit"] {
|
||||
-webkit-appearance: button; /* 2 */
|
||||
cursor: pointer; /* 3 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-set default cursor for disabled elements.
|
||||
*/
|
||||
|
||||
button[disabled],
|
||||
html input[disabled] {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove inner padding and border in Firefox 4+.
|
||||
*/
|
||||
|
||||
button::-moz-focus-inner,
|
||||
input::-moz-focus-inner {
|
||||
border: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Address Firefox 4+ setting `line-height` on `input` using `!important` in
|
||||
* the UA stylesheet.
|
||||
*/
|
||||
|
||||
input {
|
||||
line-height: normal;
|
||||
}
|
||||
|
||||
/**
|
||||
* It's recommended that you don't attempt to style these elements.
|
||||
* Firefox's implementation doesn't respect box-sizing, padding, or width.
|
||||
*
|
||||
* 1. Address box sizing set to `content-box` in IE 8/9/10.
|
||||
* 2. Remove excess padding in IE 8/9/10.
|
||||
*/
|
||||
|
||||
input[type="checkbox"],
|
||||
input[type="radio"] {
|
||||
box-sizing: border-box; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix the cursor style for Chrome's increment/decrement buttons. For certain
|
||||
* `font-size` values of the `input`, it causes the cursor style of the
|
||||
* decrement button to change from `default` to `text`.
|
||||
*/
|
||||
|
||||
input[type="number"]::-webkit-inner-spin-button,
|
||||
input[type="number"]::-webkit-outer-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Address `appearance` set to `searchfield` in Safari and Chrome.
|
||||
* 2. Address `box-sizing` set to `border-box` in Safari and Chrome.
|
||||
*/
|
||||
|
||||
input[type="search"] {
|
||||
-webkit-appearance: textfield; /* 1 */
|
||||
box-sizing: content-box; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove inner padding and search cancel button in Safari and Chrome on OS X.
|
||||
* Safari (but not Chrome) clips the cancel button when the search input has
|
||||
* padding (and `textfield` appearance).
|
||||
*/
|
||||
|
||||
input[type="search"]::-webkit-search-cancel-button,
|
||||
input[type="search"]::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define consistent border, margin, and padding.
|
||||
*/
|
||||
|
||||
fieldset {
|
||||
border: 1px solid #c0c0c0;
|
||||
margin: 0 2px;
|
||||
padding: 0.35em 0.625em 0.75em;
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Correct `color` not being inherited in IE 8/9/10/11.
|
||||
* 2. Remove padding so people aren't caught out if they zero out fieldsets.
|
||||
*/
|
||||
|
||||
legend {
|
||||
border: 0; /* 1 */
|
||||
padding: 0; /* 2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove default vertical scrollbar in IE 8/9/10/11.
|
||||
*/
|
||||
|
||||
textarea {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't inherit the `font-weight` (applied by a rule above).
|
||||
* NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
|
||||
*/
|
||||
|
||||
optgroup {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* Tables
|
||||
========================================================================== */
|
||||
|
||||
/**
|
||||
* Remove most spacing between table cells.
|
||||
*/
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
td,
|
||||
th {
|
||||
padding: 0;
|
||||
}
|
Before Width: | Height: | Size: 131 B After Width: | Height: | Size: 118 B |
Before Width: | Height: | Size: 140 B After Width: | Height: | Size: 108 B |
Before Width: | Height: | Size: 117 B After Width: | Height: | Size: 99 B |
Before Width: | Height: | Size: 228 B After Width: | Height: | Size: 219 B |
Before Width: | Height: | Size: 115 B After Width: | Height: | Size: 96 B |
Before Width: | Height: | Size: 125 B After Width: | Height: | Size: 120 B |
@@ -1,3 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
|
||||
<path fill="#a4c639" d="m 5.78125,2 c -0.00155,0.010339 -0.00155,0.020911 0,0.03125 -0.010339,-0.00155 -0.020911,-0.00155 -0.03125,0 -0.00155,0.010339 -0.00155,0.020911 0,0.03125 -0.00155,0.010339 -0.00155,0.020911 0,0.03125 -0.00155,0.010339 -0.00155,0.020911 0,0.03125 -0.00155,0.010339 -0.00155,0.020911 0,0.03125 L 6.625,3.625 C 5.9445396,4.3022596 5.5134919,5.1886446 5.5,6.15625 l 9,0 C 14.486508,5.1886446 14.05546,4.3022596 13.375,3.625 L 14.25,2.15625 c 0.0016,-0.010339 0.0016,-0.020911 0,-0.03125 0.0016,-0.010339 0.0016,-0.020911 0,-0.03125 0.0016,-0.010339 0.0016,-0.020911 0,-0.03125 -0.0081,-0.012465 -0.01878,-0.023194 -0.03125,-0.03125 C 14.210694,2.0187849 14.199965,2.0080563 14.1875,2 c -0.01034,-0.00155 -0.02091,-0.00155 -0.03125,0 -0.01034,-0.00155 -0.02091,-0.00155 -0.03125,0 -0.01034,-0.00155 -0.02091,-0.00155 -0.03125,0 -0.0016,0.010339 -0.0016,0.020911 0,0.03125 -0.01034,-0.00155 -0.02091,-0.00155 -0.03125,0 -0.0016,0.010339 -0.0016,0.020911 0,0.03125 L 13.21875,3.5 C 12.508811,2.8579404 11.574169,2.4161295 10.5,2.3125 l -1,0 C 8.4258309,2.4161295 7.4911892,2.8579404 6.78125,3.5 L 5.9375,2.0625 c 0.00155,-0.010339 0.00155,-0.020911 0,-0.03125 -0.010339,-0.00155 -0.020911,-0.00155 -0.03125,0 C 5.8981937,2.0187849 5.8874651,2.0080563 5.875,2 5.8646606,1.9984471 5.8540894,1.9984471 5.84375,2 5.8334106,1.9984471 5.8228394,1.9984471 5.8125,2 5.8021606,1.9984471 5.7915894,1.9984471 5.78125,2 z M 8,3.84375 c 0.020808,-0.00123 0.041692,-0.00123 0.0625,0 0.2933398,-0.043249 0.5943541,0.2102369 0.59375,0.5 C 8.6738727,4.6179758 8.4219324,4.8799872 8.140625,4.8799872 7.8593176,4.8799872 7.6073773,4.6179758 7.625,4.34375 7.6183882,4.1213788 7.7809375,3.9046463 8,3.84375 z m 3.84375,0 c 0.02081,-0.00123 0.04169,-0.00123 0.0625,0 0.29334,-0.043249 0.594354,0.2102369 0.59375,0.5 0.01762,0.2742258 -0.234318,0.5362372 -0.515625,0.5362372 -0.281307,0 -0.533248,-0.2620114 -0.515625,-0.5362372 -0.0066,-0.2223712 0.155938,-0.4391037 0.375,-0.5 z m -6.375,2.71875 c -2.995e-4,2.2008535 0,4.418486 0,6.625 0,0.698086 0.5327963,1.25 1.21875,1.25 l 0.0625,0 0,2.5625 c 0,0.553265 0.4467345,1 1,1 0.5532655,0 1,-0.446735 1,-1 l 0,-2.5625 2.5,0 0,2.5625 c 0,0.553265 0.446735,1 1,1 0.553265,0 1,-0.446735 1,-1 l 0,-2.5625 0.0625,0 c 0.68596,0 1.21875,-0.551914 1.21875,-1.25 10e-7,-2.205262 0,-4.4258583 0,-6.625 z m -1.625,0.59375 c -0.5532655,0 -1,0.4467345 -1,1 l 0,4.28125 c 0,0.553265 0.4467345,1 1,1 0.5532655,0 1,-0.446735 1,-1 l 0,-4.28125 c 0,-0.5532655 -0.4467345,-1 -1,-1 z m 12.3125,0 c -0.553265,0 -1,0.4467345 -1,1 l 0,4.28125 c 0,0.553265 0.446735,1 1,1 0.553265,0 1,-0.446735 1,-1 l 0,-4.28125 c 0,-0.5532655 -0.446735,-1 -1,-1 z"/>
|
||||
<path fill="#a4c639" d="M14.5 3.2C14.4 3.2 14.2 3.3 14.1 3.5L13.3 5C12.3 4.4 11.2 4 10 4 8.8 4 7.7 4.3 6.8 4.9L5.9 3.5C5.8 3.3 5.6 3.2 5.5 3.3 5.4 3.3 5.4 3.2 5.3 3.3L5.2 3.3C5 3.5 4.9 3.8 5.1 4L6 5.6C4.8 6.7 4 8.2 4 10L16 10C16 8.3 15.3 6.7 14.1 5.6L15 4C15.1 3.8 15 3.5 14.8 3.3L14.7 3.3C14.7 3.2 14.6 3.2 14.5 3.2zM7.3 7C7.8 7 8.2 7.4 8.2 7.9 8.2 8.4 7.8 8.8 7.3 8.8 6.8 8.8 6.4 8.4 6.4 7.9 6.4 7.4 6.8 7 7.3 7zM12.7 7C13.2 7 13.6 7.4 13.6 7.9 13.6 8.4 13.2 8.8 12.7 8.8 12.2 8.8 11.8 8.4 11.8 7.9 11.8 7.4 12.2 7 12.7 7zM4 10.5L4 16 16 16 16 10.5 4 10.5z"/>
|
||||
</svg>
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 656 B |
3
src/_h5ai/public/images/themes/comity/txt-rust.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
|
||||
<path fill="#795548" d="M18 9.9 17.3 9.5c0 0 0-0.1 0-0.1L17.9 8.8C17.9 8.8 18 8.6 18 8.5 18 8.4 17.9 8.4 17.9 8.4L17.1 8.1c0 0 0-0.1 0-0.1l0.4-0.7c0 0 0-0.1 0-0.3 0-0.1-0.1-0.1-0.1-0.1L16.5 6.7c0 0 0-0.1-0.1-0.1l0.3-0.7c0-0.1 0-0.1 0-0.3 0 0-0.1-0.1-0.1-0.1l-0.8 0c0 0-0.1-0.1-0.1-0.1L15.7 4.6c0-0.1 0-0.1 0-0.3 0 0-0.1-0.1-0.3 0l-0.8 0.1c0 0-0.1-0.1-0.1-0.1l0-0.8c0-0.1 0-0.1-0.1-0.1 0 0-0.1 0-0.3 0l-0.7 0.3c0 0-0.1 0-0.1-0.1L13.1 2.7c0-0.1 0-0.1-0.1-0.1-0.1 0-0.1 0-0.3 0l-0.7 0.4c0 0-0.1 0-0.1 0L11.6 2.3c0-0.1-0.1-0.1-0.1-0.1-0.1 0-0.1 0-0.3 0.1l-0.5 0.5c0 0-0.1 0-0.1 0L10.1 2.1C10.1 2 10 2 10 2 9.9 2 9.9 2 9.9 2.1l-0.4 0.7c0 0-0.1 0-0.1 0L8.8 2.3c0 0-0.1-0.1-0.3-0.1-0.1 0-0.1 0.1-0.1 0.1L8.1 2.9c0 0-0.1 0-0.1 0L7.3 2.5c0 0-0.1 0-0.3 0-0.1 0-0.1 0.1-0.1 0.1L6.7 3.5c0 0-0.1 0-0.1 0.1L5.9 3.4c-0.1 0-0.1 0-0.3 0 0 0-0.1 0.1-0.1 0.1l0 0.8c0 0-0.1 0.1-0.1 0.1L4.6 4.3c-0.1 0-0.1 0-0.3 0 0 0-0.1 0.1 0 0.3l0.1 0.8c0 0-0.1 0.1-0.1 0.1l-0.8 0c-0.1 0-0.1 0-0.1 0.1 0 0 0 0.1 0 0.3l0.3 0.7c0 0 0 0.1-0.1 0.1L2.7 6.9c-0.1 0-0.1 0-0.1 0.1 0 0.1 0 0.1 0 0.3l0.4 0.7c0 0 0 0.1 0 0.1L2.3 8.4c-0.1 0-0.1 0.1-0.1 0.1 0 0.1 0 0.1 0.1 0.3l0.5 0.5c0 0 0 0.1 0 0.1L2.1 9.9C2 9.9 2 10 2 10c0 0.1 0 0.1 0.1 0.1l0.7 0.4c0 0 0 0.1 0 0.1l-0.5 0.5c0 0-0.1 0.1-0.1 0.3 0 0.1 0.1 0.1 0.1 0.1l0.7 0.3c0 0 0 0.1 0 0.1l-0.4 0.7c0 0 0 0.1 0 0.3 0 0.1 0.1 0.1 0.1 0.1l0.8 0.1c0 0 0 0.1 0.1 0.1l-0.3 0.7c0 0.1 0 0.1 0 0.3 0 0 0.1 0.1 0.1 0.1l0.8 0c0 0 0.1 0.1 0.1 0.1l-0.1 0.8c0 0.1 0 0.1 0 0.3 0 0 0.1 0.1 0.3 0l0.8-0.1c0 0 0.1 0.1 0.1 0.1l0 0.8c0 0.1 0 0.1 0.1 0.1 0 0 0.1 0 0.3 0l0.7-0.3c0 0 0.1 0 0.1 0.1l0.1 0.8c0 0.1 0 0.1 0.1 0.1 0.1 0 0.1 0 0.3 0l0.7-0.4c0 0 0.1 0 0.1 0l0.3 0.7c0 0.1 0.1 0.1 0.1 0.1 0.1 0 0.1 0 0.3-0.1l0.5-0.5c0 0 0.1 0 0.1 0l0.4 0.7C9.9 17.9 10 18 10 18c0.1 0 0.1 0 0.1-0.1l0.4-0.7c0 0 0.1 0 0.1 0l0.5 0.5c0 0 0.1 0.1 0.3 0.1 0.1 0 0.1-0.1 0.1-0.1l0.3-0.7c0 0 0.1 0 0.1 0l0.7 0.4c0 0 0.1 0 0.3 0 0.1 0 0.1-0.1 0.1-0.1l0.1-0.8c0 0 0.1 0 0.1-0.1l0.7 0.3c0.1 0 0.1 0 0.3 0 0 0 0.1-0.1 0.1-0.1l0-0.8c0 0 0.1-0.1 0.1-0.1l0.8 0.1c0.1 0 0.1 0 0.3 0 0 0 0.1-0.1 0-0.3l-0.1-0.8c0 0 0.1-0.1 0.1-0.1l0.8 0c0.1 0 0.1 0 0.1-0.1 0 0 0-0.1 0-0.3l-0.3-0.7c0 0 0-0.1 0.1-0.1l0.8-0.1c0.1 0 0.1 0 0.1-0.1 0-0.1 0-0.1 0-0.3l-0.4-0.7c0 0 0-0.1 0-0.1l0.7-0.3c0.1 0 0.1-0.1 0.1-0.1 0-0.1 0-0.1-0.1-0.3l-0.5-0.5c0 0 0-0.1 0-0.1l0.7-0.4C18 10.1 18 10 18 10 18 9.9 18 9.9 17.9 9.9zm-4.5 5.6c-0.3 0-0.4-0.3-0.4-0.5 0-0.3 0.3-0.4 0.5-0.4 0.3 0 0.4 0.3 0.4 0.5 0 0.3-0.3 0.4-0.5 0.4zm-0.3-1.5c-0.3 0-0.4 0.1-0.5 0.3l-0.3 1.1C11.8 15.6 10.9 15.8 10 15.8c-0.8 0-1.8-0.1-2.4-0.5L7.3 14.2c0-0.3-0.3-0.4-0.5-0.3L5.8 14.2C5.7 13.9 5.5 13.7 5.4 13.5l4.7 0c0 0 0.1 0 0.1 0l0-1.6c0 0 0 0-0.1 0l-1.4 0 0-1.1 1.5 0c0.1 0 0.7 0 0.9 0.8 0 0.3 0.1 0.9 0.3 1.2 0.1 0.3 0.4 0.8 0.8 0.8l2.4 0c0 0 0 0 0.1 0-0.1 0.3-0.4 0.4-0.5 0.7l-1.1-0.4zm-6.6 1.5c-0.3 0-0.5-0.1-0.5-0.4 0-0.3 0.1-0.5 0.4-0.5 0.3 0 0.5 0.1 0.5 0.4 0 0.3-0.1 0.5-0.4 0.5zM4.8 8.1c0.1 0.3 0 0.5-0.3 0.7-0.3 0.1-0.5 0-0.7-0.3-0.1-0.3 0-0.5 0.3-0.7 0.3-0.1 0.5 0 0.7 0.3zM4.3 9.5 5.4 9.1C5.7 8.9 5.7 8.6 5.7 8.5l-0.3-0.5 0.8 0 0 3.8-1.6 0C4.4 11.2 4.3 10.7 4.3 10.1c0-0.3 0-0.4 0-0.7zm4.5-0.4 0-1.1 2 0c0.1 0 0.7 0.1 0.7 0.5 0 0.4-0.4 0.5-0.8 0.5l-1.8 0zM16 10c0 0.1 0 0.3 0 0.4l-0.5 0c0 0-0.1 0-0.1 0.1l0 0.3c0 0.7-0.4 0.8-0.7 0.8-0.3 0-0.7-0.1-0.7-0.3-0.1-0.9-0.5-1.2-0.9-1.6 0.5-0.4 1.2-0.9 1.2-1.6 0-0.8-0.5-1.4-0.9-1.5C12.7 6.2 12.2 6.2 12 6.2l-6.2 0C6.6 5.3 7.8 4.6 9.1 4.3l0.7 0.8c0.1 0.1 0.4 0.1 0.7 0l0.8-0.8c1.8 0.3 3.1 1.4 3.9 2.8l-0.5 1.2c-0.1 0.3 0 0.4 0.3 0.5l1.1 0.5c0 0.1 0 0.4 0 0.5zM9.7 3.6c0.1-0.1 0.5-0.1 0.7 0 0.1 0.1 0.1 0.5 0 0.7-0.1 0.1-0.5 0.1-0.7 0-0.1-0.1-0.1-0.5 0-0.7zm5.6 4.5C15.4 7.8 15.7 7.7 16 7.8 16.2 8 16.4 8.2 16.2 8.5 16.1 8.8 15.8 8.9 15.6 8.8 15.3 8.6 15.2 8.4 15.3 8.1z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 3.7 KiB |
@@ -1,5 +1,3 @@
|
||||
<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" width="24" height="24" version="1.1">
|
||||
<g transform="translate(0,-8)">
|
||||
<path d="m15.8 22.3h-0.8l-0.3-0.3c1-1.1 1.6-2.6 1.6-4.2 0-3.6-2.9-6.5-6.5-6.5-3.6 0-6.5 2.9-6.5 6.5 0 3.6 2.9 6.5 6.5 6.5 1.6 0 3.1-0.6 4.2-1.6l0.3 0.3v0.8l5 5 1.5-1.5-5-5zm-6 0c-2.5 0-4.5-2-4.5-4.5 0-2.5 2-4.5 4.5-4.5 2.5 0 4.5 2 4.5 4.5 0 2.5-2 4.5-4.5 4.5z" fill="#555"/>
|
||||
</g>
|
||||
</svg>
|
||||
<path d="M20 4H4l6 9v5l4 2v-7z" fill="#555"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 443 B After Width: | Height: | Size: 172 B |
@@ -1,12 +1,16 @@
|
||||
<?php
|
||||
|
||||
define('H5AI_VERSION', '{{VERSION}}');
|
||||
define('MIN_PHP_VERSION', '5.5.0');
|
||||
define('MIN_PHP_VERSION', '7.0.0');
|
||||
|
||||
if (!function_exists('version_compare') || version_compare(PHP_VERSION, MIN_PHP_VERSION, '<')) {
|
||||
header('Content-type: text/plain;charset=utf-8');
|
||||
echo '[err] h5ai requires PHP ' . MIN_PHP_VERSION . ' or later, but found PHP ' . PHP_VERSION;
|
||||
exit;
|
||||
exit('[ERR] h5ai requires PHP ' . MIN_PHP_VERSION . ' or later, but found PHP ' . PHP_VERSION);
|
||||
}
|
||||
|
||||
if (substr(H5AI_VERSION, 0, 1) === '{') {
|
||||
header('Content-type: text/plain;charset=utf-8');
|
||||
exit('[ERR] h5ai sources must be preprocessed to work correctly');
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/../private/php/class-bootstrap.php';
|
||||
|
@@ -1,25 +0,0 @@
|
||||
modulejs.define('boot', ['$', 'core/server'], function ($, server) {
|
||||
var module = $('script[data-module]').data('module');
|
||||
var data = {
|
||||
action: 'get',
|
||||
setup: true,
|
||||
options: true,
|
||||
types: true
|
||||
};
|
||||
|
||||
if (module === 'index') {
|
||||
data.theme = true;
|
||||
data.langs = true;
|
||||
} else if (module === 'info') {
|
||||
data.refresh = true;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
server.request(data, function (config) {
|
||||
modulejs.define('config', config);
|
||||
$(function () {
|
||||
modulejs.require('main/' + module);
|
||||
});
|
||||
});
|
||||
});
|
5
src/_h5ai/public/js/lib/config.js
Normal file
@@ -0,0 +1,5 @@
|
||||
const {request} = require('./server');
|
||||
|
||||
const config = module.exports = {
|
||||
_update: query => request(query).then(resp => Object.assign(config, resp))
|
||||
};
|
@@ -1,36 +1,28 @@
|
||||
modulejs.define('core/event', ['_'], function (_) {
|
||||
var slice = Array.prototype.slice;
|
||||
var subscriptions = {};
|
||||
const {isStr, isFn, dom} = require('../util');
|
||||
|
||||
function sub(topic, callback) {
|
||||
if (_.isString(topic) && _.isFunction(callback)) {
|
||||
if (!subscriptions[topic]) {
|
||||
subscriptions[topic] = [];
|
||||
}
|
||||
subscriptions[topic].push(callback);
|
||||
const subscriptions = {};
|
||||
|
||||
const sub = (topic, listener) => {
|
||||
if (isStr(topic) && isFn(listener)) {
|
||||
if (!subscriptions[topic]) {
|
||||
subscriptions[topic] = [];
|
||||
}
|
||||
subscriptions[topic].push(listener);
|
||||
}
|
||||
};
|
||||
|
||||
function unsub(topic, callback) {
|
||||
if (_.isString(topic) && _.isFunction(callback) && subscriptions[topic]) {
|
||||
subscriptions[topic] = _.without(subscriptions[topic], callback);
|
||||
}
|
||||
const pub = (topic, ...args) => {
|
||||
// console.log(topic, args);
|
||||
if (isStr(topic) && subscriptions[topic]) {
|
||||
subscriptions[topic].forEach(listener => {
|
||||
listener.apply(topic, args);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function pub(topic) {
|
||||
var args = slice.call(arguments, 1);
|
||||
dom(global.window).on('resize', () => pub('resize'));
|
||||
|
||||
if (_.isString(topic) && subscriptions[topic]) {
|
||||
_.each(subscriptions[topic], function (callback) {
|
||||
callback.apply(topic, args);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
sub: sub,
|
||||
unsub: unsub,
|
||||
pub: pub
|
||||
};
|
||||
});
|
||||
module.exports = {
|
||||
sub,
|
||||
pub
|
||||
};
|
||||
|
@@ -1,95 +1,96 @@
|
||||
modulejs.define('core/format', ['_'], function (_) {
|
||||
var decimalMetric = {
|
||||
t: 1000.0,
|
||||
k: 1000.0,
|
||||
u: ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
|
||||
const {isNum} = require('../util');
|
||||
|
||||
const decimalMetric = {
|
||||
t: 1000.0,
|
||||
k: 1000.0,
|
||||
u: ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
|
||||
};
|
||||
const binaryMetric = {
|
||||
t: 1024.0,
|
||||
k: 1024.0,
|
||||
u: ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']
|
||||
};
|
||||
let defaultMetric = decimalMetric;
|
||||
|
||||
const datePatterns = [
|
||||
[/YYYY/, 'Y', 4],
|
||||
[/YY/, 'Y', 2],
|
||||
[/Y/, 'Y', 0],
|
||||
[/MM/, 'M', 2],
|
||||
[/M/, 'M', 0],
|
||||
[/DD/, 'D', 2],
|
||||
[/D/, 'D', 0],
|
||||
[/HH/, 'H', 2],
|
||||
[/H/, 'H', 0],
|
||||
[/mm/, 'm', 2],
|
||||
[/m/, 'm', 0],
|
||||
[/ss/, 's', 2],
|
||||
[/s/, 's', 0]
|
||||
];
|
||||
let defaultDateFormat = 'YYYY-MM-DD HH:mm';
|
||||
|
||||
|
||||
const setDefaultMetric = useBinaryMetric => {
|
||||
defaultMetric = useBinaryMetric ? binaryMetric : decimalMetric;
|
||||
};
|
||||
|
||||
const formatSize = (size, metric) => {
|
||||
metric = metric || defaultMetric;
|
||||
|
||||
if (!isNum(size) || size < 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
let i = 0;
|
||||
const maxI = metric.u.length - 1;
|
||||
|
||||
while (size >= metric.t && i < maxI) {
|
||||
size /= metric.k;
|
||||
i += 1;
|
||||
}
|
||||
return (i <= 1 ? Math.round(size) : size.toFixed(1)).toString() + ' ' + metric.u[i];
|
||||
};
|
||||
|
||||
const setDefaultDateFormat = dateFormat => {
|
||||
defaultDateFormat = dateFormat;
|
||||
};
|
||||
|
||||
const formatNumber = (number, padding) => {
|
||||
let str = String(number);
|
||||
if (padding) {
|
||||
str = ('000' + str).substr(-padding);
|
||||
}
|
||||
return str;
|
||||
};
|
||||
|
||||
const formatDate = (millis, format) => {
|
||||
if (!millis || !isNum(millis)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
format = format || defaultDateFormat;
|
||||
|
||||
const date = new Date(millis);
|
||||
const d = {
|
||||
Y: date.getFullYear(),
|
||||
M: date.getMonth() + 1,
|
||||
D: date.getDate(),
|
||||
H: date.getHours(),
|
||||
m: date.getMinutes(),
|
||||
s: date.getSeconds()
|
||||
};
|
||||
var binaryMetric = {
|
||||
t: 1024.0,
|
||||
k: 1024.0,
|
||||
u: ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']
|
||||
};
|
||||
var defaultMetric = decimalMetric;
|
||||
var datePatterns = [
|
||||
[/YYYY/, 'Y', 4],
|
||||
[/YY/, 'Y', 2],
|
||||
[/Y/, 'Y', 0],
|
||||
[/MM/, 'M', 2],
|
||||
[/M/, 'M', 0],
|
||||
[/DD/, 'D', 2],
|
||||
[/D/, 'D', 0],
|
||||
[/HH/, 'H', 2],
|
||||
[/H/, 'H', 0],
|
||||
[/mm/, 'm', 2],
|
||||
[/m/, 'm', 0],
|
||||
[/ss/, 's', 2],
|
||||
[/s/, 's', 0]
|
||||
];
|
||||
var defaultDateFormat = 'YYYY-MM-DD HH:mm';
|
||||
|
||||
datePatterns.forEach(pattern => {
|
||||
format = format.replace(pattern[0], formatNumber(d[pattern[1]], pattern[2]));
|
||||
});
|
||||
|
||||
return format;
|
||||
};
|
||||
|
||||
|
||||
function setDefaultMetric(useBinaryMetric) {
|
||||
defaultMetric = useBinaryMetric ? binaryMetric : decimalMetric;
|
||||
}
|
||||
|
||||
function formatSize(size, metric) {
|
||||
metric = metric || defaultMetric;
|
||||
|
||||
if (!_.isNumber(size) || size < 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
var maxI = metric.u.length - 1;
|
||||
|
||||
while (size >= metric.t && i < maxI) {
|
||||
size /= metric.k;
|
||||
i += 1;
|
||||
}
|
||||
return (i <= 1 ? Math.round(size) : size.toFixed(1)).toString() + ' ' + metric.u[i];
|
||||
}
|
||||
|
||||
function setDefaultDateFormat(dateFormat) {
|
||||
defaultDateFormat = dateFormat;
|
||||
}
|
||||
|
||||
function formatNumber(number, padding) {
|
||||
var str = String(number);
|
||||
if (padding) {
|
||||
str = ('000' + str).substr(-padding);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
function formatDate(millis, format) {
|
||||
if (!millis || !_.isNumber(millis)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
format = format || defaultDateFormat;
|
||||
|
||||
var date = new Date(millis);
|
||||
var d = {
|
||||
Y: date.getFullYear(),
|
||||
M: date.getMonth() + 1,
|
||||
D: date.getDate(),
|
||||
H: date.getHours(),
|
||||
m: date.getMinutes(),
|
||||
s: date.getSeconds()
|
||||
};
|
||||
|
||||
datePatterns.forEach(function (pattern) {
|
||||
format = format.replace(pattern[0], formatNumber(d[pattern[1]], pattern[2]));
|
||||
});
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
setDefaultMetric: setDefaultMetric,
|
||||
formatSize: formatSize,
|
||||
setDefaultDateFormat: setDefaultDateFormat,
|
||||
formatDate: formatDate
|
||||
};
|
||||
});
|
||||
module.exports = {
|
||||
setDefaultMetric,
|
||||
formatSize,
|
||||
setDefaultDateFormat,
|
||||
formatDate
|
||||
};
|
||||
|
@@ -1,3 +1,2 @@
|
||||
modulejs.define('core/langs', ['_', 'config'], function (_, config) {
|
||||
return _.extend({}, config.langs);
|
||||
});
|
||||
const {langs} = require('../config');
|
||||
module.exports = Object.assign({}, langs);
|
||||
|
@@ -1,181 +1,181 @@
|
||||
modulejs.define('core/location', ['_', 'core/event', 'core/modernizr', 'core/settings', 'view/notification'], function (_, event, modernizr, allsettings, notification) {
|
||||
var settings = _.extend({
|
||||
fastBrowsing: true,
|
||||
unmanagedInNewWindow: true
|
||||
}, allsettings.view);
|
||||
var doc = document;
|
||||
var history = settings.fastBrowsing && modernizr.history ? window.history : null;
|
||||
var reUriToPathname = /^.*:\/\/[^\/]*|[^\/]*$/g;
|
||||
var absHref = null;
|
||||
var reForceEncoding = [
|
||||
[/\/+/g, '/'],
|
||||
[/ /g, '%20'],
|
||||
[/!/g, '%21'],
|
||||
[/#/g, '%23'],
|
||||
[/\$/g, '%24'],
|
||||
[/&/g, '%26'],
|
||||
[/'/g, '%27'],
|
||||
[/\(/g, '%28'],
|
||||
[/\)/g, '%29'],
|
||||
[/\*/g, '%2A'],
|
||||
[/\+/g, '%2B'],
|
||||
[/\,/g, '%2C'],
|
||||
[/:/g, '%3A'],
|
||||
[/;/g, '%3B'],
|
||||
[/\=/g, '%3D'],
|
||||
[/\?/g, '%3F'],
|
||||
[/@/g, '%40'],
|
||||
[/\[/g, '%5B'],
|
||||
[/\]/g, '%5D']
|
||||
];
|
||||
const {each, values, difference} = require('../util');
|
||||
const {request} = require('../server');
|
||||
const allsettings = require('./settings');
|
||||
const event = require('./event');
|
||||
const notification = require('../view/notification');
|
||||
|
||||
function forceEncoding(href) {
|
||||
return reForceEncoding.reduce(function (nuHref, data) {
|
||||
return nuHref.replace(data[0], data[1]);
|
||||
}, href);
|
||||
const win = global.window;
|
||||
const doc = win.document;
|
||||
const settings = Object.assign({
|
||||
fastBrowsing: true,
|
||||
unmanagedInNewWindow: true
|
||||
}, allsettings.view);
|
||||
const history = settings.fastBrowsing ? win.history : null;
|
||||
const reUriToPathname = /^.*:\/\/[^\/]*|[^\/]*$/g;
|
||||
const reForceEncoding = [
|
||||
[/\/+/g, '/'],
|
||||
[/ /g, '%20'],
|
||||
[/!/g, '%21'],
|
||||
[/#/g, '%23'],
|
||||
[/\$/g, '%24'],
|
||||
[/&/g, '%26'],
|
||||
[/'/g, '%27'],
|
||||
[/\(/g, '%28'],
|
||||
[/\)/g, '%29'],
|
||||
[/\*/g, '%2A'],
|
||||
[/\+/g, '%2B'],
|
||||
[/\,/g, '%2C'],
|
||||
[/:/g, '%3A'],
|
||||
[/;/g, '%3B'],
|
||||
[/\=/g, '%3D'],
|
||||
[/\?/g, '%3F'],
|
||||
[/@/g, '%40'],
|
||||
[/\[/g, '%5B'],
|
||||
[/\]/g, '%5D']
|
||||
];
|
||||
|
||||
|
||||
let absHref = null;
|
||||
|
||||
|
||||
const forceEncoding = href => {
|
||||
return reForceEncoding.reduce((nuHref, data) => {
|
||||
return nuHref.replace(data[0], data[1]);
|
||||
}, href);
|
||||
};
|
||||
|
||||
const uriToPathname = uri => {
|
||||
return uri.replace(reUriToPathname, '');
|
||||
};
|
||||
|
||||
const hrefsAreDecoded = (() => {
|
||||
const testpathname = '/a b';
|
||||
const a = doc.createElement('a');
|
||||
|
||||
a.href = testpathname;
|
||||
return uriToPathname(a.href) === testpathname;
|
||||
})();
|
||||
|
||||
const encodedHref = href => {
|
||||
const a = doc.createElement('a');
|
||||
let location;
|
||||
|
||||
a.href = href;
|
||||
location = uriToPathname(a.href);
|
||||
|
||||
if (hrefsAreDecoded) {
|
||||
location = encodeURIComponent(location).replace(/%2F/ig, '/');
|
||||
}
|
||||
|
||||
function uriToPathname(uri) {
|
||||
return uri.replace(reUriToPathname, '');
|
||||
}
|
||||
return forceEncoding(location);
|
||||
};
|
||||
|
||||
var hrefsAreDecoded = (function () {
|
||||
var testpathname = '/a b';
|
||||
var a = doc.createElement('a');
|
||||
const getDomain = () => doc.domain;
|
||||
const getAbsHref = () => absHref;
|
||||
const getItem = () => require('../model/item').get(absHref);
|
||||
|
||||
a.href = testpathname;
|
||||
return uriToPathname(a.href) === testpathname;
|
||||
}());
|
||||
const load = () => {
|
||||
return request({action: 'get', items: {href: absHref, what: 1}}).then(json => {
|
||||
const Item = require('../model/item');
|
||||
const item = Item.get(absHref);
|
||||
|
||||
function encodedHref(href) {
|
||||
var a = doc.createElement('a');
|
||||
var location;
|
||||
if (json) {
|
||||
const found = {};
|
||||
|
||||
a.href = href;
|
||||
location = uriToPathname(a.href);
|
||||
each(json.items, jsonItem => {
|
||||
const e = Item.get(jsonItem);
|
||||
found[e.absHref] = true;
|
||||
});
|
||||
|
||||
if (hrefsAreDecoded) {
|
||||
location = encodeURIComponent(location).replace(/%2F/ig, '/');
|
||||
}
|
||||
|
||||
return forceEncoding(location);
|
||||
}
|
||||
|
||||
function getDomain() {
|
||||
return doc.domain;
|
||||
}
|
||||
|
||||
function getAbsHref() {
|
||||
return absHref;
|
||||
}
|
||||
|
||||
function getItem() {
|
||||
return modulejs.require('model/item').get(absHref);
|
||||
}
|
||||
|
||||
function load(callback) {
|
||||
modulejs.require('core/server').request({action: 'get', items: {href: absHref, what: 1}}, function (json) {
|
||||
var Item = modulejs.require('model/item');
|
||||
var item = Item.get(absHref);
|
||||
|
||||
if (json) {
|
||||
var found = {};
|
||||
|
||||
_.each(json.items, function (jsonItem) {
|
||||
var e = Item.get(jsonItem);
|
||||
found[e.absHref] = true;
|
||||
});
|
||||
|
||||
_.each(item.content, function (e) {
|
||||
if (!found[e.absHref]) {
|
||||
Item.remove(e.absHref);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (_.isFunction(callback)) {
|
||||
callback(item);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function refresh() {
|
||||
var item = getItem();
|
||||
var oldItems = _.values(item.content);
|
||||
|
||||
event.pub('location.beforeRefresh');
|
||||
|
||||
load(function () {
|
||||
var newItems = _.values(item.content);
|
||||
var added = _.difference(newItems, oldItems);
|
||||
var removed = _.difference(oldItems, newItems);
|
||||
|
||||
event.pub('location.refreshed', item, added, removed);
|
||||
});
|
||||
}
|
||||
|
||||
function setLocation(newAbsHref, keepBrowserUrl) {
|
||||
event.pub('location.beforeChange');
|
||||
|
||||
newAbsHref = encodedHref(newAbsHref);
|
||||
|
||||
if (absHref !== newAbsHref) {
|
||||
absHref = newAbsHref;
|
||||
|
||||
if (history) {
|
||||
if (keepBrowserUrl) {
|
||||
history.replaceState({absHref: absHref}, '', absHref);
|
||||
} else {
|
||||
history.pushState({absHref: absHref}, '', absHref);
|
||||
each(item.content, e => {
|
||||
if (!found[e.absHref]) {
|
||||
Item.remove(e.absHref);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return item;
|
||||
});
|
||||
};
|
||||
|
||||
const refresh = () => {
|
||||
const item = getItem();
|
||||
const oldItems = values(item.content);
|
||||
|
||||
event.pub('location.beforeRefresh');
|
||||
|
||||
load().then(() => {
|
||||
const newItems = values(item.content);
|
||||
const added = difference(newItems, oldItems);
|
||||
const removed = difference(oldItems, newItems);
|
||||
|
||||
event.pub('location.refreshed', item, added, removed);
|
||||
});
|
||||
};
|
||||
|
||||
const setLocation = (newAbsHref, keepBrowserUrl) => {
|
||||
event.pub('location.beforeChange');
|
||||
|
||||
newAbsHref = encodedHref(newAbsHref);
|
||||
|
||||
if (absHref !== newAbsHref) {
|
||||
absHref = newAbsHref;
|
||||
|
||||
if (history) {
|
||||
if (keepBrowserUrl) {
|
||||
history.replaceState({absHref}, '', absHref);
|
||||
} else {
|
||||
history.pushState({absHref}, '', absHref);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var item = getItem();
|
||||
if (item.isLoaded) {
|
||||
const item = getItem();
|
||||
if (item.isLoaded) {
|
||||
event.pub('location.changed', item);
|
||||
refresh();
|
||||
} else {
|
||||
notification.set('loading...');
|
||||
load().then(() => {
|
||||
item.isLoaded = true;
|
||||
notification.set();
|
||||
event.pub('location.changed', item);
|
||||
refresh();
|
||||
} else {
|
||||
notification.set('loading...');
|
||||
load(function () {
|
||||
item.isLoaded = true;
|
||||
notification.set();
|
||||
event.pub('location.changed', item);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const setLink = ($el, item) => {
|
||||
$el.attr('href', item.absHref);
|
||||
|
||||
if (history && item.isFolder() && item.isManaged) {
|
||||
$el.on('click', ev => {
|
||||
setLocation(item.absHref);
|
||||
ev.preventDefault();
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
function setLink($el, item) {
|
||||
$el.attr('href', item.absHref);
|
||||
|
||||
if (history && item.isFolder() && item.isManaged) {
|
||||
$el.on('click', function () {
|
||||
setLocation(item.absHref);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
if (settings.unmanagedInNewWindow && !item.isManaged) {
|
||||
$el.attr('target', '_blank');
|
||||
}
|
||||
if (settings.unmanagedInNewWindow && !item.isManaged) {
|
||||
$el.attr('target', '_blank');
|
||||
}
|
||||
};
|
||||
|
||||
function onPopState(ev) {
|
||||
if (ev.state && ev.state.absHref) {
|
||||
setLocation(ev.state.absHref, true);
|
||||
}
|
||||
const onPopState = ev => {
|
||||
if (ev.state && ev.state.absHref) {
|
||||
setLocation(ev.state.absHref, true);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
window.onpopstate = history ? onPopState : null;
|
||||
win.onpopstate = history ? onPopState : null;
|
||||
|
||||
|
||||
return {
|
||||
forceEncoding: forceEncoding,
|
||||
getDomain: getDomain,
|
||||
getAbsHref: getAbsHref,
|
||||
getItem: getItem,
|
||||
setLocation: setLocation,
|
||||
refresh: refresh,
|
||||
setLink: setLink
|
||||
};
|
||||
});
|
||||
module.exports = {
|
||||
forceEncoding,
|
||||
getDomain,
|
||||
getAbsHref,
|
||||
getItem,
|
||||
setLocation,
|
||||
refresh,
|
||||
setLink
|
||||
};
|
||||
|
@@ -1,25 +0,0 @@
|
||||
modulejs.define('core/modernizr', function () {
|
||||
var hasCanvas = (function () {
|
||||
var elem = document.createElement('canvas');
|
||||
return Boolean(elem.getContext && elem.getContext('2d'));
|
||||
}());
|
||||
|
||||
var hasHistory = Boolean(window.history && history.pushState);
|
||||
|
||||
var hasLocalStorage = (function () {
|
||||
var key = '#test#';
|
||||
try {
|
||||
localStorage.setItem(key, key);
|
||||
localStorage.removeItem(key);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}());
|
||||
|
||||
return {
|
||||
canvas: hasCanvas,
|
||||
history: hasHistory,
|
||||
localstorage: hasLocalStorage
|
||||
};
|
||||
});
|
@@ -1,37 +1,37 @@
|
||||
modulejs.define('core/resource', ['_', 'config', 'core/settings'], function (_, config, settings) {
|
||||
var imagesHref = settings.publicHref + 'images/';
|
||||
var uiHref = imagesHref + 'ui/';
|
||||
var themesHref = imagesHref + 'themes/';
|
||||
var defaultThemeHref = themesHref + 'default/';
|
||||
var defaultIcons = ['file', 'folder', 'folder-page', 'folder-parent', 'ar', 'aud', 'bin', 'img', 'txt', 'vid', 'x'];
|
||||
const {includes} = require('../util');
|
||||
const config = require('../config');
|
||||
const settings = require('./settings');
|
||||
|
||||
const imagesHref = settings.publicHref + 'images/';
|
||||
const uiHref = imagesHref + 'ui/';
|
||||
const themesHref = imagesHref + 'themes/';
|
||||
const defaultThemeHref = themesHref + 'default/';
|
||||
const defaultIcons = ['file', 'folder', 'folder-page', 'folder-parent', 'ar', 'aud', 'bin', 'img', 'txt', 'vid', 'x'];
|
||||
|
||||
|
||||
function image(id) {
|
||||
return uiHref + id + '.svg';
|
||||
const image = id => uiHref + id + '.svg';
|
||||
|
||||
const icon = id => {
|
||||
const baseId = (id || '').split('-')[0];
|
||||
const href = config.theme[id] || config.theme[baseId];
|
||||
|
||||
if (href) {
|
||||
return themesHref + href;
|
||||
}
|
||||
|
||||
function icon(id) {
|
||||
var baseId = (id || '').split('-')[0];
|
||||
var href = config.theme[id] || config.theme[baseId];
|
||||
|
||||
if (href) {
|
||||
return themesHref + href;
|
||||
}
|
||||
|
||||
if (_.indexOf(defaultIcons, id) >= 0) {
|
||||
return defaultThemeHref + id + '.svg';
|
||||
}
|
||||
|
||||
if (_.indexOf(defaultIcons, baseId) >= 0) {
|
||||
return defaultThemeHref + baseId + '.svg';
|
||||
}
|
||||
|
||||
return defaultThemeHref + 'file.svg';
|
||||
if (includes(defaultIcons, id)) {
|
||||
return defaultThemeHref + id + '.svg';
|
||||
}
|
||||
|
||||
if (includes(defaultIcons, baseId)) {
|
||||
return defaultThemeHref + baseId + '.svg';
|
||||
}
|
||||
|
||||
return {
|
||||
image: image,
|
||||
icon: icon
|
||||
};
|
||||
});
|
||||
return defaultThemeHref + 'file.svg';
|
||||
};
|
||||
|
||||
|
||||
module.exports = {
|
||||
image,
|
||||
icon
|
||||
};
|
||||
|
@@ -1,35 +0,0 @@
|
||||
modulejs.define('core/server', ['_', '$'], function (_, $) {
|
||||
function request(data, callback) {
|
||||
$.ajax({
|
||||
url: '?',
|
||||
data: data,
|
||||
type: 'post',
|
||||
dataType: 'json'
|
||||
})
|
||||
.done(function (json) {
|
||||
callback(json);
|
||||
})
|
||||
.fail(function () {
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
function formRequest(data) {
|
||||
var $form = $('<form method="post" action="?" style="display:none;"/>');
|
||||
|
||||
_.each(data, function (val, key) {
|
||||
$('<input type="hidden"/>')
|
||||
.attr('name', key)
|
||||
.attr('value', val)
|
||||
.appendTo($form);
|
||||
});
|
||||
|
||||
$form.appendTo('body').submit().remove();
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
request: request,
|
||||
formRequest: formRequest
|
||||
};
|
||||
});
|
@@ -1,6 +1,6 @@
|
||||
modulejs.define('core/settings', ['_', 'config'], function (_, config) {
|
||||
return _.extend({}, config.options, {
|
||||
publicHref: config.setup.PUBLIC_HREF,
|
||||
rootHref: config.setup.ROOT_HREF
|
||||
});
|
||||
const config = require('../config');
|
||||
|
||||
module.exports = Object.assign({}, config.options, {
|
||||
publicHref: config.setup.PUBLIC_HREF,
|
||||
rootHref: config.setup.ROOT_HREF
|
||||
});
|
||||
|
@@ -1,32 +1,28 @@
|
||||
modulejs.define('core/store', ['core/modernizr'], function (modernizr) {
|
||||
var store = modernizr.localstorage ? window.localStorage : {};
|
||||
var storekey = '_h5ai';
|
||||
const store = global.window.localStorage;
|
||||
const storekey = '_h5ai';
|
||||
|
||||
|
||||
function load() {
|
||||
try {
|
||||
return JSON.parse(store[storekey]);
|
||||
} catch (e) {/* skip */}
|
||||
return {};
|
||||
}
|
||||
const load = () => {
|
||||
try {
|
||||
return JSON.parse(store[storekey]);
|
||||
} catch (e) {/* skip */}
|
||||
return {};
|
||||
};
|
||||
|
||||
function save(obj) {
|
||||
store[storekey] = JSON.stringify(obj);
|
||||
}
|
||||
const save = obj => {
|
||||
store[storekey] = JSON.stringify(obj);
|
||||
};
|
||||
|
||||
function put(key, value) {
|
||||
var obj = load();
|
||||
obj[key] = value;
|
||||
save(obj);
|
||||
}
|
||||
const put = (key, value) => {
|
||||
const obj = load();
|
||||
obj[key] = value;
|
||||
save(obj);
|
||||
};
|
||||
|
||||
function get(key) {
|
||||
return load()[key];
|
||||
}
|
||||
const get = key => load()[key];
|
||||
|
||||
|
||||
return {
|
||||
put: put,
|
||||
get: get
|
||||
};
|
||||
});
|
||||
module.exports = {
|
||||
put,
|
||||
get
|
||||
};
|
||||
|
@@ -1,43 +1,43 @@
|
||||
modulejs.define('core/types', ['_', 'config'], function (_, config) {
|
||||
var reEndsWithSlash = /\/$/;
|
||||
var regexps = {};
|
||||
const {each, map} = require('../util');
|
||||
const config = require('../config');
|
||||
|
||||
const reEndsWithSlash = /\/$/;
|
||||
const regexps = {};
|
||||
|
||||
|
||||
function escapeRegExp(sequence) {
|
||||
return sequence.replace(/[\-\[\]\/\{\}\(\)\+\?\.\\\^\$]/g, '\\$&');
|
||||
// return sequence.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
|
||||
const escapeRegExp = sequence => {
|
||||
return sequence.replace(/[\-\[\]\/\{\}\(\)\+\?\.\\\^\$]/g, '\\$&');
|
||||
// return sequence.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
|
||||
};
|
||||
|
||||
const parse = types => {
|
||||
each(types, (patterns, type) => {
|
||||
const pattern = '^(' + map(patterns, p => '(' + escapeRegExp(p).replace(/\*/g, '.*') + ')').join('|') + ')$';
|
||||
regexps[type] = new RegExp(pattern, 'i');
|
||||
});
|
||||
};
|
||||
|
||||
const getType = sequence => {
|
||||
if (reEndsWithSlash.test(sequence)) {
|
||||
return 'folder';
|
||||
}
|
||||
|
||||
function parse(types) {
|
||||
_.each(types, function (patterns, type) {
|
||||
var pattern = '^(' + _.map(patterns, function (p) { return '(' + escapeRegExp(p).replace(/\*/g, '.*') + ')'; }).join('|') + ')$';
|
||||
regexps[type] = new RegExp(pattern, 'i');
|
||||
});
|
||||
}
|
||||
const slashidx = sequence.lastIndexOf('/');
|
||||
const name = slashidx >= 0 ? sequence.substr(slashidx + 1) : sequence;
|
||||
let result;
|
||||
|
||||
function getType(sequence) {
|
||||
if (reEndsWithSlash.test(sequence)) {
|
||||
return 'folder';
|
||||
each(regexps, (regexp, type) => {
|
||||
if (regexps[type].test(name)) {
|
||||
result = type;
|
||||
}
|
||||
});
|
||||
|
||||
var slashidx = sequence.lastIndexOf('/');
|
||||
var name = slashidx >= 0 ? sequence.substr(slashidx + 1) : sequence;
|
||||
var result;
|
||||
|
||||
_.each(regexps, function (regexp, type) {
|
||||
if (regexps[type].test(name)) {
|
||||
result = type;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
return result ? result : 'file';
|
||||
}
|
||||
return result ? result : 'file';
|
||||
};
|
||||
|
||||
|
||||
parse(_.extend({}, config.types));
|
||||
parse(Object.assign({}, config.types));
|
||||
|
||||
return {
|
||||
getType: getType
|
||||
};
|
||||
});
|
||||
module.exports = {
|
||||
getType
|
||||
};
|
||||
|