· 4 years ago · Aug 21, 2021, 01:30 PM
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 'fm_admin' => 'fm_admin',
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 sprintf('<h1>Root path "%s" not found!</h1>', fm_enc($root_path));
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, fm_enc($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, fm_enc($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 = strip_tags($_GET['new']); // remove unwanted characters from folder name
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', fm_enc($new)));
194 } elseif (fm_mkdir($path . '/' . $new, false) === $path . '/' . $new) {
195 fm_set_msg(sprintf('Folder <b>%s</b> already exists', fm_enc($new)), 'alert');
196 } else {
197 fm_set_msg(sprintf('Folder <b>%s</b> not created', fm_enc($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>', fm_enc($copy), fm_enc($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>', fm_enc($copy), fm_enc($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>', fm_enc($copy), fm_enc($msg_from)));
240 } else {
241 fm_set_msg(sprintf('Error while copying from <b>%s</b> to <b>%s</b>', fm_enc($copy), fm_enc($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>', fm_enc($old), fm_enc($new)));
330 } else {
331 fm_set_msg(sprintf('Error while renaming from <b>%s</b> to <b>%s</b>', fm_enc($old), fm_enc($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>', fm_enc($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', fm_enc($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_enc(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 $copy_files_enc = array_map('fm_enc', $copy_files);
653 ?>
654 <p class="break-word">Files: <b><?php echo implode('</b>, <b>', $copy_files_enc) ?></b></p>
655 <p class="break-word">Source folder: <?php echo fm_enc(fm_convert_win(FM_ROOT_PATH . '/' . FM_PATH)) ?><br>
656 <label for="inp_copy_to">Destination folder:</label>
657 <?php echo FM_ROOT_PATH ?>/<input name="copy_to" id="inp_copy_to" value="<?php echo fm_enc(FM_PATH) ?>">
658 </p>
659 <p><label><input type="checkbox" name="move" value="1"> Move</label></p>
660 <p>
661 <button class="btn"><i class="icon-apply"></i> Copy</button>
662 <b><a href="?p=<?php echo urlencode(FM_PATH) ?>"><i class="icon-cancel"></i> Cancel</a></b>
663 </p>
664 </form>
665 </div>
666 <?php
667 fm_show_footer();
668 exit;
669}
670
671// copy form
672if (isset($_GET['copy']) && !isset($_GET['finish'])) {
673 $copy = $_GET['copy'];
674 $copy = fm_clean_path($copy);
675 if ($copy == '' || !file_exists(FM_ROOT_PATH . '/' . $copy)) {
676 fm_set_msg('File not found', 'error');
677 fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH));
678 }
679
680 fm_show_header(); // HEADER
681 fm_show_nav_path(FM_PATH); // current path
682 ?>
683 <div class="path">
684 <p><b>Copying</b></p>
685 <p class="break-word">
686 Source path: <?php echo fm_enc(fm_convert_win(FM_ROOT_PATH . '/' . $copy)) ?><br>
687 Destination folder: <?php echo fm_enc(fm_convert_win(FM_ROOT_PATH . '/' . FM_PATH)) ?>
688 </p>
689 <p>
690 <b><a href="?p=<?php echo urlencode(FM_PATH) ?>&copy=<?php echo urlencode($copy) ?>&finish=1"><i class="icon-apply"></i> Copy</a></b>
691 <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>
692 <b><a href="?p=<?php echo urlencode(FM_PATH) ?>"><i class="icon-cancel"></i> Cancel</a></b>
693 </p>
694 <p><i>Select folder:</i></p>
695 <ul class="folders break-word">
696 <?php
697 if ($parent !== false) {
698 ?>
699 <li><a href="?p=<?php echo urlencode($parent) ?>&copy=<?php echo urlencode($copy) ?>"><i class="icon-arrow_up"></i> ..</a></li>
700 <?php
701 }
702 foreach ($folders as $f) {
703 ?>
704 <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>
705 <?php
706 }
707 ?>
708 </ul>
709 </div>
710 <?php
711 fm_show_footer();
712 exit;
713}
714
715// file viewer
716if (isset($_GET['view'])) {
717 $file = $_GET['view'];
718 $file = fm_clean_path($file);
719 $file = str_replace('/', '', $file);
720 if ($file == '' || !is_file($path . '/' . $file)) {
721 fm_set_msg('File not found', 'error');
722 fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH));
723 }
724
725 fm_show_header(); // HEADER
726 fm_show_nav_path(FM_PATH); // current path
727
728 $file_url = FM_ROOT_URL . fm_convert_win((FM_PATH != '' ? '/' . FM_PATH : '') . '/' . $file);
729 $file_path = $path . '/' . $file;
730
731 $ext = strtolower(pathinfo($file_path, PATHINFO_EXTENSION));
732 $mime_type = fm_get_mime_type($file_path);
733 $filesize = filesize($file_path);
734
735 $is_zip = false;
736 $is_image = false;
737 $is_audio = false;
738 $is_video = false;
739 $is_text = false;
740
741 $view_title = 'File';
742 $filenames = false; // for zip
743 $content = ''; // for text
744
745 if ($ext == 'zip') {
746 $is_zip = true;
747 $view_title = 'Archive';
748 $filenames = fm_get_zif_info($file_path);
749 } elseif (in_array($ext, fm_get_image_exts())) {
750 $is_image = true;
751 $view_title = 'Image';
752 } elseif (in_array($ext, fm_get_audio_exts())) {
753 $is_audio = true;
754 $view_title = 'Audio';
755 } elseif (in_array($ext, fm_get_video_exts())) {
756 $is_video = true;
757 $view_title = 'Video';
758 } elseif (in_array($ext, fm_get_text_exts()) || substr($mime_type, 0, 4) == 'text' || in_array($mime_type, fm_get_text_mimes())) {
759 $is_text = true;
760 $content = file_get_contents($file_path);
761 }
762
763 ?>
764 <div class="path">
765 <p class="break-word"><b><?php echo $view_title ?> "<?php echo fm_enc(fm_convert_win($file)) ?>"</b></p>
766 <p class="break-word">
767 Full path: <?php echo fm_enc(fm_convert_win($file_path)) ?><br>
768 File size: <?php echo fm_get_filesize($filesize) ?><?php if ($filesize >= 1000): ?> (<?php echo sprintf('%s bytes', $filesize) ?>)<?php endif; ?><br>
769 MIME-type: <?php echo $mime_type ?><br>
770 <?php
771 // ZIP info
772 if ($is_zip && $filenames !== false) {
773 $total_files = 0;
774 $total_comp = 0;
775 $total_uncomp = 0;
776 foreach ($filenames as $fn) {
777 if (!$fn['folder']) {
778 $total_files++;
779 }
780 $total_comp += $fn['compressed_size'];
781 $total_uncomp += $fn['filesize'];
782 }
783 ?>
784 Files in archive: <?php echo $total_files ?><br>
785 Total size: <?php echo fm_get_filesize($total_uncomp) ?><br>
786 Size in archive: <?php echo fm_get_filesize($total_comp) ?><br>
787 Compression: <?php echo round(($total_comp / $total_uncomp) * 100) ?>%<br>
788 <?php
789 }
790 // Image info
791 if ($is_image) {
792 $image_size = getimagesize($file_path);
793 echo 'Image sizes: ' . (isset($image_size[0]) ? $image_size[0] : '0') . ' x ' . (isset($image_size[1]) ? $image_size[1] : '0') . '<br>';
794 }
795 // Text info
796 if ($is_text) {
797 $is_utf8 = fm_is_utf8($content);
798 if (function_exists('iconv')) {
799 if (!$is_utf8) {
800 $content = iconv(FM_ICONV_INPUT_ENC, 'UTF-8//IGNORE', $content);
801 }
802 }
803 echo 'Charset: ' . ($is_utf8 ? 'utf-8' : '8 bit') . '<br>';
804 }
805 ?>
806 </p>
807 <p>
808 <b><a href="?p=<?php echo urlencode(FM_PATH) ?>&dl=<?php echo urlencode($file) ?>"><i class="icon-download"></i> Download</a></b>
809 <b><a href="<?php echo fm_enc($file_url) ?>" target="_blank"><i class="icon-chain"></i> Open</a></b>
810 <?php
811 // ZIP actions
812 if ($is_zip && $filenames !== false) {
813 $zip_name = pathinfo($file_path, PATHINFO_FILENAME);
814 ?>
815 <b><a href="?p=<?php echo urlencode(FM_PATH) ?>&unzip=<?php echo urlencode($file) ?>"><i class="icon-apply"></i> Unpack</a></b>
816 <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>
817 Unpack to folder</a></b>
818 <?php
819 }
820 ?>
821 <b><a href="?p=<?php echo urlencode(FM_PATH) ?>"><i class="icon-goback"></i> Back</a></b>
822 </p>
823 <?php
824 if ($is_zip) {
825 // ZIP content
826 if ($filenames !== false) {
827 echo '<code class="maxheight">';
828 foreach ($filenames as $fn) {
829 if ($fn['folder']) {
830 echo '<b>' . fm_enc($fn['name']) . '</b><br>';
831 } else {
832 echo $fn['name'] . ' (' . fm_get_filesize($fn['filesize']) . ')<br>';
833 }
834 }
835 echo '</code>';
836 } else {
837 echo '<p>Error while fetching archive info</p>';
838 }
839 } elseif ($is_image) {
840 // Image content
841 if (in_array($ext, array('gif', 'jpg', 'jpeg', 'png', 'bmp', 'ico'))) {
842 echo '<p><img src="' . fm_enc($file_url) . '" alt="" class="preview-img"></p>';
843 }
844 } elseif ($is_audio) {
845 // Audio content
846 echo '<p><audio src="' . fm_enc($file_url) . '" controls preload="metadata"></audio></p>';
847 } elseif ($is_video) {
848 // Video content
849 echo '<div class="preview-video"><video src="' . fm_enc($file_url) . '" width="640" height="360" controls preload="metadata"></video></div>';
850 } elseif ($is_text) {
851 if (FM_USE_HIGHLIGHTJS) {
852 // highlight
853 $hljs_classes = array(
854 'shtml' => 'xml',
855 'htaccess' => 'apache',
856 'phtml' => 'php',
857 'lock' => 'json',
858 'svg' => 'xml',
859 );
860 $hljs_class = isset($hljs_classes[$ext]) ? 'lang-' . $hljs_classes[$ext] : 'lang-' . $ext;
861 if (empty($ext) || in_array(strtolower($file), fm_get_text_names()) || preg_match('#\.min\.(css|js)$#i', $file)) {
862 $hljs_class = 'nohighlight';
863 }
864 $content = '<pre class="with-hljs"><code class="' . $hljs_class . '">' . fm_enc($content) . '</code></pre>';
865 } elseif (in_array($ext, array('php', 'php4', 'php5', 'phtml', 'phps'))) {
866 // php highlight
867 $content = highlight_string($content, true);
868 } else {
869 $content = '<pre>' . fm_enc($content) . '</pre>';
870 }
871 echo $content;
872 }
873 ?>
874 </div>
875 <?php
876 fm_show_footer();
877 exit;
878}
879
880// chmod (not for Windows)
881if (isset($_GET['chmod']) && !FM_IS_WIN) {
882 $file = $_GET['chmod'];
883 $file = fm_clean_path($file);
884 $file = str_replace('/', '', $file);
885 if ($file == '' || (!is_file($path . '/' . $file) && !is_dir($path . '/' . $file))) {
886 fm_set_msg('File not found', 'error');
887 fm_redirect(FM_SELF_URL . '?p=' . urlencode(FM_PATH));
888 }
889
890 fm_show_header(); // HEADER
891 fm_show_nav_path(FM_PATH); // current path
892
893 $file_url = FM_ROOT_URL . (FM_PATH != '' ? '/' . FM_PATH : '') . '/' . $file;
894 $file_path = $path . '/' . $file;
895
896 $mode = fileperms($path . '/' . $file);
897
898 ?>
899 <div class="path">
900 <p><b>Change Permissions</b></p>
901 <p>
902 Full path: <?php echo fm_enc($file_path) ?><br>
903 </p>
904 <form action="" method="post">
905 <input type="hidden" name="p" value="<?php echo fm_enc(FM_PATH) ?>">
906 <input type="hidden" name="chmod" value="<?php echo fm_enc($file) ?>">
907
908 <table class="compact-table">
909 <tr>
910 <td></td>
911 <td><b>Owner</b></td>
912 <td><b>Group</b></td>
913 <td><b>Other</b></td>
914 </tr>
915 <tr>
916 <td style="text-align: right"><b>Read</b></td>
917 <td><label><input type="checkbox" name="ur" value="1"<?php echo ($mode & 00400) ? ' checked' : '' ?>></label></td>
918 <td><label><input type="checkbox" name="gr" value="1"<?php echo ($mode & 00040) ? ' checked' : '' ?>></label></td>
919 <td><label><input type="checkbox" name="or" value="1"<?php echo ($mode & 00004) ? ' checked' : '' ?>></label></td>
920 </tr>
921 <tr>
922 <td style="text-align: right"><b>Write</b></td>
923 <td><label><input type="checkbox" name="uw" value="1"<?php echo ($mode & 00200) ? ' checked' : '' ?>></label></td>
924 <td><label><input type="checkbox" name="gw" value="1"<?php echo ($mode & 00020) ? ' checked' : '' ?>></label></td>
925 <td><label><input type="checkbox" name="ow" value="1"<?php echo ($mode & 00002) ? ' checked' : '' ?>></label></td>
926 </tr>
927 <tr>
928 <td style="text-align: right"><b>Execute</b></td>
929 <td><label><input type="checkbox" name="ux" value="1"<?php echo ($mode & 00100) ? ' checked' : '' ?>></label></td>
930 <td><label><input type="checkbox" name="gx" value="1"<?php echo ($mode & 00010) ? ' checked' : '' ?>></label></td>
931 <td><label><input type="checkbox" name="ox" value="1"<?php echo ($mode & 00001) ? ' checked' : '' ?>></label></td>
932 </tr>
933 </table>
934
935 <p>
936 <button class="btn"><i class="icon-apply"></i> Change</button>
937 <b><a href="?p=<?php echo urlencode(FM_PATH) ?>"><i class="icon-cancel"></i> Cancel</a></b>
938 </p>
939
940 </form>
941
942 </div>
943 <?php
944 fm_show_footer();
945 exit;
946}
947
948//--- FILEMANAGER MAIN
949fm_show_header(); // HEADER
950fm_show_nav_path(FM_PATH); // current path
951
952// messages
953fm_show_message();
954
955$num_files = count($files);
956$num_folders = count($folders);
957$all_files_size = 0;
958?>
959<form action="" method="post">
960<input type="hidden" name="p" value="<?php echo fm_enc(FM_PATH) ?>">
961<input type="hidden" name="group" value="1">
962<table><tr>
963<th style="width:3%"><label><input type="checkbox" title="Invert selection" onclick="checkbox_toggle()"></label></th>
964<th>Name</th><th style="width:10%">Size</th>
965<th style="width:12%">Modified</th>
966<?php if (!FM_IS_WIN): ?><th style="width:6%">Perms</th><th style="width:10%">Owner</th><?php endif; ?>
967<th style="width:13%"></th></tr>
968<?php
969// link to parent folder
970if ($parent !== false) {
971 ?>
972<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>
973<?php
974}
975foreach ($folders as $f) {
976 $is_link = is_link($path . '/' . $f);
977 $img = $is_link ? 'icon-link_folder' : 'icon-folder';
978 $modif = date(FM_DATETIME_FORMAT, filemtime($path . '/' . $f));
979 $perms = substr(decoct(fileperms($path . '/' . $f)), -4);
980 if (function_exists('posix_getpwuid') && function_exists('posix_getgrgid')) {
981 $owner = posix_getpwuid(fileowner($path . '/' . $f));
982 $group = posix_getgrgid(filegroup($path . '/' . $f));
983 } else {
984 $owner = array('name' => '?');
985 $group = array('name' => '?');
986 }
987 ?>
988<tr>
989<td><label><input type="checkbox" name="file[]" value="<?php echo fm_enc($f) ?>"></label></td>
990<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>
991<td>Folder</td><td><?php echo $modif ?></td>
992<?php if (!FM_IS_WIN): ?>
993<td><a title="Change Permissions" href="?p=<?php echo urlencode(FM_PATH) ?>&chmod=<?php echo urlencode($f) ?>"><?php echo $perms ?></a></td>
994<td><?php echo fm_enc($owner['name'] . ':' . $group['name']) ?></td>
995<?php endif; ?>
996<td>
997<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>
998<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>
999<a title="Copy to..." href="?p=&copy=<?php echo urlencode(trim(FM_PATH . '/' . $f, '/')) ?>"><i class="icon-copy"></i></a>
1000<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>
1001</td></tr>
1002 <?php
1003 flush();
1004}
1005
1006foreach ($files as $f) {
1007 $is_link = is_link($path . '/' . $f);
1008 $img = $is_link ? 'icon-link_file' : fm_get_file_icon_class($path . '/' . $f);
1009 $modif = date(FM_DATETIME_FORMAT, filemtime($path . '/' . $f));
1010 $filesize_raw = filesize($path . '/' . $f);
1011 $filesize = fm_get_filesize($filesize_raw);
1012 $filelink = '?p=' . urlencode(FM_PATH) . '&view=' . urlencode($f);
1013 $all_files_size += $filesize_raw;
1014 $perms = substr(decoct(fileperms($path . '/' . $f)), -4);
1015 if (function_exists('posix_getpwuid') && function_exists('posix_getgrgid')) {
1016 $owner = posix_getpwuid(fileowner($path . '/' . $f));
1017 $group = posix_getgrgid(filegroup($path . '/' . $f));
1018 } else {
1019 $owner = array('name' => '?');
1020 $group = array('name' => '?');
1021 }
1022 ?>
1023<tr>
1024<td><label><input type="checkbox" name="file[]" value="<?php echo fm_enc($f) ?>"></label></td>
1025<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>
1026<td><span class="gray" title="<?php printf('%s bytes', $filesize_raw) ?>"><?php echo $filesize ?></span></td>
1027<td><?php echo $modif ?></td>
1028<?php if (!FM_IS_WIN): ?>
1029<td><a title="Change Permissions" href="?p=<?php echo urlencode(FM_PATH) ?>&chmod=<?php echo urlencode($f) ?>"><?php echo $perms ?></a></td>
1030<td><?php echo fm_enc($owner['name'] . ':' . $group['name']) ?></td>
1031<?php endif; ?>
1032<td>
1033<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>
1034<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>
1035<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>
1036<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>
1037<a title="Download" href="?p=<?php echo urlencode(FM_PATH) ?>&dl=<?php echo urlencode($f) ?>"><i class="icon-download"></i></a>
1038</td></tr>
1039 <?php
1040 flush();
1041}
1042
1043if (empty($folders) && empty($files)) {
1044 ?>
1045<tr><td></td><td colspan="<?php echo !FM_IS_WIN ? '6' : '4' ?>"><em>Folder is empty</em></td></tr>
1046<?php
1047} else {
1048 ?>
1049<tr><td class="gray"></td><td class="gray" colspan="<?php echo !FM_IS_WIN ? '6' : '4' ?>">
1050Full size: <span title="<?php printf('%s bytes', $all_files_size) ?>"><?php echo fm_get_filesize($all_files_size) ?></span>,
1051files: <?php echo $num_files ?>,
1052folders: <?php echo $num_folders ?>
1053</td></tr>
1054<?php
1055}
1056?>
1057</table>
1058<p class="path"><a href="#" onclick="select_all();return false;"><i class="icon-checkbox"></i> Select all</a>
1059<a href="#" onclick="unselect_all();return false;"><i class="icon-checkbox_uncheck"></i> Unselect all</a>
1060<a href="#" onclick="invert_all();return false;"><i class="icon-checkbox_invert"></i> Invert selection</a></p>
1061<p><input type="submit" name="delete" value="Delete" onclick="return confirm('Delete selected files and folders?')">
1062<input type="submit" name="zip" value="Pack" onclick="return confirm('Create archive?')">
1063<input type="submit" name="copy" value="Copy"></p>
1064</form>
1065
1066<?php
1067fm_show_footer();
1068
1069//--- END
1070
1071// Functions
1072
1073/**
1074 * Delete file or folder (recursively)
1075 * @param string $path
1076 * @return bool
1077 */
1078function fm_rdelete($path)
1079{
1080 if (is_link($path)) {
1081 return unlink($path);
1082 } elseif (is_dir($path)) {
1083 $objects = scandir($path);
1084 $ok = true;
1085 if (is_array($objects)) {
1086 foreach ($objects as $file) {
1087 if ($file != '.' && $file != '..') {
1088 if (!fm_rdelete($path . '/' . $file)) {
1089 $ok = false;
1090 }
1091 }
1092 }
1093 }
1094 return ($ok) ? rmdir($path) : false;
1095 } elseif (is_file($path)) {
1096 return unlink($path);
1097 }
1098 return false;
1099}
1100
1101/**
1102 * Recursive chmod
1103 * @param string $path
1104 * @param int $filemode
1105 * @param int $dirmode
1106 * @return bool
1107 * @todo Will use in mass chmod
1108 */
1109function fm_rchmod($path, $filemode, $dirmode)
1110{
1111 if (is_dir($path)) {
1112 if (!chmod($path, $dirmode)) {
1113 return false;
1114 }
1115 $objects = scandir($path);
1116 if (is_array($objects)) {
1117 foreach ($objects as $file) {
1118 if ($file != '.' && $file != '..') {
1119 if (!fm_rchmod($path . '/' . $file, $filemode, $dirmode)) {
1120 return false;
1121 }
1122 }
1123 }
1124 }
1125 return true;
1126 } elseif (is_link($path)) {
1127 return true;
1128 } elseif (is_file($path)) {
1129 return chmod($path, $filemode);
1130 }
1131 return false;
1132}
1133
1134/**
1135 * Safely rename
1136 * @param string $old
1137 * @param string $new
1138 * @return bool|null
1139 */
1140function fm_rename($old, $new)
1141{
1142 return (!file_exists($new) && file_exists($old)) ? rename($old, $new) : null;
1143}
1144
1145/**
1146 * Copy file or folder (recursively).
1147 * @param string $path
1148 * @param string $dest
1149 * @param bool $upd Update files
1150 * @param bool $force Create folder with same names instead file
1151 * @return bool
1152 */
1153function fm_rcopy($path, $dest, $upd = true, $force = true)
1154{
1155 if (is_dir($path)) {
1156 if (!fm_mkdir($dest, $force)) {
1157 return false;
1158 }
1159 $objects = scandir($path);
1160 $ok = true;
1161 if (is_array($objects)) {
1162 foreach ($objects as $file) {
1163 if ($file != '.' && $file != '..') {
1164 if (!fm_rcopy($path . '/' . $file, $dest . '/' . $file)) {
1165 $ok = false;
1166 }
1167 }
1168 }
1169 }
1170 return $ok;
1171 } elseif (is_file($path)) {
1172 return fm_copy($path, $dest, $upd);
1173 }
1174 return false;
1175}
1176
1177/**
1178 * Safely create folder
1179 * @param string $dir
1180 * @param bool $force
1181 * @return bool
1182 */
1183function fm_mkdir($dir, $force)
1184{
1185 if (file_exists($dir)) {
1186 if (is_dir($dir)) {
1187 return $dir;
1188 } elseif (!$force) {
1189 return false;
1190 }
1191 unlink($dir);
1192 }
1193 return mkdir($dir, 0777, true);
1194}
1195
1196/**
1197 * Safely copy file
1198 * @param string $f1
1199 * @param string $f2
1200 * @param bool $upd
1201 * @return bool
1202 */
1203function fm_copy($f1, $f2, $upd)
1204{
1205 $time1 = filemtime($f1);
1206 if (file_exists($f2)) {
1207 $time2 = filemtime($f2);
1208 if ($time2 >= $time1 && $upd) {
1209 return false;
1210 }
1211 }
1212 $ok = copy($f1, $f2);
1213 if ($ok) {
1214 touch($f2, $time1);
1215 }
1216 return $ok;
1217}
1218
1219/**
1220 * Get mime type
1221 * @param string $file_path
1222 * @return mixed|string
1223 */
1224function fm_get_mime_type($file_path)
1225{
1226 if (function_exists('finfo_open')) {
1227 $finfo = finfo_open(FILEINFO_MIME_TYPE);
1228 $mime = finfo_file($finfo, $file_path);
1229 finfo_close($finfo);
1230 return $mime;
1231 } elseif (function_exists('mime_content_type')) {
1232 return mime_content_type($file_path);
1233 } elseif (!stristr(ini_get('disable_functions'), 'shell_exec')) {
1234 $file = escapeshellarg($file_path);
1235 $mime = shell_exec('file -bi ' . $file);
1236 return $mime;
1237 } else {
1238 return '--';
1239 }
1240}
1241
1242/**
1243 * HTTP Redirect
1244 * @param string $url
1245 * @param int $code
1246 */
1247function fm_redirect($url, $code = 302)
1248{
1249 header('Location: ' . $url, true, $code);
1250 exit;
1251}
1252
1253/**
1254 * Clean path
1255 * @param string $path
1256 * @return string
1257 */
1258function fm_clean_path($path)
1259{
1260 $path = trim($path);
1261 $path = trim($path, '\\/');
1262 $path = str_replace(array('../', '..\\'), '', $path);
1263 if ($path == '..') {
1264 $path = '';
1265 }
1266 return str_replace('\\', '/', $path);
1267}
1268
1269/**
1270 * Get parent path
1271 * @param string $path
1272 * @return bool|string
1273 */
1274function fm_get_parent_path($path)
1275{
1276 $path = fm_clean_path($path);
1277 if ($path != '') {
1278 $array = explode('/', $path);
1279 if (count($array) > 1) {
1280 $array = array_slice($array, 0, -1);
1281 return implode('/', $array);
1282 }
1283 return '';
1284 }
1285 return false;
1286}
1287
1288/**
1289 * Get nice filesize
1290 * @param int $size
1291 * @return string
1292 */
1293function fm_get_filesize($size)
1294{
1295 if ($size < 1000) {
1296 return sprintf('%s B', $size);
1297 } elseif (($size / 1024) < 1000) {
1298 return sprintf('%s KiB', round(($size / 1024), 2));
1299 } elseif (($size / 1024 / 1024) < 1000) {
1300 return sprintf('%s MiB', round(($size / 1024 / 1024), 2));
1301 } elseif (($size / 1024 / 1024 / 1024) < 1000) {
1302 return sprintf('%s GiB', round(($size / 1024 / 1024 / 1024), 2));
1303 } else {
1304 return sprintf('%s TiB', round(($size / 1024 / 1024 / 1024 / 1024), 2));
1305 }
1306}
1307
1308/**
1309 * Get info about zip archive
1310 * @param string $path
1311 * @return array|bool
1312 */
1313function fm_get_zif_info($path)
1314{
1315 if (function_exists('zip_open')) {
1316 $arch = zip_open($path);
1317 if ($arch) {
1318 $filenames = array();
1319 while ($zip_entry = zip_read($arch)) {
1320 $zip_name = zip_entry_name($zip_entry);
1321 $zip_folder = substr($zip_name, -1) == '/';
1322 $filenames[] = array(
1323 'name' => $zip_name,
1324 'filesize' => zip_entry_filesize($zip_entry),
1325 'compressed_size' => zip_entry_compressedsize($zip_entry),
1326 'folder' => $zip_folder
1327 //'compression_method' => zip_entry_compressionmethod($zip_entry),
1328 );
1329 }
1330 zip_close($arch);
1331 return $filenames;
1332 }
1333 }
1334 return false;
1335}
1336
1337/**
1338 * Encode html entities
1339 * @param string $text
1340 * @return string
1341 */
1342function fm_enc($text)
1343{
1344 return htmlspecialchars($text, ENT_QUOTES, 'UTF-8');
1345}
1346
1347/**
1348 * Save message in session
1349 * @param string $msg
1350 * @param string $status
1351 */
1352function fm_set_msg($msg, $status = 'ok')
1353{
1354 $_SESSION['message'] = $msg;
1355 $_SESSION['status'] = $status;
1356}
1357
1358/**
1359 * Check if string is in UTF-8
1360 * @param string $string
1361 * @return int
1362 */
1363function fm_is_utf8($string)
1364{
1365 return preg_match('//u', $string);
1366}
1367
1368/**
1369 * Convert file name to UTF-8 in Windows
1370 * @param string $filename
1371 * @return string
1372 */
1373function fm_convert_win($filename)
1374{
1375 if (FM_IS_WIN && function_exists('iconv')) {
1376 $filename = iconv(FM_ICONV_INPUT_ENC, 'UTF-8//IGNORE', $filename);
1377 }
1378 return $filename;
1379}
1380
1381/**
1382 * Get CSS classname for file
1383 * @param string $path
1384 * @return string
1385 */
1386function fm_get_file_icon_class($path)
1387{
1388 // get extension
1389 $ext = strtolower(pathinfo($path, PATHINFO_EXTENSION));
1390
1391 switch ($ext) {
1392 case 'ico': case 'gif': case 'jpg': case 'jpeg': case 'jpc': case 'jp2':
1393 case 'jpx': case 'xbm': case 'wbmp': case 'png': case 'bmp': case 'tif':
1394 case 'tiff':
1395 $img = 'icon-file_image';
1396 break;
1397 case 'txt': case 'css': case 'ini': case 'conf': case 'log': case 'htaccess':
1398 case 'passwd': case 'ftpquota': case 'sql': case 'js': case 'json': case 'sh':
1399 case 'config': case 'twig': case 'tpl': case 'md': case 'gitignore':
1400 case 'less': case 'sass': case 'scss': case 'c': case 'cpp': case 'cs': case 'py':
1401 case 'map': case 'lock': case 'dtd':
1402 $img = 'icon-file_text';
1403 break;
1404 case 'zip': case 'rar': case 'gz': case 'tar': case '7z':
1405 $img = 'icon-file_zip';
1406 break;
1407 case 'php': case 'php4': case 'php5': case 'phps': case 'phtml':
1408 $img = 'icon-file_php';
1409 break;
1410 case 'htm': case 'html': case 'shtml': case 'xhtml':
1411 $img = 'icon-file_html';
1412 break;
1413 case 'xml': case 'xsl': case 'svg':
1414 $img = 'icon-file_code';
1415 break;
1416 case 'wav': case 'mp3': case 'mp2': case 'm4a': case 'aac': case 'ogg':
1417 case 'oga': case 'wma': case 'mka': case 'flac': case 'ac3': case 'tds':
1418 $img = 'icon-file_music';
1419 break;
1420 case 'm3u': case 'm3u8': case 'pls': case 'cue':
1421 $img = 'icon-file_playlist';
1422 break;
1423 case 'avi': case 'mpg': case 'mpeg': case 'mp4': case 'm4v': case 'flv':
1424 case 'f4v': case 'ogm': case 'ogv': case 'mov': case 'mkv': case '3gp':
1425 case 'asf': case 'wmv':
1426 $img = 'icon-file_film';
1427 break;
1428 case 'eml': case 'msg':
1429 $img = 'icon-file_outlook';
1430 break;
1431 case 'xls': case 'xlsx':
1432 $img = 'icon-file_excel';
1433 break;
1434 case 'csv':
1435 $img = 'icon-file_csv';
1436 break;
1437 case 'doc': case 'docx':
1438 $img = 'icon-file_word';
1439 break;
1440 case 'ppt': case 'pptx':
1441 $img = 'icon-file_powerpoint';
1442 break;
1443 case 'ttf': case 'ttc': case 'otf': case 'woff':case 'woff2': case 'eot': case 'fon':
1444 $img = 'icon-file_font';
1445 break;
1446 case 'pdf':
1447 $img = 'icon-file_pdf';
1448 break;
1449 case 'psd':
1450 $img = 'icon-file_photoshop';
1451 break;
1452 case 'ai': case 'eps':
1453 $img = 'icon-file_illustrator';
1454 break;
1455 case 'fla':
1456 $img = 'icon-file_flash';
1457 break;
1458 case 'swf':
1459 $img = 'icon-file_swf';
1460 break;
1461 case 'exe': case 'msi':
1462 $img = 'icon-file_application';
1463 break;
1464 case 'bat':
1465 $img = 'icon-file_terminal';
1466 break;
1467 default:
1468 $img = 'icon-document';
1469 }
1470
1471 return $img;
1472}
1473
1474/**
1475 * Get image files extensions
1476 * @return array
1477 */
1478function fm_get_image_exts()
1479{
1480 return array('ico', 'gif', 'jpg', 'jpeg', 'jpc', 'jp2', 'jpx', 'xbm', 'wbmp', 'png', 'bmp', 'tif', 'tiff', 'psd');
1481}
1482
1483/**
1484 * Get video files extensions
1485 * @return array
1486 */
1487function fm_get_video_exts()
1488{
1489 return array('webm', 'mp4', 'm4v', 'ogm', 'ogv', 'mov');
1490}
1491
1492/**
1493 * Get audio files extensions
1494 * @return array
1495 */
1496function fm_get_audio_exts()
1497{
1498 return array('wav', 'mp3', 'ogg', 'm4a');
1499}
1500
1501/**
1502 * Get text file extensions
1503 * @return array
1504 */
1505function fm_get_text_exts()
1506{
1507 return array(
1508 'txt', 'css', 'ini', 'conf', 'log', 'htaccess', 'passwd', 'ftpquota', 'sql', 'js', 'json', 'sh', 'config',
1509 'php', 'php4', 'php5', 'phps', 'phtml', 'htm', 'html', 'shtml', 'xhtml', 'xml', 'xsl', 'm3u', 'm3u8', 'pls', 'cue',
1510 'eml', 'msg', 'csv', 'bat', 'twig', 'tpl', 'md', 'gitignore', 'less', 'sass', 'scss', 'c', 'cpp', 'cs', 'py',
1511 'map', 'lock', 'dtd', 'svg',
1512 );
1513}
1514
1515/**
1516 * Get mime types of text files
1517 * @return array
1518 */
1519function fm_get_text_mimes()
1520{
1521 return array(
1522 'application/xml',
1523 'application/javascript',
1524 'application/x-javascript',
1525 'image/svg+xml',
1526 'message/rfc822',
1527 );
1528}
1529
1530/**
1531 * Get file names of text files w/o extensions
1532 * @return array
1533 */
1534function fm_get_text_names()
1535{
1536 return array(
1537 'license',
1538 'readme',
1539 'authors',
1540 'contributors',
1541 'changelog',
1542 );
1543}
1544
1545/**
1546 * Class to work with zip files (using ZipArchive)
1547 */
1548class FM_Zipper
1549{
1550 private $zip;
1551
1552 public function __construct()
1553 {
1554 $this->zip = new ZipArchive();
1555 }
1556
1557 /**
1558 * Create archive with name $filename and files $files (RELATIVE PATHS!)
1559 * @param string $filename
1560 * @param array|string $files
1561 * @return bool
1562 */
1563 public function create($filename, $files)
1564 {
1565 $res = $this->zip->open($filename, ZipArchive::CREATE);
1566 if ($res !== true) {
1567 return false;
1568 }
1569 if (is_array($files)) {
1570 foreach ($files as $f) {
1571 if (!$this->addFileOrDir($f)) {
1572 $this->zip->close();
1573 return false;
1574 }
1575 }
1576 $this->zip->close();
1577 return true;
1578 } else {
1579 if ($this->addFileOrDir($files)) {
1580 $this->zip->close();
1581 return true;
1582 }
1583 return false;
1584 }
1585 }
1586
1587 /**
1588 * Extract archive $filename to folder $path (RELATIVE OR ABSOLUTE PATHS)
1589 * @param string $filename
1590 * @param string $path
1591 * @return bool
1592 */
1593 public function unzip($filename, $path)
1594 {
1595 $res = $this->zip->open($filename);
1596 if ($res !== true) {
1597 return false;
1598 }
1599 if ($this->zip->extractTo($path)) {
1600 $this->zip->close();
1601 return true;
1602 }
1603 return false;
1604 }
1605
1606 /**
1607 * Add file/folder to archive
1608 * @param string $filename
1609 * @return bool
1610 */
1611 private function addFileOrDir($filename)
1612 {
1613 if (is_file($filename)) {
1614 return $this->zip->addFile($filename);
1615 } elseif (is_dir($filename)) {
1616 return $this->addDir($filename);
1617 }
1618 return false;
1619 }
1620
1621 /**
1622 * Add folder recursively
1623 * @param string $path
1624 * @return bool
1625 */
1626 private function addDir($path)
1627 {
1628 if (!$this->zip->addEmptyDir($path)) {
1629 return false;
1630 }
1631 $objects = scandir($path);
1632 if (is_array($objects)) {
1633 foreach ($objects as $file) {
1634 if ($file != '.' && $file != '..') {
1635 if (is_dir($path . '/' . $file)) {
1636 if (!$this->addDir($path . '/' . $file)) {
1637 return false;
1638 }
1639 } elseif (is_file($path . '/' . $file)) {
1640 if (!$this->zip->addFile($path . '/' . $file)) {
1641 return false;
1642 }
1643 }
1644 }
1645 }
1646 return true;
1647 }
1648 return false;
1649 }
1650}
1651
1652//--- templates functions
1653
1654/**
1655 * Show nav block
1656 * @param string $path
1657 */
1658function fm_show_nav_path($path)
1659{
1660 ?>
1661<div class="path">
1662<div class="float-right">
1663<a title="Upload files" href="?p=<?php echo urlencode(FM_PATH) ?>&upload"><i class="icon-upload"></i></a>
1664<a title="New folder" href="#" onclick="newfolder('<?php echo fm_enc(FM_PATH) ?>');return false;"><i class="icon-folder_add"></i></a>
1665<?php if (FM_USE_AUTH): ?><a title="Logout" href="?logout=1"><i class="icon-logout"></i></a><?php endif; ?>
1666</div>
1667 <?php
1668 $path = fm_clean_path($path);
1669 $root_url = "<a href='?p='><i class='icon-home' title='" . FM_ROOT_PATH . "'></i></a>";
1670 $sep = '<i class="icon-separator"></i>';
1671 if ($path != '') {
1672 $exploded = explode('/', $path);
1673 $count = count($exploded);
1674 $array = array();
1675 $parent = '';
1676 for ($i = 0; $i < $count; $i++) {
1677 $parent = trim($parent . '/' . $exploded[$i], '/');
1678 $parent_enc = urlencode($parent);
1679 $array[] = "<a href='?p={$parent_enc}'>" . fm_enc(fm_convert_win($exploded[$i])) . "</a>";
1680 }
1681 $root_url .= $sep . implode($sep, $array);
1682 }
1683 echo '<div class="break-word">' . $root_url . '</div>';
1684 ?>
1685</div>
1686<?php
1687}
1688
1689/**
1690 * Show message from session
1691 */
1692function fm_show_message()
1693{
1694 if (isset($_SESSION['message'])) {
1695 $class = isset($_SESSION['status']) ? $_SESSION['status'] : 'ok';
1696 echo '<p class="message ' . $class . '">' . $_SESSION['message'] . '</p>';
1697 unset($_SESSION['message']);
1698 unset($_SESSION['status']);
1699 }
1700}
1701
1702/**
1703 * Show page header
1704 */
1705function fm_show_header()
1706{
1707 $sprites_ver = '20160315';
1708 header("Content-Type: text/html; charset=utf-8");
1709 header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");
1710 header("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
1711 header("Pragma: no-cache");
1712 ?>
1713<!DOCTYPE html>
1714<html>
1715<head>
1716<meta charset="utf-8">
1717<title>PHP File Manager</title>
1718<style>
1719html,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}
1720html{overflow-y:scroll}body{padding:0;font:13px/16px Tahoma,Arial,sans-serif;color:#222;background:#efefef}
1721input,select,textarea,button{font-size:inherit;font-family:inherit}
1722a{color:#296ea3;text-decoration:none}a:hover{color:#b00}img{vertical-align:middle;border:none}
1723a img{border:none}span.gray{color:#777}small{font-size:11px;color:#999}p{margin-bottom:10px}
1724ul{margin-left:2em;margin-bottom:10px}ul{list-style-type:none;margin-left:0}ul li{padding:3px 0}
1725table{border-collapse:collapse;border-spacing:0;margin-bottom:10px;width:100%}
1726th,td{padding:4px 7px;text-align:left;vertical-align:top;border:1px solid #ddd;background:#fff;white-space:nowrap}
1727th,td.gray{background-color:#eee}td.gray span{color:#222}
1728tr:hover td{background-color:#f5f5f5}tr:hover td.gray{background-color:#eee}
1729code,pre{display:block;margin-bottom:10px;font:13px/16px Consolas,'Courier New',Courier,monospace;border:1px dashed #ccc;padding:5px;overflow:auto}
1730pre.with-hljs{padding:0}
1731pre.with-hljs code{margin:0;border:0;overflow:visible}
1732code.maxheight,pre.maxheight{max-height:512px}input[type="checkbox"]{margin:0;padding:0}
1733#wrapper{max-width:1000px;min-width:400px;margin:10px auto}
1734.path{padding:4px 7px;border:1px solid #ddd;background-color:#fff;margin-bottom:10px}
1735.right{text-align:right}.center{text-align:center}.float-right{float:right}
1736.message{padding:4px 7px;border:1px solid #ddd;background-color:#fff}
1737.message.ok{border-color:green;color:green}
1738.message.error{border-color:red;color:red}
1739.message.alert{border-color:orange;color:orange}
1740.btn{border:0;background:none;padding:0;margin:0;font-weight:bold;color:#296ea3;cursor:pointer}.btn:hover{color:#b00}
1741.preview-img{max-width:100%;background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAKklEQVR42mL5//8/Azbw+PFjrOJMDCSCUQ3EABZc4S0rKzsaSvTTABBgAMyfCMsY4B9iAAAAAElFTkSuQmCC") repeat 0 0}
1742.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}
1743[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}
1744.icon-document{background-position:-16px 0}.icon-folder{background-position:-32px 0}
1745.icon-folder_add{background-position:-48px 0}.icon-upload{background-position:-64px 0}
1746.icon-arrow_up{background-position:-80px 0}.icon-home{background-position:-96px 0}
1747.icon-separator{background-position:-112px 0}.icon-cross{background-position:-128px 0}
1748.icon-copy{background-position:-144px 0}.icon-apply{background-position:-160px 0}
1749.icon-cancel{background-position:-176px 0}.icon-rename{background-position:-192px 0}
1750.icon-checkbox{background-position:-208px 0}.icon-checkbox_invert{background-position:-224px 0}
1751.icon-checkbox_uncheck{background-position:-240px 0}.icon-download{background-position:-256px 0}
1752.icon-goback{background-position:-272px 0}.icon-folder_open{background-position:-288px 0}
1753.icon-file_application{background-position:0 -16px}.icon-file_code{background-position:-16px -16px}
1754.icon-file_csv{background-position:-32px -16px}.icon-file_excel{background-position:-48px -16px}
1755.icon-file_film{background-position:-64px -16px}.icon-file_flash{background-position:-80px -16px}
1756.icon-file_font{background-position:-96px -16px}.icon-file_html{background-position:-112px -16px}
1757.icon-file_illustrator{background-position:-128px -16px}.icon-file_image{background-position:-144px -16px}
1758.icon-file_music{background-position:-160px -16px}.icon-file_outlook{background-position:-176px -16px}
1759.icon-file_pdf{background-position:-192px -16px}.icon-file_photoshop{background-position:-208px -16px}
1760.icon-file_php{background-position:-224px -16px}.icon-file_playlist{background-position:-240px -16px}
1761.icon-file_powerpoint{background-position:-256px -16px}.icon-file_swf{background-position:-272px -16px}
1762.icon-file_terminal{background-position:-288px -16px}.icon-file_text{background-position:-304px -16px}
1763.icon-file_word{background-position:-320px -16px}.icon-file_zip{background-position:-336px -16px}
1764.icon-logout{background-position:-304px 0}.icon-chain{background-position:-320px 0}
1765.icon-link_folder{background-position:-352px -16px}.icon-link_file{background-position:-368px -16px}
1766.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}
1767.filename{max-width:420px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
1768.break-word{word-wrap:break-word}
1769</style>
1770<link rel="icon" href="<?php echo FM_SELF_URL ?>?img=favicon" type="image/png">
1771<link rel="shortcut icon" href="<?php echo FM_SELF_URL ?>?img=favicon" type="image/png">
1772<?php if (isset($_GET['view']) && FM_USE_HIGHLIGHTJS): ?>
1773<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.2.0/styles/<?php echo FM_HIGHLIGHTJS_STYLE ?>.min.css">
1774<?php endif; ?>
1775</head>
1776<body>
1777<div id="wrapper">
1778<?php
1779}
1780
1781/**
1782 * Show page footer
1783 */
1784function fm_show_footer()
1785{
1786 ?>
1787<p class="center"><small><a href="https://github.com/alexantr/filemanager" target="_blank">PHP File Manager</a></small></p>
1788</div>
1789<script>
1790function newfolder(p){var n=prompt('New folder name','folder');if(n!==null&&n!==''){window.location.search='p='+encodeURIComponent(p)+'&new='+encodeURIComponent(n);}}
1791function 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);}}
1792function change_checkboxes(l,v){for(var i=l.length-1;i>=0;i--){l[i].checked=(typeof v==='boolean')?v:!l[i].checked;}}
1793function 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;}
1794function select_all(){var l=get_checkboxes();change_checkboxes(l,true);}
1795function unselect_all(){var l=get_checkboxes();change_checkboxes(l,false);}
1796function invert_all(){var l=get_checkboxes();change_checkboxes(l);}
1797function checkbox_toggle(){var l=get_checkboxes();l.push(this);change_checkboxes(l);}
1798</script>
1799<?php if (isset($_GET['view']) && FM_USE_HIGHLIGHTJS): ?>
1800<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.2.0/highlight.min.js"></script>
1801<script>hljs.initHighlightingOnLoad();</script>
1802<?php endif; ?>
1803</body>
1804</html>
1805<?php
1806}
1807
1808/**
1809 * Show image
1810 * @param string $img
1811 */
1812function fm_show_image($img)
1813{
1814 $modified_time = gmdate('D, d M Y 00:00:00') . ' GMT';
1815 $expires_time = gmdate('D, d M Y 00:00:00', strtotime('+1 day')) . ' GMT';
1816
1817 $img = trim($img);
1818 $images = fm_get_images();
1819 $image = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAEElEQVR42mL4//8/A0CAAQAI/AL+26JNFgAAAABJRU5ErkJggg==';
1820 if (isset($images[$img])) {
1821 $image = $images[$img];
1822 }
1823 $image = base64_decode($image);
1824 if (function_exists('mb_strlen')) {
1825 $size = mb_strlen($image, '8bit');
1826 } else {
1827 $size = strlen($image);
1828 }
1829
1830 if (function_exists('header_remove')) {
1831 header_remove('Cache-Control');
1832 header_remove('Pragma');
1833 } else {
1834 header('Cache-Control:');
1835 header('Pragma:');
1836 }
1837
1838 header('Last-Modified: ' . $modified_time, true, 200);
1839 header('Expires: ' . $expires_time);
1840 header('Content-Length: ' . $size);
1841 header('Content-Type: image/png');
1842 echo $image;
1843
1844 exit;
1845}
1846
1847/**
1848 * Get base64-encoded images
1849 * @return array
1850 */
1851function fm_get_images()
1852{
1853 return array(
1854 'favicon' => 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJ
1855bWFnZVJlYWR5ccllPAAAAZVJREFUeNqkk79Lw0AUx1+uidTQim4Waxfpnl1BcHMR6uLkIF0cpYOI
1856f4KbOFcRwbGTc0HQSVQQXCqlFIXgFkhIyvWS870LaaPYH9CDy8vdfb+fey930aSUMEvT6VHVzw8x
1857rKUX3N3Hj/8M+cZ6GcOtBPl6KY5iAA7KJzfVWrfbhUKhALZtQ6myDf1+X5nsuzjLUmUOnpa+v5r1
1858Z4ZDDfsLiwER45xDEATgOI6KntfDd091GidzC8vZ4vH1QQ09+4MSMAMWRREKPMhmsyr6voYmrnb2
1859PKEizdEabUaeFCDKCCHAdV0wTVNFznMgpVqGlZ2cipzHGtKSZwCIZJgJwxB38KHT6Sjx21V75Jcn
1860LXmGAKTRpGVZUx2dAqQzSEqw9kqwuGqONTufPrw37D8lQFxCvjgPXIixANLEGfwuQacMOC4kZz+q
1861GdhJS550BjpRCdCbAJCMJRkMASEIg+4Bxz4JwAwDSEueAYDLIM+QrOk6GHiRxjXSkJY8KUCvdXZ6
1862kbuvNx+mOcbN9taGBlpLAWf9nX8EGADoCfqkKWV/cgAAAABJRU5ErkJggg==',
1863 'sprites' => 'iVBORw0KGgoAAAANSUhEUgAAAYAAAAAgCAMAAAAscl/XAAAC/VBMVEUAAABUfn4KKipIcXFSeXsx
1864VlZSUlNAZ2c4Xl4lSUkRDg7w8O/d3d3LhwAWFhYXODgMLCx8fHw9PT2TtdOOAACMXgE8lt+dmpq+
1865fgABS3RUpN+VUycuh9IgeMJUe4C5dUI6meKkAQEKCgoMWp5qtusJmxSUPgKudAAXCghQMieMAgIU
1866abNSUlJLe70VAQEsh85oaGjBEhIBOGxfAoyUbUQAkw8gui4LBgbOiFPHx8cZX6PMS1OqFha/MjIK
1867VKFGBABSAXovGAkrg86xAgIoS5Y7c6Nf7W1Hz1NmAQB3Hgx8fHyiTAAwp+eTz/JdDAJ0JwAAlxCQ
1868UAAvmeRiYp6ysrmIAABJr/ErmiKmcsATpRyfEBAOdQgOXahyAAAecr1JCwHMiABgfK92doQGBgZG
1869AGkqKiw0ldYuTHCYsF86gB05UlJmQSlra2tVWED////8/f3t9fX5/Pzi8/Px9vb2+/v0+fnn8vLf
18707OzZ6enV5+eTpKTo6Oj6/v765Z/U5eX4+Pjx+Pjv0ojWBASxw8O8vL52dnfR19CvAADR3PHr6+vi
18714uPDx8v/866nZDO7iNT335jtzIL+7aj86aTIztXDw8X13JOlpKJoaHDJAACltratrq3lAgKfAADb
18724vb76N2au9by2I9gYGVIRkhNTE90wfXq2sh8gL8QMZ3pyn27AADr+uu1traNiIh2olTTshifodQ4
1873ZM663PH97+YeRq2GqmRjmkGjnEDnfjLVVg6W4f7s6/p/0fr98+5UVF6wz+SjxNsmVb5RUVWMrc7d
1874zrrIpWI8PD3pkwhCltZFYbNZja82wPv05NPRdXzhvna4uFdIiibPegGQXankxyxe0P7PnOhTkDGA
1875gBrbhgR9fX9bW1u8nRFamcgvVrACJIvlXV06nvtdgON4mdn3og7AagBTufkucO7snJz4b28XEhIT
1876sflynsLEvIk55kr866aewo2YuYDrnFffOTk6Li6hgAn3y8XkusCHZQbt0NP571lqRDZyMw96lZXE
1877s6qcrMmJaTmVdRW2AAAAbnRSTlMAZodsJHZocHN7hP77gnaCZWdx/ki+RfqOd/7+zc9N/szMZlf8
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
1947RK5CYII=',
1948 );
1949}
1950