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