· 7 years ago · Dec 08, 2018, 11:24 AM
1<?php
2/**
3 * PHP File Manager (2017-08-07)
4 * https://github.com/alexantr/filemanager
5 */
6
7// Auth with login/password (set true/false to enable/disable it)
8$use_auth = true;
9
10// Users: array('Username' => 'Password', 'Username2' => 'Password2', ...)
11$auth_users = array(
12 'admin' => 'asdf123',
13);
14
15// Enable highlight.js (https://highlightjs.org/) on view's page
16$use_highlightjs = true;
17
18// highlight.js style
19$highlightjs_style = 'vs';
20
21// Default timezone for date() and time() - http://php.net/manual/en/timezones.php
22$default_timezone = 'Europe/Minsk'; // UTC+3
23
24// Root path for file manager
25$root_path = $_SERVER['DOCUMENT_ROOT'];
26
27// Root url for links in file manager.Relative to $http_host. Variants: '', 'path/to/subfolder'
28// Will not working if $root_path will be outside of server document root
29$root_url = '';
30
31// Server hostname. Can set manually if wrong
32$http_host = $_SERVER['HTTP_HOST'];
33
34// input encoding for iconv
35$iconv_input_encoding = 'CP1251';
36
37// date() format for file modification date
38$datetime_format = 'd.m.y H:i';
39
40//--- EDIT BELOW CAREFULLY OR DO NOT EDIT AT ALL
41
42// if fm included
43if (defined('FM_EMBED')) {
44 $use_auth = false;
45} else {
46 @set_time_limit(600);
47
48 date_default_timezone_set($default_timezone);
49
50 ini_set('default_charset', 'UTF-8');
51 if (version_compare(PHP_VERSION, '5.6.0', '<') && function_exists('mb_internal_encoding')) {
52 mb_internal_encoding('UTF-8');
53 }
54 if (function_exists('mb_regex_encoding')) {
55 mb_regex_encoding('UTF-8');
56 }
57
58 session_cache_limiter('');
59 session_name('filemanager');
60 session_start();
61}
62
63if (empty($auth_users)) {
64 $use_auth = false;
65}
66
67$is_https = isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] == 1)
68 || isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https';
69
70// clean and check $root_path
71$root_path = rtrim($root_path, '\\/');
72$root_path = str_replace('\\', '/', $root_path);
73if (!@is_dir($root_path)) {
74 echo "<h1>Root path \"{$root_path}\" not found!</h1>";
75 exit;
76}
77
78// clean $root_url
79$root_url = fm_clean_path($root_url);
80
81// abs path for site
82defined('FM_ROOT_PATH') || define('FM_ROOT_PATH', $root_path);
83defined('FM_ROOT_URL') || define('FM_ROOT_URL', ($is_https ? 'https' : 'http') . '://' . $http_host . (!empty($root_url) ? '/' . $root_url : ''));
84defined('FM_SELF_URL') || define('FM_SELF_URL', ($is_https ? 'https' : 'http') . '://' . $http_host . $_SERVER['PHP_SELF']);
85
86// logout
87if (isset($_GET['logout'])) {
88 unset($_SESSION['logged']);
89 fm_redirect(FM_SELF_URL);
90}
91
92// Show image here
93if (isset($_GET['img'])) {
94 fm_show_image($_GET['img']);
95}
96
97// Auth
98if ($use_auth) {
99 if (isset($_SESSION['logged'], $auth_users[$_SESSION['logged']])) {
100 // Logged
101 } elseif (isset($_POST['fm_usr'], $_POST['fm_pwd'])) {
102 // Logging In
103 sleep(1);
104 if (isset($auth_users[$_POST['fm_usr']]) && $_POST['fm_pwd'] === $auth_users[$_POST['fm_usr']]) {
105 $_SESSION['logged'] = $_POST['fm_usr'];
106 fm_set_msg('You are logged in');
107 fm_redirect(FM_SELF_URL . '?p=');
108 } else {
109 unset($_SESSION['logged']);
110 fm_set_msg('Wrong password', 'error');
111 fm_redirect(FM_SELF_URL);
112 }
113 } else {
114 // Form
115 unset($_SESSION['logged']);
116 fm_show_header();
117 fm_show_message();
118 ?>
119 <div class="path">
120 <form action="" method="post" style="margin:10px;text-align:center">
121 <input name="fm_usr" value="" placeholder="Username" required>
122 <input type="password" name="fm_pwd" value="" placeholder="Password" required>
123 <input type="submit" value="Login">
124 </form>
125 </div>
126 <?php
127 fm_show_footer();
128 exit;
129 }
130}
131
132define('FM_IS_WIN', DIRECTORY_SEPARATOR == '\\');
133
134// always use ?p=
135if (!isset($_GET['p'])) {
136 fm_redirect(FM_SELF_URL . '?p=');
137}
138
139// get path
140$p = isset($_GET['p']) ? $_GET['p'] : (isset($_POST['p']) ? $_POST['p'] : '');
141
142// clean path
143$p = fm_clean_path($p);
144
145// instead globals vars
146define('FM_PATH', $p);
147define('FM_USE_AUTH', $use_auth);
148
149defined('FM_ICONV_INPUT_ENC') || define('FM_ICONV_INPUT_ENC', $iconv_input_encoding);
150defined('FM_USE_HIGHLIGHTJS') || define('FM_USE_HIGHLIGHTJS', $use_highlightjs);
151defined('FM_HIGHLIGHTJS_STYLE') || define('FM_HIGHLIGHTJS_STYLE', $highlightjs_style);
152defined('FM_DATETIME_FORMAT') || define('FM_DATETIME_FORMAT', $datetime_format);
153
154unset($p, $use_auth, $iconv_input_encoding, $use_highlightjs, $highlightjs_style);
155
156/*************************** ACTIONS ***************************/
157
158// Delete file / folder
159if (isset($_GET['del'])) {
160 $del = $_GET['del'];
161 $del = fm_clean_path($del);
162 $del = str_replace('/', '', $del);
163 if ($del != '' && $del != '..' && $del != '.') {
164 $path = FM_ROOT_PATH;
165 if (FM_PATH != '') {
166 $path .= '/' . FM_PATH;
167 }
168 $is_dir = is_dir($path . '/' . $del);
169 if (fm_rdelete($path . '/' . $del)) {
170 $msg = $is_dir ? 'Folder <b>%s</b> deleted' : 'File <b>%s</b> deleted';
171 fm_set_msg(sprintf($msg, $del));
172 } else {
173 $msg = $is_dir ? 'Folder <b>%s</b> not deleted' : 'File <b>%s</b> not deleted';
174 fm_set_msg(sprintf($msg, $del), 'error');
175 }
176 } else {
177 fm_set_msg('Wrong file or folder name', 'error');
178 }
179 fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH));
180}
181
182// Create folder
183if (isset($_GET['new'])) {
184 $new = $_GET['new'];
185 $new = fm_clean_path($new);
186 $new = str_replace('/', '', $new);
187 if ($new != '' && $new != '..' && $new != '.') {
188 $path = FM_ROOT_PATH;
189 if (FM_PATH != '') {
190 $path .= '/' . FM_PATH;
191 }
192 if (fm_mkdir($path . '/' . $new, false) === true) {
193 fm_set_msg(sprintf('Folder <b>%s</b> created', $new));
194 } elseif (fm_mkdir($path . '/' . $new, false) === $path . '/' . $new) {
195 fm_set_msg(sprintf('Folder <b>%s</b> already exists', $new), 'alert');
196 } else {
197 fm_set_msg(sprintf('Folder <b>%s</b> not created', $new), 'error');
198 }
199 } else {
200 fm_set_msg('Wrong folder name', 'error');
201 }
202 fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH));
203}
204
205// Copy folder / file
206if (isset($_GET['copy'], $_GET['finish'])) {
207 // from
208 $copy = $_GET['copy'];
209 $copy = fm_clean_path($copy);
210 // empty path
211 if ($copy == '') {
212 fm_set_msg('Source path not defined', 'error');
213 fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH));
214 }
215 // abs path from
216 $from = FM_ROOT_PATH . '/' . $copy;
217 // abs path to
218 $dest = FM_ROOT_PATH;
219 if (FM_PATH != '') {
220 $dest .= '/' . FM_PATH;
221 }
222 $dest .= '/' . basename($from);
223 // move?
224 $move = isset($_GET['move']);
225 // copy/move
226 if ($from != $dest) {
227 $msg_from = trim(FM_PATH . '/' . basename($from), '/');
228 if ($move) {
229 $rename = fm_rename($from, $dest);
230 if ($rename) {
231 fm_set_msg(sprintf('Moved from <b>%s</b> to <b>%s</b>', $copy, $msg_from));
232 } elseif ($rename === null) {
233 fm_set_msg('File or folder with this path already exists', 'alert');
234 } else {
235 fm_set_msg(sprintf('Error while moving from <b>%s</b> to <b>%s</b>', $copy, $msg_from), 'error');
236 }
237 } else {
238 if (fm_rcopy($from, $dest)) {
239 fm_set_msg(sprintf('Copyied from <b>%s</b> to <b>%s</b>', $copy, $msg_from));
240 } else {
241 fm_set_msg(sprintf('Error while copying from <b>%s</b> to <b>%s</b>', $copy, $msg_from), 'error');
242 }
243 }
244 } else {
245 fm_set_msg('Paths must be not equal', 'alert');
246 }
247 fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH));
248}
249
250// Mass copy files/ folders
251if (isset($_POST['file'], $_POST['copy_to'], $_POST['finish'])) {
252 // from
253 $path = FM_ROOT_PATH;
254 if (FM_PATH != '') {
255 $path .= '/' . FM_PATH;
256 }
257 // to
258 $copy_to_path = FM_ROOT_PATH;
259 $copy_to = fm_clean_path($_POST['copy_to']);
260 if ($copy_to != '') {
261 $copy_to_path .= '/' . $copy_to;
262 }
263 if ($path == $copy_to_path) {
264 fm_set_msg('Paths must be not equal', 'alert');
265 fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH));
266 }
267 if (!is_dir($copy_to_path)) {
268 if (!fm_mkdir($copy_to_path, true)) {
269 fm_set_msg('Unable to create destination folder', 'error');
270 fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH));
271 }
272 }
273 // move?
274 $move = isset($_POST['move']);
275 // copy/move
276 $errors = 0;
277 $files = $_POST['file'];
278 if (is_array($files) && count($files)) {
279 foreach ($files as $f) {
280 if ($f != '') {
281 // abs path from
282 $from = $path . '/' . $f;
283 // abs path to
284 $dest = $copy_to_path . '/' . $f;
285 // do
286 if ($move) {
287 $rename = fm_rename($from, $dest);
288 if ($rename === false) {
289 $errors++;
290 }
291 } else {
292 if (!fm_rcopy($from, $dest)) {
293 $errors++;
294 }
295 }
296 }
297 }
298 if ($errors == 0) {
299 $msg = $move ? 'Selected files and folders moved' : 'Selected files and folders copied';
300 fm_set_msg($msg);
301 } else {
302 $msg = $move ? 'Error while moving items' : 'Error while copying items';
303 fm_set_msg($msg, 'error');
304 }
305 } else {
306 fm_set_msg('Nothing selected', 'alert');
307 }
308 fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH));
309}
310
311// Rename
312if (isset($_GET['ren'], $_GET['to'])) {
313 // old name
314 $old = $_GET['ren'];
315 $old = fm_clean_path($old);
316 $old = str_replace('/', '', $old);
317 // new name
318 $new = $_GET['to'];
319 $new = fm_clean_path($new);
320 $new = str_replace('/', '', $new);
321 // path
322 $path = FM_ROOT_PATH;
323 if (FM_PATH != '') {
324 $path .= '/' . FM_PATH;
325 }
326 // rename
327 if ($old != '' && $new != '') {
328 if (fm_rename($path . '/' . $old, $path . '/' . $new)) {
329 fm_set_msg(sprintf('Renamed from <b>%s</b> to <b>%s</b>', $old, $new));
330 } else {
331 fm_set_msg(sprintf('Error while renaming from <b>%s</b> to <b>%s</b>', $old, $new), 'error');
332 }
333 } else {
334 fm_set_msg('Names not set', 'error');
335 }
336 fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH));
337}
338
339// Download
340if (isset($_GET['dl'])) {
341 $dl = $_GET['dl'];
342 $dl = fm_clean_path($dl);
343 $dl = str_replace('/', '', $dl);
344 $path = FM_ROOT_PATH;
345 if (FM_PATH != '') {
346 $path .= '/' . FM_PATH;
347 }
348 if ($dl != '' && is_file($path . '/' . $dl)) {
349 header('Content-Description: File Transfer');
350 header('Content-Type: application/octet-stream');
351 header('Content-Disposition: attachment; filename="' . basename($path . '/' . $dl) . '"');
352 header('Content-Transfer-Encoding: binary');
353 header('Connection: Keep-Alive');
354 header('Expires: 0');
355 header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
356 header('Pragma: public');
357 header('Content-Length: ' . filesize($path . '/' . $dl));
358 readfile($path . '/' . $dl);
359 exit;
360 } else {
361 fm_set_msg('File not found', 'error');
362 fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH));
363 }
364}
365
366// Upload
367if (isset($_POST['upl'])) {
368 $path = FM_ROOT_PATH;
369 if (FM_PATH != '') {
370 $path .= '/' . FM_PATH;
371 }
372
373 $errors = 0;
374 $uploads = 0;
375 $total = count($_FILES['upload']['name']);
376
377 for ($i = 0; $i < $total; $i++) {
378 $tmp_name = $_FILES['upload']['tmp_name'][$i];
379 if (empty($_FILES['upload']['error'][$i]) && !empty($tmp_name) && $tmp_name != 'none') {
380 if (move_uploaded_file($tmp_name, $path . '/' . $_FILES['upload']['name'][$i])) {
381 $uploads++;
382 } else {
383 $errors++;
384 }
385 }
386 }
387
388 if ($errors == 0 && $uploads > 0) {
389 fm_set_msg(sprintf('All files uploaded to <b>%s</b>', $path));
390 } elseif ($errors == 0 && $uploads == 0) {
391 fm_set_msg('Nothing uploaded', 'alert');
392 } else {
393 fm_set_msg(sprintf('Error while uploading files. Uploaded files: %s', $uploads), 'error');
394 }
395
396 fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH));
397}
398
399// Mass deleting
400if (isset($_POST['group'], $_POST['delete'])) {
401 $path = FM_ROOT_PATH;
402 if (FM_PATH != '') {
403 $path .= '/' . FM_PATH;
404 }
405
406 $errors = 0;
407 $files = $_POST['file'];
408 if (is_array($files) && count($files)) {
409 foreach ($files as $f) {
410 if ($f != '') {
411 $new_path = $path . '/' . $f;
412 if (!fm_rdelete($new_path)) {
413 $errors++;
414 }
415 }
416 }
417 if ($errors == 0) {
418 fm_set_msg('Selected files and folder deleted');
419 } else {
420 fm_set_msg('Error while deleting items', 'error');
421 }
422 } else {
423 fm_set_msg('Nothing selected', 'alert');
424 }
425
426 fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH));
427}
428
429// Pack files
430if (isset($_POST['group'], $_POST['zip'])) {
431 $path = FM_ROOT_PATH;
432 if (FM_PATH != '') {
433 $path .= '/' . FM_PATH;
434 }
435
436 if (!class_exists('ZipArchive')) {
437 fm_set_msg('Operations with archives are not available', 'error');
438 fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH));
439 }
440
441 $files = $_POST['file'];
442 if (!empty($files)) {
443 chdir($path);
444
445 if (count($files) == 1) {
446 $one_file = reset($files);
447 $one_file = basename($one_file);
448 $zipname = $one_file . '_' . date('ymd_His') . '.zip';
449 } else {
450 $zipname = 'archive_' . date('ymd_His') . '.zip';
451 }
452
453 $zipper = new FM_Zipper();
454 $res = $zipper->create($zipname, $files);
455
456 if ($res) {
457 fm_set_msg(sprintf('Archive <b>%s</b> created', $zipname));
458 } else {
459 fm_set_msg('Archive not created', 'error');
460 }
461 } else {
462 fm_set_msg('Nothing selected', 'alert');
463 }
464
465 fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH));
466}
467
468// Unpack
469if (isset($_GET['unzip'])) {
470 $unzip = $_GET['unzip'];
471 $unzip = fm_clean_path($unzip);
472 $unzip = str_replace('/', '', $unzip);
473
474 $path = FM_ROOT_PATH;
475 if (FM_PATH != '') {
476 $path .= '/' . FM_PATH;
477 }
478
479 if (!class_exists('ZipArchive')) {
480 fm_set_msg('Operations with archives are not available', 'error');
481 fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH));
482 }
483
484 if ($unzip != '' && is_file($path . '/' . $unzip)) {
485 $zip_path = $path . '/' . $unzip;
486
487 //to folder
488 $tofolder = '';
489 if (isset($_GET['tofolder'])) {
490 $tofolder = pathinfo($zip_path, PATHINFO_FILENAME);
491 if (fm_mkdir($path . '/' . $tofolder, true)) {
492 $path .= '/' . $tofolder;
493 }
494 }
495
496 $zipper = new FM_Zipper();
497 $res = $zipper->unzip($zip_path, $path);
498
499 if ($res) {
500 fm_set_msg('Archive unpacked');
501 } else {
502 fm_set_msg('Archive not unpacked', 'error');
503 }
504
505 } else {
506 fm_set_msg('File not found', 'error');
507 }
508 fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH));
509}
510
511// Change Perms (not for Windows)
512if (isset($_POST['chmod']) && !FM_IS_WIN) {
513 $path = FM_ROOT_PATH;
514 if (FM_PATH != '') {
515 $path .= '/' . FM_PATH;
516 }
517
518 $file = $_POST['chmod'];
519 $file = fm_clean_path($file);
520 $file = str_replace('/', '', $file);
521 if ($file == '' || (!is_file($path . '/' . $file) && !is_dir($path . '/' . $file))) {
522 fm_set_msg('File not found', 'error');
523 fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH));
524 }
525
526 $mode = 0;
527 if (!empty($_POST['ur'])) {
528 $mode |= 0400;
529 }
530 if (!empty($_POST['uw'])) {
531 $mode |= 0200;
532 }
533 if (!empty($_POST['ux'])) {
534 $mode |= 0100;
535 }
536 if (!empty($_POST['gr'])) {
537 $mode |= 0040;
538 }
539 if (!empty($_POST['gw'])) {
540 $mode |= 0020;
541 }
542 if (!empty($_POST['gx'])) {
543 $mode |= 0010;
544 }
545 if (!empty($_POST['or'])) {
546 $mode |= 0004;
547 }
548 if (!empty($_POST['ow'])) {
549 $mode |= 0002;
550 }
551 if (!empty($_POST['ox'])) {
552 $mode |= 0001;
553 }
554
555 if (@chmod($path . '/' . $file, $mode)) {
556 fm_set_msg('Permissions changed');
557 } else {
558 fm_set_msg('Permissions not changed', 'error');
559 }
560
561 fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH));
562}
563
564/*************************** /ACTIONS ***************************/
565
566// get current path
567$path = FM_ROOT_PATH;
568if (FM_PATH != '') {
569 $path .= '/' . FM_PATH;
570}
571
572// check path
573if (!is_dir($path)) {
574 fm_redirect(FM_SELF_URL . '?p=');
575}
576
577// get parent folder
578$parent = fm_get_parent_path(FM_PATH);
579
580$objects = is_readable($path) ? scandir($path) : array();
581$folders = array();
582$files = array();
583if (is_array($objects)) {
584 foreach ($objects as $file) {
585 if ($file == '.' || $file == '..') {
586 continue;
587 }
588 $new_path = $path . '/' . $file;
589 if (is_file($new_path)) {
590 $files[] = $file;
591 } elseif (is_dir($new_path) && $file != '.' && $file != '..') {
592 $folders[] = $file;
593 }
594 }
595}
596
597if (!empty($files)) {
598 natcasesort($files);
599}
600if (!empty($folders)) {
601 natcasesort($folders);
602}
603
604// upload form
605if (isset($_GET['upload'])) {
606 fm_show_header(); // HEADER
607 fm_show_nav_path(FM_PATH); // current path
608 ?>
609 <div class="path">
610 <p><b>Uploading files</b></p>
611 <p class="break-word">Destination folder: <?php echo fm_convert_win(FM_ROOT_PATH . '/' . FM_PATH) ?></p>
612 <form action="" method="post" enctype="multipart/form-data">
613 <input type="hidden" name="p" value="<?php echo fm_enc(FM_PATH) ?>">
614 <input type="hidden" name="upl" value="1">
615 <input type="file" name="upload[]"><br>
616 <input type="file" name="upload[]"><br>
617 <input type="file" name="upload[]"><br>
618 <input type="file" name="upload[]"><br>
619 <input type="file" name="upload[]"><br>
620 <br>
621 <p>
622 <button class="btn"><i class="icon-apply"></i> Upload</button>
623 <b><a href="?p=<?php echo urlencode(FM_PATH) ?>"><i class="icon-cancel"></i> Cancel</a></b>
624 </p>
625 </form>
626 </div>
627 <?php
628 fm_show_footer();
629 exit;
630}
631
632// copy form POST
633if (isset($_POST['copy'])) {
634 $copy_files = $_POST['file'];
635 if (!is_array($copy_files) || empty($copy_files)) {
636 fm_set_msg('Nothing selected', 'alert');
637 fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH));
638 }
639
640 fm_show_header(); // HEADER
641 fm_show_nav_path(FM_PATH); // current path
642 ?>
643 <div class="path">
644 <p><b>Copying</b></p>
645 <form action="" method="post">
646 <input type="hidden" name="p" value="<?php echo fm_enc(FM_PATH) ?>">
647 <input type="hidden" name="finish" value="1">
648 <?php
649 foreach ($copy_files as $cf) {
650 echo '<input type="hidden" name="file[]" value="' . fm_enc($cf) . '">' . PHP_EOL;
651 }
652 ?>
653 <p class="break-word">Files: <b><?php echo implode('</b>, <b>', $copy_files) ?></b></p>
654 <p class="break-word">Source folder: <?php echo fm_convert_win(FM_ROOT_PATH . '/' . FM_PATH) ?><br>
655 <label for="inp_copy_to">Destination folder:</label>
656 <?php echo FM_ROOT_PATH ?>/<input name="copy_to" id="inp_copy_to" value="<?php echo fm_enc(FM_PATH) ?>">
657 </p>
658 <p><label><input type="checkbox" name="move" value="1"> Move</label></p>
659 <p>
660 <button class="btn"><i class="icon-apply"></i> Copy</button>
661 <b><a href="?p=<?php echo urlencode(FM_PATH) ?>"><i class="icon-cancel"></i> Cancel</a></b>
662 </p>
663 </form>
664 </div>
665 <?php
666 fm_show_footer();
667 exit;
668}
669
670// copy form
671if (isset($_GET['copy']) && !isset($_GET['finish'])) {
672 $copy = $_GET['copy'];
673 $copy = fm_clean_path($copy);
674 if ($copy == '' || !file_exists(FM_ROOT_PATH . '/' . $copy)) {
675 fm_set_msg('File not found', 'error');
676 fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH));
677 }
678
679 fm_show_header(); // HEADER
680 fm_show_nav_path(FM_PATH); // current path
681 ?>
682 <div class="path">
683 <p><b>Copying</b></p>
684 <p class="break-word">
685 Source path: <?php echo fm_convert_win(FM_ROOT_PATH . '/' . $copy) ?><br>
686 Destination folder: <?php echo fm_convert_win(FM_ROOT_PATH . '/' . FM_PATH) ?>
687 </p>
688 <p>
689 <b><a href="?p=<?php echo urlencode(FM_PATH) ?>&copy=<?php echo urlencode($copy) ?>&finish=1"><i class="icon-apply"></i> Copy</a></b>
690 <b><a href="?p=<?php echo urlencode(FM_PATH) ?>&copy=<?php echo urlencode($copy) ?>&finish=1&move=1"><i class="icon-apply"></i> Move</a></b>
691 <b><a href="?p=<?php echo urlencode(FM_PATH) ?>"><i class="icon-cancel"></i> Cancel</a></b>
692 </p>
693 <p><i>Select folder:</i></p>
694 <ul class="folders break-word">
695 <?php
696 if ($parent !== false) {
697 ?>
698 <li><a href="?p=<?php echo urlencode($parent) ?>&copy=<?php echo urlencode($copy) ?>"><i class="icon-arrow_up"></i> ..</a></li>
699 <?php
700 }
701 foreach ($folders as $f) {
702 ?>
703 <li><a href="?p=<?php echo urlencode(trim(FM_PATH . '/' . $f, '/')) ?>&copy=<?php echo urlencode($copy) ?>"><i class="icon-folder"></i> <?php echo fm_convert_win($f) ?></a></li>
704 <?php
705 }
706 ?>
707 </ul>
708 </div>
709 <?php
710 fm_show_footer();
711 exit;
712}
713
714// file viewer
715if (isset($_GET['view'])) {
716 $file = $_GET['view'];
717 $file = fm_clean_path($file);
718 $file = str_replace('/', '', $file);
719 if ($file == '' || !is_file($path . '/' . $file)) {
720 fm_set_msg('File not found', 'error');
721 fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH));
722 }
723
724 fm_show_header(); // HEADER
725 fm_show_nav_path(FM_PATH); // current path
726
727 $file_url = FM_ROOT_URL . fm_convert_win((FM_PATH != '' ? '/' . FM_PATH : '') . '/' . $file);
728 $file_path = $path . '/' . $file;
729
730 $ext = strtolower(pathinfo($file_path, PATHINFO_EXTENSION));
731 $mime_type = fm_get_mime_type($file_path);
732 $filesize = filesize($file_path);
733
734 $is_zip = false;
735 $is_image = false;
736 $is_audio = false;
737 $is_video = false;
738 $is_text = false;
739
740 $view_title = 'File';
741 $filenames = false; // for zip
742 $content = ''; // for text
743
744 if ($ext == 'zip') {
745 $is_zip = true;
746 $view_title = 'Archive';
747 $filenames = fm_get_zif_info($file_path);
748 } elseif (in_array($ext, fm_get_image_exts())) {
749 $is_image = true;
750 $view_title = 'Image';
751 } elseif (in_array($ext, fm_get_audio_exts())) {
752 $is_audio = true;
753 $view_title = 'Audio';
754 } elseif (in_array($ext, fm_get_video_exts())) {
755 $is_video = true;
756 $view_title = 'Video';
757 } elseif (in_array($ext, fm_get_text_exts()) || substr($mime_type, 0, 4) == 'text' || in_array($mime_type, fm_get_text_mimes())) {
758 $is_text = true;
759 $content = file_get_contents($file_path);
760 }
761
762 ?>
763 <div class="path">
764 <p class="break-word"><b><?php echo $view_title ?> "<?php echo fm_convert_win($file) ?>"</b></p>
765 <p class="break-word">
766 Full path: <?php echo fm_convert_win($file_path) ?><br>
767 File size: <?php echo fm_get_filesize($filesize) ?><?php if ($filesize >= 1000): ?> (<?php echo sprintf('%s bytes', $filesize) ?>)<?php endif; ?><br>
768 MIME-type: <?php echo $mime_type ?><br>
769 <?php
770 // ZIP info
771 if ($is_zip && $filenames !== false) {
772 $total_files = 0;
773 $total_comp = 0;
774 $total_uncomp = 0;
775 foreach ($filenames as $fn) {
776 if (!$fn['folder']) {
777 $total_files++;
778 }
779 $total_comp += $fn['compressed_size'];
780 $total_uncomp += $fn['filesize'];
781 }
782 ?>
783 Files in archive: <?php echo $total_files ?><br>
784 Total size: <?php echo fm_get_filesize($total_uncomp) ?><br>
785 Size in archive: <?php echo fm_get_filesize($total_comp) ?><br>
786 Compression: <?php echo round(($total_comp / $total_uncomp) * 100) ?>%<br>
787 <?php
788 }
789 // Image info
790 if ($is_image) {
791 $image_size = getimagesize($file_path);
792 echo 'Image sizes: ' . (isset($image_size[0]) ? $image_size[0] : '0') . ' x ' . (isset($image_size[1]) ? $image_size[1] : '0') . '<br>';
793 }
794 // Text info
795 if ($is_text) {
796 $is_utf8 = fm_is_utf8($content);
797 if (function_exists('iconv')) {
798 if (!$is_utf8) {
799 $content = iconv(FM_ICONV_INPUT_ENC, 'UTF-8//IGNORE', $content);
800 }
801 }
802 echo 'Charset: ' . ($is_utf8 ? 'utf-8' : '8 bit') . '<br>';
803 }
804 ?>
805 </p>
806 <p>
807 <b><a href="?p=<?php echo urlencode(FM_PATH) ?>&dl=<?php echo urlencode($file) ?>"><i class="icon-download"></i> Download</a></b>
808 <b><a href="<?php echo $file_url ?>" target="_blank"><i class="icon-chain"></i> Open</a></b>
809 <?php
810 // ZIP actions
811 if ($is_zip && $filenames !== false) {
812 $zip_name = pathinfo($file_path, PATHINFO_FILENAME);
813 ?>
814 <b><a href="?p=<?php echo urlencode(FM_PATH) ?>&unzip=<?php echo urlencode($file) ?>"><i class="icon-apply"></i> Unpack</a></b>
815 <b><a href="?p=<?php echo urlencode(FM_PATH) ?>&unzip=<?php echo urlencode($file) ?>&tofolder=1" title="Unpack to <?php echo fm_enc($zip_name) ?>"><i class="icon-apply"></i>
816 Unpack to folder</a></b>
817 <?php
818 }
819 ?>
820 <b><a href="?p=<?php echo urlencode(FM_PATH) ?>"><i class="icon-goback"></i> Back</a></b>
821 </p>
822 <?php
823 if ($is_zip) {
824 // ZIP content
825 if ($filenames !== false) {
826 echo '<code class="maxheight">';
827 foreach ($filenames as $fn) {
828 if ($fn['folder']) {
829 echo '<b>' . $fn['name'] . '</b><br>';
830 } else {
831 echo $fn['name'] . ' (' . fm_get_filesize($fn['filesize']) . ')<br>';
832 }
833 }
834 echo '</code>';
835 } else {
836 echo '<p>Error while fetching archive info</p>';
837 }
838 } elseif ($is_image) {
839 // Image content
840 if (in_array($ext, array('gif', 'jpg', 'jpeg', 'png', 'bmp', 'ico'))) {
841 echo '<p><img src="' . $file_url . '" alt="" class="preview-img"></p>';
842 }
843 } elseif ($is_audio) {
844 // Audio content
845 echo '<p><audio src="' . $file_url . '" controls preload="metadata"></audio></p>';
846 } elseif ($is_video) {
847 // Video content
848 echo '<div class="preview-video"><video src="' . $file_url . '" width="640" height="360" controls preload="metadata"></video></div>';
849 } elseif ($is_text) {
850 if (FM_USE_HIGHLIGHTJS) {
851 // highlight
852 $hljs_classes = array(
853 'shtml' => 'xml',
854 'htaccess' => 'apache',
855 'phtml' => 'php',
856 'lock' => 'json',
857 'svg' => 'xml',
858 );
859 $hljs_class = isset($hljs_classes[$ext]) ? 'lang-' . $hljs_classes[$ext] : 'lang-' . $ext;
860 if (empty($ext) || in_array(strtolower($file), fm_get_text_names()) || preg_match('#\.min\.(css|js)$#i', $file)) {
861 $hljs_class = 'nohighlight';
862 }
863 $content = '<pre class="with-hljs"><code class="' . $hljs_class . '">' . fm_enc($content) . '</code></pre>';
864 } elseif (in_array($ext, array('php', 'php4', 'php5', 'phtml', 'phps'))) {
865 // php highlight
866 $content = highlight_string($content, true);
867 } else {
868 $content = '<pre>' . fm_enc($content) . '</pre>';
869 }
870 echo $content;
871 }
872 ?>
873 </div>
874 <?php
875 fm_show_footer();
876 exit;
877}
878
879// chmod (not for Windows)
880if (isset($_GET['chmod']) && !FM_IS_WIN) {
881 $file = $_GET['chmod'];
882 $file = fm_clean_path($file);
883 $file = str_replace('/', '', $file);
884 if ($file == '' || (!is_file($path . '/' . $file) && !is_dir($path . '/' . $file))) {
885 fm_set_msg('File not found', 'error');
886 fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH));
887 }
888
889 fm_show_header(); // HEADER
890 fm_show_nav_path(FM_PATH); // current path
891
892 $file_url = FM_ROOT_URL . (FM_PATH != '' ? '/' . FM_PATH : '') . '/' . $file;
893 $file_path = $path . '/' . $file;
894
895 $mode = fileperms($path . '/' . $file);
896
897 ?>
898 <div class="path">
899 <p><b>Change Permissions</b></p>
900 <p>
901 Full path: <?php echo $file_path ?><br>
902 </p>
903 <form action="" method="post">
904 <input type="hidden" name="p" value="<?php echo fm_enc(FM_PATH) ?>">
905 <input type="hidden" name="chmod" value="<?php echo fm_enc($file) ?>">
906
907 <table class="compact-table">
908 <tr>
909 <td></td>
910 <td><b>Owner</b></td>
911 <td><b>Group</b></td>
912 <td><b>Other</b></td>
913 </tr>
914 <tr>
915 <td style="text-align: right"><b>Read</b></td>
916 <td><label><input type="checkbox" name="ur" value="1"<?php echo ($mode & 00400) ? ' checked' : '' ?>></label></td>
917 <td><label><input type="checkbox" name="gr" value="1"<?php echo ($mode & 00040) ? ' checked' : '' ?>></label></td>
918 <td><label><input type="checkbox" name="or" value="1"<?php echo ($mode & 00004) ? ' checked' : '' ?>></label></td>
919 </tr>
920 <tr>
921 <td style="text-align: right"><b>Write</b></td>
922 <td><label><input type="checkbox" name="uw" value="1"<?php echo ($mode & 00200) ? ' checked' : '' ?>></label></td>
923 <td><label><input type="checkbox" name="gw" value="1"<?php echo ($mode & 00020) ? ' checked' : '' ?>></label></td>
924 <td><label><input type="checkbox" name="ow" value="1"<?php echo ($mode & 00002) ? ' checked' : '' ?>></label></td>
925 </tr>
926 <tr>
927 <td style="text-align: right"><b>Execute</b></td>
928 <td><label><input type="checkbox" name="ux" value="1"<?php echo ($mode & 00100) ? ' checked' : '' ?>></label></td>
929 <td><label><input type="checkbox" name="gx" value="1"<?php echo ($mode & 00010) ? ' checked' : '' ?>></label></td>
930 <td><label><input type="checkbox" name="ox" value="1"<?php echo ($mode & 00001) ? ' checked' : '' ?>></label></td>
931 </tr>
932 </table>
933
934 <p>
935 <button class="btn"><i class="icon-apply"></i> Change</button>
936 <b><a href="?p=<?php echo urlencode(FM_PATH) ?>"><i class="icon-cancel"></i> Cancel</a></b>
937 </p>
938
939 </form>
940
941 </div>
942 <?php
943 fm_show_footer();
944 exit;
945}
946
947//--- FILEMANAGER MAIN
948fm_show_header(); // HEADER
949fm_show_nav_path(FM_PATH); // current path
950
951// messages
952fm_show_message();
953
954$num_files = count($files);
955$num_folders = count($folders);
956$all_files_size = 0;
957?>
958<form action="" method="post">
959<input type="hidden" name="p" value="<?php echo fm_enc(FM_PATH) ?>">
960<input type="hidden" name="group" value="1">
961<table><tr>
962<th style="width:3%"><label><input type="checkbox" title="Invert selection" onclick="checkbox_toggle()"></label></th>
963<th>Name</th><th style="width:10%">Size</th>
964<th style="width:12%">Modified</th>
965<?php if (!FM_IS_WIN): ?><th style="width:6%">Perms</th><th style="width:10%">Owner</th><?php endif; ?>
966<th style="width:13%"></th></tr>
967<?php
968// link to parent folder
969if ($parent !== false) {
970 ?>
971<tr><td></td><td colspan="<?php echo !FM_IS_WIN ? '6' : '4' ?>"><a href="?p=<?php echo urlencode($parent) ?>"><i class="icon-arrow_up"></i> ..</a></td></tr>
972<?php
973}
974foreach ($folders as $f) {
975 $is_link = is_link($path . '/' . $f);
976 $img = $is_link ? 'icon-link_folder' : 'icon-folder';
977 $modif = date(FM_DATETIME_FORMAT, filemtime($path . '/' . $f));
978 $perms = substr(decoct(fileperms($path . '/' . $f)), -4);
979 if (function_exists('posix_getpwuid') && function_exists('posix_getgrgid')) {
980 $owner = posix_getpwuid(fileowner($path . '/' . $f));
981 $group = posix_getgrgid(filegroup($path . '/' . $f));
982 } else {
983 $owner = array('name' => '?');
984 $group = array('name' => '?');
985 }
986 ?>
987<tr>
988<td><label><input type="checkbox" name="file[]" value="<?php echo fm_enc($f) ?>"></label></td>
989<td><div class="filename"><a href="?p=<?php echo urlencode(trim(FM_PATH . '/' . $f, '/')) ?>"><i class="<?php echo $img ?>"></i> <?php echo fm_convert_win($f) ?></a><?php echo ($is_link ? ' → <i>' . readlink($path . '/' . $f) . '</i>' : '') ?></div></td>
990<td>Folder</td><td><?php echo $modif ?></td>
991<?php if (!FM_IS_WIN): ?>
992<td><a title="Change Permissions" href="?p=<?php echo urlencode(FM_PATH) ?>&chmod=<?php echo urlencode($f) ?>"><?php echo $perms ?></a></td>
993<td><?php echo $owner['name'] . ':' . $group['name'] ?></td>
994<?php endif; ?>
995<td>
996<a title="Delete" href="?p=<?php echo urlencode(FM_PATH) ?>&del=<?php echo urlencode($f) ?>" onclick="return confirm('Delete folder?');"><i class="icon-cross"></i></a>
997<a title="Rename" href="#" onclick="rename('<?php echo fm_enc(FM_PATH) ?>', '<?php echo fm_enc($f) ?>');return false;"><i class="icon-rename"></i></a>
998<a title="Copy to..." href="?p=&copy=<?php echo urlencode(trim(FM_PATH . '/' . $f, '/')) ?>"><i class="icon-copy"></i></a>
999<a title="Direct link" href="<?php echo FM_ROOT_URL . (FM_PATH != '' ? '/' . FM_PATH : '') . '/' . $f . '/' ?>" target="_blank"><i class="icon-chain"></i></a>
1000</td></tr>
1001 <?php
1002 flush();
1003}
1004
1005foreach ($files as $f) {
1006 $is_link = is_link($path . '/' . $f);
1007 $img = $is_link ? 'icon-link_file' : fm_get_file_icon_class($path . '/' . $f);
1008 $modif = date(FM_DATETIME_FORMAT, filemtime($path . '/' . $f));
1009 $filesize_raw = filesize($path . '/' . $f);
1010 $filesize = fm_get_filesize($filesize_raw);
1011 $filelink = '?p=' . urlencode(FM_PATH) . '&view=' . urlencode($f);
1012 $all_files_size += $filesize_raw;
1013 $perms = substr(decoct(fileperms($path . '/' . $f)), -4);
1014 if (function_exists('posix_getpwuid') && function_exists('posix_getgrgid')) {
1015 $owner = posix_getpwuid(fileowner($path . '/' . $f));
1016 $group = posix_getgrgid(filegroup($path . '/' . $f));
1017 } else {
1018 $owner = array('name' => '?');
1019 $group = array('name' => '?');
1020 }
1021 ?>
1022<tr>
1023<td><label><input type="checkbox" name="file[]" value="<?php echo fm_enc($f) ?>"></label></td>
1024<td><div class="filename"><a href="<?php echo $filelink ?>" title="File info"><i class="<?php echo $img ?>"></i> <?php echo fm_convert_win($f) ?></a><?php echo ($is_link ? ' → <i>' . readlink($path . '/' . $f) . '</i>' : '') ?></div></td>
1025<td><span class="gray" title="<?php printf('%s bytes', $filesize_raw) ?>"><?php echo $filesize ?></span></td>
1026<td><?php echo $modif ?></td>
1027<?php if (!FM_IS_WIN): ?>
1028<td><a title="Change Permissions" href="?p=<?php echo urlencode(FM_PATH) ?>&chmod=<?php echo urlencode($f) ?>"><?php echo $perms ?></a></td>
1029<td><?php echo $owner['name'] . ':' . $group['name'] ?></td>
1030<?php endif; ?>
1031<td>
1032<a title="Delete" href="?p=<?php echo urlencode(FM_PATH) ?>&del=<?php echo urlencode($f) ?>" onclick="return confirm('Delete file?');"><i class="icon-cross"></i></a>
1033<a title="Rename" href="#" onclick="rename('<?php echo fm_enc(FM_PATH) ?>', '<?php echo fm_enc($f) ?>');return false;"><i class="icon-rename"></i></a>
1034<a title="Copy to..." href="?p=<?php echo urlencode(FM_PATH) ?>&copy=<?php echo urlencode(trim(FM_PATH . '/' . $f, '/')) ?>"><i class="icon-copy"></i></a>
1035<a title="Direct link" href="<?php echo FM_ROOT_URL . (FM_PATH != '' ? '/' . FM_PATH : '') . '/' . $f ?>" target="_blank"><i class="icon-chain"></i></a>
1036<a title="Download" href="?p=<?php echo urlencode(FM_PATH) ?>&dl=<?php echo urlencode($f) ?>"><i class="icon-download"></i></a>
1037</td></tr>
1038 <?php
1039 flush();
1040}
1041
1042if (empty($folders) && empty($files)) {
1043 ?>
1044<tr><td></td><td colspan="<?php echo !FM_IS_WIN ? '6' : '4' ?>"><em>Folder is empty</em></td></tr>
1045<?php
1046} else {
1047 ?>
1048<tr><td class="gray"></td><td class="gray" colspan="<?php echo !FM_IS_WIN ? '6' : '4' ?>">
1049Full size: <span title="<?php printf('%s bytes', $all_files_size) ?>"><?php echo fm_get_filesize($all_files_size) ?></span>,
1050files: <?php echo $num_files ?>,
1051folders: <?php echo $num_folders ?>
1052</td></tr>
1053<?php
1054}
1055?>
1056</table>
1057<p class="path"><a href="#" onclick="select_all();return false;"><i class="icon-checkbox"></i> Select all</a>
1058<a href="#" onclick="unselect_all();return false;"><i class="icon-checkbox_uncheck"></i> Unselect all</a>
1059<a href="#" onclick="invert_all();return false;"><i class="icon-checkbox_invert"></i> Invert selection</a></p>
1060<p><input type="submit" name="delete" value="Delete" onclick="return confirm('Delete selected files and folders?')">
1061<input type="submit" name="zip" value="Pack" onclick="return confirm('Create archive?')">
1062<input type="submit" name="copy" value="Copy"></p>
1063</form>
1064
1065<?php
1066fm_show_footer();
1067
1068//--- END
1069
1070// Functions
1071
1072/**
1073 * Delete file or folder (recursively)
1074 * @param string $path
1075 * @return bool
1076 */
1077function fm_rdelete($path)
1078{
1079 if (is_link($path)) {
1080 return unlink($path);
1081 } elseif (is_dir($path)) {
1082 $objects = scandir($path);
1083 $ok = true;
1084 if (is_array($objects)) {
1085 foreach ($objects as $file) {
1086 if ($file != '.' && $file != '..') {
1087 if (!fm_rdelete($path . '/' . $file)) {
1088 $ok = false;
1089 }
1090 }
1091 }
1092 }
1093 return ($ok) ? rmdir($path) : false;
1094 } elseif (is_file($path)) {
1095 return unlink($path);
1096 }
1097 return false;
1098}
1099
1100/**
1101 * Recursive chmod
1102 * @param string $path
1103 * @param int $filemode
1104 * @param int $dirmode
1105 * @return bool
1106 * @todo Will use in mass chmod
1107 */
1108function fm_rchmod($path, $filemode, $dirmode)
1109{
1110 if (is_dir($path)) {
1111 if (!chmod($path, $dirmode)) {
1112 return false;
1113 }
1114 $objects = scandir($path);
1115 if (is_array($objects)) {
1116 foreach ($objects as $file) {
1117 if ($file != '.' && $file != '..') {
1118 if (!fm_rchmod($path . '/' . $file, $filemode, $dirmode)) {
1119 return false;
1120 }
1121 }
1122 }
1123 }
1124 return true;
1125 } elseif (is_link($path)) {
1126 return true;
1127 } elseif (is_file($path)) {
1128 return chmod($path, $filemode);
1129 }
1130 return false;
1131}
1132
1133/**
1134 * Safely rename
1135 * @param string $old
1136 * @param string $new
1137 * @return bool|null
1138 */
1139function fm_rename($old, $new)
1140{
1141 return (!file_exists($new) && file_exists($old)) ? rename($old, $new) : null;
1142}
1143
1144/**
1145 * Copy file or folder (recursively).
1146 * @param string $path
1147 * @param string $dest
1148 * @param bool $upd Update files
1149 * @param bool $force Create folder with same names instead file
1150 * @return bool
1151 */
1152function fm_rcopy($path, $dest, $upd = true, $force = true)
1153{
1154 if (is_dir($path)) {
1155 if (!fm_mkdir($dest, $force)) {
1156 return false;
1157 }
1158 $objects = scandir($path);
1159 $ok = true;
1160 if (is_array($objects)) {
1161 foreach ($objects as $file) {
1162 if ($file != '.' && $file != '..') {
1163 if (!fm_rcopy($path . '/' . $file, $dest . '/' . $file)) {
1164 $ok = false;
1165 }
1166 }
1167 }
1168 }
1169 return $ok;
1170 } elseif (is_file($path)) {
1171 return fm_copy($path, $dest, $upd);
1172 }
1173 return false;
1174}
1175
1176/**
1177 * Safely create folder
1178 * @param string $dir
1179 * @param bool $force
1180 * @return bool
1181 */
1182function fm_mkdir($dir, $force)
1183{
1184 if (file_exists($dir)) {
1185 if (is_dir($dir)) {
1186 return $dir;
1187 } elseif (!$force) {
1188 return false;
1189 }
1190 unlink($dir);
1191 }
1192 return mkdir($dir, 0777, true);
1193}
1194
1195/**
1196 * Safely copy file
1197 * @param string $f1
1198 * @param string $f2
1199 * @param bool $upd
1200 * @return bool
1201 */
1202function fm_copy($f1, $f2, $upd)
1203{
1204 $time1 = filemtime($f1);
1205 if (file_exists($f2)) {
1206 $time2 = filemtime($f2);
1207 if ($time2 >= $time1 && $upd) {
1208 return false;
1209 }
1210 }
1211 $ok = copy($f1, $f2);
1212 if ($ok) {
1213 touch($f2, $time1);
1214 }
1215 return $ok;
1216}
1217
1218/**
1219 * Get mime type
1220 * @param string $file_path
1221 * @return mixed|string
1222 */
1223function fm_get_mime_type($file_path)
1224{
1225 if (function_exists('finfo_open')) {
1226 $finfo = finfo_open(FILEINFO_MIME_TYPE);
1227 $mime = finfo_file($finfo, $file_path);
1228 finfo_close($finfo);
1229 return $mime;
1230 } elseif (function_exists('mime_content_type')) {
1231 return mime_content_type($file_path);
1232 } elseif (!stristr(ini_get('disable_functions'), 'shell_exec')) {
1233 $file = escapeshellarg($file_path);
1234 $mime = shell_exec('file -bi ' . $file);
1235 return $mime;
1236 } else {
1237 return '--';
1238 }
1239}
1240
1241/**
1242 * HTTP Redirect
1243 * @param string $url
1244 * @param int $code
1245 */
1246function fm_redirect($url, $code = 302)
1247{
1248 header('Location: ' . $url, true, $code);
1249 exit;
1250}
1251
1252/**
1253 * Clean path
1254 * @param string $path
1255 * @return string
1256 */
1257function fm_clean_path($path)
1258{
1259 $path = trim($path);
1260 $path = trim($path, '\\/');
1261 $path = str_replace(array('../', '..\\'), '', $path);
1262 if ($path == '..') {
1263 $path = '';
1264 }
1265 return str_replace('\\', '/', $path);
1266}
1267
1268/**
1269 * Get parent path
1270 * @param string $path
1271 * @return bool|string
1272 */
1273function fm_get_parent_path($path)
1274{
1275 $path = fm_clean_path($path);
1276 if ($path != '') {
1277 $array = explode('/', $path);
1278 if (count($array) > 1) {
1279 $array = array_slice($array, 0, -1);
1280 return implode('/', $array);
1281 }
1282 return '';
1283 }
1284 return false;
1285}
1286
1287/**
1288 * Get nice filesize
1289 * @param int $size
1290 * @return string
1291 */
1292function fm_get_filesize($size)
1293{
1294 if ($size < 1000) {
1295 return sprintf('%s B', $size);
1296 } elseif (($size / 1024) < 1000) {
1297 return sprintf('%s KiB', round(($size / 1024), 2));
1298 } elseif (($size / 1024 / 1024) < 1000) {
1299 return sprintf('%s MiB', round(($size / 1024 / 1024), 2));
1300 } elseif (($size / 1024 / 1024 / 1024) < 1000) {
1301 return sprintf('%s GiB', round(($size / 1024 / 1024 / 1024), 2));
1302 } else {
1303 return sprintf('%s TiB', round(($size / 1024 / 1024 / 1024 / 1024), 2));
1304 }
1305}
1306
1307/**
1308 * Get info about zip archive
1309 * @param string $path
1310 * @return array|bool
1311 */
1312function fm_get_zif_info($path)
1313{
1314 if (function_exists('zip_open')) {
1315 $arch = zip_open($path);
1316 if ($arch) {
1317 $filenames = array();
1318 while ($zip_entry = zip_read($arch)) {
1319 $zip_name = zip_entry_name($zip_entry);
1320 $zip_folder = substr($zip_name, -1) == '/';
1321 $filenames[] = array(
1322 'name' => $zip_name,
1323 'filesize' => zip_entry_filesize($zip_entry),
1324 'compressed_size' => zip_entry_compressedsize($zip_entry),
1325 'folder' => $zip_folder
1326 //'compression_method' => zip_entry_compressionmethod($zip_entry),
1327 );
1328 }
1329 zip_close($arch);
1330 return $filenames;
1331 }
1332 }
1333 return false;
1334}
1335
1336/**
1337 * Encode html entities
1338 * @param string $text
1339 * @return string
1340 */
1341function fm_enc($text)
1342{
1343 return htmlspecialchars($text, ENT_QUOTES, 'UTF-8');
1344}
1345
1346/**
1347 * Save message in session
1348 * @param string $msg
1349 * @param string $status
1350 */
1351function fm_set_msg($msg, $status = 'ok')
1352{
1353 $_SESSION['message'] = $msg;
1354 $_SESSION['status'] = $status;
1355}
1356
1357/**
1358 * Check if string is in UTF-8
1359 * @param string $string
1360 * @return int
1361 */
1362function fm_is_utf8($string)
1363{
1364 return preg_match('//u', $string);
1365}
1366
1367/**
1368 * Convert file name to UTF-8 in Windows
1369 * @param string $filename
1370 * @return string
1371 */
1372function fm_convert_win($filename)
1373{
1374 if (FM_IS_WIN && function_exists('iconv')) {
1375 $filename = iconv(FM_ICONV_INPUT_ENC, 'UTF-8//IGNORE', $filename);
1376 }
1377 return $filename;
1378}
1379
1380/**
1381 * Get CSS classname for file
1382 * @param string $path
1383 * @return string
1384 */
1385function fm_get_file_icon_class($path)
1386{
1387 // get extension
1388 $ext = strtolower(pathinfo($path, PATHINFO_EXTENSION));
1389
1390 switch ($ext) {
1391 case 'ico': case 'gif': case 'jpg': case 'jpeg': case 'jpc': case 'jp2':
1392 case 'jpx': case 'xbm': case 'wbmp': case 'png': case 'bmp': case 'tif':
1393 case 'tiff':
1394 $img = 'icon-file_image';
1395 break;
1396 case 'txt': case 'css': case 'ini': case 'conf': case 'log': case 'htaccess':
1397 case 'passwd': case 'ftpquota': case 'sql': case 'js': case 'json': case 'sh':
1398 case 'config': case 'twig': case 'tpl': case 'md': case 'gitignore':
1399 case 'less': case 'sass': case 'scss': case 'c': case 'cpp': case 'cs': case 'py':
1400 case 'map': case 'lock': case 'dtd':
1401 $img = 'icon-file_text';
1402 break;
1403 case 'zip': case 'rar': case 'gz': case 'tar': case '7z':
1404 $img = 'icon-file_zip';
1405 break;
1406 case 'php': case 'php4': case 'php5': case 'phps': case 'phtml':
1407 $img = 'icon-file_php';
1408 break;
1409 case 'htm': case 'html': case 'shtml': case 'xhtml':
1410 $img = 'icon-file_html';
1411 break;
1412 case 'xml': case 'xsl': case 'svg':
1413 $img = 'icon-file_code';
1414 break;
1415 case 'wav': case 'mp3': case 'mp2': case 'm4a': case 'aac': case 'ogg':
1416 case 'oga': case 'wma': case 'mka': case 'flac': case 'ac3': case 'tds':
1417 $img = 'icon-file_music';
1418 break;
1419 case 'm3u': case 'm3u8': case 'pls': case 'cue':
1420 $img = 'icon-file_playlist';
1421 break;
1422 case 'avi': case 'mpg': case 'mpeg': case 'mp4': case 'm4v': case 'flv':
1423 case 'f4v': case 'ogm': case 'ogv': case 'mov': case 'mkv': case '3gp':
1424 case 'asf': case 'wmv':
1425 $img = 'icon-file_film';
1426 break;
1427 case 'eml': case 'msg':
1428 $img = 'icon-file_outlook';
1429 break;
1430 case 'xls': case 'xlsx':
1431 $img = 'icon-file_excel';
1432 break;
1433 case 'csv':
1434 $img = 'icon-file_csv';
1435 break;
1436 case 'doc': case 'docx':
1437 $img = 'icon-file_word';
1438 break;
1439 case 'ppt': case 'pptx':
1440 $img = 'icon-file_powerpoint';
1441 break;
1442 case 'ttf': case 'ttc': case 'otf': case 'woff':case 'woff2': case 'eot': case 'fon':
1443 $img = 'icon-file_font';
1444 break;
1445 case 'pdf':
1446 $img = 'icon-file_pdf';
1447 break;
1448 case 'psd':
1449 $img = 'icon-file_photoshop';
1450 break;
1451 case 'ai': case 'eps':
1452 $img = 'icon-file_illustrator';
1453 break;
1454 case 'fla':
1455 $img = 'icon-file_flash';
1456 break;
1457 case 'swf':
1458 $img = 'icon-file_swf';
1459 break;
1460 case 'exe': case 'msi':
1461 $img = 'icon-file_application';
1462 break;
1463 case 'bat':
1464 $img = 'icon-file_terminal';
1465 break;
1466 default:
1467 $img = 'icon-document';
1468 }
1469
1470 return $img;
1471}
1472
1473/**
1474 * Get image files extensions
1475 * @return array
1476 */
1477function fm_get_image_exts()
1478{
1479 return array('ico', 'gif', 'jpg', 'jpeg', 'jpc', 'jp2', 'jpx', 'xbm', 'wbmp', 'png', 'bmp', 'tif', 'tiff', 'psd');
1480}
1481
1482/**
1483 * Get video files extensions
1484 * @return array
1485 */
1486function fm_get_video_exts()
1487{
1488 return array('webm', 'mp4', 'm4v', 'ogm', 'ogv', 'mov');
1489}
1490
1491/**
1492 * Get audio files extensions
1493 * @return array
1494 */
1495function fm_get_audio_exts()
1496{
1497 return array('wav', 'mp3', 'ogg', 'm4a');
1498}
1499
1500/**
1501 * Get text file extensions
1502 * @return array
1503 */
1504function fm_get_text_exts()
1505{
1506 return array(
1507 'txt', 'css', 'ini', 'conf', 'log', 'htaccess', 'passwd', 'ftpquota', 'sql', 'js', 'json', 'sh', 'config',
1508 'php', 'php4', 'php5', 'phps', 'phtml', 'htm', 'html', 'shtml', 'xhtml', 'xml', 'xsl', 'm3u', 'm3u8', 'pls', 'cue',
1509 'eml', 'msg', 'csv', 'bat', 'twig', 'tpl', 'md', 'gitignore', 'less', 'sass', 'scss', 'c', 'cpp', 'cs', 'py',
1510 'map', 'lock', 'dtd', 'svg',
1511 );
1512}
1513
1514/**
1515 * Get mime types of text files
1516 * @return array
1517 */
1518function fm_get_text_mimes()
1519{
1520 return array(
1521 'application/xml',
1522 'application/javascript',
1523 'application/x-javascript',
1524 'image/svg+xml',
1525 'message/rfc822',
1526 );
1527}
1528
1529/**
1530 * Get file names of text files w/o extensions
1531 * @return array
1532 */
1533function fm_get_text_names()
1534{
1535 return array(
1536 'license',
1537 'readme',
1538 'authors',
1539 'contributors',
1540 'changelog',
1541 );
1542}
1543
1544/**
1545 * Class to work with zip files (using ZipArchive)
1546 */
1547class FM_Zipper
1548{
1549 private $zip;
1550
1551 public function __construct()
1552 {
1553 $this->zip = new ZipArchive();
1554 }
1555
1556 /**
1557 * Create archive with name $filename and files $files (RELATIVE PATHS!)
1558 * @param string $filename
1559 * @param array|string $files
1560 * @return bool
1561 */
1562 public function create($filename, $files)
1563 {
1564 $res = $this->zip->open($filename, ZipArchive::CREATE);
1565 if ($res !== true) {
1566 return false;
1567 }
1568 if (is_array($files)) {
1569 foreach ($files as $f) {
1570 if (!$this->addFileOrDir($f)) {
1571 $this->zip->close();
1572 return false;
1573 }
1574 }
1575 $this->zip->close();
1576 return true;
1577 } else {
1578 if ($this->addFileOrDir($files)) {
1579 $this->zip->close();
1580 return true;
1581 }
1582 return false;
1583 }
1584 }
1585
1586 /**
1587 * Extract archive $filename to folder $path (RELATIVE OR ABSOLUTE PATHS)
1588 * @param string $filename
1589 * @param string $path
1590 * @return bool
1591 */
1592 public function unzip($filename, $path)
1593 {
1594 $res = $this->zip->open($filename);
1595 if ($res !== true) {
1596 return false;
1597 }
1598 if ($this->zip->extractTo($path)) {
1599 $this->zip->close();
1600 return true;
1601 }
1602 return false;
1603 }
1604
1605 /**
1606 * Add file/folder to archive
1607 * @param string $filename
1608 * @return bool
1609 */
1610 private function addFileOrDir($filename)
1611 {
1612 if (is_file($filename)) {
1613 return $this->zip->addFile($filename);
1614 } elseif (is_dir($filename)) {
1615 return $this->addDir($filename);
1616 }
1617 return false;
1618 }
1619
1620 /**
1621 * Add folder recursively
1622 * @param string $path
1623 * @return bool
1624 */
1625 private function addDir($path)
1626 {
1627 if (!$this->zip->addEmptyDir($path)) {
1628 return false;
1629 }
1630 $objects = scandir($path);
1631 if (is_array($objects)) {
1632 foreach ($objects as $file) {
1633 if ($file != '.' && $file != '..') {
1634 if (is_dir($path . '/' . $file)) {
1635 if (!$this->addDir($path . '/' . $file)) {
1636 return false;
1637 }
1638 } elseif (is_file($path . '/' . $file)) {
1639 if (!$this->zip->addFile($path . '/' . $file)) {
1640 return false;
1641 }
1642 }
1643 }
1644 }
1645 return true;
1646 }
1647 return false;
1648 }
1649}
1650
1651//--- templates functions
1652
1653/**
1654 * Show nav block
1655 * @param string $path
1656 */
1657function fm_show_nav_path($path)
1658{
1659 ?>
1660<div class="path">
1661<div class="float-right">
1662<a title="Upload files" href="?p=<?php echo urlencode(FM_PATH) ?>&upload"><i class="icon-upload"></i></a>
1663<a title="New folder" href="#" onclick="newfolder('<?php echo fm_enc(FM_PATH) ?>');return false;"><i class="icon-folder_add"></i></a>
1664<?php if (FM_USE_AUTH): ?><a title="Logout" href="?logout=1"><i class="icon-logout"></i></a><?php endif; ?>
1665</div>
1666 <?php
1667 $path = fm_clean_path($path);
1668 $root_url = "<a href='?p='><i class='icon-home' title='" . FM_ROOT_PATH . "'></i></a>";
1669 $sep = '<i class="icon-separator"></i>';
1670 if ($path != '') {
1671 $exploded = explode('/', $path);
1672 $count = count($exploded);
1673 $array = array();
1674 $parent = '';
1675 for ($i = 0; $i < $count; $i++) {
1676 $parent = trim($parent . '/' . $exploded[$i], '/');
1677 $parent_enc = urlencode($parent);
1678 $array[] = "<a href='?p={$parent_enc}'>" . fm_convert_win($exploded[$i]) . "</a>";
1679 }
1680 $root_url .= $sep . implode($sep, $array);
1681 }
1682 echo '<div class="break-word">' . $root_url . '</div>';
1683 ?>
1684</div>
1685<?php
1686}
1687
1688/**
1689 * Show message from session
1690 */
1691function fm_show_message()
1692{
1693 if (isset($_SESSION['message'])) {
1694 $class = isset($_SESSION['status']) ? $_SESSION['status'] : 'ok';
1695 echo '<p class="message ' . $class . '">' . $_SESSION['message'] . '</p>';
1696 unset($_SESSION['message']);
1697 unset($_SESSION['status']);
1698 }
1699}
1700
1701/**
1702 * Show page header
1703 */
1704function fm_show_header()
1705{
1706 $sprites_ver = '20160315';
1707 header("Content-Type: text/html; charset=utf-8");
1708 header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");
1709 header("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
1710 header("Pragma: no-cache");
1711 ?>
1712<!DOCTYPE html>
1713<html>
1714<head>
1715<meta charset="utf-8">
1716<title>PHP File Manager</title>
1717<style>
1718html,body,div,span,p,pre,a,code,em,img,small,strong,ol,ul,li,form,label,table,tr,th,td{margin:0;padding:0;vertical-align:baseline;outline:none;font-size:100%;background:transparent;border:none;text-decoration:none}
1719html{overflow-y:scroll}body{padding:0;font:13px/16px Tahoma,Arial,sans-serif;color:#222;background:#efefef}
1720input,select,textarea,button{font-size:inherit;font-family:inherit}
1721a{color:#296ea3;text-decoration:none}a:hover{color:#b00}img{vertical-align:middle;border:none}
1722a img{border:none}span.gray{color:#777}small{font-size:11px;color:#999}p{margin-bottom:10px}
1723ul{margin-left:2em;margin-bottom:10px}ul{list-style-type:none;margin-left:0}ul li{padding:3px 0}
1724table{border-collapse:collapse;border-spacing:0;margin-bottom:10px;width:100%}
1725th,td{padding:4px 7px;text-align:left;vertical-align:top;border:1px solid #ddd;background:#fff;white-space:nowrap}
1726th,td.gray{background-color:#eee}td.gray span{color:#222}
1727tr:hover td{background-color:#f5f5f5}tr:hover td.gray{background-color:#eee}
1728code,pre{display:block;margin-bottom:10px;font:13px/16px Consolas,'Courier New',Courier,monospace;border:1px dashed #ccc;padding:5px;overflow:auto}
1729pre.with-hljs{padding:0}
1730pre.with-hljs code{margin:0;border:0;overflow:visible}
1731code.maxheight,pre.maxheight{max-height:512px}input[type="checkbox"]{margin:0;padding:0}
1732#wrapper{max-width:1000px;min-width:400px;margin:10px auto}
1733.path{padding:4px 7px;border:1px solid #ddd;background-color:#fff;margin-bottom:10px}
1734.right{text-align:right}.center{text-align:center}.float-right{float:right}
1735.message{padding:4px 7px;border:1px solid #ddd;background-color:#fff}
1736.message.ok{border-color:green;color:green}
1737.message.error{border-color:red;color:red}
1738.message.alert{border-color:orange;color:orange}
1739.btn{border:0;background:none;padding:0;margin:0;font-weight:bold;color:#296ea3;cursor:pointer}.btn:hover{color:#b00}
1740.preview-img{max-width:100%;background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAKklEQVR42mL5//8/Azbw+PFjrOJMDCSCUQ3EABZc4S0rKzsaSvTTABBgAMyfCMsY4B9iAAAAAElFTkSuQmCC") repeat 0 0}
1741.preview-video{position:relative;max-width:100%;height:0;padding-bottom:62.5%;margin-bottom:10px}.preview-video video{position:absolute;width:100%;height:100%;left:0;top:0;background:#000}
1742[class*="icon-"]{display:inline-block;width:16px;height:16px;background:url("<?php echo FM_SELF_URL ?>?img=sprites&t=<?php echo $sprites_ver ?>") no-repeat 0 0;vertical-align:bottom}
1743.icon-document{background-position:-16px 0}.icon-folder{background-position:-32px 0}
1744.icon-folder_add{background-position:-48px 0}.icon-upload{background-position:-64px 0}
1745.icon-arrow_up{background-position:-80px 0}.icon-home{background-position:-96px 0}
1746.icon-separator{background-position:-112px 0}.icon-cross{background-position:-128px 0}
1747.icon-copy{background-position:-144px 0}.icon-apply{background-position:-160px 0}
1748.icon-cancel{background-position:-176px 0}.icon-rename{background-position:-192px 0}
1749.icon-checkbox{background-position:-208px 0}.icon-checkbox_invert{background-position:-224px 0}
1750.icon-checkbox_uncheck{background-position:-240px 0}.icon-download{background-position:-256px 0}
1751.icon-goback{background-position:-272px 0}.icon-folder_open{background-position:-288px 0}
1752.icon-file_application{background-position:0 -16px}.icon-file_code{background-position:-16px -16px}
1753.icon-file_csv{background-position:-32px -16px}.icon-file_excel{background-position:-48px -16px}
1754.icon-file_film{background-position:-64px -16px}.icon-file_flash{background-position:-80px -16px}
1755.icon-file_font{background-position:-96px -16px}.icon-file_html{background-position:-112px -16px}
1756.icon-file_illustrator{background-position:-128px -16px}.icon-file_image{background-position:-144px -16px}
1757.icon-file_music{background-position:-160px -16px}.icon-file_outlook{background-position:-176px -16px}
1758.icon-file_pdf{background-position:-192px -16px}.icon-file_photoshop{background-position:-208px -16px}
1759.icon-file_php{background-position:-224px -16px}.icon-file_playlist{background-position:-240px -16px}
1760.icon-file_powerpoint{background-position:-256px -16px}.icon-file_swf{background-position:-272px -16px}
1761.icon-file_terminal{background-position:-288px -16px}.icon-file_text{background-position:-304px -16px}
1762.icon-file_word{background-position:-320px -16px}.icon-file_zip{background-position:-336px -16px}
1763.icon-logout{background-position:-304px 0}.icon-chain{background-position:-320px 0}
1764.icon-link_folder{background-position:-352px -16px}.icon-link_file{background-position:-368px -16px}
1765.compact-table{border:0;width:auto}.compact-table td,.compact-table th{width:100px;border:0;text-align:center}.compact-table tr:hover td{background-color:#fff}
1766.filename{max-width:420px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
1767.break-word{word-wrap:break-word}
1768</style>
1769<link rel="icon" href="<?php echo FM_SELF_URL ?>?img=favicon" type="image/png">
1770<link rel="shortcut icon" href="<?php echo FM_SELF_URL ?>?img=favicon" type="image/png">
1771<?php if (isset($_GET['view']) && FM_USE_HIGHLIGHTJS): ?>
1772<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.2.0/styles/<?php echo FM_HIGHLIGHTJS_STYLE ?>.min.css">
1773<?php endif; ?>
1774</head>
1775<body>
1776<div id="wrapper">
1777<?php
1778}
1779
1780/**
1781 * Show page footer
1782 */
1783function fm_show_footer()
1784{
1785 ?>
1786<p class="center"><small></small></p>
1787</div>
1788<script>
1789function newfolder(p){var n=prompt('New folder name','folder');if(n!==null&&n!==''){window.location.search='p='+encodeURIComponent(p)+'&new='+encodeURIComponent(n);}}
1790function rename(p,f){var n=prompt('New name',f);if(n!==null&&n!==''&&n!=f){window.location.search='p='+encodeURIComponent(p)+'&ren='+encodeURIComponent(f)+'&to='+encodeURIComponent(n);}}
1791function change_checkboxes(l,v){for(var i=l.length-1;i>=0;i--){l[i].checked=(typeof v==='boolean')?v:!l[i].checked;}}
1792function get_checkboxes(){var i=document.getElementsByName('file[]'),a=[];for(var j=i.length-1;j>=0;j--){if(i[j].type='checkbox'){a.push(i[j]);}}return a;}
1793function select_all(){var l=get_checkboxes();change_checkboxes(l,true);}
1794function unselect_all(){var l=get_checkboxes();change_checkboxes(l,false);}
1795function invert_all(){var l=get_checkboxes();change_checkboxes(l);}
1796function checkbox_toggle(){var l=get_checkboxes();l.push(this);change_checkboxes(l);}
1797</script>
1798<?php if (isset($_GET['view']) && FM_USE_HIGHLIGHTJS): ?>
1799<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.2.0/highlight.min.js"></script>
1800<script>hljs.initHighlightingOnLoad();</script>
1801<?php endif; ?>
1802</body>
1803</html>
1804<?php
1805}
1806
1807/**
1808 * Show image
1809 * @param string $img
1810 */
1811function fm_show_image($img)
1812{
1813 $modified_time = gmdate('D, d M Y 00:00:00') . ' GMT';
1814 $expires_time = gmdate('D, d M Y 00:00:00', strtotime('+1 day')) . ' GMT';
1815
1816 $img = trim($img);
1817 $images = fm_get_images();
1818 $image = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAEElEQVR42mL4//8/A0CAAQAI/AL+26JNFgAAAABJRU5ErkJggg==';
1819 if (isset($images[$img])) {
1820 $image = $images[$img];
1821 }
1822 $image = base64_decode($image);
1823 if (function_exists('mb_strlen')) {
1824 $size = mb_strlen($image, '8bit');
1825 } else {
1826 $size = strlen($image);
1827 }
1828
1829 if (function_exists('header_remove')) {
1830 header_remove('Cache-Control');
1831 header_remove('Pragma');
1832 } else {
1833 header('Cache-Control:');
1834 header('Pragma:');
1835 }
1836
1837 header('Last-Modified: ' . $modified_time, true, 200);
1838 header('Expires: ' . $expires_time);
1839 header('Content-Length: ' . $size);
1840 header('Content-Type: image/png');
1841 echo $image;
1842
1843 exit;
1844}
1845
1846/**
1847 * Get base64-encoded images
1848 * @return array
1849 */
1850function fm_get_images()
1851{
1852 return array(
1853 'favicon' => 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJ
1854bWFnZVJlYWR5ccllPAAAAZVJREFUeNqkk79Lw0AUx1+uidTQim4Waxfpnl1BcHMR6uLkIF0cpYOI
1855f4KbOFcRwbGTc0HQSVQQXCqlFIXgFkhIyvWS870LaaPYH9CDy8vdfb+fey930aSUMEvT6VHVzw8x
1856rKUX3N3Hj/8M+cZ6GcOtBPl6KY5iAA7KJzfVWrfbhUKhALZtQ6myDf1+X5nsuzjLUmUOnpa+v5r1
1857Z4ZDDfsLiwER45xDEATgOI6KntfDd091GidzC8vZ4vH1QQ09+4MSMAMWRREKPMhmsyr6voYmrnb2
1858PKEizdEabUaeFCDKCCHAdV0wTVNFznMgpVqGlZ2cipzHGtKSZwCIZJgJwxB38KHT6Sjx21V75Jcn
1859LXmGAKTRpGVZUx2dAqQzSEqw9kqwuGqONTufPrw37D8lQFxCvjgPXIixANLEGfwuQacMOC4kZz+q
1860GdhJS550BjpRCdCbAJCMJRkMASEIg+4Bxz4JwAwDSEueAYDLIM+QrOk6GHiRxjXSkJY8KUCvdXZ6
1861kbuvNx+mOcbN9taGBlpLAWf9nX8EGADoCfqkKWV/cgAAAABJRU5ErkJggg==',
1862 'sprites' => 'iVBORw0KGgoAAAANSUhEUgAAAYAAAAAgCAMAAAAscl/XAAAC/VBMVEUAAABUfn4KKipIcXFSeXsx
1863VlZSUlNAZ2c4Xl4lSUkRDg7w8O/d3d3LhwAWFhYXODgMLCx8fHw9PT2TtdOOAACMXgE8lt+dmpq+
1864fgABS3RUpN+VUycuh9IgeMJUe4C5dUI6meKkAQEKCgoMWp5qtusJmxSUPgKudAAXCghQMieMAgIU
1865abNSUlJLe70VAQEsh85oaGjBEhIBOGxfAoyUbUQAkw8gui4LBgbOiFPHx8cZX6PMS1OqFha/MjIK
1866VKFGBABSAXovGAkrg86xAgIoS5Y7c6Nf7W1Hz1NmAQB3Hgx8fHyiTAAwp+eTz/JdDAJ0JwAAlxCQ
1867UAAvmeRiYp6ysrmIAABJr/ErmiKmcsATpRyfEBAOdQgOXahyAAAecr1JCwHMiABgfK92doQGBgZG
1868AGkqKiw0ldYuTHCYsF86gB05UlJmQSlra2tVWED////8/f3t9fX5/Pzi8/Px9vb2+/v0+fnn8vLf
18697OzZ6enV5+eTpKTo6Oj6/v765Z/U5eX4+Pjx+Pjv0ojWBASxw8O8vL52dnfR19CvAADR3PHr6+vi
18704uPDx8v/866nZDO7iNT335jtzIL+7aj86aTIztXDw8X13JOlpKJoaHDJAACltratrq3lAgKfAADb
18714vb76N2au9by2I9gYGVIRkhNTE90wfXq2sh8gL8QMZ3pyn27AADr+uu1traNiIh2olTTshifodQ4
1872ZM663PH97+YeRq2GqmRjmkGjnEDnfjLVVg6W4f7s6/p/0fr98+5UVF6wz+SjxNsmVb5RUVWMrc7d
1873zrrIpWI8PD3pkwhCltZFYbNZja82wPv05NPRdXzhvna4uFdIiibPegGQXankxyxe0P7PnOhTkDGA
1874gBrbhgR9fX9bW1u8nRFamcgvVrACJIvlXV06nvtdgON4mdn3og7AagBTufkucO7snJz4b28XEhIT
1875sflynsLEvIk55kr866aewo2YuYDrnFffOTk6Li6hgAn3y8XkusCHZQbt0NP571lqRDZyMw96lZXE
1876s6qcrMmJaTmVdRW2AAAAbnRSTlMAZodsJHZocHN7hP77gnaCZWdx/ki+RfqOd/7+zc9N/szMZlf8
1877z8yeQybOzlv+tP5q/qKRbk78i/vZmf798s3MojiYjTj+/vqKbFc2/vvMzJiPXPzbs4z9++bj1XbN
1878uJxhyMBWwJbp28C9tJ6L1xTnMfMAAA79SURBVGje7Jn5b8thHMcfzLDWULXq2upqHT2kbrVSrJYx
1879NzHmviWOrCudqxhbNdZqHauKJTZHm0j0ByYkVBCTiC1+EH6YRBY/EJnjD3D84PMc3++39Z1rjp+8
1880Kn189rT5Pt/363k+3YHEDOrCSKP16t48q8U1IysLAUKZk1obLBYDKjAUoB8ziLv4vyQLQD+Lcf4Q
1881jvno90kfDaQTRhcioIv7QPk2oJqF0PsIT29RzQdOEhfKG6QW8lcoLIYxjWPQD2GXr/63BhYsWrQA
1882fYc0JSaNxa8dH4zUEYag32f009DTkNTnC4WkpcRAl4ryHTt37d5/ugxCIIEfZ0Dg4poFThIXygSp
1883hfybmhSWLS0dCpDrdFMRZubUkmJ2+d344qIU8sayN8iFQaBgMDy+FWA/wjelOmbrHUKVtQgxFqFc
1884JeE2RpmLEIlfFazzer3hcOAPCQiFasNheAo9HQ1f6FZRTgzs2bOnFwn8+AnG8d6impClTkSjCXWW
1885kH80GmUGWP6A4kKkQwG616/tOhin6kii3dzl5YHqT58+bf5KQdq8IjCAg3+tk3NDCoPZC2fQuGcI
18867+8nKQMk/b41r048UKOk48zln4MgesydOw0NDbeVCA2B+FVaEIDz/0MCSkOlAa+3tDRQSgW4t1MD
1887+7d1Q8DA9/sY7weKapZ/Qp+tzwYDtLyRiOrBANQ0/3hTMBIJNsXPb0GM5ANfrLO3telmTrWXGBG7
1888fHVHbWjetKKiPCJsAkQv17VNaANv6zJTWAcvmCEtI0hnII4RLsIIBIjmHStXaqKzNCtXOvj+STxl
1889OXKwgDuEBuAOEQDxgwDIv85bCwKMw6B5DzOyoVMCHpc+Dnu9gUD4MSeAGWACTnCBnxgorgGHRqPR
1890Z8OTg5ZqtRoEwLODy79JdfiwqgkMGBAlJ4caYK3HNGGCHedPBLgqtld30IbmLZk2jTsB9jadboJ9
1891Aj4BMqlAXCqV4e3udGH8zn6CgMrtQCUIoPMEbj5Xk3jS3N78UpPL7R81kJOTHdU7QACff/9kAbD/
1892IxHvEGTcmi/1+/NlMjJsNXZKAAcIoAkwA0zAvqOMfQNFNcOsf2BGAppotl6D+P0fi6nOnFHFYk1x
1893CzOgvqEGA4ICk91uQpQee90V1W58fdYDx0Ls+JnmTwy02e32iRNJB5L5X7y4/Pzq1buXX/lb/X4Z
1894SRtTo4C8uf6/Nez11dRI0pkNCswzA+Yn7e3NZi5/aKcYaKPqLBDw5iHPKGUutCAQoKqri0QizsgW
1895lJ6/1mqNK4C41bo2P72TnwEMEEASYAa29SCBHz1J2fdo4ExRTbHl5NiSBWQ/yGYCLBnFLbFY8PPn
1896YCzWUpxhYS9IJDSIx1iydKJpKTPQ0+lyV9MuCEcQJw+tH57Hjcubhyhy00TAJEdAuocX4Gn1eNJJ
1897wHG/xB+PQ8BC/6/0ejw1nAAJAeZ5A83tNH+kuaHHZD8A1MsRUvZ/c0WgPwhQBbGAiAQz2CjzZSJr
1898GOxKw1aU6ZOhX2ZK6GYZ42ZoChbgdDED5UzAWcLRR4+cA0U1ZfmiRcuRgJkIYIwBARThuyDzE7hf
1899nulLR5qKS5aWMAFOV7WrghjAAvKKpoEByH8J5C8WMELCC5AckkhGYCeS1lZfa6uf2/AuoM51yePB
1900DYrM18AD/sE8Z2DSJLaeLHNCr385C9iowbekfHOvQWBN4dzxXhUIuIRPgD+yCskWrs3MOETIyFy7
1901sFMC9roYe0EA2YLMwIGeCBh68iDh5P2TFUOhzhs3LammFC5YUIgEVmY/mKVJ4wTUx2JvP358G4vV
19028wLo/TKKl45cWgwaTNNx1b3M6TwNh5DuANJ7xk37Kv+RBDCAtzMvoPJUZSUVID116pTUw3ecyPZI
1903vHIzfEQXMAEeAszzpKUhoR81m4GVNnJHyocN/Xnu2NLmaj/CEVBdqvX5FArvXGTYoAhIaxUb2GDo
1904jAD3doabCeAMVFABZ6mAs/fP7sCBLykal1KjYemMYYhh2zgrWUBLi2r8eFVLiyDAlpS/ccXIkSXk
1905IJTIiYAy52l8COkOoAZE+ZtMzEA/p8ApJ/lcldX4fc98fn8Nt+Fhd/Lbnc4DdF68fjgNzZMQhQkQ
1906UKK52mAQC/D5fHVe6VyEDBlWqzXDwAbUGQEHdjAOgACcAGegojsRcPAY4eD9g7uGonl5S4oWL77G
190717D+fF/AewmzkDNQaG5v1+SmCtASAWKgAVWtKKD/w0egD/TC005igO2AsctAQB6/RU1VVVUmuZwM
1908CM3oJ2CB7+1xwPkeQj4TUOM5x/o/IJoXrR8MJAkY9ab/PZ41uZwAr88nBUDA7wICyncyypkAzoCb
1909CbhIgMCbh6K8d5jFfA3346qUePywmtrDfAdcrmmfZeMENNbXq7Taj/X1Hf8qYk7VxOlcMwIRfbt2
19107bq5jBqAHUANLFlmRBzyFVUr5NyQgoUdqcGZhMFGmrfUA5D+L57vcP25thQBArZCIkCl/eCF/IE5
19116PdZHzqwjXEgtB6+0KuMM+DuRQQcowKO3T/WjE/A4ndwAmhNBXjq4q1wyluLamWIN2Aebl4uCAhq
1912x2u/JUA+Z46Ri4aeBLYHYAEggBooSHmDXBgE1lnggcQU0LgLUMekrl+EclQSSgQCVFrVnFWTKav+
1913xAlY35Vn/RTSA4gB517X3j4IGMC1oOsHB8yEetm7xSl15kL4TVIAfjDxKjIRT6Ft0iQb3da3GhuD
1914QGPjrWL0E7AlsAX8ZUTr/xFzIP7pRvQ36SsI6Yvr+QN45uN607JlKbUhg8eAOgB2S4bFarVk/PyG
19156Sss4O/y4/WL7+avxS/+e8D/+ku31tKbRBSFXSg+6iOpMRiiLrQ7JUQ3vhIXKks36h/QhY+FIFJ8
1916pEkx7QwdxYUJjRC1mAEF0aK2WEActVVpUbE2mBYp1VofaGyibW19LDSeOxdm7jCDNI0rv0lIvp7v
1917nnPnHKaQ+zHV/sxcPlPZT5Hrp69SEVg1vdgP+C/58cOT00+5P2pKreynyPWr1s+Ff4EOOzpctTt2
1918rir2A/bdxPhSghfrt9TxcCVlcWU+r5NH+ukk9fu6MYZL1NtwA9De3n6/dD4GA/N1EYwRxXzl+7NL
1919i/FJUo9y0Mp+inw/Kgp9BwZz5wxArV5e7AfcNGDcLMGL9XXnEOpcAVlcmXe+QYAJTFLfbcDoLlGv
1920/QaeQKiwfusuH8BB5EMnfYcKPGLAiCjmK98frQFDK9kvNZdW9lPk96cySKAq9gOCxmBw7hd4LcGl
1921enQDBsOoAW5AFlfkMICnhqdvDJ3pSerDRje8/93GMM9xwwznhHowAINhCA0gz5f5MOxiviYG8K4F
1922XoBHjO6RkdNuY4TI9wFuoZBPFfd6vR6EOAIaQHV9vaO+sJ8Ek7gAF5OQ7JeqoJX9FPn9qYwSqIr9
1923gGB10BYMfqkOluBIr6Y7AHQz4q4667k6q8sVIOI4n5zjARjfGDtH0j1E/FoepP4dg+Nha/fwk+Fu
1924axj0uN650e+vxHqhG6YbptcmbSjPd13H8In5TRaU7+Ix4GgAI5Fx7qkxIuY7N54T86m89mba6WTZ
1925Do/H2+HhB3Cstra2sP9EdSIGV3VCcn+Umlb2U+T9UJmsBEyqYj+gzWJrg8vSVoIjPW3vWLjQY6fx
1926DXDcKOcKNBBxyFdTQ3KmSqOpauF5upPjuE4u3UPEhQGI66FhR4/iAYQfwGUNgx7Xq3v1anxUqBdq
1927j8WG7mlD/jzfcf0jf+0Q8s9saoJnYFBzkWHgrC9qjUS58RFrVMw3ynE5IZ/Km2lsZtmMF9p/544X
1928DcAEDwDAXo/iA5bEXd9dn2VAcr/qWlrZT5H7LSqrmYBVxfsBc5trTjbbeD+g7crNNuj4lTZYocSR
1929nqa99+97aBrxgKvV5WoNNDTgeMFfSCYJzmi2ATQtiKfTrZ2t6daeHiLeD81PpVLXiPVmaBgfD1eE
1930hy8Nwyvocb1X7tx4a7JQz98eg/8/sYQ/z3cXngDJfizm94feHzqMBsBFotFohIsK+Vw5t0vcv8pD
19310SzVjPvPdixH648eO1YLmIviUMp33Xc9FpLkp2i1sp8i91sqzRUEzJUgMNbQdrPZTtceBEHvlc+f
1932P/f2XumFFUoc6Z2Nnvu/4o1OxBsC7kAgl2s4T8RN1RPJ5ITIP22rulXVsi2LeE/aja6et4T+Zxja
1933/yOVEtfzDePjfRW2cF/YVtGH9LhebuPqBqGeP9QUCjVd97/M82U7fAg77EL+WU0Igy2DDDMLDeBS
1934JBq5xEWFfDl3MiDmq/R0wNvfy7efdd5BAzDWow8Bh6OerxdLDDgGHDE/eb9oAsp+itxvqaw4QaCi
1935Eh1HXz2DFGfOHp+FGo7RCyuUONI7nZ7MWNzpRLwhj/NE3GRKfp9Iilyv0XVpuqr0iPfk8ZbQj/2E
1936/v/4kQIu+BODhwYhjgaAN9oHeqV6L/0YLwv5tu7dAXCYJfthtg22tPA8yrUicFHlfDCATKYD+o/a
193774QBoPVHjuJnAOIwAAy/JD9Fk37K/auif0L6LRc38IfjNQRO8AOoYRthhuxJCyTY/wwjaKZpCS/4
1938BaBnG+NDQ/FGFvEt5zGSRNz4fSPgu8D1XTqdblCnR3zxW4yHhP7j2M/fT09dTgnr8w1DfFEfRhj0
1939SvXWvMTwYa7gb8yA97/unQ59F5oBJnsUI6KcDz0B0H/+7S8MwG6DR8Bhd6D4Jj9GQlqPogk/JZs9
1940K/gn5H40e7aL7oToUYAfYMvUnMw40Gkw4Q80O6XcLMRZFgYwxrKl4saJjabqjRMCf6QDdOkeldJ/
1941BfSnrvWLcWgYxGX6KfPswEKLZVL6yrgXvv6g9uMBoDic3B/9e36KLvDNS7TZ7K3sGdE/wfoqDQD9
1942NGG+9AmYL/MDRM5iLo9nqDEYAJWRx5U5o+3SaHRaplS8H+Faf78Yh4bJ8k2Vz24qgJldXj8/DkCf
1943wDy8fH/sdpujTD2KxhxM/ueA249E/wTru/Dfl05bPkeC5TI/QOAvbJjL47TnI8BDy+KlOJPV6bJM
1944yfg3wNf+r99KxafOibNu5IQvKKsv2x9lTtEFvmGlXq9/rFeL/gnWD2kB6KcwcpB+wP/IyeP2svqp
19459oeiCT9Fr1cL/gmp125aUc4P+B85iX+qJ/la0k/Ze0D0T0j93jXTpv0BYUGhQhdSooYAAAAASUVO
1946RK5CYII=',
1947 );
1948}