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