60 | 61 | {{file.name || 'Home'}} 62 |
63 | {{file.path ? 'Home' + (file.path == '/' ? '' : file.path) : ''}} 64 |Home{{file.path}} 101 |
Home{{file.path}} 112 |
115 | {{file.sizeReadable}} 116 | 117 | 118 |
├── LICENSE
├── Procfile
├── app.json
├── composer.json
├── composer.lock
├── config
├── config.yml
└── nginx.conf
├── install
├── install.php
└── mysql.sql
├── public
├── .htaccess
├── cheryl.css
├── cheryl.js
├── cheryl.phtml
├── icon.png
├── index.php
└── wink.svg
├── readme.md
└── src
├── Cheryl.php
└── User.php
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2003-2016 Devin Smith (http://devin.la)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Procfile:
--------------------------------------------------------------------------------
1 | web: vendor/bin/heroku-php-nginx -C config/nginx.conf public/
2 |
--------------------------------------------------------------------------------
/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Cheryl",
3 | "description": "Web based file management for the modern web",
4 | "website": "http://cheryl.io",
5 | "repository": "https://github.com/arzynik/cheryl",
6 | "keywords": ["cheryl", "tipsy", "php", "file", "manager"],
7 | "addons": ["heroku-postgresql"],
8 | "scripts": {
9 | "postdeploy": "php install/install.php"
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "require": {
3 | "tipsyphp/tipsy": "^0.11.6",
4 | "symfony/yaml": "^3.0"
5 | },
6 | "require-dev": {
7 | "satooshi/php-coveralls": "dev-master"
8 | },
9 | "autoload": {
10 | "psr-4": {
11 | "Cheryl\\": "src/"
12 | },
13 | "files": [
14 | ]
15 | },
16 | "archive": {
17 | "exclude": ["/tests", "/.travis.yml", "/.gitignore"]
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/composer.lock:
--------------------------------------------------------------------------------
1 | {
2 | "_readme": [
3 | "This file locks the dependencies of your project to a known state",
4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
5 | "This file is @generated automatically"
6 | ],
7 | "hash": "69f1c7b1475df47b8eff2d61d9dcbf4c",
8 | "content-hash": "11da3b374f3794c549eb6dd3c9d4c496",
9 | "packages": [
10 | {
11 | "name": "symfony/yaml",
12 | "version": "v3.0.6",
13 | "source": {
14 | "type": "git",
15 | "url": "https://github.com/symfony/yaml.git",
16 | "reference": "0047c8366744a16de7516622c5b7355336afae96"
17 | },
18 | "dist": {
19 | "type": "zip",
20 | "url": "https://api.github.com/repos/symfony/yaml/zipball/0047c8366744a16de7516622c5b7355336afae96",
21 | "reference": "0047c8366744a16de7516622c5b7355336afae96",
22 | "shasum": ""
23 | },
24 | "require": {
25 | "php": ">=5.5.9"
26 | },
27 | "type": "library",
28 | "extra": {
29 | "branch-alias": {
30 | "dev-master": "3.0-dev"
31 | }
32 | },
33 | "autoload": {
34 | "psr-4": {
35 | "Symfony\\Component\\Yaml\\": ""
36 | },
37 | "exclude-from-classmap": [
38 | "/Tests/"
39 | ]
40 | },
41 | "notification-url": "https://packagist.org/downloads/",
42 | "license": [
43 | "MIT"
44 | ],
45 | "authors": [
46 | {
47 | "name": "Fabien Potencier",
48 | "email": "fabien@symfony.com"
49 | },
50 | {
51 | "name": "Symfony Community",
52 | "homepage": "https://symfony.com/contributors"
53 | }
54 | ],
55 | "description": "Symfony Yaml Component",
56 | "homepage": "https://symfony.com",
57 | "time": "2016-03-04 07:55:57"
58 | },
59 | {
60 | "name": "tipsyphp/tipsy",
61 | "version": "v0.11.8",
62 | "source": {
63 | "type": "git",
64 | "url": "https://github.com/tipsyphp/tipsy.git",
65 | "reference": "3dac011472cc22917fbb90930e70d9ff1e48800d"
66 | },
67 | "dist": {
68 | "type": "zip",
69 | "url": "https://api.github.com/repos/tipsyphp/tipsy/zipball/3dac011472cc22917fbb90930e70d9ff1e48800d",
70 | "reference": "3dac011472cc22917fbb90930e70d9ff1e48800d",
71 | "shasum": ""
72 | },
73 | "require": {
74 | "php": ">=5.5.0"
75 | },
76 | "require-dev": {
77 | "satooshi/php-coveralls": "dev-master"
78 | },
79 | "type": "library",
80 | "autoload": {
81 | "psr-4": {
82 | "Tipsy\\": "src/"
83 | },
84 | "files": [
85 | "src/Tipsy.php"
86 | ]
87 | },
88 | "notification-url": "https://packagist.org/downloads/",
89 | "license": [
90 | "MIT"
91 | ],
92 | "authors": [
93 | {
94 | "name": "Devin Smith",
95 | "email": "devin@tipsy.la",
96 | "homepage": "http://devin.la",
97 | "role": "Developer"
98 | }
99 | ],
100 | "description": "An MVW PHP framework",
101 | "keywords": [
102 | "framework",
103 | "mvc",
104 | "mvw",
105 | "php"
106 | ],
107 | "time": "2014-07-24 00:00:00"
108 | }
109 | ],
110 | "packages-dev": [
111 | {
112 | "name": "guzzlehttp/guzzle",
113 | "version": "6.2.0",
114 | "source": {
115 | "type": "git",
116 | "url": "https://github.com/guzzle/guzzle.git",
117 | "reference": "d094e337976dff9d8e2424e8485872194e768662"
118 | },
119 | "dist": {
120 | "type": "zip",
121 | "url": "https://api.github.com/repos/guzzle/guzzle/zipball/d094e337976dff9d8e2424e8485872194e768662",
122 | "reference": "d094e337976dff9d8e2424e8485872194e768662",
123 | "shasum": ""
124 | },
125 | "require": {
126 | "guzzlehttp/promises": "~1.0",
127 | "guzzlehttp/psr7": "~1.1",
128 | "php": ">=5.5.0"
129 | },
130 | "require-dev": {
131 | "ext-curl": "*",
132 | "phpunit/phpunit": "~4.0",
133 | "psr/log": "~1.0"
134 | },
135 | "type": "library",
136 | "extra": {
137 | "branch-alias": {
138 | "dev-master": "6.2-dev"
139 | }
140 | },
141 | "autoload": {
142 | "files": [
143 | "src/functions_include.php"
144 | ],
145 | "psr-4": {
146 | "GuzzleHttp\\": "src/"
147 | }
148 | },
149 | "notification-url": "https://packagist.org/downloads/",
150 | "license": [
151 | "MIT"
152 | ],
153 | "authors": [
154 | {
155 | "name": "Michael Dowling",
156 | "email": "mtdowling@gmail.com",
157 | "homepage": "https://github.com/mtdowling"
158 | }
159 | ],
160 | "description": "Guzzle is a PHP HTTP client library",
161 | "homepage": "http://guzzlephp.org/",
162 | "keywords": [
163 | "client",
164 | "curl",
165 | "framework",
166 | "http",
167 | "http client",
168 | "rest",
169 | "web service"
170 | ],
171 | "time": "2016-03-21 20:02:09"
172 | },
173 | {
174 | "name": "guzzlehttp/promises",
175 | "version": "1.2.0",
176 | "source": {
177 | "type": "git",
178 | "url": "https://github.com/guzzle/promises.git",
179 | "reference": "c10d860e2a9595f8883527fa0021c7da9e65f579"
180 | },
181 | "dist": {
182 | "type": "zip",
183 | "url": "https://api.github.com/repos/guzzle/promises/zipball/c10d860e2a9595f8883527fa0021c7da9e65f579",
184 | "reference": "c10d860e2a9595f8883527fa0021c7da9e65f579",
185 | "shasum": ""
186 | },
187 | "require": {
188 | "php": ">=5.5.0"
189 | },
190 | "require-dev": {
191 | "phpunit/phpunit": "~4.0"
192 | },
193 | "type": "library",
194 | "extra": {
195 | "branch-alias": {
196 | "dev-master": "1.0-dev"
197 | }
198 | },
199 | "autoload": {
200 | "psr-4": {
201 | "GuzzleHttp\\Promise\\": "src/"
202 | },
203 | "files": [
204 | "src/functions_include.php"
205 | ]
206 | },
207 | "notification-url": "https://packagist.org/downloads/",
208 | "license": [
209 | "MIT"
210 | ],
211 | "authors": [
212 | {
213 | "name": "Michael Dowling",
214 | "email": "mtdowling@gmail.com",
215 | "homepage": "https://github.com/mtdowling"
216 | }
217 | ],
218 | "description": "Guzzle promises library",
219 | "keywords": [
220 | "promise"
221 | ],
222 | "time": "2016-05-18 16:56:05"
223 | },
224 | {
225 | "name": "guzzlehttp/psr7",
226 | "version": "1.3.0",
227 | "source": {
228 | "type": "git",
229 | "url": "https://github.com/guzzle/psr7.git",
230 | "reference": "31382fef2889136415751badebbd1cb022a4ed72"
231 | },
232 | "dist": {
233 | "type": "zip",
234 | "url": "https://api.github.com/repos/guzzle/psr7/zipball/31382fef2889136415751badebbd1cb022a4ed72",
235 | "reference": "31382fef2889136415751badebbd1cb022a4ed72",
236 | "shasum": ""
237 | },
238 | "require": {
239 | "php": ">=5.4.0",
240 | "psr/http-message": "~1.0"
241 | },
242 | "provide": {
243 | "psr/http-message-implementation": "1.0"
244 | },
245 | "require-dev": {
246 | "phpunit/phpunit": "~4.0"
247 | },
248 | "type": "library",
249 | "extra": {
250 | "branch-alias": {
251 | "dev-master": "1.0-dev"
252 | }
253 | },
254 | "autoload": {
255 | "psr-4": {
256 | "GuzzleHttp\\Psr7\\": "src/"
257 | },
258 | "files": [
259 | "src/functions_include.php"
260 | ]
261 | },
262 | "notification-url": "https://packagist.org/downloads/",
263 | "license": [
264 | "MIT"
265 | ],
266 | "authors": [
267 | {
268 | "name": "Michael Dowling",
269 | "email": "mtdowling@gmail.com",
270 | "homepage": "https://github.com/mtdowling"
271 | }
272 | ],
273 | "description": "PSR-7 message implementation",
274 | "keywords": [
275 | "http",
276 | "message",
277 | "stream",
278 | "uri"
279 | ],
280 | "time": "2016-04-13 19:56:01"
281 | },
282 | {
283 | "name": "psr/http-message",
284 | "version": "1.0",
285 | "source": {
286 | "type": "git",
287 | "url": "https://github.com/php-fig/http-message.git",
288 | "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298"
289 | },
290 | "dist": {
291 | "type": "zip",
292 | "url": "https://api.github.com/repos/php-fig/http-message/zipball/85d63699f0dbedb190bbd4b0d2b9dc707ea4c298",
293 | "reference": "85d63699f0dbedb190bbd4b0d2b9dc707ea4c298",
294 | "shasum": ""
295 | },
296 | "require": {
297 | "php": ">=5.3.0"
298 | },
299 | "type": "library",
300 | "extra": {
301 | "branch-alias": {
302 | "dev-master": "1.0.x-dev"
303 | }
304 | },
305 | "autoload": {
306 | "psr-4": {
307 | "Psr\\Http\\Message\\": "src/"
308 | }
309 | },
310 | "notification-url": "https://packagist.org/downloads/",
311 | "license": [
312 | "MIT"
313 | ],
314 | "authors": [
315 | {
316 | "name": "PHP-FIG",
317 | "homepage": "http://www.php-fig.org/"
318 | }
319 | ],
320 | "description": "Common interface for HTTP messages",
321 | "keywords": [
322 | "http",
323 | "http-message",
324 | "psr",
325 | "psr-7",
326 | "request",
327 | "response"
328 | ],
329 | "time": "2015-05-04 20:22:00"
330 | },
331 | {
332 | "name": "psr/log",
333 | "version": "1.0.0",
334 | "source": {
335 | "type": "git",
336 | "url": "https://github.com/php-fig/log.git",
337 | "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b"
338 | },
339 | "dist": {
340 | "type": "zip",
341 | "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b",
342 | "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b",
343 | "shasum": ""
344 | },
345 | "type": "library",
346 | "autoload": {
347 | "psr-0": {
348 | "Psr\\Log\\": ""
349 | }
350 | },
351 | "notification-url": "https://packagist.org/downloads/",
352 | "license": [
353 | "MIT"
354 | ],
355 | "authors": [
356 | {
357 | "name": "PHP-FIG",
358 | "homepage": "http://www.php-fig.org/"
359 | }
360 | ],
361 | "description": "Common interface for logging libraries",
362 | "keywords": [
363 | "log",
364 | "psr",
365 | "psr-3"
366 | ],
367 | "time": "2012-12-21 11:40:51"
368 | },
369 | {
370 | "name": "satooshi/php-coveralls",
371 | "version": "dev-master",
372 | "source": {
373 | "type": "git",
374 | "url": "https://github.com/satooshi/php-coveralls.git",
375 | "reference": "50c60bb64054974f8ed7540ae6e75fd7981a5fd3"
376 | },
377 | "dist": {
378 | "type": "zip",
379 | "url": "https://api.github.com/repos/satooshi/php-coveralls/zipball/50c60bb64054974f8ed7540ae6e75fd7981a5fd3",
380 | "reference": "50c60bb64054974f8ed7540ae6e75fd7981a5fd3",
381 | "shasum": ""
382 | },
383 | "require": {
384 | "ext-json": "*",
385 | "ext-simplexml": "*",
386 | "guzzlehttp/guzzle": "^6.0",
387 | "php": ">=5.5",
388 | "psr/log": "^1.0",
389 | "symfony/config": "^2.1|^3.0",
390 | "symfony/console": "^2.1|^3.0",
391 | "symfony/stopwatch": "^2.0|^3.0",
392 | "symfony/yaml": "^2.0|^3.0"
393 | },
394 | "suggest": {
395 | "symfony/http-kernel": "Allows Symfony integration"
396 | },
397 | "bin": [
398 | "bin/coveralls"
399 | ],
400 | "type": "library",
401 | "extra": {
402 | "branch-alias": {
403 | "dev-master": "2.0-dev"
404 | }
405 | },
406 | "autoload": {
407 | "psr-4": {
408 | "Satooshi\\": "src/Satooshi/"
409 | }
410 | },
411 | "notification-url": "https://packagist.org/downloads/",
412 | "license": [
413 | "MIT"
414 | ],
415 | "authors": [
416 | {
417 | "name": "Kitamura Satoshi",
418 | "email": "with.no.parachute@gmail.com",
419 | "homepage": "https://www.facebook.com/satooshi.jp"
420 | }
421 | ],
422 | "description": "PHP client library for Coveralls API",
423 | "homepage": "https://github.com/satooshi/php-coveralls",
424 | "keywords": [
425 | "ci",
426 | "coverage",
427 | "github",
428 | "test"
429 | ],
430 | "time": "2016-01-20 17:44:41"
431 | },
432 | {
433 | "name": "symfony/config",
434 | "version": "v3.0.6",
435 | "source": {
436 | "type": "git",
437 | "url": "https://github.com/symfony/config.git",
438 | "reference": "24f155da1ff180df8e15e34a8f6e2f8a0eadefa8"
439 | },
440 | "dist": {
441 | "type": "zip",
442 | "url": "https://api.github.com/repos/symfony/config/zipball/24f155da1ff180df8e15e34a8f6e2f8a0eadefa8",
443 | "reference": "24f155da1ff180df8e15e34a8f6e2f8a0eadefa8",
444 | "shasum": ""
445 | },
446 | "require": {
447 | "php": ">=5.5.9",
448 | "symfony/filesystem": "~2.8|~3.0"
449 | },
450 | "suggest": {
451 | "symfony/yaml": "To use the yaml reference dumper"
452 | },
453 | "type": "library",
454 | "extra": {
455 | "branch-alias": {
456 | "dev-master": "3.0-dev"
457 | }
458 | },
459 | "autoload": {
460 | "psr-4": {
461 | "Symfony\\Component\\Config\\": ""
462 | },
463 | "exclude-from-classmap": [
464 | "/Tests/"
465 | ]
466 | },
467 | "notification-url": "https://packagist.org/downloads/",
468 | "license": [
469 | "MIT"
470 | ],
471 | "authors": [
472 | {
473 | "name": "Fabien Potencier",
474 | "email": "fabien@symfony.com"
475 | },
476 | {
477 | "name": "Symfony Community",
478 | "homepage": "https://symfony.com/contributors"
479 | }
480 | ],
481 | "description": "Symfony Config Component",
482 | "homepage": "https://symfony.com",
483 | "time": "2016-04-20 18:53:54"
484 | },
485 | {
486 | "name": "symfony/console",
487 | "version": "v3.0.6",
488 | "source": {
489 | "type": "git",
490 | "url": "https://github.com/symfony/console.git",
491 | "reference": "34a214710e0714b6efcf40ba3cd1e31373a97820"
492 | },
493 | "dist": {
494 | "type": "zip",
495 | "url": "https://api.github.com/repos/symfony/console/zipball/34a214710e0714b6efcf40ba3cd1e31373a97820",
496 | "reference": "34a214710e0714b6efcf40ba3cd1e31373a97820",
497 | "shasum": ""
498 | },
499 | "require": {
500 | "php": ">=5.5.9",
501 | "symfony/polyfill-mbstring": "~1.0"
502 | },
503 | "require-dev": {
504 | "psr/log": "~1.0",
505 | "symfony/event-dispatcher": "~2.8|~3.0",
506 | "symfony/process": "~2.8|~3.0"
507 | },
508 | "suggest": {
509 | "psr/log": "For using the console logger",
510 | "symfony/event-dispatcher": "",
511 | "symfony/process": ""
512 | },
513 | "type": "library",
514 | "extra": {
515 | "branch-alias": {
516 | "dev-master": "3.0-dev"
517 | }
518 | },
519 | "autoload": {
520 | "psr-4": {
521 | "Symfony\\Component\\Console\\": ""
522 | },
523 | "exclude-from-classmap": [
524 | "/Tests/"
525 | ]
526 | },
527 | "notification-url": "https://packagist.org/downloads/",
528 | "license": [
529 | "MIT"
530 | ],
531 | "authors": [
532 | {
533 | "name": "Fabien Potencier",
534 | "email": "fabien@symfony.com"
535 | },
536 | {
537 | "name": "Symfony Community",
538 | "homepage": "https://symfony.com/contributors"
539 | }
540 | ],
541 | "description": "Symfony Console Component",
542 | "homepage": "https://symfony.com",
543 | "time": "2016-04-28 09:48:42"
544 | },
545 | {
546 | "name": "symfony/filesystem",
547 | "version": "v3.0.6",
548 | "source": {
549 | "type": "git",
550 | "url": "https://github.com/symfony/filesystem.git",
551 | "reference": "74fec3511b62cb934b64bce1d96f06fffa4beafd"
552 | },
553 | "dist": {
554 | "type": "zip",
555 | "url": "https://api.github.com/repos/symfony/filesystem/zipball/74fec3511b62cb934b64bce1d96f06fffa4beafd",
556 | "reference": "74fec3511b62cb934b64bce1d96f06fffa4beafd",
557 | "shasum": ""
558 | },
559 | "require": {
560 | "php": ">=5.5.9"
561 | },
562 | "type": "library",
563 | "extra": {
564 | "branch-alias": {
565 | "dev-master": "3.0-dev"
566 | }
567 | },
568 | "autoload": {
569 | "psr-4": {
570 | "Symfony\\Component\\Filesystem\\": ""
571 | },
572 | "exclude-from-classmap": [
573 | "/Tests/"
574 | ]
575 | },
576 | "notification-url": "https://packagist.org/downloads/",
577 | "license": [
578 | "MIT"
579 | ],
580 | "authors": [
581 | {
582 | "name": "Fabien Potencier",
583 | "email": "fabien@symfony.com"
584 | },
585 | {
586 | "name": "Symfony Community",
587 | "homepage": "https://symfony.com/contributors"
588 | }
589 | ],
590 | "description": "Symfony Filesystem Component",
591 | "homepage": "https://symfony.com",
592 | "time": "2016-04-12 18:09:53"
593 | },
594 | {
595 | "name": "symfony/polyfill-mbstring",
596 | "version": "v1.2.0",
597 | "source": {
598 | "type": "git",
599 | "url": "https://github.com/symfony/polyfill-mbstring.git",
600 | "reference": "dff51f72b0706335131b00a7f49606168c582594"
601 | },
602 | "dist": {
603 | "type": "zip",
604 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/dff51f72b0706335131b00a7f49606168c582594",
605 | "reference": "dff51f72b0706335131b00a7f49606168c582594",
606 | "shasum": ""
607 | },
608 | "require": {
609 | "php": ">=5.3.3"
610 | },
611 | "suggest": {
612 | "ext-mbstring": "For best performance"
613 | },
614 | "type": "library",
615 | "extra": {
616 | "branch-alias": {
617 | "dev-master": "1.2-dev"
618 | }
619 | },
620 | "autoload": {
621 | "psr-4": {
622 | "Symfony\\Polyfill\\Mbstring\\": ""
623 | },
624 | "files": [
625 | "bootstrap.php"
626 | ]
627 | },
628 | "notification-url": "https://packagist.org/downloads/",
629 | "license": [
630 | "MIT"
631 | ],
632 | "authors": [
633 | {
634 | "name": "Nicolas Grekas",
635 | "email": "p@tchwork.com"
636 | },
637 | {
638 | "name": "Symfony Community",
639 | "homepage": "https://symfony.com/contributors"
640 | }
641 | ],
642 | "description": "Symfony polyfill for the Mbstring extension",
643 | "homepage": "https://symfony.com",
644 | "keywords": [
645 | "compatibility",
646 | "mbstring",
647 | "polyfill",
648 | "portable",
649 | "shim"
650 | ],
651 | "time": "2016-05-18 14:26:46"
652 | },
653 | {
654 | "name": "symfony/stopwatch",
655 | "version": "v3.0.6",
656 | "source": {
657 | "type": "git",
658 | "url": "https://github.com/symfony/stopwatch.git",
659 | "reference": "6015187088421e9499d8f8316bdb396f8b806c06"
660 | },
661 | "dist": {
662 | "type": "zip",
663 | "url": "https://api.github.com/repos/symfony/stopwatch/zipball/6015187088421e9499d8f8316bdb396f8b806c06",
664 | "reference": "6015187088421e9499d8f8316bdb396f8b806c06",
665 | "shasum": ""
666 | },
667 | "require": {
668 | "php": ">=5.5.9"
669 | },
670 | "type": "library",
671 | "extra": {
672 | "branch-alias": {
673 | "dev-master": "3.0-dev"
674 | }
675 | },
676 | "autoload": {
677 | "psr-4": {
678 | "Symfony\\Component\\Stopwatch\\": ""
679 | },
680 | "exclude-from-classmap": [
681 | "/Tests/"
682 | ]
683 | },
684 | "notification-url": "https://packagist.org/downloads/",
685 | "license": [
686 | "MIT"
687 | ],
688 | "authors": [
689 | {
690 | "name": "Fabien Potencier",
691 | "email": "fabien@symfony.com"
692 | },
693 | {
694 | "name": "Symfony Community",
695 | "homepage": "https://symfony.com/contributors"
696 | }
697 | ],
698 | "description": "Symfony Stopwatch Component",
699 | "homepage": "https://symfony.com",
700 | "time": "2016-03-04 07:55:57"
701 | }
702 | ],
703 | "aliases": [],
704 | "minimum-stability": "stable",
705 | "stability-flags": {
706 | "satooshi/php-coveralls": 20
707 | },
708 | "prefer-stable": false,
709 | "prefer-lowest": false,
710 | "platform": [],
711 | "platform-dev": []
712 | }
713 |
--------------------------------------------------------------------------------
/config/config.yml:
--------------------------------------------------------------------------------
1 | view:
2 | path: ./
3 | layout:
4 |
5 | cheryl:
6 | root: ../files
7 | CHANGE_ME_FOR_PDO__authentication: pdo
8 | authentication: simple
9 | storage: local
10 | users:
11 | - username: admin
12 | password_hash: $2y$10$LQhNZMW3E66NPcTUkCPDyenq3Pn5mJJyZmIVRWzOrIP/2c7HrtodC
13 | permissions: all
14 |
15 | db:
16 | host: localhost
17 | user: root
18 | pass: root
19 | database: cheryl
20 |
--------------------------------------------------------------------------------
/config/nginx.conf:
--------------------------------------------------------------------------------
1 | client_max_body_size 16M;
2 |
3 | location / {
4 | # try to serve file directly, fallback to rewrite
5 | try_files $uri @rewriteapp;
6 | }
7 |
8 | location @rewriteapp {
9 | # rewrite all to app.php
10 | rewrite ^(.*)$ /index.php last;
11 | }
12 |
--------------------------------------------------------------------------------
/install/install.php:
--------------------------------------------------------------------------------
1 | setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
11 | $db->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
12 | $db->exec($sql);
13 |
--------------------------------------------------------------------------------
/install/mysql.sql:
--------------------------------------------------------------------------------
1 | DROP TABLE IF EXISTS `user`;
2 |
3 | CREATE TABLE `user` (
4 | `id_user` int(11) unsigned NOT NULL AUTO_INCREMENT,
5 | `username` varchar(40) DEFAULT NULL,
6 | `password_hash` varchar(255) DEFAULT NULL,
7 | PRIMARY KEY (`id_user`),
8 | UNIQUE KEY `username` (`username`)
9 | ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
10 |
11 | INSERT INTO `user` (`id_user`, `username`, `password_hash`)
12 | VALUES
13 | (1,'admin','$2y$10$LQhNZMW3E66NPcTUkCPDyenq3Pn5mJJyZmIVRWzOrIP/2c7HrtodC');
14 |
15 |
16 |
17 | DROP TABLE IF EXISTS `permission`;
18 |
19 | CREATE TABLE `permission` (
20 | `id_user_permission` int(11) unsigned NOT NULL AUTO_INCREMENT,
21 | `permission` varchar(40) DEFAULT NULL,
22 | `allow` tinyint(1) NOT NULL DEFAULT '1',
23 | `id_user` int(10) unsigned DEFAULT NULL,
24 | PRIMARY KEY (`id_user_permission`),
25 | KEY `id_user` (`id_user`),
26 | CONSTRAINT `permission_ibfk_1` FOREIGN KEY (`id_user`) REFERENCES `user` (`id_user`) ON DELETE CASCADE ON UPDATE CASCADE
27 | ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
28 |
29 | INSERT INTO `permission` (`id_user_permission`, `id_user`, `permission`, `allow`)
30 | VALUES
31 | (1,1,'all',1);
32 |
33 |
34 |
--------------------------------------------------------------------------------
/public/.htaccess:
--------------------------------------------------------------------------------
1 | allow from all
2 |
3 | RewriteEngine on
4 | Options +Followsymlinks -Indexes
5 |
6 | ReWriteCond %{REQUEST_METHOD} ^(TRACE|TRACK)
7 | ReWriteRule .* - [F]
8 |
9 | RewriteCond %{REQUEST_FILENAME} !-f
10 | RewriteCond %{REQUEST_FILENAME} !-d
11 | RewriteRule ^(.+)$ index.php?__url=$1 [L,QSA]
12 |
13 | AddDefaultCharset UTF-8
14 |
--------------------------------------------------------------------------------
/public/cheryl.css:
--------------------------------------------------------------------------------
1 | html, body, margin, form, a, h1, h2, h3, h4, h5, h6, select, input, tr, td, table, ul, ol, li, textarea, p, button {
2 | margin: 0;
3 | padding: 0;
4 | }
5 | body {
6 | background: #eceff1;
7 | color: #404040;
8 | background: #eceff1 -webkit-gradient(linear, left top, left bottom, color-stop(0%,#48aed9), color-stop(1000%,#48aed9));
9 | background-size: 100% 142px;
10 | background-repeat:no-repeat;
11 | }
12 | body, input, button {
13 | font: 10px "Open Sans", "Helvetica", "Arial", sans-serif;
14 | }
15 | :focus {
16 | outline: none;
17 | }
18 | ::selection {
19 | background: rgba(255,39,151,.75);
20 | color: #fff;
21 | }
22 | ::-moz-selection {
23 | background: rgba(255,39,151,.75);
24 | color: #fff;
25 | }
26 | a, a:visited, a:active {
27 | text-decoration: none;
28 | color: #404040;
29 | }
30 | .wrapper {
31 | width: 870px;
32 | margin: 0 auto;
33 | margin-bottom: 25px;
34 | }
35 | .clearfix:after {
36 | content: '';
37 | display: block;
38 | clear: both;
39 | visibility: hidden;
40 | line-height: 0;
41 | height: 0;
42 | }
43 |
44 | .logo {
45 | height: 90px;
46 | width: 90px;
47 | margin: 30px 0 40px 40px;
48 | background: url(./wink.svg) no-repeat;
49 | background-size: 100%;
50 | }
51 | .panel {
52 | float: left;
53 | width: 170px;
54 | margin: 0 20px 0 0;
55 | }
56 | .toggles {
57 | float: left;
58 | width: 680px;
59 | margin: 20px 0 0 0;
60 | }
61 | .content {
62 | float: left;
63 | width: 630px;
64 | min-height: 500px;
65 | background: #fff;
66 | box-shadow: 0px 1px 4px rgba(0,0,0,.3);
67 | padding: 25px;
68 | margin: 25px 0 20px 0;
69 | }
70 | h1 {
71 | color: #555963;
72 | font-weight: 100;
73 | font-size: 2em;
74 | }
75 | h2 {
76 | color: #404040;
77 | font-weight: 100;
78 | font-size: 1.5em;
79 | margin-bottom: .5em;
80 | }
81 | h1 input, h2 input {
82 | margin: 0;
83 | padding: 0;
84 | border: 1px dashed #f6f6f6;
85 | width: 20em;
86 | color: #555963;
87 | font-weight: 100;
88 | font-size: 1em;
89 | -webkit-transition: .2s border;
90 | }
91 | h2 input {
92 | border: 1px dashed #d0d0d0;
93 | padding: .3em;
94 | }
95 | .file-name-top, h1 input {
96 | padding-left: .2em;
97 | }
98 | h1 input:hover {
99 | border: 1px dashed #d0d0d0;
100 | }
101 | h1 input:focus, h2 input:focus {
102 | border: 1px dashed #b0b0b0;
103 | }
104 | .file-name-top {
105 | border: 1px solid transparent;
106 | }
107 | .toggles button {
108 | border: 0;
109 | background: rgba(0,0,0,.2);
110 | border-radius: 5px;
111 | color: #fff;
112 | font-size: 1.1em;
113 | padding: .5em 1.2em .6em 1.2em;
114 | cursor: pointer;
115 | opacity: .5;
116 | -webkit-transition: .2s opacity;
117 | width: 12em;
118 | }
119 | .toggles button.enabled {
120 | opacity: .8;
121 | }
122 | .toggles button:hover {
123 | opacity: .7;
124 | }
125 | .toggles button.enabled:hover {
126 | opacity: 1;
127 | }
128 | .toggles .search {
129 | border: 0;
130 | background: rgba(0,0,0,.2);
131 | border-radius: 5px;
132 | color: #fff;
133 | font-size: 1.1em;
134 | padding: .2em .4em .2em .8em;
135 | opacity: .5;
136 | -webkit-transition: .2s opacity;
137 | float: right;
138 | }
139 | .toggles .search .fa {
140 | vertical-align: middle;
141 | }
142 | .toggles .search .search-box {
143 | background: 0;
144 | padding: .35em .4em .45em .4em;
145 | border: 0;
146 | color: #fff;
147 | width: 8em;
148 | font-size: 1em;
149 | margin: 0;
150 | vertical-align: middle;
151 | -webkit-transition: .2s width;
152 | }
153 | .toggles .search.active {
154 | opacity: .8;
155 | }
156 | .toggles .search.active .search-box {
157 | width: 15em;
158 | }
159 |
160 | .toggles .search .search-box::-webkit-input-placeholder {
161 | color: #fff;
162 | -webkit-transition: .2s opacity;
163 | }
164 | .toggles .search .search-box::-moz-placeholder {
165 | color: #fff;
166 | -moz-transition: .2s opacity;
167 | }
168 | .toggles .search .search-box::-ms-input-placeholder {
169 | color: #fff;
170 | -ms-transition: .2s opacity;
171 | }
172 | .toggles .search .search-box::-o-input-placeholder {
173 | color: #fff;
174 | -o-transition: .2s opacity;
175 | }
176 | .toggles .search .search-box::input-placeholder {
177 | color: #fff;
178 | transition: .2s opacity;
179 | }
180 |
181 | .toggles .search.active .search-box::-webkit-input-placeholder {
182 | opacity: 0;
183 | }
184 | .toggles .search.active .search-box::-moz-placeholder {
185 | opacity: 0;
186 | }
187 | .toggles .search.active .search-box::-ms-placeholder {
188 | opacity: 0;
189 | }
190 | .toggles .search.active .search-box::-o-input-placeholder {
191 | opacity: 0;
192 | }
193 | .toggles .search.active .search-box::input-placeholder {
194 | opacity: 0;
195 | }
196 |
197 | .copyright {
198 | clear: both;
199 | float: right;
200 | cursor: pointer;
201 | }
202 | .copyright a {
203 | text-decoration: none;
204 | color: #cacccd;
205 | font-size: 2em;
206 | }
207 | .powered, .cheryl {
208 | -webkit-transition: .4s all;
209 | }
210 | .powered {
211 | opacity: .3;
212 | }
213 | .copyright:hover .powered {
214 | opacity: .7;
215 | }
216 | .copyright:hover .cheryl {
217 | color: #f83ca2;
218 | }
219 | .details .info {
220 | color: #767676;
221 | border-radius: 4px;
222 | padding: .2em 0 .2em 0;
223 | font-size: 1.2em;
224 | list-style: none;
225 | }
226 | .filter {
227 | background: #e0e2e4;
228 | color: #767676;
229 | display: block;
230 | border-radius: 4px;
231 | padding: .4em .8em .4em .8em;
232 | margin-bottom: .2em;
233 | font-size: 1.2em;
234 | cursor: pointer;
235 | }
236 | .filter.enabled {
237 | background: #a4d4e9;
238 | color: #fff;
239 | }
240 | .file .icon {
241 | font-size: 4em;
242 | color: #c0c0c0;
243 | width: 1em;
244 | height: 1em;
245 | display: inline-block;
246 | vertical-align: top;
247 | }
248 | .file .icon .fa {
249 | -webkit-transition: .2s all;
250 | position: absolute;
251 | display: block;
252 | }
253 | .file .icon .fa-cloud-upload {
254 | font-size: .85em;
255 | padding-top: .2em;
256 | }
257 | .file .icon .fa-download {
258 | opacity: 0;
259 | font-size: .9em;
260 | padding-top: .2em;
261 | }
262 | .file {
263 | background: #f0f0f0;
264 | padding: .8em 1.4em .8em 1.4em;
265 | cursor: pointer;
266 | -webkit-transition: .2s all;
267 | margin-bottom: .8em;
268 | display: block;
269 | border: 1px solid #f0f0f0;
270 | }
271 | .files .file:hover {
272 | background: #ecf3f9;
273 | }
274 | .files .file .icon:hover .fa-file-text-o {
275 | opacity: 0;
276 | }
277 | .files .file .icon:hover .fa-download {
278 | opacity: 1;
279 | }
280 | .files .file:focus {
281 | background: #ecf3f9;
282 | border: 1px solid #e0e6ec;
283 | }
284 | .files .file:hover .icon {
285 | color: #b5b5b5;
286 | }
287 | .uploads {
288 | margin-top: 1.4em;
289 | }
290 | .files {
291 | margin-top: 1.4em;
292 | }
293 | .file .attrs {
294 | display: inline-block;
295 | color: #9ea0a4;
296 | font-size: 1.1em;
297 | text-align: right;
298 | line-height: 1.7em;
299 | margin-top: .3em;
300 | float: right;
301 | }
302 | .file .filename {
303 | color: #303238;
304 | font-size: 17px;
305 | font-weight: 600;
306 | overflow: hidden;
307 | text-overflow: ellipsis;
308 | display: inline-block;
309 | white-space: nowrap;
310 | max-width: 100%;
311 | }
312 | .file .path {
313 | color: #9ea0a4;
314 | font-size: 1.1em;
315 | line-height: 1.6em;
316 | }
317 | .file .fileinfo {
318 | display: inline-block;
319 | margin-left: 1.5em;
320 | max-width: 70%;
321 | }
322 | .item-count {
323 | float: right;
324 | opacity: .7;
325 | }
326 | button, .filter {
327 | -webkit-touch-callout: none;
328 | -webkit-user-select: none;
329 | -khtml-user-select: none;
330 | -moz-user-select: none;
331 | -ms-user-select: none;
332 | -o-user-select: none;
333 | user-select: none;
334 | }
335 | .file-image {
336 | background-size: contain !important;
337 | background-repeat: no-repeat !important;
338 | width: 500px;
339 | height: 500px;
340 | }
341 | #downloader {
342 | display: none;
343 | }
344 |
345 | .upload {
346 | visibility: hidden;
347 | width: 0;
348 | height: 0;
349 | }
350 | .actions {
351 | float: right;
352 | text-align: right;
353 | margin-top: -4.3em;
354 | }
355 | .actions button {
356 | background: #555963;
357 | border: 1px solid #555963;
358 | border-radius: 4px;
359 | color: #fff;
360 | font-size: 1.4em;
361 | padding: .2em .4em .2em .4em;
362 | width: 2.7em;
363 | cursor: pointer;
364 | -webkit-transition: .15s all;
365 | margin-right: .3em;
366 | }
367 | .actions button:hover {
368 | background: #48aed9;
369 | color: #fff;
370 | border: 1px solid #48aed9;
371 | }
372 | .location .path {
373 | display: inline-block;
374 | margin-left: 4.1em;
375 | }
376 |
377 |
378 | @-webkit-keyframes progress-bar-stripes {
379 | from {
380 | background-position: 40px 0;
381 | }
382 | to {
383 | background-position: 0 0;
384 | }
385 | }
386 |
387 | @-moz-keyframes progress-bar-stripes {
388 | from {
389 | background-position: 40px 0;
390 | }
391 | to {
392 | background-position: 0 0;
393 | }
394 | }
395 |
396 | @-o-keyframes progress-bar-stripes {
397 | from {
398 | background-position: 40px 0;
399 | }
400 | to {
401 | background-position: 0 0;
402 | }
403 | }
404 |
405 | @keyframes progress-bar-stripes {
406 | from {
407 | background-position: 40px 0;
408 | }
409 | to {
410 | background-position: 0 0;
411 | }
412 | }
413 |
414 | .progress {
415 | height: 5.8em;
416 | overflow: hidden;
417 | background-color: #555963;
418 | float: left;
419 | width: 100%;
420 | }
421 | .progress-bar {
422 | overflow: hidden;
423 | height: 100%;
424 | width: 100%;
425 | background-color: #428bca;
426 | -webkit-transition: width 0.6s ease;
427 | -moz-transition: width 0.6s ease;
428 | -ms-transition: width 0.6s ease;
429 | -o-transition: width 0.6s ease;
430 | transition: width 0.6s ease;
431 | }
432 | .progress-striped .progress-bar {
433 | background-image: -webkit-gradient(linear, 0 100%, 100% 0, color-stop(0.25, rgba(255, 255, 255, 0.15)), color-stop(0.25, transparent), color-stop(0.5, transparent), color-stop(0.5, rgba(255, 255, 255, 0.15)), color-stop(0.75, rgba(255, 255, 255, 0.15)), color-stop(0.75, transparent), to(transparent));
434 | background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
435 | background-image: -moz-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
436 | background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
437 | background-size: 40px 40px;
438 | }
439 | .progress.active .progress-bar {
440 | -webkit-animation: progress-bar-stripes 2s linear infinite;
441 | -moz-animation: progress-bar-stripes 2s linear infinite;
442 | -ms-animation: progress-bar-stripes 2s linear infinite;
443 | -o-animation: progress-bar-stripes 2s linear infinite;
444 | animation: progress-bar-stripes 2s linear infinite;
445 | }
446 | .progress-bar-success {
447 | background-color: #5cb85c;
448 | }
449 | .progress-bar-info {
450 | background-color: #5bc0de;
451 | }
452 | .progress-bar-danger {
453 | background-color: #d9534f;
454 | }
455 |
456 |
457 | .upload-item {
458 | padding: 0;
459 | }
460 | .upload-content {
461 | padding: .8em 1.4em .8em 1.4em;
462 | float: left;
463 | margin-top: -5.8em;
464 | width: 95%;
465 | }
466 | .upload-content .filename, .upload-content .icon, .upload-content .attrs, .upload-content .path {
467 | color: #fff;
468 | }
469 |
470 | .modal-wrap {
471 | opacity: 0;
472 | pointer-events: none;
473 | -webkit-transition: .2s opacity;
474 | position: fixed;
475 | bottom: 0;
476 | height: 0;
477 | width: 0;
478 | z-index: 1000;
479 | }
480 |
481 | .modal-enabled {
482 | overflow: hidden;
483 | }
484 |
485 | .login-wrap, .modal-enabled .modal-wrap {
486 | position: fixed;
487 | width: 100%;
488 | height: 100%;
489 | top: 0;
490 | left: 0;
491 | right: 0;
492 | bottom: 0;
493 | overflow: hidden;
494 | }
495 |
496 | .login-wrap {
497 | background: #46aad5;
498 | }
499 |
500 | .modal-wrap {
501 | background: rgba(34,53,62,.7);
502 | }
503 |
504 | .modal-enabled .modal-wrap {
505 | opacity: 1;
506 | pointer-events: auto;
507 | }
508 |
509 | .login .welcome {
510 | color: #fff;
511 | font-size: 4.5em;
512 | font-weight: 100;
513 | text-align: center;
514 | margin-bottom: .8em;
515 | }
516 |
517 | .login .input-wrap {
518 | color: #fff;
519 | border-radius: 5px;
520 | background: rgba(0,0,0,.26);
521 | font-size: 2em;
522 | padding: .4em .6em .4em .6em;
523 | width: 100%;
524 | box-sizing: border-box;
525 | font-weight: 100;
526 | margin-bottom: .27em;
527 | }
528 |
529 | .login input {
530 | width: 100%;
531 | font-size: 1em;
532 | font-weight: 100;
533 | border: 0;
534 | background: none;
535 | color: #fff;
536 | }
537 | .login .field, .login .label {
538 | display: table-cell;
539 | }
540 | .login .field {
541 | width: 100%;
542 | }
543 | .login .label {
544 | min-width: 5.5em;
545 | opacity: .7;
546 | }
547 |
548 | .login {
549 | width: 35em;
550 | margin: 0 auto;
551 | margin-top: 10em;
552 | }
553 |
554 | .login-button {
555 | border-radius: 5px;
556 | background: rgba(0,0,0,.76);
557 | padding: .4em .6em .4em .6em;
558 | width: 100%;
559 | box-sizing: border-box;
560 | border: none;
561 | font-size: 2em;
562 | color: #fff;
563 | cursor: pointer;
564 | -webkit-transition: .2s all;
565 | }
566 |
567 | .copyright-login {
568 | opacity: .2;
569 | font-size: 2em;
570 | margin-top: 2em;
571 | text-align: right;
572 | -webkit-transition: .4s all;
573 | }
574 | .copyright-login:hover {
575 | opacity: .7;
576 | }
577 | .copyright-login:hover .cheryl {
578 | color: #f83ca2;
579 | }
580 |
581 | .filter-name {
582 | max-width: 2em;
583 | text-overflow:ellipsis;
584 | display: inline-block;
585 | overflow: hidden;
586 | max-width: 10em;
587 | height: 1.3em;
588 | vertical-align: top;
589 | }
590 | .modal {
591 | background: #fff;
592 | width: 36em;
593 | margin: 0 auto;
594 | margin-top: 20em;
595 | padding: 2em;
596 | min-height: 11em;
597 | text-align: center;
598 | box-shadow: 0px 0px 0px 4px rgba(0,0,0,.14);
599 | }
600 |
601 | .modal-dropupload {
602 | background: none;
603 | border-radius: 10px;
604 | border: 2px dashed #fff;
605 | box-shadow: none;
606 | width: 28em;
607 | color: #fff;
608 | }
609 |
610 | .modal-dropupload h1 {
611 | color: #fff;
612 | font-size: 9em;
613 | margin-top: .4em;
614 | line-height: 1em;
615 | }
616 | .modal-dropupload h2 {
617 | color: #fff;
618 | font-size: 2em;
619 | margin-bottom: 1.6em;
620 | }
621 |
622 | .modal button {
623 | border: none;
624 | padding: .45em 2em .45em 2em;
625 | font-size: 1.4em;
626 | margin: 0 .5em 0 .5em;
627 | cursor: pointer;
628 | border-radius: 3px;
629 | background: #555963;
630 | color: #fff;
631 | border: 1px solid #9ea1a7;
632 | -webkit-transition: .15s all;
633 | }
634 |
635 | .modal button:focus, .modal button:hover {
636 | background: #48aed9;
637 | color: #fff;
638 | border: 1px solid #48aed9;
639 | }
640 |
641 | @-webkit-keyframes shake {
642 | 0% { -webkit-transform: translate(2px, 1px) rotate(0deg); }
643 | 10% { -webkit-transform: translate(-1px, -2px) rotate(-1deg); }
644 | 20% { -webkit-transform: translate(-3px, 0px) rotate(1deg); }
645 | 30% { -webkit-transform: translate(0px, 2px) rotate(0deg); }
646 | 40% { -webkit-transform: translate(1px, -1px) rotate(1deg); }
647 | 50% { -webkit-transform: translate(-1px, 1px) rotate(-1deg); }
648 | 60% { -webkit-transform: translate(-3px, -2px) rotate(0deg); }
649 | 70% { -webkit-transform: translate(2px, 1px) rotate(-1deg); }
650 | 80% { -webkit-transform: translate(-1px, -2px) rotate(1deg); }
651 | 90% { -webkit-transform: translate(2px, -1px) rotate(0deg); }
652 | 100% { -webkit-transform: translate(1px, -2px) rotate(-1deg); }
653 | }
654 |
655 | .global-error .logo {
656 | -webkit-animation-name: 'shake';
657 | -webkit-animation-duration: 0.3s;
658 | -webkit-transform-origin:50% 50%;
659 | -webkit-animation-iteration-count: 3;
660 | -webkit-animation-timing-function: linear;
661 | }
662 | #editor {
663 | height: 100%;
664 | min-height: 500px;
665 | font-size: 11px;
666 |
667 | }
668 | .file-contents {
669 | margin-top: 1em;
670 | }
671 |
672 |
673 | .fullscreen-editor #editor {
674 | height: auto !important;
675 | width: auto !important;
676 | border: 0;
677 | margin: 0;
678 | position: fixed !important;
679 | top: 0;
680 | bottom: 0;
681 | left: 0;
682 | right: 0;
683 | z-index: 10000
684 | }
685 | .fullscreen-editor {
686 | overflow: hidden
687 | }
688 |
689 |
690 |
691 |
692 |
693 |
694 |
695 |
696 |
697 |
698 | .animated {
699 | -webkit-animation-fill-mode: both;
700 | -moz-animation-fill-mode: both;
701 | -ms-animation-fill-mode: both;
702 | -o-animation-fill-mode: both;
703 | animation-fill-mode: both;
704 |
705 | -webkit-animation-duration: 1s;
706 | -moz-animation-duration: 1s;
707 | -ms-animation-duration: 1s;
708 | -o-animation-duration: 1s;
709 | animation-duration: 1s;
710 | }
711 | .welcome {
712 | -webkit-animation-delay: .4s;
713 | -moz-animation-delay: .4s;
714 | -ms-animation-delay: .4s;
715 | -o-animation-delay: .4s;
716 | animation-delay: .4s;
717 | }
718 | .login-form {
719 | -webkit-animation-delay: 1.1s;
720 | -moz-animation-delay: 1.1s;
721 | -ms-animation-delay: 1.1s;
722 | -o-animation-delay: 1.1s;
723 | animation-delay: 1.1s;
724 | }
725 | @-webkit-keyframes fadeIn {
726 | 0% {
727 | opacity: 0;
728 | }
729 | 100% {
730 | opacity: 1;
731 | }
732 | }
733 | @-moz-keyframes fadeIn {
734 | 0% {
735 | opacity: 0;
736 | }
737 | 100% {
738 | opacity: 1;
739 | }
740 | }
741 | @-ms-keyframes fadeIn {
742 | 0% {
743 | opacity: 0;
744 | }
745 | 100% {
746 | opacity: 1;
747 | }
748 | }
749 | @-o-keyframes fadeIn {
750 | 0% {
751 | opacity: 0;
752 | }
753 | 100% {
754 | opacity: 1;
755 | }
756 | }
757 | @keyframes fadeIn {
758 | 0% {
759 | opacity: 0;
760 | }
761 | 100% {
762 | opacity: 1;
763 | }
764 | }
765 | @-webkit-keyframes fadeInDown {
766 | 0% {
767 | opacity: 0;
768 | -webkit-transform: translateY(-20px);
769 | }
770 | 100% {
771 | opacity: 1;
772 | -webkit-transform: translateY(0);
773 | }
774 | }
775 |
776 | @-moz-keyframes fadeInDown {
777 | 0% {
778 | opacity: 0;
779 | -moz-transform: translateY(-20px);
780 | }
781 | 100% {
782 | opacity: 1;
783 | -moz-transform: translateY(0);
784 | }
785 | }
786 |
787 | @-ms-keyframes fadeInDown {
788 | 0% {
789 | opacity: 0;
790 | -ms-transform: translateY(-20px);
791 | }
792 | 100% {
793 | opacity: 1;
794 | -ms-transform: translateY(0);
795 | }
796 | }
797 |
798 | @-o-keyframes fadeInDown {
799 | 0% {
800 | opacity: 0;
801 | -o-transform: translateY(-20px);
802 | }
803 | 100% {
804 | opacity: 1;
805 | -o-transform: translateY(0);
806 | }
807 | }
808 |
809 | @keyframes fadeInDown {
810 | 0% {
811 | opacity: 0;
812 | transform: translateY(-20px);
813 | }
814 | 100% {
815 | opacity: 1;
816 | transform: translateY(0);
817 | }
818 | }
819 |
820 | .fadeInDown {
821 | -webkit-animation-name: fadeInDown;
822 | -moz-animation-name: fadeInDown;
823 | -ms-animation-name: fadeInDown;
824 | -o-animation-name: fadeInDown;
825 | animation-name: fadeInDown;
826 | }
827 | .fadeIn {
828 | -webkit-animation-name: fadeIn;
829 | -moz-animation-name: fadeIn;
830 | -ms-animation-name: fadeIn;
831 | -o-animation-name: fadeIn;
832 | animation-name: fadeIn;
833 | }
834 |
835 | .preview img {
836 | width: 100%;
837 | }
838 |
--------------------------------------------------------------------------------
/public/cheryl.js:
--------------------------------------------------------------------------------
1 | var editor;
2 |
3 | var Cheryl =
4 | angular.module('Cheryl', ['ngRoute'])
5 | .config(function($routeProvider){
6 | $routeProvider
7 | .when('/logout', {
8 | action: 'logout',
9 | controller: 'LogoutCtrl',
10 | })
11 | .when('/login', {
12 | action: 'login',
13 | controller: 'LoginCtrl',
14 | })
15 | .otherwise({
16 | action: 'home',
17 | controller: 'RootCtrl'
18 | });
19 | })
20 | .config(function($locationProvider){
21 | $locationProvider.html5Mode(true).hashPrefix('!');
22 | })
23 | .controller('RootCtrl', function ($scope, $http, $location, $anchorScroll, $route) {
24 | $scope.now = new Date;
25 | $scope.yesterday = new Date;
26 | $scope.yesterday.setDate($scope.yesterday.getDate() - 1);
27 |
28 | $scope.user = [];
29 | $scope.welcomeDefault = $scope.welcome = 'Welcome!';
30 |
31 | $scope.types = [];
32 | $scope.dates = [];
33 | $scope.type = 'dir';
34 | $scope.dialog = false;
35 | $scope.config = false;
36 |
37 | $scope.dateFormat = 'm/d/Y H:i:s';
38 |
39 | $scope.path = function() {
40 | return location.href + $scope.script;
41 | };
42 |
43 | $scope.dirPath = function() {
44 | return $location.path().replace($scope.script,'') || '/';
45 | };
46 |
47 | $scope.getConfig = function() {
48 | $http({method: 'GET', url: $scope.path() + '?__p=config'}).
49 | success(function(data) {
50 | if (data.status) {
51 | $scope.authed = data.authed;
52 | $scope.config = true;
53 | }
54 | });
55 | };
56 |
57 | $scope.login = function() {
58 | $http.post($scope.path(), {'__p': 'login', '__username': $scope.user.username, '__password': $scope.user.password}).
59 | success(function(data) {
60 | if (data.status) {
61 | $scope.welcome = $scope.welcomeDefault;
62 | $scope.authed = true;
63 | $scope.user.password = '';
64 | } else {
65 | $scope.welcome = 'Try again!';
66 | }
67 | }).
68 | error(function(data) {
69 | $scope.welcome = 'Try again!';
70 | });
71 | };
72 |
73 | $scope.authed = false;
74 | $scope.script = '';
75 |
76 | $scope.dateFilterNames = {
77 | 0: 'Today',
78 | 1: 'Last week',
79 | 2: 'Last month',
80 | 3: 'Archive'
81 | };
82 |
83 | $scope.filters = {
84 | recursive: 0,
85 | types: [],
86 | dates: [],
87 | search: ''
88 | };
89 |
90 | $scope.uploads = [];
91 |
92 | $scope.filter = function(filter, value) {
93 | switch (filter) {
94 | case 'recursive':
95 | $scope.filters[filter] = value;
96 | break;
97 | case 'types':
98 | case 'dates':
99 | $scope.filters[filter][value] = !$scope.filters[filter][value];
100 | var hasValue = false;
101 | for (var x in $scope.filters[filter]) {
102 | if ($scope.filters[filter][x]) {
103 | hasValue = true;
104 | break;
105 | }
106 | }
107 | if (!hasValue) {
108 | $scope.filters[filter] = [];
109 | }
110 |
111 | break;
112 | }
113 | };
114 |
115 | $scope.filterFiles = function(file) {
116 | if (Object.size($scope.filters.types)) {
117 | if (!$scope.filters.types[file.ext.toUpperCase()]) {
118 | return false;
119 | }
120 | }
121 | if (Object.size($scope.filters.dates)) {
122 | if (!$scope.filters.dates[file.dateFilter]) {
123 | return false;
124 | }
125 | }
126 | if ($scope.filters.search && file.name.indexOf($scope.filters.search) === -1) {
127 | return false;
128 | }
129 | return true;
130 | };
131 |
132 | $scope.filterFolders = function(file) {
133 | if ($scope.filters.search && file.name.indexOf($scope.filters.search) === -1) {
134 | return false;
135 | }
136 | return true;
137 | };
138 |
139 | $scope.filterCheck = function(filter, value) {
140 | return $scope.filters[filter][value];
141 | };
142 |
143 | var formatDate = function(file) {
144 | var time = new Date(file.mtime * 1000);
145 | var timeOfDay = (time.getHours() > 12 ? time.getHours() - 12 : time.getHours()) + ':' + time.getMinutes() + (time.getHours() > 12 ? ' PM' : ' AM');
146 | var daysAgo = Math.ceil(($scope.now.getTime() / 1000 / 60 / 60 / 24) - (time.getTime() / 1000 / 60 / 60 / 24));
147 |
148 | if ('' + time.getFullYear() + time.getMonth() + time.getDate() == '' + $scope.now.getFullYear() + $scope.now.getMonth() + $scope.now.getDate()) {
149 | file.dateReadable = 'Today @ ' + timeOfDay;
150 | file.dateFilter = 0;
151 |
152 | } else if ('' + time.getFullYear() + time.getMonth() + time.getDate() == '' + $scope.yesterday.getFullYear() + $scope.yesterday.getMonth() + $scope.yesterday.getDate()) {
153 | file.dateReadable = 'Yesterday @ ' + timeOfDay;
154 | file.dateFilter = 1;
155 |
156 | } else if (daysAgo < 7) {
157 | file.dateReadable = daysAgo + ' day' + (daysAgo == 1 ? '' : 's') + ' ago';
158 | file.dateFilter = 1;
159 |
160 | } else if (daysAgo < 28) {
161 | var weeks = Math.floor(daysAgo / 7);
162 | file.dateReadable = weeks + ' week' + (weeks == 1 ? '' : 's') + ' ago';
163 | file.dateFilter = 2;
164 |
165 | } else if (daysAgo < 363) {
166 | var months = Math.floor(daysAgo / 30);
167 | file.dateReadable = months + ' month' + (months == 1 ? '' : 's') + ' ago';
168 | file.dateFilter = 3;
169 |
170 | } else {
171 | var years = Math.floor(daysAgo / 365);
172 | file.dateReadable = years + ' year' + (years == 1 ? '' : 's') + ' ago';
173 | file.dateFilter = 3;
174 | }
175 |
176 | $scope.dates[file.dateFilter] = $scope.dates[file.dateFilter] ? $scope.dates[file.dateFilter] + 1 : 1;
177 | };
178 |
179 | $scope.formatSize = function(file) {
180 | var size = file.size;
181 | var i = -1;
182 | var byteUnits = [' KB', ' MB', ' GB', ' TB', 'PB', 'EB', 'ZB', 'YB'];
183 | do {
184 | size = size / 1024;
185 | i++;
186 | } while (size > 1024);
187 | file.sizeReadable = Math.max(size, 0.1).toFixed(1) + byteUnits[i];
188 | };
189 |
190 | $scope.loadFiles = function() {
191 | if (!$scope.config) {
192 | $scope.getConfig();
193 | return;
194 | }
195 | if (!$scope.authed) {
196 | return;
197 | }
198 | $scope.fullscreenEdit = false;
199 | $scope.filters.search = '';
200 |
201 | var url = $scope.path() + '?__p=ls&_d=' + $scope.dirPath();
202 | for (var x in $scope.filters) {
203 | url += '&filters[' + x + ']=' + $scope.filters[x];
204 | }
205 |
206 | $http({method: 'GET', url: url}).
207 | success(function(data) {
208 | $scope.type = data.type;
209 | $scope.file = data.file;
210 | $scope.file.nameUser = $scope.file.name;
211 |
212 | if (data.type == 'dir') {
213 | $scope.files = data.list.files;
214 | $scope.dirs = data.list.dirs;
215 |
216 | $scope.types = {};
217 | $scope.dates = {};
218 |
219 | for (var x in $scope.files) {
220 | var type = $scope.files[x].ext.toUpperCase();
221 | $scope.types[type] = $scope.types[type] ? $scope.types[type]+1 : 1;
222 | formatDate($scope.files[x]);
223 | $scope.formatSize($scope.files[x]);
224 | }
225 | } else {
226 | formatDate($scope.file);
227 | $scope.formatSize($scope.file);
228 |
229 | }
230 | }).
231 | error(function() {
232 | $scope.files = null;
233 | });
234 | };
235 |
236 | $scope.$watch('filters.recursive', $scope.loadFiles);
237 | $scope.$watch('authed', $scope.loadFiles);
238 | $scope.$on('$locationChangeSuccess', function() {
239 | $anchorScroll();
240 |
241 | switch ($location.$$hash) {
242 | case 'NewFile':
243 | break;
244 |
245 | default:
246 | $scope.loadFiles();
247 | break;
248 | }
249 | });
250 |
251 | $scope.modes = {
252 | php: 'php',
253 | js: 'javascript',
254 | css: 'css',
255 | md: 'markdown',
256 | svg: 'svg',
257 | xml: 'xml',
258 | asp: 'asp',
259 | c: 'c',
260 | sql: 'mysql'
261 | };
262 |
263 | $scope.$watch('file.contents', function() {
264 | if (!$scope.file || !$scope.file.contents) {
265 | return;
266 | }
267 |
268 | if (!$scope.editor) {
269 | $scope.editor = ace.edit('editor');
270 | $scope.editor.renderer.setShowPrintMargin(false);
271 | $scope.editor.session.setWrapLimitRange(null, null);
272 |
273 | $scope.editor.commands.addCommand({
274 | name: 'saveFile',
275 | bindKey: {
276 | win: 'Ctrl-S',
277 | mac: 'Command-S',
278 | sender: 'editor|cli'
279 | },
280 | exec: function(env, args, request) {
281 | $scope.saveFile();
282 | }
283 | });
284 | }
285 |
286 | var mode = 'text';
287 | for (var x in $scope.modes) {
288 | if (x == $scope.file.ext) {
289 | mode = $scope.modes[x];
290 | break;
291 | }
292 | }
293 |
294 | $scope.editor.getSession().setMode('ace/mode/' + mode);
295 |
296 | $scope.editor.getSession().setValue($scope.file.contents);
297 | $scope.editor.setReadOnly(!$scope.file.writeable);
298 |
299 | fullscreenToggle();
300 | });
301 |
302 | var fullscreenToggle = function() {
303 | if (!$scope.editor) {
304 | return;
305 | }
306 | if ($scope.fullscreenEdit) {
307 | $scope.editor.renderer.setShowGutter(true);
308 | $scope.editor.setHighlightActiveLine(true);
309 | $scope.editor.session.setUseWrapMode(false);
310 | $scope.editor.setTheme('ace/theme/ambiance');
311 | } else {
312 | $scope.editor.renderer.setShowGutter(false);
313 | $scope.editor.setHighlightActiveLine(false);
314 | $scope.editor.session.setUseWrapMode(true);
315 | $scope.editor.setTheme('ace/theme/clouds');
316 | }
317 | setTimeout(function(){
318 | $scope.editor.resize();
319 | });
320 | };
321 |
322 | $scope.$watch('fullscreenEdit', fullscreenToggle);
323 |
324 | $scope.$watch('file.nameUser', function() {
325 | if (!$scope.file || $scope.file.name == $scope.file.nameUser) {
326 | return;
327 | }
328 | console.log('CHANGED');
329 | });
330 |
331 | $scope.downloadFile = function(event, file) {
332 | event.preventDefault();
333 | event.stopPropagation();
334 | var iframe = document.getElementById('downloader');
335 | iframe.src = $scope.path() + '?__p=dl&_d=' + file.path + '/' + file.name;
336 | };
337 |
338 | $scope.saveFile = function() {
339 | $scope.$apply(function() {
340 | var error = function() {
341 | $scope.dialog = {type: 'error', message: 'There was an error saving the file.'};
342 | };
343 | $http.post($scope.path() + '/', {
344 | '__p': 'sv',
345 | '_d': $scope.dirPath(),
346 | 'c': $scope.editor.getSession().getValue()
347 | }).
348 | success(function(data) {
349 | if (data.status) {
350 | $scope.dialog = false;
351 | } else {
352 | error();
353 | }
354 | }).
355 | error(error);
356 | });
357 | };
358 |
359 | $scope.upload = function(event, scope) {
360 | var files = event.target.files || event.dataTransfer.files;
361 |
362 | for (var i = 0, f; f = files[i]; i++) {
363 | var xhr = new XMLHttpRequest();
364 | var file = files[i];
365 |
366 | if (xhr.upload && file.size <= 9000000000) {
367 | var fd = new FormData();
368 | fd.append(file.name, file);
369 |
370 | scope.$apply(function() {
371 |
372 | var upload = {
373 | name: file.name,
374 | path: $location.path(),
375 | size: file.size,
376 | uploaded: 0,
377 | progress: 0,
378 | status: 'uploading'
379 | };
380 | scope.formatSize(upload);
381 | scope.uploads.push(upload);
382 |
383 |
384 | xhr.upload.addEventListener('progress', function(e) {
385 | scope.$apply(function() {
386 | upload.uploaded = e.loaded;
387 | upload.progress = parseInt(e.loaded / e.total * 100);
388 | });
389 | }, false);
390 |
391 | xhr.onload = function() {
392 | var status = this.status;
393 | scope.$apply(function() {
394 | upload.status = (status == 200 ? 'success' : 'error');
395 | scope.loadFiles();
396 | });
397 | setTimeout(function() {
398 | scope.$apply(function() {
399 | scope.uploads.splice(scope.uploads.indexOf(upload), 1);
400 | });
401 | },5000);
402 | };
403 |
404 | xhr.open('POST', scope.path() + '?__p=ul&_d=' + scope.dirPath(), true);
405 | xhr.setRequestHeader('X-File-Name', file.name);
406 | xhr.send(fd);
407 | });
408 | }
409 | }
410 | };
411 | })
412 | .directive('ngEnter', function() {
413 | return function(scope, element, attrs) {
414 | if (attrs.ngEnter) {
415 | element.bind('keydown keypress', function(event) {
416 | if (event.which === 13) {
417 | event.preventDefault();
418 | scope.$eval(attrs.ngEnter);
419 | }
420 | });
421 | }
422 | };
423 | })
424 | .directive('ngDropUpload', function () {
425 | return function (scope, element) {
426 |
427 | var dragEnd = function() {
428 | scope.$apply(function() {
429 | scope.dialog = false;
430 | });
431 | };
432 |
433 | var autoEndClean;
434 |
435 | angular.element(document).bind('dragover', function(event) {
436 | clearTimeout(autoEndClean);
437 | for (var x in event.dataTransfer.files) {
438 | console.log(event.dataTransfer.files[x]);
439 | }
440 | event.preventDefault();
441 | scope.$apply(function() {
442 | scope.dialog = {
443 | type: 'dropupload'
444 | }
445 | });
446 | autoEndClean = setTimeout(dragEnd,1000);
447 | });
448 |
449 | element
450 | .bind('drop', function(event) {
451 | event.preventDefault();
452 | scope.upload(event, scope);
453 | });
454 | }
455 | })
456 | .directive('ngUploader', function($location) {
457 | return function(scope, element) {
458 | element.bind('change', function(event) {
459 | scope.upload(event, scope);
460 | });
461 | };
462 | })
463 | .directive('ngUpload', function() {
464 | return function(scope, element) {
465 | element.bind('click', function(event) {
466 | document.querySelector('.upload').click();
467 | });
468 | };
469 | })
470 | .directive('ngMakeDir', function($http, $location) {
471 | return function(scope, element) {
472 | element.bind('click', function(event) {
473 | scope.$apply(function() {
474 | scope.dialog = {
475 | type: 'makeDir',
476 | path: scope.file,
477 | file: '',
478 | no: function() {
479 | scope.dialog = false;
480 | },
481 | yes: function() {
482 | if (!scope.dialog.file) {
483 | return;
484 | }
485 | var error = function() {
486 | scope.dialog = {type: 'error', message: 'There was an error creating the folder.'};
487 | };
488 | $http({method: 'GET', url: scope.path() + '?__p=mk&_d=' + scope.dirPath() + '&_n=' + scope.dialog.file}).
489 | success(function(data) {
490 | if (data.status) {
491 | scope.dialog = false;
492 | scope.loadFiles();
493 | } else {
494 | error();
495 | }
496 | }).
497 | error(error);
498 | }
499 | };
500 | });
501 | });
502 | };
503 | })
504 | .directive('ngDelete', function($http, $location) {
505 | return function(scope, element) {
506 | element.bind('click', function(event) {
507 | scope.$apply(function() {
508 | scope.dialog = {
509 | type: 'confirmDelete',
510 | file: scope.file,
511 | no: function() {
512 | scope.dialog = false;
513 | },
514 | yes: function() {
515 | var error = function() {
516 | scope.dialog = {type: 'error', message: 'There was an error deleting the ' + (scope.type == 'dir' ? 'folder' : 'file') + '.'};
517 | };
518 | $http({method: 'GET', url: scope.path() + '?__p=rm&_d=' + scope.dirPath()}).
519 | success(function(data) {
520 | if (data.status) {
521 | scope.dialog = false;
522 | $location.path(scope.script + scope.file.path);
523 | } else {
524 | error();
525 | }
526 | }).
527 | error(error);
528 | }
529 | };
530 | });
531 | });
532 | };
533 | })
534 | .directive('ngSave', function($http, $location) {
535 | return function(scope, element) {
536 | element.bind('click', function(event) {
537 | scope.saveFile();
538 | });
539 | };
540 | })
541 | .directive('ngFullscreenEditor', function($http, $location) {
542 | return function(scope, element) {
543 | element.bind('click', function(event) {
544 | scope.$apply(function() {
545 | scope.fullscreenEdit = true;
546 | });
547 | });
548 | };
549 | })
550 | .directive('ngModal', function() {
551 | return function(scope, element) {
552 | element.bind('click', function(event) {
553 | if (event.target == element[0]) {
554 | scope.$apply(function() {
555 | scope.dialog = false;
556 | });
557 | }
558 | });
559 | };
560 | })
561 | .directive('ngBody', function() {
562 | return function(scope, element) {
563 | element.bind('keydown keypress', function(event) {
564 | if (event.which == 27) {
565 | scope.$apply(function() {
566 | scope.dialog = false;
567 | scope.fullscreenEdit = false;
568 | });
569 | }
570 | });
571 | };
572 | })
573 | .directive('ngAutofocus', function() {
574 | return function(scope, element, attrs) {
575 | if (attrs.ngAutofocus) {
576 | scope.$watch(attrs.ngAutofocus, function(value) {
577 | setTimeout(function() {
578 | element[0].focus();
579 | },10);
580 | });
581 | }
582 | };
583 | })
584 | .directive('ngFileName', function($http) {
585 | return function(scope, element) {
586 | var save = function() {
587 | var error = function() {
588 | scope.dialog = {type: 'error', message: 'There was an error renaming the file.'};
589 | };
590 | $http({method: 'GET', url: scope.path() + '?__p=rn&_d=' + scope.dirPath() + '&_n=' + scope.file.name}).
591 | success(function(data) {
592 | console.log(data);
593 | if (data.status) {
594 |
595 | } else {
596 | error();
597 | }
598 | }).
599 | error(error);
600 | };
601 | element
602 | .bind('change', function(event) {
603 | clearTimeout(scope.nameChange);
604 | scope.nameChange = setTimeout(save, 1000);
605 | })
606 | .bind('blur', function(event) {
607 | save();
608 | });
609 | };
610 | });
611 |
612 | Object.size = function(obj) {
613 | var size = 0, key;
614 | for (key in obj) {
615 | if (obj.hasOwnProperty(key)) size++;
616 | }
617 | return size;
618 | };
619 |
620 |
--------------------------------------------------------------------------------
/public/cheryl.phtml:
--------------------------------------------------------------------------------
1 |
2 |
3 |