NoPaste

XmasCLOUD

von uname

SNIPPET_TEXT:
  1. <?php
  2. //Default Configuration
  3. $CONFIG = '{"lang":"en","error_reporting":false,"show_hidden":false,"hide_Cols":false,"theme":"light"}';
  4.  
  5. /**
  6.  * H3K | Tiny File Manager V2.5.2
  7.  * @author Prasath Mani | CCP Programmers
  8.  * @email ccpprogrammers@gmail.com
  9.  * @github https://github.com/prasathmani/tinyfilemanager
  10.  * @link https://tinyfilemanager.github.io
  11.  */
  12.  
  13.  
  14.  
  15. //TFM version
  16. define('VERSION', '2.5.2');
  17.  
  18. //Application Title
  19. //define('APP_TITLE', 'Tiny File Manager');
  20. define('APP_TITLE', 'XmasCLOUD'); // XmasCLOUD
  21.  
  22.  
  23.  
  24. // --- EDIT BELOW CONFIGURATION CAREFULLY ---
  25.  
  26. // Auth with login/password
  27. // set true/false to enable/disable it
  28. // Is independent from IP white- and blacklisting
  29. $use_auth = false; // xmascloud
  30.  
  31. // Login user name and password
  32. // Users: array('Username' => 'Password', 'Username2' => 'Password2', ...)
  33. // Generate secure password hash - https://tinyfilemanager.github.io/docs/pwd.html
  34. $auth_users = array(
  35.     'admin' => '$2y$10$/K.hjNr84lLNDt8fTXjoI.DBp6PpeyoJ.mGwrrLuCZfAwfSAGqhOW', //admin@123
  36.     'user' => '$2y$10$Fg6Dz8oH9fPoZ2jJan5tZuv6Z4Kp7avtQ9bDfrdRntXtPeiMAZyGO' //12345
  37. );
  38.  
  39. // Readonly users
  40. // e.g. array('users', 'guest', ...)
  41. $readonly_users = array(
  42.     'user'
  43. );
  44.  
  45. // Global readonly, including when auth is not being used
  46. $global_readonly = false; // XmasCLOUD
  47.  
  48. // user specific directories
  49. // array('Username' => 'Directory path', 'Username2' => 'Directory path', ...)
  50. $directories_users = array();
  51.  
  52. // Enable highlight.js (https://highlightjs.org/) on view's page
  53. $use_highlightjs = true;
  54.  
  55. // highlight.js style
  56. // for dark theme use 'ir-black'
  57. $highlightjs_style = 'vs';
  58.  
  59. // Enable ace.js (https://ace.c9.io/) on view's page
  60. $edit_files = true;
  61.  
  62. // Default timezone for date() and time()
  63. // Doc - http://php.net/manual/en/timezones.php
  64. //$default_timezone = 'Etc/UTC'; // UTC
  65. $default_timezone = "Europe/Berlin"; // XmasCLOUD
  66.  
  67. // Root path for file manager
  68. // use absolute path of directory i.e: '/var/www/folder' or $_SERVER['DOCUMENT_ROOT'].'/folder'
  69. // $root_path = $_SERVER['DOCUMENT_ROOT'];
  70. $root_path = $_SERVER['DOCUMENT_ROOT'] . '/xmascloud/'; // XmasCLOUD
  71.  
  72.  
  73. // Root url for links in file manager.Relative to $http_host. Variants: '', 'path/to/subfolder'
  74. // Will not working if $root_path will be outside of server document root
  75. $root_url = 'xmascloud'; // XmasCLOUD
  76.  
  77. // Server hostname. Can set manually if wrong
  78. // $_SERVER['HTTP_HOST'].'/folder'
  79. $http_host = $_SERVER['HTTP_HOST'];
  80.  
  81. // input encoding for iconv
  82. $iconv_input_encoding = 'UTF-8';
  83.  
  84. // date() format for file modification date
  85. // Doc - https://www.php.net/manual/en/function.date.php
  86. $datetime_format = 'm/d/Y g:i A';
  87.  
  88. // Allowed file extensions for create and rename files
  89. // e.g. 'txt,html,css,js'
  90. // $allowed_file_extensions = '';  // XmasCLOUD
  91. $allowed_file_extensions = 'webm,jpg,png,bmp,ico,csv,dbf,dif,doc,docm,docx,dot,dotm,dotx,emf,emf,gif,htm,html,mht,mhtml,mp3,mp4 ,odp ,ods,odt,pdf,pot,potm,potx,ppa,ppam,pps,ppsm,ppsx,ppt,pptm,pptx,prm,rtf,rtf,slk,thmx,tif,txt,wmf,wmv,wps,xla,xlam,xls,xlsb,xlsm,xlsx,xlt,xltm,xltx,xlw,xml,xps,xps';
  92.  
  93.  
  94. // Allowed file extensions for upload files
  95. // e.g. 'gif,png,jpg,html,txt'
  96. // $allowed_upload_extensions = ''; // XmasCLOUD
  97. $allowed_upload_extensions = 'webm,jpg,png,bmp,ico,csv,dbf,dif,doc,docm,docx,dot,dotm,dotx,emf,emf,gif,htm,html,mht,mhtml,mp3,mp4 ,odp ,ods,odt,pdf,pot,potm,potx,ppa,ppam,pps,ppsm,ppsx,ppt,pptm,pptx,prm,rtf,rtf,slk,thmx,tif,txt,wmf,wmv,wps,xla,xlam,xls,xlsb,xlsm,xlsx,xlt,xltm,xltx,xlw,xml,xps,xps';
  98.  
  99.  
  100. // Favicon path. This can be either a full url to an .PNG image, or a path based on the document root.
  101. // full path, e.g http://example.com/favicon.png
  102. // local path, e.g images/icons/favicon.png
  103. $favicon_path = '';
  104.  
  105. // Files and folders to excluded from listing
  106. // e.g. array('myfile.html', 'personal-folder', '*.php', ...)
  107. $exclude_items = array();
  108.  
  109. // Online office Docs Viewer
  110. // Availabe rules are 'google', 'microsoft' or false
  111. // Google => View documents using Google Docs Viewer
  112. // Microsoft => View documents using Microsoft Web Apps Viewer
  113. // false => disable online doc viewer
  114. $online_viewer = false; // xmascloud
  115.  
  116. // Sticky Nav bar
  117. // true => enable sticky header
  118. // false => disable sticky header
  119. $sticky_navbar = true;
  120.  
  121. // Maximum file upload size
  122. // Increase the following values in php.ini to work properly
  123. // memory_limit, upload_max_filesize, post_max_size
  124. $max_upload_size_bytes = 5000000000; // size 5,000,000,000 bytes (~5GB)
  125.  
  126. // Possible rules are 'OFF', 'AND' or 'OR'
  127. // OFF => Don't check connection IP, defaults to OFF
  128. // AND => Connection must be on the whitelist, and not on the blacklist
  129. // OR => Connection must be on the whitelist, or not on the blacklist
  130. $ip_ruleset = 'OFF';
  131.  
  132. // Should users be notified of their block?
  133. $ip_silent = true;
  134.  
  135. // IP-addresses, both ipv4 and ipv6
  136. $ip_whitelist = array(
  137.     '127.0.0.1',    // local ipv4
  138.     '::1'           // local ipv6
  139. );
  140.  
  141. // IP-addresses, both ipv4 and ipv6
  142. $ip_blacklist = array(
  143.     '0.0.0.0',      // non-routable meta ipv4
  144.     '::'            // non-routable meta ipv6
  145. );
  146.  
  147. // if User has the external config file, try to use it to override the default config above [config.php]
  148. // sample config - https://tinyfilemanager.github.io/config-sample.txt
  149. $config_file = __DIR__.'/config.php';
  150. if (is_readable($config_file)) {
  151.     @include($config_file);
  152. }
  153.  
  154. // --- EDIT BELOW CAREFULLY OR DO NOT EDIT AT ALL ---
  155.  
  156. // max upload file size
  157. define('MAX_UPLOAD_SIZE', $max_upload_size_bytes);
  158.  
  159. // private key and session name to store to the session
  160. if ( !defined( 'FM_SESSION_ID')) {
  161.     define('FM_SESSION_ID', 'filemanager');
  162. }
  163.  
  164. // Configuration
  165. $cfg = new FM_Config();
  166.  
  167. // Default language
  168. $lang = isset($cfg->data['lang']) ? $cfg->data['lang'] : 'en';
  169.  
  170. // Show or hide files and folders that starts with a dot
  171. $show_hidden_files = isset($cfg->data['show_hidden']) ? $cfg->data['show_hidden'] : true;
  172.  
  173. // PHP error reporting - false = Turns off Errors, true = Turns on Errors
  174. $report_errors = isset($cfg->data['error_reporting']) ? $cfg->data['error_reporting'] : true;
  175.  
  176. // Hide Permissions and Owner cols in file-listing
  177. $hide_Cols = isset($cfg->data['hide_Cols']) ? $cfg->data['hide_Cols'] : true;
  178.  
  179. // Theme
  180. $theme = isset($cfg->data['theme']) ? $cfg->data['theme'] : 'light';
  181.  
  182. define('FM_THEME', $theme);
  183.  
  184. //available languages
  185. $lang_list = array(
  186.     'en' => 'English'
  187. );
  188.  
  189. if ($report_errors == true) {
  190.     @ini_set('error_reporting', E_ALL);
  191.     @ini_set('display_errors', 1);
  192. } else {
  193.     @ini_set('error_reporting', E_ALL);
  194.     @ini_set('display_errors', 0);
  195. }
  196.  
  197. // if fm included
  198. if (defined('FM_EMBED')) {
  199.     $use_auth = false;
  200.     $sticky_navbar = false;
  201. } else {
  202.     @set_time_limit(600);
  203.  
  204.     date_default_timezone_set($default_timezone);
  205.  
  206.     ini_set('default_charset', 'UTF-8');
  207.     if (version_compare(PHP_VERSION, '5.6.0', '<') && function_exists('mb_internal_encoding')) {
  208.         mb_internal_encoding('UTF-8');
  209.     }
  210.     if (function_exists('mb_regex_encoding')) {
  211.         mb_regex_encoding('UTF-8');
  212.     }
  213.  
  214.     session_name(FM_SESSION_ID );
  215.     function session_error_handling_function($code, $msg, $file, $line) {
  216.         // Permission denied for default session, try to create a new one
  217.         if ($code == 2) {
  218.             session_abort();
  219.             session_id(session_create_id());
  220.             @session_start();
  221.         }
  222.     }
  223.     set_error_handler('session_error_handling_function');
  224.     session_start();
  225. }
  226.  
  227. //Genrating CSRF Token
  228. if (empty($_SESSION['token'])) {
  229.     $_SESSION['token'] = bin2hex(random_bytes(32));
  230. }
  231.  
  232. if (empty($auth_users)) {
  233.     $use_auth = false;
  234. }
  235.  
  236. $is_https = isset($_SERVER['HTTPS']) && ($_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] == 1)
  237.     || isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https';
  238.  
  239. // update $root_url based on user specific directories
  240. if (isset($_SESSION[FM_SESSION_ID]['logged']) && !empty($directories_users[$_SESSION[FM_SESSION_ID]['logged']])) {
  241.     $wd = fm_clean_path(dirname($_SERVER['PHP_SELF']));
  242.     $root_url =  $root_url.$wd.DIRECTORY_SEPARATOR.$directories_users[$_SESSION[FM_SESSION_ID]['logged']];
  243. }
  244. // clean $root_url
  245. $root_url = fm_clean_path($root_url);
  246.  
  247. // abs path for site
  248. defined('FM_ROOT_URL') || define('FM_ROOT_URL', ($is_https ? 'https' : 'http') . '://' . $http_host . (!empty($root_url) ? '/' . $root_url : ''));
  249. defined('FM_SELF_URL') || define('FM_SELF_URL', ($is_https ? 'https' : 'http') . '://' . $http_host . $_SERVER['PHP_SELF']);
  250.  
  251. // logout
  252. if (isset($_GET['logout'])) {
  253.     unset($_SESSION[FM_SESSION_ID]['logged']);
  254.     unset( $_SESSION['token']);
  255.     fm_redirect(FM_SELF_URL);
  256. }
  257.  
  258. // Validate connection IP
  259. if ($ip_ruleset != 'OFF') {
  260.     function getClientIP() {
  261.         if (array_key_exists('HTTP_CF_CONNECTING_IP', $_SERVER)) {
  262.             return  $_SERVER["HTTP_CF_CONNECTING_IP"];
  263.         }else if (array_key_exists('HTTP_X_FORWARDED_FOR', $_SERVER)) {
  264.             return  $_SERVER["HTTP_X_FORWARDED_FOR"];
  265.         }else if (array_key_exists('REMOTE_ADDR', $_SERVER)) {
  266.             return $_SERVER['REMOTE_ADDR'];
  267.         }else if (array_key_exists('HTTP_CLIENT_IP', $_SERVER)) {
  268.             return $_SERVER['HTTP_CLIENT_IP'];
  269.         }
  270.         return '';
  271.     }
  272.  
  273.     $clientIp = getClientIP();
  274.     $proceed = false;
  275.     $whitelisted = in_array($clientIp, $ip_whitelist);
  276.     $blacklisted = in_array($clientIp, $ip_blacklist);
  277.  
  278.     if($ip_ruleset == 'AND'){
  279.         if($whitelisted == true && $blacklisted == false){
  280.             $proceed = true;
  281.         }
  282.     } else
  283.     if($ip_ruleset == 'OR'){
  284.          if($whitelisted == true || $blacklisted == false){
  285.             $proceed = true;
  286.         }
  287.     }
  288.  
  289.     if($proceed == false){
  290.         trigger_error('User connection denied from: ' . $clientIp, E_USER_WARNING);
  291.  
  292.         if($ip_silent == false){
  293.             fm_set_msg(lng('Access denied. IP restriction applicable'), 'error');
  294.             fm_show_header_login();
  295.             fm_show_message();
  296.         }
  297.         exit();
  298.     }
  299. }
  300.  
  301. // Checking if the user is logged in or not. If not, it will show the login form.
  302. if ($use_auth) {
  303.     if (isset($_SESSION[FM_SESSION_ID]['logged'], $auth_users[$_SESSION[FM_SESSION_ID]['logged']])) {
  304.         // Logged
  305.     } elseif (isset($_POST['fm_usr'], $_POST['fm_pwd'], $_POST['token'])) {
  306.         // Logging In
  307.         sleep(1);
  308.         if(function_exists('password_verify')) {
  309.             if (isset($auth_users[$_POST['fm_usr']]) && isset($_POST['fm_pwd']) && password_verify($_POST['fm_pwd'], $auth_users[$_POST['fm_usr']]) && verifyToken($_POST['token'])) {
  310.                 $_SESSION[FM_SESSION_ID]['logged'] = $_POST['fm_usr'];
  311.                 fm_set_msg(lng('You are logged in'));
  312.                 fm_redirect(FM_ROOT_URL . $_SERVER['REQUEST_URI']);
  313.             } else {
  314.                 unset($_SESSION[FM_SESSION_ID]['logged']);
  315.                 fm_set_msg(lng('Login failed. Invalid username or password'), 'error');
  316.                 fm_redirect(FM_ROOT_URL . $_SERVER['REQUEST_URI']);
  317.             }
  318.         } else {
  319.             fm_set_msg(lng('password_hash not supported, Upgrade PHP version'), 'error');;
  320.         }
  321.     } else {
  322.         // Form
  323.         unset($_SESSION[FM_SESSION_ID]['logged']);
  324.         fm_show_header_login();
  325.         ?>
  326.         <section class="h-100">
  327.             <div class="container h-100">
  328.                 <div class="row justify-content-md-center h-100">
  329.                     <div class="card-wrapper">
  330.                         <div class="card fat <?php echo fm_get_theme(); ?>">
  331.                             <div class="card-body">
  332.                                 <form class="form-signin" action="" method="post" autocomplete="off">
  333.                                     <div class="mb-3">
  334.                                        <div class="brand">
  335.                                             <svg version="1.0" xmlns="http://www.w3.org/2000/svg" M1008 width="100%" height="80px" viewBox="0 0 238.000000 140.000000" aria-label="H3K Tiny File Manager">
  336.                                                 <g transform="translate(0.000000,140.000000) scale(0.100000,-0.100000)" fill="#000000" stroke="none">
  337.                                                     <path d="M160 700 l0 -600 110 0 110 0 0 260 0 260 70 0 70 0 0 -260 0 -260 110 0 110 0 0 600 0 600 -110 0 -110 0 0 -260 0 -260 -70 0 -70 0 0 260 0 260 -110 0 -110 0 0 -600z"/>
  338.                                                     <path fill="#003500" d="M1008 1227 l-108 -72 0 -117 0 -118 110 0 110 0 0 110 0 110 70 0 70 0 0 -180 0 -180 -125 0 c-69 0 -125 -3 -125 -6 0 -3 23 -39 52 -80 l52 -74 73 0 73 0 0 -185 0 -185 -70 0 -70 0 0 115 0 115 -110 0 -110 0 0 -190 0 -190 181 0 181 0 109 73 108 72 1 181 0 181 -69 48 -68 49 68 50 69 49 0 249 0 248 -182 -1 -183 0 -107 -72z"/>
  339.                                                     <path d="M1640 700 l0 -600 110 0 110 0 0 208 0 208 35 34 35 34 35 -34 35 -34 0 -208 0 -208 110 0 110 0 0 212 0 213 -87 87 -88 88 88 88 87 87 0 213 0 212 -110 0 -110 0 0 -208 0 -208 -70 -69 -70 -69 0 277 0 277 -110 0 -110 0 0 -600z"/></g>
  340.                                             </svg>
  341.                                         </div>
  342.                                         <div class="text-center">
  343.                                             <h1 class="card-title"><?php echo APP_TITLE; ?></h1>
  344.                                         </div>
  345.                                     </div>
  346.                                     <hr />
  347.                                     <div class="mb-3">
  348.                                         <label for="fm_usr" class="pb-2"><?php echo lng('Username'); ?></label>
  349.                                         <input type="text" class="form-control" id="fm_usr" name="fm_usr" required autofocus>
  350.                                     </div>
  351.  
  352.                                     <div class="mb-3">
  353.                                         <label for="fm_pwd" class="pb-2"><?php echo lng('Password'); ?></label>
  354.                                         <input type="password" class="form-control" id="fm_pwd" name="fm_pwd" required>
  355.                                     </div>
  356.  
  357.                                     <div class="mb-3">
  358.                                         <?php fm_show_message(); ?>
  359.                                     </div>
  360.                                     <input type="hidden" name="token" value="<?php echo htmlentities($_SESSION['token']); ?>" />
  361.                                     <div class="mb-3">
  362.                                         <button type="submit" class="btn btn-success btn-block w-100 mt-4" role="button">
  363.                                             <?php echo lng('Login'); ?>
  364.                                         </button>
  365.                                     </div>
  366.                                 </form>
  367.                             </div>
  368.                         </div>
  369.                         <div class="footer text-center">
  370.                             &mdash;&mdash; &copy;
  371.                             <a href="https://tinyfilemanager.github.io/" target="_blank" class="text-decoration-none text-muted" data-version="<?php echo VERSION; ?>">CCP Programmers</a> &mdash;&mdash;
  372.                         </div>
  373.                     </div>
  374.                 </div>
  375.             </div>
  376.         </section>
  377.  
  378.         <?php
  379.         fm_show_footer_login();
  380.         exit;
  381.     }
  382. }
  383.  
  384. // update root path
  385. if ($use_auth && isset($_SESSION[FM_SESSION_ID]['logged'])) {
  386.     $root_path = isset($directories_users[$_SESSION[FM_SESSION_ID]['logged']]) ? $directories_users[$_SESSION[FM_SESSION_ID]['logged']] : $root_path;
  387. }
  388.  
  389. // clean and check $root_path
  390. $root_path = rtrim($root_path, '\\/');
  391. $root_path = str_replace('\\', '/', $root_path);
  392. if (!@is_dir($root_path)) {
  393.     echo "<h1>".lng('Root path')." \"{$root_path}\" ".lng('not found!')." </h1>";
  394.     exit;
  395. }
  396.  
  397. defined('FM_SHOW_HIDDEN') || define('FM_SHOW_HIDDEN', $show_hidden_files);
  398. defined('FM_ROOT_PATH') || define('FM_ROOT_PATH', $root_path);
  399. defined('FM_LANG') || define('FM_LANG', $lang);
  400. defined('FM_FILE_EXTENSION') || define('FM_FILE_EXTENSION', $allowed_file_extensions);
  401. defined('FM_UPLOAD_EXTENSION') || define('FM_UPLOAD_EXTENSION', $allowed_upload_extensions);
  402. defined('FM_EXCLUDE_ITEMS') || define('FM_EXCLUDE_ITEMS', (version_compare(PHP_VERSION, '7.0.0', '<') ? serialize($exclude_items) : $exclude_items));
  403. defined('FM_DOC_VIEWER') || define('FM_DOC_VIEWER', $online_viewer);
  404. define('FM_READONLY', $global_readonly || ($use_auth && !empty($readonly_users) && isset($_SESSION[FM_SESSION_ID]['logged']) && in_array($_SESSION[FM_SESSION_ID]['logged'], $readonly_users)));
  405. define('FM_IS_WIN', DIRECTORY_SEPARATOR == '\\');
  406.  
  407. // always use ?p=
  408. if (!isset($_GET['p']) && empty($_FILES)) {
  409.     fm_redirect(FM_SELF_URL . '?p=');
  410. }
  411.  
  412. // get path
  413. $p = isset($_GET['p']) ? $_GET['p'] : (isset($_POST['p']) ? $_POST['p'] : '');
  414.  
  415. // clean path // XmasCLOUD
  416. $p = fm_clean_path($p);
  417. if (!$p) {
  418.    exit;
  419. }
  420.  
  421. // for ajax request - save
  422. $input = file_get_contents('php://input');
  423. $_POST = (strpos($input, 'ajax') != FALSE && strpos($input, 'save') != FALSE) ? json_decode($input, true) : $_POST;
  424.  
  425. // instead globals vars
  426. define('FM_PATH', $p);
  427. define('FM_USE_AUTH', $use_auth);
  428. define('FM_EDIT_FILE', $edit_files);
  429. defined('FM_ICONV_INPUT_ENC') || define('FM_ICONV_INPUT_ENC', $iconv_input_encoding);
  430. defined('FM_USE_HIGHLIGHTJS') || define('FM_USE_HIGHLIGHTJS', $use_highlightjs);
  431. defined('FM_HIGHLIGHTJS_STYLE') || define('FM_HIGHLIGHTJS_STYLE', $highlightjs_style);
  432. defined('FM_DATETIME_FORMAT') || define('FM_DATETIME_FORMAT', $datetime_format);
  433.  
  434. unset($p, $use_auth, $iconv_input_encoding, $use_highlightjs, $highlightjs_style);
  435.  
  436. /*************************** ACTIONS ***************************/
  437.  
  438. // Handle all AJAX Request
  439. if (isset($_SESSION[FM_SESSION_ID]['logged'], $auth_users[$_SESSION[FM_SESSION_ID]['logged']]) && isset($_POST['ajax'], $_POST['token']) && !FM_READONLY) {
  440.     if(!verifyToken($_POST['token'])) {
  441.         header('HTTP/1.0 401 Unauthorized');
  442.         die("Invalid Token.");
  443.     }
  444.  
  445.     //search : get list of files from the current folder
  446.     if(isset($_POST['type']) && $_POST['type']=="search") {
  447.         $dir = $_POST['path'] == "." ? '': $_POST['path'];
  448.         $response = scan(fm_clean_path($dir), $_POST['content']);
  449.         echo json_encode($response);
  450.         exit();
  451.     }
  452.  
  453.     // save editor file
  454.     if (isset($_POST['type']) && $_POST['type'] == "save") {
  455.         // get current path
  456.         $path = FM_ROOT_PATH;
  457.         if (FM_PATH != '') {
  458.             $path .= '/' . FM_PATH;
  459.         }
  460.         // check path
  461.         if (!is_dir($path)) {
  462.             fm_redirect(FM_SELF_URL . '?p=');
  463.         }
  464.         $file = $_GET['edit'];
  465.         $file = fm_clean_path($file);
  466.         $file = str_replace('/', '', $file);
  467.         if ($file == '' || !is_file($path . '/' . $file)) {
  468.             fm_set_msg(lng('File not found'), 'error');
  469.             $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
  470.         }
  471.         header('X-XSS-Protection:0');
  472.         $file_path = $path . '/' . $file;
  473.  
  474.         $writedata = $_POST['content'];
  475.         $fd = fopen($file_path, "w");
  476.         $write_results = @fwrite($fd, $writedata);
  477.         fclose($fd);
  478.         if ($write_results === false){
  479.             header("HTTP/1.1 500 Internal Server Error");
  480.             die("Could Not Write File! - Check Permissions / Ownership");
  481.         }
  482.         die(true);
  483.     }
  484.  
  485.     // backup files
  486.     if (isset($_POST['type']) && $_POST['type'] == "backup" && !empty($_POST['file'])) {
  487.         $fileName = fm_clean_path($_POST['file']);
  488.         $fullPath = FM_ROOT_PATH . '/';
  489.         if (!empty($_POST['path'])) {
  490.             $relativeDirPath = fm_clean_path($_POST['path']);
  491.             $fullPath .= "{$relativeDirPath}/";
  492.         }
  493.         $date = date("dMy-His");
  494.         $newFileName = "{$fileName}-{$date}.bak";
  495.         $fullyQualifiedFileName = $fullPath . $fileName;
  496.         try {
  497.             if (!file_exists($fullyQualifiedFileName)) {
  498.                 throw new Exception("File {$fileName} not found");
  499.             }
  500.             if (copy($fullyQualifiedFileName, $fullPath . $newFileName)) {
  501.                 echo "Backup {$newFileName} created";
  502.             } else {
  503.                 throw new Exception("Could not copy file {$fileName}");
  504.             }
  505.         } catch (Exception $e) {
  506.             echo $e->getMessage();
  507.         }
  508.     }
  509.  
  510.     // Save Config
  511.     if (isset($_POST['type']) && $_POST['type'] == "settings") {
  512.         global $cfg, $lang, $report_errors, $show_hidden_files, $lang_list, $hide_Cols, $theme;
  513.         $newLng = $_POST['js-language'];
  514.         fm_get_translations([]);
  515.         if (!array_key_exists($newLng, $lang_list)) {
  516.             $newLng = 'en';
  517.         }
  518.  
  519.         $erp = isset($_POST['js-error-report']) && $_POST['js-error-report'] == "true" ? true : false;
  520.         $shf = isset($_POST['js-show-hidden']) && $_POST['js-show-hidden'] == "true" ? true : false;
  521.         $hco = isset($_POST['js-hide-cols']) && $_POST['js-hide-cols'] == "true" ? true : false;
  522.         $te3 = $_POST['js-theme-3'];
  523.  
  524.         if ($cfg->data['lang'] != $newLng) {
  525.             $cfg->data['lang'] = $newLng;
  526.             $lang = $newLng;
  527.         }
  528.         if ($cfg->data['error_reporting'] != $erp) {
  529.             $cfg->data['error_reporting'] = $erp;
  530.             $report_errors = $erp;
  531.         }
  532.         if ($cfg->data['show_hidden'] != $shf) {
  533.             $cfg->data['show_hidden'] = $shf;
  534.             $show_hidden_files = $shf;
  535.         }
  536.         if ($cfg->data['show_hidden'] != $shf) {
  537.             $cfg->data['show_hidden'] = $shf;
  538.             $show_hidden_files = $shf;
  539.         }
  540.         if ($cfg->data['hide_Cols'] != $hco) {
  541.             $cfg->data['hide_Cols'] = $hco;
  542.             $hide_Cols = $hco;
  543.         }
  544.         if ($cfg->data['theme'] != $te3) {
  545.             $cfg->data['theme'] = $te3;
  546.             $theme = $te3;
  547.         }
  548.         $cfg->save();
  549.         echo true;
  550.     }
  551.  
  552.     // new password hash
  553.     if (isset($_POST['type']) && $_POST['type'] == "pwdhash") {
  554.         $res = isset($_POST['inputPassword2']) && !empty($_POST['inputPassword2']) ? password_hash($_POST['inputPassword2'], PASSWORD_DEFAULT) : '';
  555.         echo $res;
  556.     }
  557.  
  558.     //upload using url
  559.     if(isset($_POST['type']) && $_POST['type'] == "upload" && !empty($_REQUEST["uploadurl"])) {
  560.         $path = FM_ROOT_PATH;
  561.         if (FM_PATH != '') {
  562.             $path .= '/' . FM_PATH;
  563.         }
  564.  
  565.          function event_callback ($message) {
  566.             global $callback;
  567.             echo json_encode($message);
  568.         }
  569.  
  570.         function get_file_path () {
  571.             global $path, $fileinfo, $temp_file;
  572.             return $path."/".basename($fileinfo->name);
  573.         }
  574.  
  575.         $url = !empty($_REQUEST["uploadurl"]) && preg_match("|^http(s)?://.+$|", stripslashes($_REQUEST["uploadurl"])) ? stripslashes($_REQUEST["uploadurl"]) : null;
  576.  
  577.         //prevent 127.* domain and known ports
  578.         $domain = parse_url($url, PHP_URL_HOST);
  579.         $port = parse_url($url, PHP_URL_PORT);
  580.         $knownPorts = [22, 23, 25, 3306];
  581.  
  582.         if (preg_match("/^localhost$|^127(?:\.[0-9]+){0,2}\.[0-9]+$|^(?:0*\:)*?:?0*1$/i", $domain) || in_array($port, $knownPorts)) {
  583.             $err = array("message" => "URL is not allowed");
  584.             event_callback(array("fail" => $err));
  585.             exit();
  586.         }
  587.  
  588.         $use_curl = false;
  589.         $temp_file = tempnam(sys_get_temp_dir(), "upload-");
  590.         $fileinfo = new stdClass();
  591.         $fileinfo->name = trim(basename($url), ".\x00..\x20");
  592.  
  593.         $allowed = (FM_UPLOAD_EXTENSION) ? explode(',', FM_UPLOAD_EXTENSION) : false;
  594.         $ext = strtolower(pathinfo($fileinfo->name, PATHINFO_EXTENSION));
  595.         $isFileAllowed = ($allowed) ? in_array($ext, $allowed) : true;
  596.  
  597.         $err = false;
  598.  
  599.         if(!$isFileAllowed) {
  600.             $err = array("message" => "File extension is not allowed");
  601.             event_callback(array("fail" => $err));
  602.             exit();
  603.         }
  604.  
  605.         if (!$url) {
  606.             $success = false;
  607.         } else if ($use_curl) {
  608.             @$fp = fopen($temp_file, "w");
  609.             @$ch = curl_init($url);
  610.             curl_setopt($ch, CURLOPT_NOPROGRESS, false );
  611.             curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
  612.             curl_setopt($ch, CURLOPT_FILE, $fp);
  613.             @$success = curl_exec($ch);
  614.             $curl_info = curl_getinfo($ch);
  615.             if (!$success) {
  616.                 $err = array("message" => curl_error($ch));
  617.             }
  618.             @curl_close($ch);
  619.             fclose($fp);
  620.             $fileinfo->size = $curl_info["size_download"];
  621.             $fileinfo->type = $curl_info["content_type"];
  622.         } else {
  623.             $ctx = stream_context_create();
  624.             @$success = copy($url, $temp_file, $ctx);
  625.             if (!$success) {
  626.                 $err = error_get_last();
  627.             }
  628.         }
  629.  
  630.         if ($success) {
  631.             $success = rename($temp_file, strtok(get_file_path(), '?'));
  632.         }
  633.  
  634.         if ($success) {
  635.             event_callback(array("done" => $fileinfo));
  636.         } else {
  637.             unlink($temp_file);
  638.             if (!$err) {
  639.                 $err = array("message" => "Invalid url parameter");
  640.             }
  641.             event_callback(array("fail" => $err));
  642.         }
  643.     }
  644.     exit();
  645. }
  646.  
  647. // Delete file / folder
  648. if (isset($_GET['del'], $_POST['token']) && !FM_READONLY) {
  649.     $del = str_replace( '/', '', fm_clean_path( $_GET['del'] ) );
  650.     if ($del != '' && $del != '..' && $del != '.' && verifyToken($_POST['token'])) {
  651.         $path = FM_ROOT_PATH;
  652.         if (FM_PATH != '') {
  653.             $path .= '/' . FM_PATH;
  654.         }
  655.         $is_dir = is_dir($path . '/' . $del);
  656.         if (fm_rdelete($path . '/' . $del)) {
  657.             $msg = $is_dir ? lng('Folder').' <b>%s</b> '.lng('Deleted') : lng('File').' <b>%s</b> '.lng('Deleted');
  658.             fm_set_msg(sprintf($msg, fm_enc($del)));
  659.         } else {
  660.             $msg = $is_dir ? lng('Folder').' <b>%s</b> '.lng('not deleted') : lng('File').' <b>%s</b> '.lng('not deleted');
  661.             fm_set_msg(sprintf($msg, fm_enc($del)), 'error');
  662.         }
  663.     } else {
  664.         fm_set_msg(lng('Invalid file or folder name'), 'error');
  665.     }
  666.     $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
  667. }
  668.  
  669. // Create a new file/folder
  670. if (isset($_POST['newfilename'], $_POST['newfile'], $_POST['token']) && !FM_READONLY) {
  671.     $type = urldecode($_POST['newfile']);
  672.     $new = str_replace( '/', '', fm_clean_path( strip_tags( $_POST['newfilename'] ) ) );
  673.     if (fm_isvalid_filename($new) && $new != '' && $new != '..' && $new != '.' && verifyToken($_POST['token'])) {
  674.         $path = FM_ROOT_PATH;
  675.         if (FM_PATH != '') {
  676.             $path .= '/' . FM_PATH;
  677.         }
  678.         if ($type == "file") {
  679.             if (!file_exists($path . '/' . $new)) {
  680.                 if(fm_is_valid_ext($new)) {
  681.                     @fopen($path . '/' . $new, 'w') or die('Cannot open file:  ' . $new);
  682.                     fm_set_msg(sprintf(lng('File').' <b>%s</b> '.lng('Created'), fm_enc($new)));
  683.                 } else {
  684.                     fm_set_msg(lng('File extension is not allowed'), 'error');
  685.                 }
  686.             } else {
  687.                 fm_set_msg(sprintf(lng('File').' <b>%s</b> '.lng('already exists'), fm_enc($new)), 'alert');
  688.             }
  689.         } else {
  690.             if (fm_mkdir($path . '/' . $new, false) === true) {
  691.                 fm_set_msg(sprintf(lng('Folder').' <b>%s</b> '.lng('Created'), $new));
  692.             } elseif (fm_mkdir($path . '/' . $new, false) === $path . '/' . $new) {
  693.                 fm_set_msg(sprintf(lng('Folder').' <b>%s</b> '.lng('already exists'), fm_enc($new)), 'alert');
  694.             } else {
  695.                 fm_set_msg(sprintf(lng('Folder').' <b>%s</b> '.lng('not created'), fm_enc($new)), 'error');
  696.             }
  697.         }
  698.     } else {
  699.         fm_set_msg(lng('Invalid characters in file or folder name'), 'error');
  700.     }
  701.     $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
  702. }
  703.  
  704. // Copy folder / file
  705. if (isset($_GET['copy'], $_GET['finish']) && !FM_READONLY) {
  706.     // from
  707.     $copy = urldecode($_GET['copy']);
  708.     $copy = fm_clean_path($copy);
  709.     // empty path
  710.     if ($copy == '') {
  711.         fm_set_msg(lng('Source path not defined'), 'error');
  712.         $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
  713.     }
  714.     // abs path from
  715.     $from = FM_ROOT_PATH . '/' . $copy;
  716.     // abs path to
  717.     $dest = FM_ROOT_PATH;
  718.     if (FM_PATH != '') {
  719.         $dest .= '/' . FM_PATH;
  720.     }
  721.     $dest .= '/' . basename($from);
  722.     // move?
  723.     $move = isset($_GET['move']);
  724.     $move = fm_clean_path(urldecode($move));
  725.     // copy/move/duplicate
  726.     if ($from != $dest) {
  727.         $msg_from = trim(FM_PATH . '/' . basename($from), '/');
  728.         if ($move) { // Move and to != from so just perform move
  729.             $rename = fm_rename($from, $dest);
  730.             if ($rename) {
  731.                 fm_set_msg(sprintf(lng('Moved from').' <b>%s</b> '.lng('to').' <b>%s</b>', fm_enc($copy), fm_enc($msg_from)));
  732.             } elseif ($rename === null) {
  733.                 fm_set_msg(lng('File or folder with this path already exists'), 'alert');
  734.             } else {
  735.                 fm_set_msg(sprintf(lng('Error while moving from').' <b>%s</b> '.lng('to').' <b>%s</b>', fm_enc($copy), fm_enc($msg_from)), 'error');
  736.             }
  737.         } else { // Not move and to != from so copy with original name
  738.             if (fm_rcopy($from, $dest)) {
  739.                 fm_set_msg(sprintf(lng('Copied from').' <b>%s</b> '.lng('to').' <b>%s</b>', fm_enc($copy), fm_enc($msg_from)));
  740.             } else {
  741.                 fm_set_msg(sprintf(lng('Error while copying from').' <b>%s</b> '.lng('to').' <b>%s</b>', fm_enc($copy), fm_enc($msg_from)), 'error');
  742.             }
  743.         }
  744.     } else {
  745.        if (!$move){ //Not move and to = from so duplicate
  746.             $msg_from = trim(FM_PATH . '/' . basename($from), '/');
  747.             $fn_parts = pathinfo($from);
  748.             $extension_suffix = '';
  749.             if(!is_dir($from)){
  750.                $extension_suffix = '.'.$fn_parts['extension'];
  751.             }
  752.             //Create new name for duplicate
  753.             $fn_duplicate = $fn_parts['dirname'].'/'.$fn_parts['filename'].'-'.date('YmdHis').$extension_suffix;
  754.             $loop_count = 0;
  755.             $max_loop = 1000;
  756.             // Check if a file with the duplicate name already exists, if so, make new name (edge case...)
  757.             while(file_exists($fn_duplicate) & $loop_count < $max_loop){
  758.                $fn_parts = pathinfo($fn_duplicate);
  759.                $fn_duplicate = $fn_parts['dirname'].'/'.$fn_parts['filename'].'-copy'.$extension_suffix;
  760.                $loop_count++;
  761.             }
  762.             if (fm_rcopy($from, $fn_duplicate, False)) {
  763.                 fm_set_msg(sprintf('Copyied from <b>%s</b> to <b>%s</b>', fm_enc($copy), fm_enc($fn_duplicate)));
  764.             } else {
  765.                 fm_set_msg(sprintf('Error while copying from <b>%s</b> to <b>%s</b>', fm_enc($copy), fm_enc($fn_duplicate)), 'error');
  766.             }
  767.        }
  768.        else{
  769.            fm_set_msg(lng('Paths must be not equal'), 'alert');
  770.        }
  771.     }
  772.     $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
  773. }
  774.  
  775. // Mass copy files/ folders
  776. if (isset($_POST['file'], $_POST['copy_to'], $_POST['finish'], $_POST['token']) && !FM_READONLY) {
  777.  
  778.     if(!verifyToken($_POST['token'])) {
  779.         fm_set_msg(lng('Invalid Token.'), 'error');
  780.     }
  781.    
  782.     // from
  783.     $path = FM_ROOT_PATH;
  784.     if (FM_PATH != '') {
  785.         $path .= '/' . FM_PATH;
  786.     }
  787.     // to
  788.     $copy_to_path = FM_ROOT_PATH;
  789.     $copy_to = fm_clean_path($_POST['copy_to']);
  790.     if ($copy_to != '') {
  791.         $copy_to_path .= '/' . $copy_to;
  792.     }
  793.     if ($path == $copy_to_path) {
  794.         fm_set_msg(lng('Paths must be not equal'), 'alert');
  795.         $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
  796.     }
  797.     if (!is_dir($copy_to_path)) {
  798.         if (!fm_mkdir($copy_to_path, true)) {
  799.             fm_set_msg('Unable to create destination folder', 'error');
  800.             $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
  801.         }
  802.     }
  803.     // move?
  804.     $move = isset($_POST['move']);
  805.     // copy/move
  806.     $errors = 0;
  807.     $files = $_POST['file'];
  808.     if (is_array($files) && count($files)) {
  809.         foreach ($files as $f) {
  810.             if ($f != '') {
  811.                 $f = fm_clean_path($f);
  812.                 // abs path from
  813.                 $from = $path . '/' . $f;
  814.                 // abs path to
  815.                 $dest = $copy_to_path . '/' . $f;
  816.                 // do
  817.                 if ($move) {
  818.                     $rename = fm_rename($from, $dest);
  819.                     if ($rename === false) {
  820.                         $errors++;
  821.                     }
  822.                 } else {
  823.                     if (!fm_rcopy($from, $dest)) {
  824.                         $errors++;
  825.                     }
  826.                 }
  827.             }
  828.         }
  829.         if ($errors == 0) {
  830.             $msg = $move ? 'Selected files and folders moved' : 'Selected files and folders copied';
  831.             fm_set_msg($msg);
  832.         } else {
  833.             $msg = $move ? 'Error while moving items' : 'Error while copying items';
  834.             fm_set_msg($msg, 'error');
  835.         }
  836.     } else {
  837.         fm_set_msg(lng('Nothing selected'), 'alert');
  838.     }
  839.     $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
  840. }
  841.  
  842. // Rename
  843. if (isset($_POST['rename_from'], $_POST['rename_to'], $_POST['token']) && !FM_READONLY) {
  844.     if(!verifyToken($_POST['token'])) {
  845.         fm_set_msg("Invalid Token.", 'error');
  846.     }
  847.     // old name
  848.     $old = urldecode($_POST['rename_from']);
  849.     $old = fm_clean_path($old);
  850.     $old = str_replace('/', '', $old);
  851.     // new name
  852.     $new = urldecode($_POST['rename_to']);
  853.     $new = fm_clean_path(strip_tags($new));
  854.     $new = str_replace('/', '', $new);
  855.     // path
  856.     $path = FM_ROOT_PATH;
  857.     if (FM_PATH != '') {
  858.         $path .= '/' . FM_PATH;
  859.     }
  860.     // rename
  861.     if (fm_isvalid_filename($new) && $old != '' && $new != '') {
  862.         if (fm_rename($path . '/' . $old, $path . '/' . $new)) {
  863.             fm_set_msg(sprintf(lng('Renamed from').' <b>%s</b> '. lng('to').' <b>%s</b>', fm_enc($old), fm_enc($new)));
  864.         } else {
  865.             fm_set_msg(sprintf(lng('Error while renaming from').' <b>%s</b> '. lng('to').' <b>%s</b>', fm_enc($old), fm_enc($new)), 'error');
  866.         }
  867.     } else {
  868.         fm_set_msg(lng('Invalid characters in file name'), 'error');
  869.     }
  870.     $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
  871. }
  872.  
  873. // Download
  874. if (isset($_GET['dl'], $_POST['token'])) {
  875.     if(!verifyToken($_POST['token'])) {
  876.         fm_set_msg("Invalid Token.", 'error');
  877.     }
  878.  
  879.     $dl = urldecode($_GET['dl']);
  880.     $dl = fm_clean_path($dl);
  881.     $dl = str_replace('/', '', $dl);
  882.     $path = FM_ROOT_PATH;
  883.     if (FM_PATH != '') {
  884.         $path .= '/' . FM_PATH;
  885.     }
  886.     if ($dl != '' && is_file($path . '/' . $dl)) {
  887.         fm_download_file($path . '/' . $dl, $dl, 1024);
  888.         exit;
  889.     } else {
  890.         fm_set_msg(lng('File not found'), 'error');
  891.         $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
  892.     }
  893. }
  894.  
  895. // Upload
  896. if (!empty($_FILES) && !FM_READONLY) {
  897.     if(isset($_POST['token'])) {
  898.         if(!verifyToken($_POST['token'])) {
  899.             $response = array ('status' => 'error','info' => "Invalid Token.");
  900.             echo json_encode($response); exit();
  901.         }
  902.     } else {
  903.         $response = array ('status' => 'error','info' => "Token Missing.");
  904.         echo json_encode($response); exit();
  905.     }
  906.  
  907.     $override_file_name = false;
  908.     $chunkIndex = $_POST['dzchunkindex'];
  909.     $chunkTotal = $_POST['dztotalchunkcount'];
  910.     $fullPathInput = fm_clean_path($_REQUEST['fullpath']);
  911.  
  912.     $f = $_FILES;
  913.     $path = FM_ROOT_PATH;
  914.     $ds = DIRECTORY_SEPARATOR;
  915.     if (FM_PATH != '') {
  916.         $path .= '/' . FM_PATH;
  917.     }
  918.  
  919.     $errors = 0;
  920.     $uploads = 0;
  921.     $allowed = (FM_UPLOAD_EXTENSION) ? explode(',', FM_UPLOAD_EXTENSION) : false;
  922.     $response = array (
  923.         'status' => 'error',
  924.         'info'   => 'Oops! Try again'
  925.     );
  926.  
  927.     $filename = $f['file']['name'];
  928.     $tmp_name = $f['file']['tmp_name'];
  929.     $ext = pathinfo($filename, PATHINFO_FILENAME) != '' ? strtolower(pathinfo($filename, PATHINFO_EXTENSION)) : '';
  930.     $isFileAllowed = ($allowed) ? in_array($ext, $allowed) : true;
  931.  
  932.     if(!fm_isvalid_filename($filename) && !fm_isvalid_filename($fullPathInput)) {
  933.         $response = array (
  934.             'status'    => 'error',
  935.             'info'      => "Invalid File name!",
  936.         );
  937.         echo json_encode($response); exit();
  938.     }
  939.  
  940.     $targetPath = $path . $ds;
  941.     if ( is_writable($targetPath) ) {
  942.         $fullPath = $path . '/' . basename($fullPathInput);
  943.         $folder = substr($fullPath, 0, strrpos($fullPath, "/"));
  944.  
  945.         if(file_exists ($fullPath) && !$override_file_name && !$chunks) {
  946.             $ext_1 = $ext ? '.'.$ext : '';
  947.             $fullPath = $path . '/' . basename($fullPathInput, $ext_1) .'_'. date('ymdHis'). $ext_1;
  948.         }
  949.  
  950.         if (!is_dir($folder)) {
  951.             $old = umask(0);
  952.             mkdir($folder, 0777, true);
  953.             umask($old);
  954.         }
  955.  
  956.         if (empty($f['file']['error']) && !empty($tmp_name) && $tmp_name != 'none' && $isFileAllowed) {
  957.             if ($chunkTotal){
  958.                 $out = @fopen("{$fullPath}.part", $chunkIndex == 0 ? "wb" : "ab");
  959.                 if ($out) {
  960.                     $in = @fopen($tmp_name, "rb");
  961.                     if ($in) {
  962.                         while ($buff = fread($in, 4096)) { fwrite($out, $buff); }
  963.                         $response = array (
  964.                             'status'    => 'success',
  965.                             'info' => "file upload successful"
  966.                         );
  967.                     } else {
  968.                         $response = array (
  969.                         'status'    => 'error',
  970.                         'info' => "failed to open output stream",
  971.                         'errorDetails' => error_get_last()
  972.                         );
  973.                     }
  974.                     @fclose($in);
  975.                     @fclose($out);
  976.                     @unlink($tmp_name);
  977.  
  978.                     $response = array (
  979.                         'status'    => 'success',
  980.                         'info' => "file upload successful"
  981.                     );
  982.                 } else {
  983.                     $response = array (
  984.                         'status'    => 'error',
  985.                         'info' => "failed to open output stream"
  986.                         );
  987.                 }
  988.  
  989.                 if ($chunkIndex == $chunkTotal - 1) {
  990.                     rename("{$fullPath}.part", $fullPath);
  991.                 }
  992.  
  993.             } else if (move_uploaded_file($tmp_name, $fullPath)) {
  994.                 // Be sure that the file has been uploaded
  995.                 if ( file_exists($fullPath) ) {
  996.                     $response = array (
  997.                         'status'    => 'success',
  998.                         'info' => "file upload successful"
  999.                     );
  1000.                 } else {
  1001.                     $response = array (
  1002.                         'status' => 'error',
  1003.                         'info'   => 'Couldn\'t upload the requested file.'
  1004.                     );
  1005.                 }
  1006.             } else {
  1007.                 $response = array (
  1008.                     'status'    => 'error',
  1009.                     'info'      => "Error while uploading files. Uploaded files $uploads",
  1010.                 );
  1011.             }
  1012.         }
  1013.     } else {
  1014.         $response = array (
  1015.             'status' => 'error',
  1016.             'info'   => 'The specified folder for upload isn\'t writeable.'
  1017.         );
  1018.     }
  1019.     // Return the response
  1020.     echo json_encode($response);
  1021.     exit();
  1022. }
  1023.  
  1024. // Mass deleting
  1025. if (isset($_POST['group'], $_POST['delete'], $_POST['token']) && !FM_READONLY) {
  1026.  
  1027.     if(!verifyToken($_POST['token'])) {
  1028.         fm_set_msg(lng("Invalid Token."), 'error');
  1029.     }
  1030.  
  1031.     $path = FM_ROOT_PATH;
  1032.     if (FM_PATH != '') {
  1033.         $path .= '/' . FM_PATH;
  1034.     }
  1035.  
  1036.     $errors = 0;
  1037.     $files = $_POST['file'];
  1038.     if (is_array($files) && count($files)) {
  1039.         foreach ($files as $f) {
  1040.             if ($f != '') {
  1041.                 $new_path = $path . '/' . $f;
  1042.                 if (!fm_rdelete($new_path)) {
  1043.                     $errors++;
  1044.                 }
  1045.             }
  1046.         }
  1047.         if ($errors == 0) {
  1048.             fm_set_msg(lng('Selected files and folder deleted'));
  1049.         } else {
  1050.             fm_set_msg(lng('Error while deleting items'), 'error');
  1051.         }
  1052.     } else {
  1053.         fm_set_msg(lng('Nothing selected'), 'alert');
  1054.     }
  1055.  
  1056.     $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
  1057. }
  1058.  
  1059. // Pack files zip, tar
  1060. if (isset($_POST['group'], $_POST['token']) && (isset($_POST['zip']) || isset($_POST['tar'])) && !FM_READONLY) {
  1061.  
  1062.     if(!verifyToken($_POST['token'])) {
  1063.         fm_set_msg(lng("Invalid Token."), 'error');
  1064.     }
  1065.  
  1066.     $path = FM_ROOT_PATH;
  1067.     $ext = 'zip';
  1068.     if (FM_PATH != '') {
  1069.         $path .= '/' . FM_PATH;
  1070.     }
  1071.  
  1072.     //set pack type
  1073.     $ext = isset($_POST['tar']) ? 'tar' : 'zip';
  1074.  
  1075.     if (($ext == "zip" && !class_exists('ZipArchive')) || ($ext == "tar" && !class_exists('PharData'))) {
  1076.         fm_set_msg(lng('Operations with archives are not available'), 'error');
  1077.         $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
  1078.     }
  1079.  
  1080.     $files = $_POST['file'];
  1081.     if (!empty($files)) {
  1082.         chdir($path);
  1083.  
  1084.         if (count($files) == 1) {
  1085.             $one_file = reset($files);
  1086.             $one_file = basename($one_file);
  1087.             $zipname = $one_file . '_' . date('ymd_His') . '.'.$ext;
  1088.         } else {
  1089.             $zipname = 'archive_' . date('ymd_His') . '.'.$ext;
  1090.         }
  1091.  
  1092.         if($ext == 'zip') {
  1093.             $zipper = new FM_Zipper();
  1094.             $res = $zipper->create($zipname, $files);
  1095.         } elseif ($ext == 'tar') {
  1096.             $tar = new FM_Zipper_Tar();
  1097.             $res = $tar->create($zipname, $files);
  1098.         }
  1099.  
  1100.         if ($res) {
  1101.             fm_set_msg(sprintf(lng('Archive').' <b>%s</b> '.lng('Created'), fm_enc($zipname)));
  1102.         } else {
  1103.             fm_set_msg(lng('Archive not created'), 'error');
  1104.         }
  1105.     } else {
  1106.         fm_set_msg(lng('Nothing selected'), 'alert');
  1107.     }
  1108.  
  1109.     $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
  1110. }
  1111.  
  1112. // Unpack zip, tar
  1113. if (isset($_POST['unzip'], $_POST['token']) && !FM_READONLY) {
  1114.  
  1115.     if(!verifyToken($_POST['token'])) {
  1116.         fm_set_msg(lng("Invalid Token."), 'error');
  1117.     }
  1118.  
  1119.     $unzip = urldecode($_POST['unzip']);
  1120.     $unzip = fm_clean_path($unzip);
  1121.     $unzip = str_replace('/', '', $unzip);
  1122.     $isValid = false;
  1123.  
  1124.     $path = FM_ROOT_PATH;
  1125.     if (FM_PATH != '') {
  1126.         $path .= '/' . FM_PATH;
  1127.     }
  1128.  
  1129.     if ($unzip != '' && is_file($path . '/' . $unzip)) {
  1130.         $zip_path = $path . '/' . $unzip;
  1131.         $ext = pathinfo($zip_path, PATHINFO_EXTENSION);
  1132.         $isValid = true;
  1133.     } else {
  1134.         fm_set_msg(lng('File not found'), 'error');
  1135.     }
  1136.  
  1137.     if (($ext == "zip" && !class_exists('ZipArchive')) || ($ext == "tar" && !class_exists('PharData'))) {
  1138.         fm_set_msg(lng('Operations with archives are not available'), 'error');
  1139.         $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
  1140.     }
  1141.  
  1142.     if ($isValid) {
  1143.         //to folder
  1144.         $tofolder = '';
  1145.         if (isset($_POST['tofolder'])) {
  1146.             $tofolder = pathinfo($zip_path, PATHINFO_FILENAME);
  1147.             if (fm_mkdir($path . '/' . $tofolder, true)) {
  1148.                 $path .= '/' . $tofolder;
  1149.             }
  1150.         }
  1151.  
  1152.         if($ext == "zip") {
  1153.             $zipper = new FM_Zipper();
  1154.             $res = $zipper->unzip($zip_path, $path);
  1155.         } elseif ($ext == "tar") {
  1156.             try {
  1157.                 $gzipper = new PharData($zip_path);
  1158.                 if (@$gzipper->extractTo($path,null, true)) {
  1159.                     $res = true;
  1160.                 } else {
  1161.                     $res = false;
  1162.                 }
  1163.             } catch (Exception $e) {
  1164.                 //TODO:: need to handle the error
  1165.                 $res = true;
  1166.             }
  1167.         }
  1168.  
  1169.         if ($res) {
  1170.             fm_set_msg(lng('Archive unpacked'));
  1171.         } else {
  1172.             fm_set_msg(lng('Archive not unpacked'), 'error');
  1173.         }
  1174.     } else {
  1175.         fm_set_msg(lng('File not found'), 'error');
  1176.     }
  1177.     $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
  1178. }
  1179.  
  1180. // Change Perms (not for Windows)
  1181. if (isset($_POST['chmod'], $_POST['token']) && !FM_READONLY && !FM_IS_WIN) {
  1182.  
  1183.     if(!verifyToken($_POST['token'])) {
  1184.         fm_set_msg(lng("Invalid Token."), 'error');
  1185.     }
  1186.    
  1187.     $path = FM_ROOT_PATH;
  1188.     if (FM_PATH != '') {
  1189.         $path .= '/' . FM_PATH;
  1190.     }
  1191.  
  1192.     $file = $_POST['chmod'];
  1193.     $file = fm_clean_path($file);
  1194.     $file = str_replace('/', '', $file);
  1195.     if ($file == '' || (!is_file($path . '/' . $file) && !is_dir($path . '/' . $file))) {
  1196.         fm_set_msg(lng('File not found'), 'error');
  1197.         $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
  1198.     }
  1199.  
  1200.     $mode = 0;
  1201.     if (!empty($_POST['ur'])) {
  1202.         $mode |= 0400;
  1203.     }
  1204.     if (!empty($_POST['uw'])) {
  1205.         $mode |= 0200;
  1206.     }
  1207.     if (!empty($_POST['ux'])) {
  1208.         $mode |= 0100;
  1209.     }
  1210.     if (!empty($_POST['gr'])) {
  1211.         $mode |= 0040;
  1212.     }
  1213.     if (!empty($_POST['gw'])) {
  1214.         $mode |= 0020;
  1215.     }
  1216.     if (!empty($_POST['gx'])) {
  1217.         $mode |= 0010;
  1218.     }
  1219.     if (!empty($_POST['or'])) {
  1220.         $mode |= 0004;
  1221.     }
  1222.     if (!empty($_POST['ow'])) {
  1223.         $mode |= 0002;
  1224.     }
  1225.     if (!empty($_POST['ox'])) {
  1226.         $mode |= 0001;
  1227.     }
  1228.  
  1229.     if (@chmod($path . '/' . $file, $mode)) {
  1230.         fm_set_msg(lng('Permissions changed'));
  1231.     } else {
  1232.         fm_set_msg(lng('Permissions not changed'), 'error');
  1233.     }
  1234.  
  1235.     $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
  1236. }
  1237.  
  1238. /*************************** ACTIONS ***************************/
  1239.  
  1240. // get current path
  1241. $path = FM_ROOT_PATH;
  1242. if (FM_PATH != '') {
  1243.     $path .= '/' . FM_PATH;
  1244. }
  1245.  
  1246. // check path
  1247. if (!is_dir($path)) {
  1248.     fm_redirect(FM_SELF_URL . '?p=');
  1249. }
  1250.  
  1251. // get parent folder
  1252. $parent = fm_get_parent_path(FM_PATH);
  1253.  
  1254. $objects = is_readable($path) ? scandir($path) : array();
  1255. $folders = array();
  1256. $files = array();
  1257. $current_path = array_slice(explode("/",$path), -1)[0];
  1258. if (is_array($objects) && fm_is_exclude_items($current_path)) {
  1259.     foreach ($objects as $file) {
  1260.         if ($file == '.' || $file == '..') {
  1261.             continue;
  1262.         }
  1263.         if (!FM_SHOW_HIDDEN && substr($file, 0, 1) === '.') {
  1264.             continue;
  1265.         }
  1266.         $new_path = $path . '/' . $file;
  1267.         if (@is_file($new_path) && fm_is_exclude_items($file)) {
  1268.             $files[] = $file;
  1269.         } elseif (@is_dir($new_path) && $file != '.' && $file != '..' && fm_is_exclude_items($file)) {
  1270.             $folders[] = $file;
  1271.         }
  1272.     }
  1273. }
  1274.  
  1275. if (!empty($files)) {
  1276.     natcasesort($files);
  1277. }
  1278. if (!empty($folders)) {
  1279.     natcasesort($folders);
  1280. }
  1281.  
  1282. // upload form
  1283. if (isset($_GET['upload']) && !FM_READONLY) {
  1284.     fm_show_header(); // HEADER
  1285.     fm_show_nav_path(FM_PATH); // current path
  1286.     //get the allowed file extensions
  1287.     function getUploadExt() {
  1288.         $extArr = explode(',', FM_UPLOAD_EXTENSION);
  1289.         if(FM_UPLOAD_EXTENSION && $extArr) {
  1290.             array_walk($extArr, function(&$x) {$x = ".$x";});
  1291.             return implode(',', $extArr);
  1292.         }
  1293.         return '';
  1294.     }
  1295.     ?>
  1296.     <link href="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.9.3/min/dropzone.min.css" rel="stylesheet">
  1297.     <div class="path">
  1298.  
  1299.         <div class="card mb-2 fm-upload-wrapper <?php echo fm_get_theme(); ?>">
  1300.             <div class="card-header">
  1301.                 <ul class="nav nav-tabs card-header-tabs">
  1302.                     <li class="nav-item">
  1303.                         <a class="nav-link active" href="#fileUploader" data-target="#fileUploader"><i class="fa fa-arrow-circle-o-up"></i> <?php echo lng('UploadingFiles') ?></a>
  1304.                     </li>
  1305.                     <li class="nav-item">
  1306.                         <a class="nav-link" href="#urlUploader" class="js-url-upload" data-target="#urlUploader"><i class="fa fa-link"></i> <?php echo lng('Upload from URL') ?></a>
  1307.                     </li>
  1308.                 </ul>
  1309.             </div>
  1310.             <div class="card-body">
  1311.                 <p class="card-text">
  1312.                     <a href="?p=<?php echo FM_PATH ?>" class="float-right"><i class="fa fa-chevron-circle-left go-back"></i> <?php echo lng('Back')?></a>
  1313.                     <strong><?php echo lng('DestinationFolder') ?></strong>: <?php echo fm_enc(fm_convert_win(FM_PATH)) ?>
  1314.                 </p>
  1315.  
  1316.                 <form action="<?php echo htmlspecialchars(FM_SELF_URL) . '?p=' . fm_enc(FM_PATH) ?>" class="dropzone card-tabs-container" id="fileUploader" enctype="multipart/form-data">
  1317.                     <input type="hidden" name="p" value="<?php echo fm_enc(FM_PATH) ?>">
  1318.                     <input type="hidden" name="fullpath" id="fullpath" value="<?php echo fm_enc(FM_PATH) ?>">
  1319.                     <input type="hidden" name="token" value="<?php echo $_SESSION['token']; ?>">
  1320.                     <div class="fallback">
  1321.                         <input name="file" type="file" multiple/>
  1322.                     </div>
  1323.                 </form>
  1324.  
  1325.                 <div class="upload-url-wrapper card-tabs-container hidden" id="urlUploader">
  1326.                     <form id="js-form-url-upload" class="row row-cols-lg-auto g-3 align-items-center" onsubmit="return upload_from_url(this);" method="POST" action="">
  1327.                         <input type="hidden" name="type" value="upload" aria-label="hidden" aria-hidden="true">
  1328.                         <input type="url" placeholder="URL" name="uploadurl" required class="form-control" style="width: 80%">
  1329.                         <input type="hidden" name="token" value="<?php echo $_SESSION['token']; ?>">
  1330.                         <button type="submit" class="btn btn-primary ms-3"><?php echo lng('Upload') ?></button>
  1331.                         <div class="lds-facebook"><div></div><div></div><div></div></div>
  1332.                     </form>
  1333.                     <div id="js-url-upload__list" class="col-9 mt-3"></div>
  1334.                 </div>
  1335.             </div>
  1336.         </div>
  1337.     </div>
  1338.     <script src="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.9.3/min/dropzone.min.js"></script>
  1339.     <script>
  1340.         Dropzone.options.fileUploader = {
  1341.             chunking: true,
  1342.             chunkSize: 2000000, // chunk size 2,000,000 bytes (~2MB)
  1343.             forceChunking: true,
  1344.             retryChunks: true,
  1345.             retryChunksLimit: 3,
  1346.             parallelUploads: 1,
  1347.             parallelChunkUploads: false,
  1348.             timeout: 120000,
  1349.             maxFilesize: "<?php echo MAX_UPLOAD_SIZE; ?>",
  1350.             acceptedFiles : "<?php echo getUploadExt() ?>",
  1351.             init: function () {
  1352.                 this.on("sending", function (file, xhr, formData) {
  1353.                     let _path = (file.fullPath) ? file.fullPath : file.name;
  1354.                     document.getElementById("fullpath").value = _path;
  1355.                     xhr.ontimeout = (function() {
  1356.                         toast('Error: Server Timeout');
  1357.                     });
  1358.                 }).on("success", function (res) {
  1359.                     let _response = JSON.parse(res.xhr.response);
  1360.  
  1361.                     if(_response.status == "error") {
  1362.                         toast(_response.info);
  1363.                     }
  1364.                 }).on("error", function(file, response) {
  1365.                     toast(response);
  1366.                 });
  1367.             }
  1368.         }
  1369.     </script>
  1370.     <?php
  1371.     fm_show_footer();
  1372.     exit;
  1373. }
  1374.  
  1375. // copy form POST
  1376. if (isset($_POST['copy']) && !FM_READONLY) {
  1377.     $copy_files = isset($_POST['file']) ? $_POST['file'] : null;
  1378.     if (!is_array($copy_files) || empty($copy_files)) {
  1379.         fm_set_msg(lng('Nothing selected'), 'alert');
  1380.         $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
  1381.     }
  1382.  
  1383.     fm_show_header(); // HEADER
  1384.     fm_show_nav_path(FM_PATH); // current path
  1385.     ?>
  1386.     <div class="path">
  1387.         <div class="card <?php echo fm_get_theme(); ?>">
  1388.             <div class="card-header">
  1389.                 <h6><?php echo lng('Copying') ?></h6>
  1390.             </div>
  1391.             <div class="card-body">
  1392.                 <form action="" method="post">
  1393.                     <input type="hidden" name="p" value="<?php echo fm_enc(FM_PATH) ?>">
  1394.                     <input type="hidden" name="finish" value="1">
  1395.                     <?php
  1396.                     foreach ($copy_files as $cf) {
  1397.                         echo '<input type="hidden" name="file[]" value="' . fm_enc($cf) . '">' . PHP_EOL;
  1398.                     }
  1399.                     ?>
  1400.                     <p class="break-word"><strong><?php echo lng('Files') ?></strong>: <b><?php echo implode('</b>, <b>', $copy_files) ?></b></p>
  1401.                     <p class="break-word"><strong><?php echo lng('SourceFolder') ?></strong>: <?php echo fm_enc(fm_convert_win(FM_ROOT_PATH . '/' . FM_PATH)) ?><br>
  1402.                         <label for="inp_copy_to"><strong><?php echo lng('DestinationFolder') ?></strong>:</label>
  1403.                         <?php echo FM_ROOT_PATH ?>/<input type="text" name="copy_to" id="inp_copy_to" value="<?php echo fm_enc(FM_PATH) ?>">
  1404.                     </p>
  1405.                     <p class="custom-checkbox custom-control"><input type="checkbox" name="move" value="1" id="js-move-files" class="custom-control-input"><label for="js-move-files" class="custom-control-label ms-2"> <?php echo lng('Move') ?></label></p>
  1406.                     <p>
  1407.                         <b><a href="?p=<?php echo urlencode(FM_PATH) ?>" class="btn btn-outline-danger"><i class="fa fa-times-circle"></i> <?php echo lng('Cancel') ?></a></b>&nbsp;
  1408.                         <input type="hidden" name="token" value="<?php echo $_SESSION['token']; ?>">
  1409.                         <button type="submit" class="btn btn-success"><i class="fa fa-check-circle"></i> <?php echo lng('Copy') ?></button>
  1410.                     </p>
  1411.                 </form>
  1412.             </div>
  1413.         </div>
  1414.     </div>
  1415.     <?php
  1416.     fm_show_footer();
  1417.     exit;
  1418. }
  1419.  
  1420. // copy form
  1421. if (isset($_GET['copy']) && !isset($_GET['finish']) && !FM_READONLY) {
  1422.     $copy = $_GET['copy'];
  1423.     $copy = fm_clean_path($copy);
  1424.     if ($copy == '' || !file_exists(FM_ROOT_PATH . '/' . $copy)) {
  1425.         fm_set_msg(lng('File not found'), 'error');
  1426.         $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
  1427.     }
  1428.  
  1429.     fm_show_header(); // HEADER
  1430.     fm_show_nav_path(FM_PATH); // current path
  1431.     ?>
  1432.     <div class="path">
  1433.         <p><b>Copying</b></p>
  1434.         <p class="break-word">
  1435.             <strong>Source path:</strong> <?php echo fm_enc(fm_convert_win(FM_ROOT_PATH . '/' . $copy)) ?><br>
  1436.             <strong>Destination folder:</strong> <?php echo fm_enc(fm_convert_win(FM_ROOT_PATH . '/' . FM_PATH)) ?>
  1437.         </p>
  1438.         <p>
  1439.             <b><a href="?p=<?php echo urlencode(FM_PATH) ?>&amp;copy=<?php echo urlencode($copy) ?>&amp;finish=1"><i class="fa fa-check-circle"></i> Copy</a></b> &nbsp;
  1440.             <b><a href="?p=<?php echo urlencode(FM_PATH) ?>&amp;copy=<?php echo urlencode($copy) ?>&amp;finish=1&amp;move=1"><i class="fa fa-check-circle"></i> Move</a></b> &nbsp;
  1441.             <b><a href="?p=<?php echo urlencode(FM_PATH) ?>" class="text-danger"><i class="fa fa-times-circle"></i> Cancel</a></b>
  1442.         </p>
  1443.         <p><i><?php echo lng('Select folder') ?></i></p>
  1444.         <ul class="folders break-word">
  1445.             <?php
  1446.             if ($parent !== false) {
  1447.                 ?>
  1448.                 <li><a href="?p=<?php echo urlencode($parent) ?>&amp;copy=<?php echo urlencode($copy) ?>"><i class="fa fa-chevron-circle-left"></i> ..</a></li>
  1449.                 <?php
  1450.             }
  1451.             foreach ($folders as $f) {
  1452.                 ?>
  1453.                 <li>
  1454.                     <a href="?p=<?php echo urlencode(trim(FM_PATH . '/' . $f, '/')) ?>&amp;copy=<?php echo urlencode($copy) ?>"><i class="fa fa-folder-o"></i> <?php echo fm_convert_win($f) ?></a></li>
  1455.                 <?php
  1456.             }
  1457.             ?>
  1458.         </ul>
  1459.     </div>
  1460.     <?php
  1461.     fm_show_footer();
  1462.     exit;
  1463. }
  1464.  
  1465. if (isset($_GET['settings']) && !FM_READONLY) {
  1466.     fm_show_header(); // HEADER
  1467.     fm_show_nav_path(FM_PATH); // current path
  1468.     global $cfg, $lang, $lang_list;
  1469.     ?>
  1470.  
  1471.     <div class="col-md-8 offset-md-2 pt-3">
  1472.         <div class="card mb-2 <?php echo fm_get_theme(); ?>">
  1473.             <h6 class="card-header d-flex justify-content-between">
  1474.                 <span><i class="fa fa-cog"></i>  <?php echo lng('Settings') ?></span>
  1475.                 <a href="?p=<?php echo FM_PATH ?>" class="text-danger"><i class="fa fa-times-circle-o"></i> <?php echo lng('Cancel')?></a>
  1476.             </h6>
  1477.             <div class="card-body">
  1478.                 <form id="js-settings-form" action="" method="post" data-type="ajax" onsubmit="return save_settings(this)">
  1479.                     <input type="hidden" name="type" value="settings" aria-label="hidden" aria-hidden="true">
  1480.                     <div class="form-group row">
  1481.                         <label for="js-language" class="col-sm-3 col-form-label"><?php echo lng('Language') ?></label>
  1482.                         <div class="col-sm-5">
  1483.                             <select class="form-select" id="js-language" name="js-language">
  1484.                                 <?php
  1485.                                 function getSelected($l) {
  1486.                                     global $lang;
  1487.                                     return ($lang == $l) ? 'selected' : '';
  1488.                                 }
  1489.                                 foreach ($lang_list as $k => $v) {
  1490.                                     echo "<option value='$k' ".getSelected($k).">$v</option>";
  1491.                                 }
  1492.                                 ?>
  1493.                             </select>
  1494.                         </div>
  1495.                     </div>
  1496.                     <div class="mt-3 mb-3 row ">
  1497.                         <label for="js-error-report" class="col-sm-3 col-form-label"><?php echo lng('ErrorReporting') ?></label>
  1498.                         <div class="col-sm-9">
  1499.                             <div class="form-check form-switch">
  1500.                               <input class="form-check-input" type="checkbox" role="switch" id="js-error-report" name="js-error-report" value="true" <?php echo $report_errors ? 'checked' : ''; ?> />
  1501.                             </div>
  1502.                         </div>
  1503.                     </div>
  1504.  
  1505.                     <div class="mb-3 row">
  1506.                         <label for="js-show-hidden" class="col-sm-3 col-form-label"><?php echo lng('ShowHiddenFiles') ?></label>
  1507.                         <div class="col-sm-9">
  1508.                             <div class="form-check form-switch">
  1509.                               <input class="form-check-input" type="checkbox" role="switch" id="js-show-hidden" name="js-show-hidden" value="true" <?php echo $show_hidden_files ? 'checked' : ''; ?> />
  1510.                             </div>
  1511.                         </div>
  1512.                     </div>
  1513.  
  1514.                     <div class="mb-3 row">
  1515.                         <label for="js-hide-cols" class="col-sm-3 col-form-label"><?php echo lng('HideColumns') ?></label>
  1516.                         <div class="col-sm-9">
  1517.                             <div class="form-check form-switch">
  1518.                               <input class="form-check-input" type="checkbox" role="switch" id="js-hide-cols" name="js-hide-cols" value="true" <?php echo $hide_Cols ? 'checked' : ''; ?> />
  1519.                             </div>
  1520.                         </div>
  1521.                     </div>
  1522.  
  1523.                     <div class="mb-3 row">
  1524.                         <label for="js-3-1" class="col-sm-3 col-form-label"><?php echo lng('Theme') ?></label>
  1525.                         <div class="col-sm-5">
  1526.                             <select class="form-select w-100" id="js-3-0" name="js-theme-3">
  1527.                                 <option value='light' <?php if($theme == "light"){echo "selected";} ?>><?php echo lng('light') ?></option>
  1528.                                 <option value='dark' <?php if($theme == "dark"){echo "selected";} ?>><?php echo lng('dark') ?></option>
  1529.                             </select>
  1530.                         </div>
  1531.                     </div>
  1532.  
  1533.                     <div class="mb-3 row">
  1534.                         <div class="col-sm-10">
  1535.                             <button type="submit" class="btn btn-success"> <i class="fa fa-check-circle"></i> <?php echo lng('Save'); ?></button>
  1536.                         </div>
  1537.                     </div>
  1538.  
  1539.                 </form>
  1540.             </div>
  1541.         </div>
  1542.     </div>
  1543.     <?php
  1544.     fm_show_footer();
  1545.     exit;
  1546. }
  1547.  
  1548. if (isset($_GET['help'])) {
  1549.     fm_show_header(); // HEADER
  1550.     fm_show_nav_path(FM_PATH); // current path
  1551.     global $cfg, $lang;
  1552.     ?>
  1553.  
  1554.     <div class="col-md-8 offset-md-2 pt-3">
  1555.         <div class="card mb-2 <?php echo fm_get_theme(); ?>">
  1556.             <h6 class="card-header d-flex justify-content-between">
  1557.                 <span><i class="fa fa-exclamation-circle"></i> <?php echo lng('Help') ?></span>
  1558.                 <a href="?p=<?php echo FM_PATH ?>" class="text-danger"><i class="fa fa-times-circle-o"></i> <?php echo lng('Cancel')?></a>
  1559.             </h6>
  1560.             <div class="card-body">
  1561.                 <div class="row">
  1562.                     <div class="col-xs-12 col-sm-6">
  1563.                         <p><h3><a href="https://github.com/prasathmani/tinyfilemanager" target="_blank" class="app-v-title"> Tiny File Manager <?php echo VERSION; ?></a></h3></p>
  1564.                         <p>Author: Prasath Mani</p>
  1565.                         <p>Mail Us: <a href="mailto:ccpprogrammers@gmail.com">ccpprogrammers[at]gmail.com</a> </p>
  1566.                     </div>
  1567.                     <div class="col-xs-12 col-sm-6">
  1568.                         <div class="card">
  1569.                             <ul class="list-group list-group-flush">
  1570.                                 <li class="list-group-item"><a href="https://github.com/prasathmani/tinyfilemanager/wiki" target="_blank"><i class="fa fa-question-circle"></i> <?php echo lng('Help Documents') ?> </a> </li>
  1571.                                 <li class="list-group-item"><a href="https://github.com/prasathmani/tinyfilemanager/issues" target="_blank"><i class="fa fa-bug"></i> <?php echo lng('Report Issue') ?></a></li>
  1572.                                 <?php if(!FM_READONLY) { ?>
  1573.                                 <li class="list-group-item"><a href="javascript:show_new_pwd();"><i class="fa fa-lock"></i> <?php echo lng('Generate new password hash') ?></a></li>
  1574.                                 <?php } ?>
  1575.                             </ul>
  1576.                         </div>
  1577.                     </div>
  1578.                 </div>
  1579.                 <div class="row js-new-pwd hidden mt-2">
  1580.                     <div class="col-12">
  1581.                         <form class="form-inline" onsubmit="return new_password_hash(this)" method="POST" action="">
  1582.                             <input type="hidden" name="type" value="pwdhash" aria-label="hidden" aria-hidden="true">
  1583.                             <div class="form-group mb-2">
  1584.                                 <label for="staticEmail2"><?php echo lng('Generate new password hash') ?></label>
  1585.                             </div>
  1586.                             <div class="form-group mx-sm-3 mb-2">
  1587.                                 <label for="inputPassword2" class="sr-only"><?php echo lng('Password') ?></label>
  1588.                                 <input type="text" class="form-control btn-sm" id="inputPassword2" name="inputPassword2" placeholder="<?php echo lng('Password') ?>" required>
  1589.                             </div>
  1590.                             <button type="submit" class="btn btn-success btn-sm mb-2"><?php echo lng('Generate') ?></button>
  1591.                         </form>
  1592.                         <textarea class="form-control" rows="2" readonly id="js-pwd-result"></textarea>
  1593.                     </div>
  1594.                 </div>
  1595.             </div>
  1596.         </div>
  1597.     </div>
  1598.     <?php
  1599.     fm_show_footer();
  1600.     exit;
  1601. }
  1602.  
  1603. // file viewer
  1604. if (isset($_GET['view'])) {
  1605.     $file = $_GET['view'];
  1606.     $file = fm_clean_path($file, false);
  1607.     $file = str_replace('/', '', $file);
  1608.     if ($file == '' || !is_file($path . '/' . $file) || in_array($file, $GLOBALS['exclude_items'])) {
  1609.         fm_set_msg(lng('File not found'), 'error');
  1610.         $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
  1611.     }
  1612.  
  1613.     fm_show_header(); // HEADER
  1614.     fm_show_nav_path(FM_PATH); // current path
  1615.  
  1616.     $file_url = FM_ROOT_URL . fm_convert_win((FM_PATH != '' ? '/' . FM_PATH : '') . '/' . $file);
  1617.     $file_path = $path . '/' . $file;
  1618.  
  1619.     $ext = strtolower(pathinfo($file_path, PATHINFO_EXTENSION));
  1620.     $mime_type = fm_get_mime_type($file_path);
  1621.     $filesize_raw = fm_get_size($file_path);
  1622.     $filesize = fm_get_filesize($filesize_raw);
  1623.  
  1624.     $is_zip = false;
  1625.     $is_gzip = false;
  1626.     $is_image = false;
  1627.     $is_audio = false;
  1628.     $is_video = false;
  1629.     $is_text = false;
  1630.     $is_onlineViewer = false;
  1631.  
  1632.     $view_title = 'File';
  1633.     $filenames = false; // for zip
  1634.     $content = ''; // for text
  1635.     $online_viewer = strtolower(FM_DOC_VIEWER);
  1636.  
  1637.     if($online_viewer && $online_viewer !== 'false' && in_array($ext, fm_get_onlineViewer_exts())){
  1638.         $is_onlineViewer = true;
  1639.     }
  1640.     elseif ($ext == 'zip' || $ext == 'tar') {
  1641.         $is_zip = true;
  1642.         $view_title = 'Archive';
  1643.         $filenames = fm_get_zif_info($file_path, $ext);
  1644.     } elseif (in_array($ext, fm_get_image_exts())) {
  1645.         $is_image = true;
  1646.         $view_title = 'Image';
  1647.     } elseif (in_array($ext, fm_get_audio_exts())) {
  1648.         $is_audio = true;
  1649.         $view_title = 'Audio';
  1650.     } elseif (in_array($ext, fm_get_video_exts())) {
  1651.         $is_video = true;
  1652.         $view_title = 'Video';
  1653.     } elseif (in_array($ext, fm_get_text_exts()) || substr($mime_type, 0, 4) == 'text' || in_array($mime_type, fm_get_text_mimes())) {
  1654.         $is_text = true;
  1655.         $content = file_get_contents($file_path);
  1656.     }
  1657.  
  1658.     ?>
  1659.     <div class="row">
  1660.         <div class="col-12">
  1661.             <p class="break-word"><b><?php echo lng($view_title) ?> "<?php echo fm_enc(fm_convert_win($file)) ?>"</b></p>
  1662.             <p class="break-word">
  1663.                 <strong>Full path:</strong> <?php echo fm_enc(fm_convert_win($file_path)) ?><br>
  1664.                 <strong>File size:</strong> <?php echo ($filesize_raw <= 1000) ? "$filesize_raw bytes" : $filesize; ?><br>
  1665.                 <strong>MIME-type:</strong> <?php echo $mime_type ?><br>
  1666.                 <?php
  1667.                 // ZIP info
  1668.                 if (($is_zip || $is_gzip) && $filenames !== false) {
  1669.                     $total_files = 0;
  1670.                     $total_comp = 0;
  1671.                     $total_uncomp = 0;
  1672.                     foreach ($filenames as $fn) {
  1673.                         if (!$fn['folder']) {
  1674.                             $total_files++;
  1675.                         }
  1676.                         $total_comp += $fn['compressed_size'];
  1677.                         $total_uncomp += $fn['filesize'];
  1678.                     }
  1679.                     ?>
  1680.                     <?php echo lng('Files in archive') ?>: <?php echo $total_files ?><br>
  1681.                     <?php echo lng('Total size') ?>: <?php echo fm_get_filesize($total_uncomp) ?><br>
  1682.                     <?php echo lng('Size in archive') ?>: <?php echo fm_get_filesize($total_comp) ?><br>
  1683.                     <?php echo lng('Compression') ?>: <?php echo round(($total_comp / max($total_uncomp, 1)) * 100) ?>%<br>
  1684.                     <?php
  1685.                 }
  1686.                 // Image info
  1687.                 if ($is_image) {
  1688.                     $image_size = getimagesize($file_path);
  1689.                     echo lng('Image sizes').': ' . (isset($image_size[0]) ? $image_size[0] : '0') . ' x ' . (isset($image_size[1]) ? $image_size[1] : '0') . '<br>';
  1690.                 }
  1691.                 // Text info
  1692.                 if ($is_text) {
  1693.                     $is_utf8 = fm_is_utf8($content);
  1694.                     if (function_exists('iconv')) {
  1695.                         if (!$is_utf8) {
  1696.                             $content = iconv(FM_ICONV_INPUT_ENC, 'UTF-8//IGNORE', $content);
  1697.                         }
  1698.                     }
  1699.                     echo '<strong>'.lng('Charset').':</strong> ' . ($is_utf8 ? 'utf-8' : '8 bit') . '<br>';
  1700.                 }
  1701.                 ?>
  1702.             </p>
  1703.             <div class="d-flex align-items-center mb-3">
  1704.                 <form method="post" class="d-inline ms-2" action="?p=<?php echo urlencode(FM_PATH) ?>&amp;dl=<?php echo urlencode($file) ?>">
  1705.                     <input type="hidden" name="token" value="<?php echo $_SESSION['token']; ?>">
  1706.                     <button type="submit" class="btn btn-link text-decoration-none fw-bold p-0"><i class="fa fa-cloud-download"></i> <?php echo lng('Download') ?></button> &nbsp;
  1707.                 </form>
  1708.                 <b class="ms-2"><a href="<?php echo fm_enc($file_url) ?>" target="_blank"><i class="fa fa-external-link-square"></i> <?php echo lng('Open') ?></a></b>
  1709.                 <?php
  1710.                 // ZIP actions
  1711.                 if (!FM_READONLY && ($is_zip || $is_gzip) && $filenames !== false) {
  1712.                     $zip_name = pathinfo($file_path, PATHINFO_FILENAME);
  1713.                     ?>
  1714.                     <form method="post" class="d-inline ms-2">
  1715.                         <input type="hidden" name="token" value="<?php echo $_SESSION['token']; ?>">
  1716.                         <input type="hidden" name="unzip" value="<?php echo urlencode($file); ?>">
  1717.                         <button type="submit" class="btn btn-link text-decoration-none fw-bold p-0" style="font-size: 14px;"><i class="fa fa-check-circle"></i> <?php echo lng('UnZip') ?></button>
  1718.                     </form>&nbsp;
  1719.                     <form method="post" class="d-inline ms-2">
  1720.                         <input type="hidden" name="token" value="<?php echo $_SESSION['token']; ?>">
  1721.                         <input type="hidden" name="unzip" value="<?php echo urlencode($file); ?>">
  1722.                         <input type="hidden" name="tofolder" value="1">
  1723.                         <button type="submit" class="btn btn-link text-decoration-none fw-bold p-0" style="font-size: 14px;" title="UnZip to <?php echo fm_enc($zip_name) ?>"><i class="fa fa-check-circle"></i> <?php echo lng('UnZipToFolder') ?></button>
  1724.                     </form>&nbsp;
  1725.                     <?php
  1726.                 }
  1727.                 if ($is_text && !FM_READONLY) {
  1728.                     ?>
  1729.                     <b class="ms-2"><a href="?p=<?php echo urlencode(trim(FM_PATH)) ?>&amp;edit=<?php echo urlencode($file) ?>" class="edit-file"><i class="fa fa-pencil-square"></i> <?php echo lng('Edit') ?>
  1730.                         </a></b> &nbsp;
  1731.                     <b class="ms-2"><a href="?p=<?php echo urlencode(trim(FM_PATH)) ?>&amp;edit=<?php echo urlencode($file) ?>&env=ace"
  1732.                             class="edit-file"><i class="fa fa-pencil-square-o"></i> <?php echo lng('AdvancedEditor') ?>
  1733.                         </a></b> &nbsp;
  1734.                 <?php } ?>
  1735.                 <b class="ms-2"><a href="?p=<?php echo urlencode(FM_PATH) ?>"><i class="fa fa-chevron-circle-left go-back"></i> <?php echo lng('Back') ?></a></b>
  1736.             </div>
  1737.             <?php
  1738.             if($is_onlineViewer) {
  1739.                 if($online_viewer == 'google') {
  1740.                     echo '<iframe src="https://docs.google.com/viewer?embedded=true&hl=en&url=' . fm_enc($file_url) . '" frameborder="no" style="width:100%;min-height:460px"></iframe>';
  1741.                 } else if($online_viewer == 'microsoft') {
  1742.                     echo '<iframe src="https://view.officeapps.live.com/op/embed.aspx?src=' . fm_enc($file_url) . '" frameborder="no" style="width:100%;min-height:460px"></iframe>';
  1743.                 }
  1744.             } elseif ($is_zip) {
  1745.                 // ZIP content
  1746.                 if ($filenames !== false) {
  1747.                     echo '<code class="maxheight">';
  1748.                     foreach ($filenames as $fn) {
  1749.                         if ($fn['folder']) {
  1750.                             echo '<b>' . fm_enc($fn['name']) . '</b><br>';
  1751.                         } else {
  1752.                             echo $fn['name'] . ' (' . fm_get_filesize($fn['filesize']) . ')<br>';
  1753.                         }
  1754.                     }
  1755.                     echo '</code>';
  1756.                 } else {
  1757.                     echo '<p>'.lng('Error while fetching archive info').'</p>';
  1758.                 }
  1759.             } elseif ($is_image) {
  1760.                 // Image content
  1761.                 if (in_array($ext, array('gif', 'jpg', 'jpeg', 'png', 'bmp', 'ico', 'svg', 'webp', 'avif'))) {
  1762.                     echo '<p><img src="' . fm_enc($file_url) . '" alt="image" class="preview-img-container" class="preview-img"></p>';
  1763.                 }
  1764.             } elseif ($is_audio) {
  1765.                 // Audio content
  1766.                 echo '<p><audio src="' . fm_enc($file_url) . '" controls preload="metadata"></audio></p>';
  1767.             } elseif ($is_video) {
  1768.                 // Video content
  1769.                 echo '<div class="preview-video"><video src="' . fm_enc($file_url) . '" width="640" height="360" controls preload="metadata"></video></div>';
  1770.             } elseif ($is_text) {
  1771.                 if (FM_USE_HIGHLIGHTJS) {
  1772.                     // highlight
  1773.                     $hljs_classes = array(
  1774.                         'shtml' => 'xml',
  1775.                         'htaccess' => 'apache',
  1776.                         'phtml' => 'php',
  1777.                         'lock' => 'json',
  1778.                         'svg' => 'xml',
  1779.                     );
  1780.                     $hljs_class = isset($hljs_classes[$ext]) ? 'lang-' . $hljs_classes[$ext] : 'lang-' . $ext;
  1781.                     if (empty($ext) || in_array(strtolower($file), fm_get_text_names()) || preg_match('#\.min\.(css|js)$#i', $file)) {
  1782.                         $hljs_class = 'nohighlight';
  1783.                     }
  1784.                     $content = '<pre class="with-hljs"><code class="' . $hljs_class . '">' . fm_enc($content) . '</code></pre>';
  1785.                 } elseif (in_array($ext, array('php', 'php4', 'php5', 'phtml', 'phps'))) {
  1786.                     // php highlight
  1787.                     $content = highlight_string($content, true);
  1788.                 } else {
  1789.                     $content = '<pre>' . fm_enc($content) . '</pre>';
  1790.                 }
  1791.                 echo $content;
  1792.             }
  1793.             ?>
  1794.         </div>
  1795.     </div>
  1796.     <?php
  1797.         fm_show_footer();
  1798.     exit;
  1799. }
  1800.  
  1801. // file editor
  1802. if (isset($_GET['edit']) && !FM_READONLY) {
  1803.     $file = $_GET['edit'];
  1804.     $file = fm_clean_path($file, false);
  1805.     $file = str_replace('/', '', $file);
  1806.     if ($file == '' || !is_file($path . '/' . $file) || in_array($file, $GLOBALS['exclude_items'])) {
  1807.         fm_set_msg(lng('File not found'), 'error');
  1808.         $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
  1809.     }
  1810.     $editFile = ' : <i><b>'. $file. '</b></i>';
  1811.     header('X-XSS-Protection:0');
  1812.     fm_show_header(); // HEADER
  1813.     fm_show_nav_path(FM_PATH); // current path
  1814.  
  1815.     $file_url = FM_ROOT_URL . fm_convert_win((FM_PATH != '' ? '/' . FM_PATH : '') . '/' . $file);
  1816.     $file_path = $path . '/' . $file;
  1817.  
  1818.     // normal editer
  1819.     $isNormalEditor = true;
  1820.     if (isset($_GET['env'])) {
  1821.         if ($_GET['env'] == "ace") {
  1822.             $isNormalEditor = false;
  1823.         }
  1824.     }
  1825.  
  1826.     // Save File
  1827.     if (isset($_POST['savedata'])) {
  1828.         $writedata = $_POST['savedata'];
  1829.         $fd = fopen($file_path, "w");
  1830.         @fwrite($fd, $writedata);
  1831.         fclose($fd);
  1832.         fm_set_msg(lng('File Saved Successfully'));
  1833.     }
  1834.  
  1835.     $ext = strtolower(pathinfo($file_path, PATHINFO_EXTENSION));
  1836.     $mime_type = fm_get_mime_type($file_path);
  1837.     $filesize = filesize($file_path);
  1838.     $is_text = false;
  1839.     $content = ''; // for text
  1840.  
  1841.     if (in_array($ext, fm_get_text_exts()) || substr($mime_type, 0, 4) == 'text' || in_array($mime_type, fm_get_text_mimes())) {
  1842.         $is_text = true;
  1843.         $content = file_get_contents($file_path);
  1844.     }
  1845.  
  1846.     ?>
  1847.     <div class="path">
  1848.         <div class="row">
  1849.             <div class="col-xs-12 col-sm-5 col-lg-6 pt-1">
  1850.                 <div class="btn-toolbar" role="toolbar">
  1851.                     <?php if (!$isNormalEditor) { ?>
  1852.                         <div class="btn-group js-ace-toolbar">
  1853.                             <button data-cmd="none" data-option="fullscreen" class="btn btn-sm btn-outline-secondary" id="js-ace-fullscreen" title="<?php echo lng('Fullscreen') ?>"><i class="fa fa-expand" title="<?php echo lng('Fullscreen') ?>"></i></button>
  1854.                             <button data-cmd="find" class="btn btn-sm btn-outline-secondary" id="js-ace-search" title="<?php echo lng('Search') ?>"><i class="fa fa-search" title="<?php echo lng('Search') ?>"></i></button>
  1855.                             <button data-cmd="undo" class="btn btn-sm btn-outline-secondary" id="js-ace-undo" title="<?php echo lng('Undo') ?>"><i class="fa fa-undo" title="<?php echo lng('Undo') ?>"></i></button>
  1856.                             <button data-cmd="redo" class="btn btn-sm btn-outline-secondary" id="js-ace-redo" title="<?php echo lng('Redo') ?>"><i class="fa fa-repeat" title="<?php echo lng('Redo') ?>"></i></button>
  1857.                             <button data-cmd="none" data-option="wrap" class="btn btn-sm btn-outline-secondary" id="js-ace-wordWrap" title="<?php echo lng('Word Wrap') ?>"><i class="fa fa-text-width" title="<?php echo lng('Word Wrap') ?>"></i></button>
  1858.                             <select id="js-ace-mode" data-type="mode" title="<?php echo lng('Select Document Type') ?>" class="btn-outline-secondary border-start-0 d-none d-md-block"><option>-- <?php echo lng('Select Mode') ?> --</option></select>
  1859.                             <select id="js-ace-theme" data-type="theme" title="<?php echo lng('Select Theme') ?>" class="btn-outline-secondary border-start-0 d-none d-lg-block"><option>-- <?php echo lng('Select Theme') ?> --</option></select>
  1860.                             <select id="js-ace-fontSize" data-type="fontSize" title="<?php echo lng('Select Font Size') ?>" class="btn-outline-secondary border-start-0 d-none d-lg-block"><option>-- <?php echo lng('Select Font Size') ?> --</option></select>
  1861.                         </div>
  1862.                     <?php } ?>
  1863.                 </div>
  1864.             </div>
  1865.             <div class="edit-file-actions col-xs-12 col-sm-7 col-lg-6 text-end pt-1">
  1866.                 <a title="<?php echo lng('Back') ?>" class="btn btn-sm btn-outline-primary" href="?p=<?php echo urlencode(trim(FM_PATH)) ?>&amp;view=<?php echo urlencode($file) ?>"><i class="fa fa-reply-all"></i> <?php echo lng('Back') ?></a>
  1867.                 <a title="<?php echo lng('BackUp') ?>" class="btn btn-sm btn-outline-primary" href="javascript:void(0);" onclick="backup('<?php echo urlencode(trim(FM_PATH)) ?>','<?php echo urlencode($file) ?>')"><i class="fa fa-database"></i> <?php echo lng('BackUp') ?></a>
  1868.                 <?php if ($is_text) { ?>
  1869.                     <?php if ($isNormalEditor) { ?>
  1870.                         <a title="Advanced" class="btn btn-sm btn-outline-primary" href="?p=<?php echo urlencode(trim(FM_PATH)) ?>&amp;edit=<?php echo urlencode($file) ?>&amp;env=ace"><i class="fa fa-pencil-square-o"></i> <?php echo lng('AdvancedEditor') ?></a>
  1871.                         <button type="button" class="btn btn-sm btn-success" name="Save" data-url="<?php echo fm_enc($file_url) ?>" onclick="edit_save(this,'nrl')"><i class="fa fa-floppy-o"></i> Save
  1872.                         </button>
  1873.                     <?php } else { ?>
  1874.                         <a title="Plain Editor" class="btn btn-sm btn-outline-primary" href="?p=<?php echo urlencode(trim(FM_PATH)) ?>&amp;edit=<?php echo urlencode($file) ?>"><i class="fa fa-text-height"></i> <?php echo lng('NormalEditor') ?></a>
  1875.                         <button type="button" class="btn btn-sm btn-success" name="Save" data-url="<?php echo fm_enc($file_url) ?>" onclick="edit_save(this,'ace')"><i class="fa fa-floppy-o"></i> <?php echo lng('Save') ?>
  1876.                         </button>
  1877.                     <?php } ?>
  1878.                 <?php } ?>
  1879.             </div>
  1880.         </div>
  1881.         <?php
  1882.         if ($is_text && $isNormalEditor) {
  1883.             echo '<textarea class="mt-2" id="normal-editor" rows="33" cols="120" style="width: 99.5%;">' . htmlspecialchars($content) . '</textarea>';
  1884.             echo '<script>document.addEventListener("keydown", function(e) {if ((window.navigator.platform.match("Mac") ? e.metaKey : e.ctrlKey)  && e.keyCode == 83) { e.preventDefault();edit_save(this,"nrl");}}, false);</script>';
  1885.         } elseif ($is_text) {
  1886.             echo '<div id="editor" contenteditable="true">' . htmlspecialchars($content) . '</div>';
  1887.         } else {
  1888.             fm_set_msg(lng('FILE EXTENSION HAS NOT SUPPORTED'), 'error');
  1889.         }
  1890.         ?>
  1891.     </div>
  1892.     <?php
  1893.     fm_show_footer();
  1894.     exit;
  1895. }
  1896.  
  1897. // chmod (not for Windows)
  1898. if (isset($_GET['chmod']) && !FM_READONLY && !FM_IS_WIN) {
  1899.     $file = $_GET['chmod'];
  1900.     $file = fm_clean_path($file);
  1901.     $file = str_replace('/', '', $file);
  1902.     if ($file == '' || (!is_file($path . '/' . $file) && !is_dir($path . '/' . $file))) {
  1903.         fm_set_msg(lng('File not found'), 'error');
  1904.         $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
  1905.     }
  1906.  
  1907.     fm_show_header(); // HEADER
  1908.     fm_show_nav_path(FM_PATH); // current path
  1909.  
  1910.     $file_url = FM_ROOT_URL . (FM_PATH != '' ? '/' . FM_PATH : '') . '/' . $file;
  1911.     $file_path = $path . '/' . $file;
  1912.  
  1913.     $mode = fileperms($path . '/' . $file);
  1914.     ?>
  1915.     <div class="path">
  1916.         <div class="card mb-2 <?php echo fm_get_theme(); ?>">
  1917.             <h6 class="card-header">
  1918.                 <?php echo lng('ChangePermissions') ?>
  1919.             </h6>
  1920.             <div class="card-body">
  1921.                 <p class="card-text">
  1922.                     Full path: <?php echo $file_path ?><br>
  1923.                 </p>
  1924.                 <form action="" method="post">
  1925.                     <input type="hidden" name="p" value="<?php echo fm_enc(FM_PATH) ?>">
  1926.                     <input type="hidden" name="chmod" value="<?php echo fm_enc($file) ?>">
  1927.  
  1928.                     <table class="table compact-table <?php echo fm_get_theme(); ?>">
  1929.                         <tr>
  1930.                             <td></td>
  1931.                             <td><b><?php echo lng('Owner') ?></b></td>
  1932.                             <td><b><?php echo lng('Group') ?></b></td>
  1933.                             <td><b><?php echo lng('Other') ?></b></td>
  1934.                         </tr>
  1935.                         <tr>
  1936.                             <td style="text-align: right"><b><?php echo lng('Read') ?></b></td>
  1937.                             <td><label><input type="checkbox" name="ur" value="1"<?php echo ($mode & 00400) ? ' checked' : '' ?>></label></td>
  1938.                             <td><label><input type="checkbox" name="gr" value="1"<?php echo ($mode & 00040) ? ' checked' : '' ?>></label></td>
  1939.                             <td><label><input type="checkbox" name="or" value="1"<?php echo ($mode & 00004) ? ' checked' : '' ?>></label></td>
  1940.                         </tr>
  1941.                         <tr>
  1942.                             <td style="text-align: right"><b><?php echo lng('Write') ?></b></td>
  1943.                             <td><label><input type="checkbox" name="uw" value="1"<?php echo ($mode & 00200) ? ' checked' : '' ?>></label></td>
  1944.                             <td><label><input type="checkbox" name="gw" value="1"<?php echo ($mode & 00020) ? ' checked' : '' ?>></label></td>
  1945.                             <td><label><input type="checkbox" name="ow" value="1"<?php echo ($mode & 00002) ? ' checked' : '' ?>></label></td>
  1946.                         </tr>
  1947.                         <tr>
  1948.                             <td style="text-align: right"><b><?php echo lng('Execute') ?></b></td>
  1949.                             <td><label><input type="checkbox" name="ux" value="1"<?php echo ($mode & 00100) ? ' checked' : '' ?>></label></td>
  1950.                             <td><label><input type="checkbox" name="gx" value="1"<?php echo ($mode & 00010) ? ' checked' : '' ?>></label></td>
  1951.                             <td><label><input type="checkbox" name="ox" value="1"<?php echo ($mode & 00001) ? ' checked' : '' ?>></label></td>
  1952.                         </tr>
  1953.                     </table>
  1954.  
  1955.                     <p>
  1956.                        <input type="hidden" name="token" value="<?php echo $_SESSION['token']; ?>">
  1957.                         <b><a href="?p=<?php echo urlencode(FM_PATH) ?>" class="btn btn-outline-primary"><i class="fa fa-times-circle"></i> <?php echo lng('Cancel') ?></a></b>&nbsp;
  1958.                         <button type="submit" class="btn btn-success"><i class="fa fa-check-circle"></i> <?php echo lng('Change') ?></button>
  1959.                     </p>
  1960.                 </form>
  1961.             </div>
  1962.         </div>
  1963.     </div>
  1964.     <?php
  1965.     fm_show_footer();
  1966.     exit;
  1967. }
  1968.  
  1969. // --- TINYFILEMANAGER MAIN ---
  1970. fm_show_header(); // HEADER
  1971. fm_show_nav_path(FM_PATH); // current path
  1972.  
  1973. // show alert messages
  1974. fm_show_message();
  1975.  
  1976. $num_files = count($files);
  1977. $num_folders = count($folders);
  1978. $all_files_size = 0;
  1979. $tableTheme = (FM_THEME == "dark") ? "text-white bg-dark table-dark" : "bg-white";
  1980. ?>
  1981. <form action="" method="post" class="pt-3">
  1982.     <input type="hidden" name="p" value="<?php echo fm_enc(FM_PATH) ?>">
  1983.     <input type="hidden" name="group" value="1">
  1984.     <input type="hidden" name="token" value="<?php echo $_SESSION['token']; ?>">
  1985.     <div class="table-responsive">
  1986.         <table class="table table-bordered table-hover table-sm <?php echo $tableTheme; ?>" id="main-table">
  1987.             <thead class="thead-white">
  1988.             <tr>
  1989.                 <?php if (!FM_READONLY): ?>
  1990.                     <th style="width:3%" class="custom-checkbox-header">
  1991.                         <div class="custom-control custom-checkbox">
  1992.                             <input type="checkbox" class="custom-control-input" id="js-select-all-items" onclick="checkbox_toggle()">
  1993.                             <label class="custom-control-label" for="js-select-all-items"></label>
  1994.                         </div>
  1995.                     </th><?php endif; ?>
  1996.                 <th><?php echo lng('Name') ?></th>
  1997.                 <th><?php echo lng('Size') ?></th>
  1998.                 <th><?php echo lng('Modified') ?></th>
  1999.                 <?php if (!FM_IS_WIN && !$hide_Cols): ?>
  2000.                     <th><?php echo lng('Perms') ?></th>
  2001.                     <th><?php echo lng('Owner') ?></th><?php endif; ?>
  2002.                 <th><?php echo lng('Actions') ?></th>
  2003.             </tr>
  2004.             </thead>
  2005.             <?php
  2006.             // link to parent folder
  2007.             if ($parent !== false) {
  2008.                 ?>
  2009.                 <tr><?php if (!FM_READONLY): ?>
  2010.                     <td class="nosort"></td><?php endif; ?>
  2011.                     <td class="border-0" data-sort><a href="?p=<?php echo urlencode($parent) ?>"><i class="fa fa-chevron-circle-left go-back"></i> ..</a></td>
  2012.                     <td class="border-0" data-order></td>
  2013.                     <td class="border-0" data-order></td>
  2014.                     <td class="border-0"></td>
  2015.                     <?php if (!FM_IS_WIN && !$hide_Cols) { ?>
  2016.                         <td class="border-0"></td>
  2017.                         <td class="border-0"></td>
  2018.                     <?php } ?>
  2019.                 </tr>
  2020.                 <?php
  2021.             }
  2022.             $ii = 3399;
  2023.             foreach ($folders as $f) {
  2024.                 $is_link = is_link($path . '/' . $f);
  2025.                 $img = $is_link ? 'icon-link_folder' : 'fa fa-folder-o';
  2026.                 $modif_raw = filemtime($path . '/' . $f);
  2027.                 $modif = date(FM_DATETIME_FORMAT, $modif_raw);
  2028.                 $date_sorting = strtotime(date("F d Y H:i:s.", $modif_raw));
  2029.                 $filesize_raw = "";
  2030.                 $filesize = lng('Folder');
  2031.                 $perms = substr(decoct(fileperms($path . '/' . $f)), -4);
  2032.                 if (function_exists('posix_getpwuid') && function_exists('posix_getgrgid')) {
  2033.                     $owner = posix_getpwuid(fileowner($path . '/' . $f));
  2034.                     $group = posix_getgrgid(filegroup($path . '/' . $f));
  2035.                 } else {
  2036.                     $owner = array('name' => '?');
  2037.                     $group = array('name' => '?');
  2038.                 }
  2039.                 ?>
  2040.                 <tr>
  2041.                     <?php if (!FM_READONLY): ?>
  2042.                         <td class="custom-checkbox-td">
  2043.                         <div class="custom-control custom-checkbox">
  2044.                             <input type="checkbox" class="custom-control-input" id="<?php echo $ii ?>" name="file[]" value="<?php echo fm_enc($f) ?>">
  2045.                             <label class="custom-control-label" for="<?php echo $ii ?>"></label>
  2046.                         </div>
  2047.                         </td><?php endif; ?>
  2048.                     <td data-sort=<?php echo fm_convert_win(fm_enc($f)) ?>>
  2049.                         <div class="filename"><a href="?p=<?php echo urlencode(trim(FM_PATH . '/' . $f, '/')) ?>"><i class="<?php echo $img ?>"></i> <?php echo fm_convert_win(fm_enc($f)) ?>
  2050.                             </a><?php echo($is_link ? ' &rarr; <i>' . readlink($path . '/' . $f) . '</i>' : '') ?></div>
  2051.                     </td>
  2052.                     <td data-order="a-<?php echo str_pad($filesize_raw, 18, "0", STR_PAD_LEFT);?>">
  2053.                         <?php echo $filesize; ?>
  2054.                     </td>
  2055.                     <td data-order="a-<?php echo $date_sorting;?>"><?php echo $modif ?></td>
  2056.                     <?php if (!FM_IS_WIN && !$hide_Cols): ?>
  2057.                         <td><?php if (!FM_READONLY): ?><a title="Change Permissions" href="?p=<?php echo urlencode(FM_PATH) ?>&amp;chmod=<?php echo urlencode($f) ?>"><?php echo $perms ?></a><?php else: ?><?php echo $perms ?><?php endif; ?>
  2058.                         </td>
  2059.                         <td><?php echo $owner['name'] . ':' . $group['name'] ?></td>
  2060.                     <?php endif; ?>
  2061.                     <td class="inline-actions"><?php if (!FM_READONLY): ?>
  2062.                             <a title="<?php echo lng('Delete')?>" href="?p=<?php echo urlencode(FM_PATH) ?>&amp;del=<?php echo urlencode($f) ?>" onclick="confirmDailog(event, '1028','<?php echo lng('Delete').' '.lng('Folder'); ?>','<?php echo urlencode($f) ?>', this.href);"> <i class="fa fa-trash-o" aria-hidden="true"></i></a>
  2063.                             <a title="<?php echo lng('Rename')?>" href="#" onclick="rename('<?php echo fm_enc(addslashes(FM_PATH)) ?>', '<?php echo fm_enc(addslashes($f)) ?>');return false;"><i class="fa fa-pencil-square-o" aria-hidden="true"></i></a>
  2064.                             <a title="<?php echo lng('CopyTo')?>..." href="?p=&amp;copy=<?php echo urlencode(trim(FM_PATH . '/' . $f, '/')) ?>"><i class="fa fa-files-o" aria-hidden="true"></i></a>
  2065.                         <?php endif; ?>
  2066.                         <a title="<?php echo lng('DirectLink')?>" href="<?php echo fm_enc(FM_ROOT_URL . (FM_PATH != '' ? '/' . FM_PATH : '') . '/' . $f . '/') ?>" target="_blank"><i class="fa fa-link" aria-hidden="true"></i></a>
  2067.                     </td>
  2068.                 </tr>
  2069.                 <?php
  2070.                 flush();
  2071.                 $ii++;
  2072.             }
  2073.             $ik = 6070;
  2074.             foreach ($files as $f) {
  2075.                 $is_link = is_link($path . '/' . $f);
  2076.                 $img = $is_link ? 'fa fa-file-text-o' : fm_get_file_icon_class($path . '/' . $f);
  2077.                 $modif_raw = filemtime($path . '/' . $f);
  2078.                 $modif = date(FM_DATETIME_FORMAT, $modif_raw);
  2079.                 $date_sorting = strtotime(date("F d Y H:i:s.", $modif_raw));
  2080.                 $filesize_raw = fm_get_size($path . '/' . $f);
  2081.                 $filesize = fm_get_filesize($filesize_raw);
  2082.                 $filelink = '?p=' . urlencode(FM_PATH) . '&amp;view=' . urlencode($f);
  2083.                 $all_files_size += $filesize_raw;
  2084.                 $perms = substr(decoct(fileperms($path . '/' . $f)), -4);
  2085.                 if (function_exists('posix_getpwuid') && function_exists('posix_getgrgid')) {
  2086.                     $owner = posix_getpwuid(fileowner($path . '/' . $f));
  2087.                     $group = posix_getgrgid(filegroup($path . '/' . $f));
  2088.                 } else {
  2089.                     $owner = array('name' => '?');
  2090.                     $group = array('name' => '?');
  2091.                 }
  2092.                 ?>
  2093.                 <tr>
  2094.                     <?php if (!FM_READONLY): ?>
  2095.                         <td class="custom-checkbox-td">
  2096.                         <div class="custom-control custom-checkbox">
  2097.                             <input type="checkbox" class="custom-control-input" id="<?php echo $ik ?>" name="file[]" value="<?php echo fm_enc($f) ?>">
  2098.                             <label class="custom-control-label" for="<?php echo $ik ?>"></label>
  2099.                         </div>
  2100.                         </td><?php endif; ?>
  2101.                     <td data-sort=<?php echo fm_enc($f) ?>>
  2102.                         <div class="filename">
  2103.                         <?php
  2104.                            if (in_array(strtolower(pathinfo($f, PATHINFO_EXTENSION)), array('gif', 'jpg', 'jpeg', 'png', 'bmp', 'ico', 'svg', 'webp', 'avif'))): ?>
  2105.                                 <?php $imagePreview = fm_enc(FM_ROOT_URL . (FM_PATH != '' ? '/' . FM_PATH : '') . '/' . $f); ?>
  2106.                                 <a href="<?php echo $filelink ?>" data-preview-image="<?php echo $imagePreview ?>" title="<?php echo fm_enc($f) ?>">
  2107.                            <?php else: ?>
  2108.                                 <a href="<?php echo $filelink ?>" title="<?php echo $f ?>">
  2109.                             <?php endif; ?>
  2110.                                     <i class="<?php echo $img ?>"></i> <?php echo fm_convert_win(fm_enc($f)) ?>
  2111.                                 </a>
  2112.                                 <?php echo($is_link ? ' &rarr; <i>' . readlink($path . '/' . $f) . '</i>' : '') ?>
  2113.                         </div>
  2114.                     </td>
  2115.                     <td data-order="b-<?php echo str_pad($filesize_raw, 18, "0", STR_PAD_LEFT); ?>"><span title="<?php printf('%s bytes', $filesize_raw) ?>">
  2116.                         <?php echo $filesize; ?>
  2117.                         </span></td>
  2118.                     <td data-order="b-<?php echo $date_sorting;?>"><?php echo $modif ?></td>
  2119.                     <?php if (!FM_IS_WIN && !$hide_Cols): ?>
  2120.                         <td><?php if (!FM_READONLY): ?><a title="<?php echo 'Change Permissions' ?>" href="?p=<?php echo urlencode(FM_PATH) ?>&amp;chmod=<?php echo urlencode($f) ?>"><?php echo $perms ?></a><?php else: ?><?php echo $perms ?><?php endif; ?>
  2121.                         </td>
  2122.                         <td><?php echo fm_enc($owner['name'] . ':' . $group['name']) ?></td>
  2123.                     <?php endif; ?>
  2124.                     <td class="inline-actions">
  2125.                         <?php if (!FM_READONLY): ?>
  2126.                             <a title="<?php echo lng('Delete') ?>" href="?p=<?php echo urlencode(FM_PATH) ?>&amp;del=<?php echo urlencode($f) ?>" onclick="confirmDailog(event, 1209, '<?php echo lng('Delete').' '.lng('File'); ?>','<?php echo urlencode($f); ?>', this.href);"> <i class="fa fa-trash-o"></i></a>
  2127.                             <a title="<?php echo lng('Rename') ?>" href="#" onclick="rename('<?php echo fm_enc(addslashes(FM_PATH)) ?>', '<?php echo fm_enc(addslashes($f)) ?>');return false;"><i class="fa fa-pencil-square-o"></i></a>
  2128.                             <a title="<?php echo lng('CopyTo') ?>..."
  2129.                                href="?p=<?php echo urlencode(FM_PATH) ?>&amp;copy=<?php echo urlencode(trim(FM_PATH . '/' . $f, '/')) ?>"><i class="fa fa-files-o"></i></a>
  2130.                         <?php endif; ?>
  2131.                         <a title="<?php echo lng('DirectLink') ?>" href="<?php echo fm_enc(FM_ROOT_URL . (FM_PATH != '' ? '/' . FM_PATH : '') . '/' . $f) ?>" target="_blank"><i class="fa fa-link"></i></a>
  2132.                         <a title="<?php echo lng('Download') ?>" href="?p=<?php echo urlencode(FM_PATH) ?>&amp;dl=<?php echo urlencode($f) ?>" onclick="confirmDailog(event, 1211, '<?php echo lng('Download'); ?>','<?php echo urlencode($f); ?>', this.href);"><i class="fa fa-download"></i></a>
  2133.                     </td>
  2134.                 </tr>
  2135.                 <?php
  2136.                 flush();
  2137.                 $ik++;
  2138.             }
  2139.  
  2140.             if (empty($folders) && empty($files)) { ?>
  2141.                 <tfoot>
  2142.                     <tr><?php if (!FM_READONLY): ?>
  2143.                             <td></td><?php endif; ?>
  2144.                         <td colspan="<?php echo (!FM_IS_WIN && !$hide_Cols) ? '6' : '4' ?>"><em><?php echo lng('Folder is empty') ?></em></td>
  2145.                     </tr>
  2146.                 </tfoot>
  2147.                 <?php
  2148.             } else { ?>
  2149.                 <tfoot>
  2150.                     <tr>
  2151.                         <td class="gray" colspan="<?php echo (!FM_IS_WIN && !$hide_Cols) ? (FM_READONLY ? '6' :'7') : (FM_READONLY ? '4' : '5') ?>">
  2152.                             <?php echo lng('FullSize').': <span class="badge text-bg-light border-radius-0">'.fm_get_filesize($all_files_size).'</span>' ?>
  2153.                             <?php echo lng('File').': <span class="badge text-bg-light border-radius-0">'.$num_files.'</span>' ?>
  2154.                             <?php echo lng('Folder').': <span class="badge text-bg-light border-radius-0">'.$num_folders.'</span>' ?>
  2155.                         </td>
  2156.                     </tr>
  2157.                 </tfoot>
  2158.                 <?php } ?>
  2159.         </table>
  2160.     </div>
  2161.  
  2162.     <div class="row">
  2163.         <?php if (!FM_READONLY): ?>
  2164.         <div class="col-xs-12 col-sm-9">
  2165.             <ul class="list-inline footer-action">
  2166.                 <li class="list-inline-item"> <a href="#/select-all" class="btn btn-small btn-outline-primary btn-2" onclick="select_all();return false;"><i class="fa fa-check-square"></i> <?php echo lng('SelectAll') ?> </a></li>
  2167.                 <li class="list-inline-item"><a href="#/unselect-all" class="btn btn-small btn-outline-primary btn-2" onclick="unselect_all();return false;"><i class="fa fa-window-close"></i> <?php echo lng('UnSelectAll') ?> </a></li>
  2168.                 <li class="list-inline-item"><a href="#/invert-all" class="btn btn-small btn-outline-primary btn-2" onclick="invert_all();return false;"><i class="fa fa-th-list"></i> <?php echo lng('InvertSelection') ?> </a></li>
  2169.                 <li class="list-inline-item"><input type="submit" class="hidden" name="delete" id="a-delete" value="Delete" onclick="return confirm('<?php echo lng('Delete selected files and folders?'); ?>')">
  2170.                     <a href="javascript:document.getElementById('a-delete').click();" class="btn btn-small btn-outline-primary btn-2"><i class="fa fa-trash"></i> <?php echo lng('Delete') ?> </a></li>
  2171.                 <li class="list-inline-item"><input type="submit" class="hidden" name="zip" id="a-zip" value="zip" onclick="return confirm('<?php echo lng('Create archive?'); ?>')">
  2172.                     <a href="javascript:document.getElementById('a-zip').click();" class="btn btn-small btn-outline-primary btn-2"><i class="fa fa-file-archive-o"></i> <?php echo lng('Zip') ?> </a></li>
  2173.                 <li class="list-inline-item"><input type="submit" class="hidden" name="tar" id="a-tar" value="tar" onclick="return confirm('<?php echo lng('Create archive?'); ?>')">
  2174.                     <a href="javascript:document.getElementById('a-tar').click();" class="btn btn-small btn-outline-primary btn-2"><i class="fa fa-file-archive-o"></i> <?php echo lng('Tar') ?> </a></li>
  2175.                 <li class="list-inline-item"><input type="submit" class="hidden" name="copy" id="a-copy" value="Copy">
  2176.                     <a href="javascript:document.getElementById('a-copy').click();" class="btn btn-small btn-outline-primary btn-2"><i class="fa fa-files-o"></i> <?php echo lng('Copy') ?> </a></li>
  2177.             </ul>
  2178.         </div>
  2179.         <div class="col-3 d-none d-sm-block"><a href="https://tinyfilemanager.github.io" target="_blank" class="float-right text-muted">Tiny File Manager <?php echo VERSION; ?></a></div>
  2180.         <?php else: ?>
  2181.             <div class="col-12"><a href="https://tinyfilemanager.github.io" target="_blank" class="float-right text-muted">Tiny File Manager <?php echo VERSION; ?></a></div>
  2182.         <?php endif; ?>
  2183.     </div>
  2184. </form>
  2185.  
  2186. <?php
  2187. fm_show_footer();
  2188.  
  2189. // --- END HTML ---
  2190.  
  2191. // Functions
  2192.  
  2193. /**
  2194.  * Verify CSRF TOKEN and remove after cerify
  2195.  * @param string $token
  2196.  * @return bool
  2197.  */
  2198. function verifyToken($token)
  2199. {
  2200.     if (hash_equals($_SESSION['token'], $token)) {
  2201.         return true;
  2202.     }
  2203.     return false;
  2204. }
  2205.  
  2206. /**
  2207.  * Delete  file or folder (recursively)
  2208.  * @param string $path
  2209.  * @return bool
  2210.  */
  2211. function fm_rdelete($path)
  2212. {
  2213.     if (is_link($path)) {
  2214.         return unlink($path);
  2215.     } elseif (is_dir($path)) {
  2216.         $objects = scandir($path);
  2217.         $ok = true;
  2218.         if (is_array($objects)) {
  2219.             foreach ($objects as $file) {
  2220.                 if ($file != '.' && $file != '..') {
  2221.                     if (!fm_rdelete($path . '/' . $file)) {
  2222.                         $ok = false;
  2223.                     }
  2224.                 }
  2225.             }
  2226.         }
  2227.         return ($ok) ? rmdir($path) : false;
  2228.     } elseif (is_file($path)) {
  2229.         return unlink($path);
  2230.     }
  2231.     return false;
  2232. }
  2233.  
  2234. /**
  2235.  * Recursive chmod
  2236.  * @param string $path
  2237.  * @param int $filemode
  2238.  * @param int $dirmode
  2239.  * @return bool
  2240.  * @todo Will use in mass chmod
  2241.  */
  2242. function fm_rchmod($path, $filemode, $dirmode)
  2243. {
  2244.     if (is_dir($path)) {
  2245.         if (!chmod($path, $dirmode)) {
  2246.             return false;
  2247.         }
  2248.         $objects = scandir($path);
  2249.         if (is_array($objects)) {
  2250.             foreach ($objects as $file) {
  2251.                 if ($file != '.' && $file != '..') {
  2252.                     if (!fm_rchmod($path . '/' . $file, $filemode, $dirmode)) {
  2253.                         return false;
  2254.                     }
  2255.                 }
  2256.             }
  2257.         }
  2258.         return true;
  2259.     } elseif (is_link($path)) {
  2260.         return true;
  2261.     } elseif (is_file($path)) {
  2262.         return chmod($path, $filemode);
  2263.     }
  2264.     return false;
  2265. }
  2266.  
  2267. /**
  2268.  * Check the file extension which is allowed or not
  2269.  * @param string $filename
  2270.  * @return bool
  2271.  */
  2272. function fm_is_valid_ext($filename)
  2273. {
  2274.     $allowed = (FM_FILE_EXTENSION) ? explode(',', FM_FILE_EXTENSION) : false;
  2275.  
  2276.     $ext = pathinfo($filename, PATHINFO_EXTENSION);
  2277.     $isFileAllowed = ($allowed) ? in_array($ext, $allowed) : true;
  2278.  
  2279.     return ($isFileAllowed) ? true : false;
  2280. }
  2281.  
  2282. /**
  2283.  * Safely rename
  2284.  * @param string $old
  2285.  * @param string $new
  2286.  * @return bool|null
  2287.  */
  2288. function fm_rename($old, $new)
  2289. {
  2290.     $isFileAllowed = fm_is_valid_ext($new);
  2291.  
  2292.     if(!is_dir($old)) {
  2293.         if (!$isFileAllowed) return false;
  2294.     }
  2295.  
  2296.     return (!file_exists($new) && file_exists($old)) ? rename($old, $new) : null;
  2297. }
  2298.  
  2299. /**
  2300.  * Copy file or folder (recursively).
  2301.  * @param string $path
  2302.  * @param string $dest
  2303.  * @param bool $upd Update files
  2304.  * @param bool $force Create folder with same names instead file
  2305.  * @return bool
  2306.  */
  2307. function fm_rcopy($path, $dest, $upd = true, $force = true)
  2308. {
  2309.     if (is_dir($path)) {
  2310.         if (!fm_mkdir($dest, $force)) {
  2311.             return false;
  2312.         }
  2313.         $objects = scandir($path);
  2314.         $ok = true;
  2315.         if (is_array($objects)) {
  2316.             foreach ($objects as $file) {
  2317.                 if ($file != '.' && $file != '..') {
  2318.                     if (!fm_rcopy($path . '/' . $file, $dest . '/' . $file)) {
  2319.                         $ok = false;
  2320.                     }
  2321.                 }
  2322.             }
  2323.         }
  2324.         return $ok;
  2325.     } elseif (is_file($path)) {
  2326.         return fm_copy($path, $dest, $upd);
  2327.     }
  2328.     return false;
  2329. }
  2330.  
  2331. /**
  2332.  * Safely create folder
  2333.  * @param string $dir
  2334.  * @param bool $force
  2335.  * @return bool
  2336.  */
  2337. function fm_mkdir($dir, $force)
  2338. {
  2339.     if (file_exists($dir)) {
  2340.         if (is_dir($dir)) {
  2341.             return $dir;
  2342.         } elseif (!$force) {
  2343.             return false;
  2344.         }
  2345.         unlink($dir);
  2346.     }
  2347.     return mkdir($dir, 0777, true);
  2348. }
  2349.  
  2350. /**
  2351.  * Safely copy file
  2352.  * @param string $f1
  2353.  * @param string $f2
  2354.  * @param bool $upd Indicates if file should be updated with new content
  2355.  * @return bool
  2356.  */
  2357. function fm_copy($f1, $f2, $upd)
  2358. {
  2359.     $time1 = filemtime($f1);
  2360.     if (file_exists($f2)) {
  2361.         $time2 = filemtime($f2);
  2362.         if ($time2 >= $time1 && $upd) {
  2363.             return false;
  2364.         }
  2365.     }
  2366.     $ok = copy($f1, $f2);
  2367.     if ($ok) {
  2368.         touch($f2, $time1);
  2369.     }
  2370.     return $ok;
  2371. }
  2372.  
  2373. /**
  2374.  * Get mime type
  2375.  * @param string $file_path
  2376.  * @return mixed|string
  2377.  */
  2378. function fm_get_mime_type($file_path)
  2379. {
  2380.     if (function_exists('finfo_open')) {
  2381.         $finfo = finfo_open(FILEINFO_MIME_TYPE);
  2382.         $mime = finfo_file($finfo, $file_path);
  2383.         finfo_close($finfo);
  2384.         return $mime;
  2385.     } elseif (function_exists('mime_content_type')) {
  2386.         return mime_content_type($file_path);
  2387.     } elseif (!stristr(ini_get('disable_functions'), 'shell_exec')) {
  2388.         $file = escapeshellarg($file_path);
  2389.         $mime = shell_exec('file -bi ' . $file);
  2390.         return $mime;
  2391.     } else {
  2392.         return '--';
  2393.     }
  2394. }
  2395.  
  2396. /**
  2397.  * HTTP Redirect
  2398.  * @param string $url
  2399.  * @param int $code
  2400.  */
  2401. function fm_redirect($url, $code = 302)
  2402. {
  2403.     header('Location: ' . $url, true, $code);
  2404.     exit;
  2405. }
  2406.  
  2407. /**
  2408.  * Path traversal prevention and clean the url
  2409.  * It replaces (consecutive) occurrences of / and \\ with whatever is in DIRECTORY_SEPARATOR, and processes /. and /.. fine.
  2410.  * @param $path
  2411.  * @return string
  2412.  */
  2413. function get_absolute_path($path) {
  2414.     $path = str_replace(array('/', '\\'), DIRECTORY_SEPARATOR, $path);
  2415.     $parts = array_filter(explode(DIRECTORY_SEPARATOR, $path), 'strlen');
  2416.     $absolutes = array();
  2417.     foreach ($parts as $part) {
  2418.         if ('.' == $part) continue;
  2419.         if ('..' == $part) {
  2420.             array_pop($absolutes);
  2421.         } else {
  2422.             $absolutes[] = $part;
  2423.         }
  2424.     }
  2425.     return implode(DIRECTORY_SEPARATOR, $absolutes);
  2426. }
  2427.  
  2428. /**
  2429.  * Clean path
  2430.  * @param string $path
  2431.  * @return string
  2432.  */
  2433. function fm_clean_path($path, $trim = true)
  2434. {
  2435.     $path = $trim ? trim($path) : $path;
  2436.     $path = trim($path, '\\/');
  2437.     $path = str_replace(array('../', '..\\'), '', $path);
  2438.     $path =  get_absolute_path($path);
  2439.     if ($path == '..') {
  2440.         $path = '';
  2441.     }
  2442.     return str_replace('\\', '/', $path);
  2443. }
  2444.  
  2445. /**
  2446.  * Get parent path
  2447.  * @param string $path
  2448.  * @return bool|string
  2449.  */
  2450. function fm_get_parent_path($path)
  2451. {
  2452.     $path = fm_clean_path($path);
  2453.     if ($path != '') {
  2454.         $array = explode('/', $path);
  2455.         if (count($array) > 1) {
  2456.             $array = array_slice($array, 0, -1);
  2457.             return implode('/', $array);
  2458.         }
  2459.         return '';
  2460.     }
  2461.     return false;
  2462. }
  2463.  
  2464. /**
  2465.  * Check file is in exclude list
  2466.  * @param string $file
  2467.  * @return bool
  2468.  */
  2469. function fm_is_exclude_items($file) {
  2470.     $ext = strtolower(pathinfo($file, PATHINFO_EXTENSION));
  2471.     if (isset($exclude_items) and sizeof($exclude_items)) {
  2472.         unset($exclude_items);
  2473.     }
  2474.  
  2475.     $exclude_items = FM_EXCLUDE_ITEMS;
  2476.     if (version_compare(PHP_VERSION, '7.0.0', '<')) {
  2477.         $exclude_items = unserialize($exclude_items);
  2478.     }
  2479.     if (!in_array($file, $exclude_items) && !in_array("*.$ext", $exclude_items)) {
  2480.         return true;
  2481.     }
  2482.     return false;
  2483. }
  2484.  
  2485. /**
  2486.  * get language translations from json file
  2487.  * @param int $tr
  2488.  * @return array
  2489.  */
  2490. function fm_get_translations($tr) {
  2491.     try {
  2492.         $content = @file_get_contents('translation.json');
  2493.         if($content !== FALSE) {
  2494.             $lng = json_decode($content, TRUE);
  2495.             global $lang_list;
  2496.             foreach ($lng["language"] as $key => $value)
  2497.             {
  2498.                 $code = $value["code"];
  2499.                 $lang_list[$code] = $value["name"];
  2500.                 if ($tr)
  2501.                     $tr[$code] = $value["translation"];
  2502.             }
  2503.             return $tr;
  2504.         }
  2505.  
  2506.     }
  2507.     catch (Exception $e) {
  2508.         echo $e;
  2509.     }
  2510. }
  2511.  
  2512. /**
  2513.  * @param string $file
  2514.  * Recover all file sizes larger than > 2GB.
  2515.  * Works on php 32bits and 64bits and supports linux
  2516.  * @return int|string
  2517.  */
  2518. function fm_get_size($file)
  2519. {
  2520.     static $iswin;
  2521.     static $isdarwin;
  2522.     if (!isset($iswin)) {
  2523.         $iswin = (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN');
  2524.     }
  2525.     if (!isset($isdarwin)) {
  2526.         $isdarwin = (strtoupper(substr(PHP_OS, 0)) == "DARWIN");
  2527.     }
  2528.  
  2529.     static $exec_works;
  2530.     if (!isset($exec_works)) {
  2531.         $exec_works = (function_exists('exec') && !ini_get('safe_mode') && @exec('echo EXEC') == 'EXEC');
  2532.     }
  2533.  
  2534.     // try a shell command
  2535.     if ($exec_works) {
  2536.         $arg = escapeshellarg($file);
  2537.         $cmd = ($iswin) ? "for %F in (\"$file\") do @echo %~zF" : ($isdarwin ? "stat -f%z $arg" : "stat -c%s $arg");
  2538.         @exec($cmd, $output);
  2539.         if (is_array($output) && ctype_digit($size = trim(implode("\n", $output)))) {
  2540.             return $size;
  2541.         }
  2542.     }
  2543.  
  2544.     // try the Windows COM interface
  2545.     if ($iswin && class_exists("COM")) {
  2546.         try {
  2547.             $fsobj = new COM('Scripting.FileSystemObject');
  2548.             $f = $fsobj->GetFile( realpath($file) );
  2549.             $size = $f->Size;
  2550.         } catch (Exception $e) {
  2551.             $size = null;
  2552.         }
  2553.         if (ctype_digit($size)) {
  2554.             return $size;
  2555.         }
  2556.     }
  2557.  
  2558.     // if all else fails
  2559.     return filesize($file);
  2560. }
  2561.  
  2562. /**
  2563.  * Get nice filesize
  2564.  * @param int $size
  2565.  * @return string
  2566.  */
  2567. function fm_get_filesize($size)
  2568. {
  2569.     $size = (float) $size;
  2570.     $units = array('B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
  2571.     $power = ($size > 0) ? floor(log($size, 1024)) : 0;
  2572.     $power = ($power > (count($units) - 1)) ? (count($units) - 1) : $power;
  2573.     return sprintf('%s %s', round($size / pow(1024, $power), 2), $units[$power]);
  2574. }
  2575.  
  2576. /**
  2577.  * Get total size of directory tree.
  2578.  *
  2579.  * @param  string $directory Relative or absolute directory name.
  2580.  * @return int Total number of bytes.
  2581.  */
  2582. function fm_get_directorysize($directory) {
  2583.     $bytes = 0;
  2584.     $directory = realpath($directory);
  2585.     if ($directory !== false && $directory != '' && file_exists($directory)){
  2586.         foreach(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory, FilesystemIterator::SKIP_DOTS)) as $file){
  2587.             $bytes += $file->getSize();
  2588.         }
  2589.     }
  2590.     return $bytes;
  2591. }
  2592.  
  2593. /**
  2594.  * Get info about zip archive
  2595.  * @param string $path
  2596.  * @return array|bool
  2597.  */
  2598. function fm_get_zif_info($path, $ext) {
  2599.     if ($ext == 'zip' && function_exists('zip_open')) {
  2600.         $arch = @zip_open($path);
  2601.         if ($arch) {
  2602.             $filenames = array();
  2603.             while ($zip_entry = @zip_read($arch)) {
  2604.                 $zip_name = @zip_entry_name($zip_entry);
  2605.                 $zip_folder = substr($zip_name, -1) == '/';
  2606.                 $filenames[] = array(
  2607.                     'name' => $zip_name,
  2608.                     'filesize' => @zip_entry_filesize($zip_entry),
  2609.                     'compressed_size' => @zip_entry_compressedsize($zip_entry),
  2610.                     'folder' => $zip_folder
  2611.                     //'compression_method' => zip_entry_compressionmethod($zip_entry),
  2612.                 );
  2613.             }
  2614.             @zip_close($arch);
  2615.             return $filenames;
  2616.         }
  2617.     } elseif($ext == 'tar' && class_exists('PharData')) {
  2618.         $archive = new PharData($path);
  2619.         $filenames = array();
  2620.         foreach(new RecursiveIteratorIterator($archive) as $file) {
  2621.             $parent_info = $file->getPathInfo();
  2622.             $zip_name = str_replace("phar://".$path, '', $file->getPathName());
  2623.             $zip_name = substr($zip_name, ($pos = strpos($zip_name, '/')) !== false ? $pos + 1 : 0);
  2624.             $zip_folder = $parent_info->getFileName();
  2625.             $zip_info = new SplFileInfo($file);
  2626.             $filenames[] = array(
  2627.                 'name' => $zip_name,
  2628.                 'filesize' => $zip_info->getSize(),
  2629.                 'compressed_size' => $file->getCompressedSize(),
  2630.                 'folder' => $zip_folder
  2631.             );
  2632.         }
  2633.         return $filenames;
  2634.     }
  2635.     return false;
  2636. }
  2637.  
  2638. /**
  2639.  * Encode html entities
  2640.  * @param string $text
  2641.  * @return string
  2642.  */
  2643. function fm_enc($text)
  2644. {
  2645.     return htmlspecialchars($text, ENT_QUOTES, 'UTF-8');
  2646. }
  2647.  
  2648. /**
  2649.  * Prevent XSS attacks
  2650.  * @param string $text
  2651.  * @return string
  2652.  */
  2653. function fm_isvalid_filename($text) {
  2654.     return (strpbrk($text, '/?%*:|"<>') === FALSE) ? true : false;
  2655. }
  2656.  
  2657. /**
  2658.  * Save message in session
  2659.  * @param string $msg
  2660.  * @param string $status
  2661.  */
  2662. function fm_set_msg($msg, $status = 'ok')
  2663. {
  2664.     $_SESSION[FM_SESSION_ID]['message'] = $msg;
  2665.     $_SESSION[FM_SESSION_ID]['status'] = $status;
  2666. }
  2667.  
  2668. /**
  2669.  * Check if string is in UTF-8
  2670.  * @param string $string
  2671.  * @return int
  2672.  */
  2673. function fm_is_utf8($string)
  2674. {
  2675.     return preg_match('//u', $string);
  2676. }
  2677.  
  2678. /**
  2679.  * Convert file name to UTF-8 in Windows
  2680.  * @param string $filename
  2681.  * @return string
  2682.  */
  2683. function fm_convert_win($filename)
  2684. {
  2685.     if (FM_IS_WIN && function_exists('iconv')) {
  2686.         $filename = iconv(FM_ICONV_INPUT_ENC, 'UTF-8//IGNORE', $filename);
  2687.     }
  2688.     return $filename;
  2689. }
  2690.  
  2691. /**
  2692.  * @param $obj
  2693.  * @return array
  2694.  */
  2695. function fm_object_to_array($obj)
  2696. {
  2697.     if (!is_object($obj) && !is_array($obj)) {
  2698.         return $obj;
  2699.     }
  2700.     if (is_object($obj)) {
  2701.         $obj = get_object_vars($obj);
  2702.     }
  2703.     return array_map('fm_object_to_array', $obj);
  2704. }
  2705.  
  2706. /**
  2707.  * Get CSS classname for file
  2708.  * @param string $path
  2709.  * @return string
  2710.  */
  2711. function fm_get_file_icon_class($path)
  2712. {
  2713.     // get extension
  2714.     $ext = strtolower(pathinfo($path, PATHINFO_EXTENSION));
  2715.  
  2716.     switch ($ext) {
  2717.         case 'ico':
  2718.         case 'gif':
  2719.         case 'jpg':
  2720.         case 'jpeg':
  2721.         case 'jpc':
  2722.         case 'jp2':
  2723.         case 'jpx':
  2724.         case 'xbm':
  2725.         case 'wbmp':
  2726.         case 'png':
  2727.         case 'bmp':
  2728.         case 'tif':
  2729.         case 'tiff':
  2730.         case 'webp':
  2731.         case 'avif':
  2732.         case 'svg':
  2733.             $img = 'fa fa-picture-o';
  2734.             break;
  2735.         case 'passwd':
  2736.         case 'ftpquota':
  2737.         case 'sql':
  2738.         case 'js':
  2739.         case 'ts':
  2740.         case 'jsx':
  2741.         case 'tsx':
  2742.         case 'hbs':
  2743.         case 'json':
  2744.         case 'sh':
  2745.         case 'config':
  2746.         case 'twig':
  2747.         case 'tpl':
  2748.         case 'md':
  2749.         case 'gitignore':
  2750.         case 'c':
  2751.         case 'cpp':
  2752.         case 'cs':
  2753.         case 'py':
  2754.         case 'rs':
  2755.         case 'map':
  2756.         case 'lock':
  2757.         case 'dtd':
  2758.             $img = 'fa fa-file-code-o';
  2759.             break;
  2760.         case 'txt':
  2761.         case 'ini':
  2762.         case 'conf':
  2763.         case 'log':
  2764.         case 'htaccess':
  2765.         case 'yaml':
  2766.         case 'yml':
  2767.         case 'toml':
  2768.             $img = 'fa fa-file-text-o';
  2769.             break;
  2770.         case 'css':
  2771.         case 'less':
  2772.         case 'sass':
  2773.         case 'scss':
  2774.             $img = 'fa fa-css3';
  2775.             break;
  2776.         case 'bz2':
  2777.         case 'zip':
  2778.         case 'rar':
  2779.         case 'gz':
  2780.         case 'tar':
  2781.         case '7z':
  2782.         case 'xz':
  2783.             $img = 'fa fa-file-archive-o';
  2784.             break;
  2785.         case 'php':
  2786.         case 'php4':
  2787.         case 'php5':
  2788.         case 'phps':
  2789.         case 'phtml':
  2790.             $img = 'fa fa-code';
  2791.             break;
  2792.         case 'htm':
  2793.         case 'html':
  2794.         case 'shtml':
  2795.         case 'xhtml':
  2796.             $img = 'fa fa-html5';
  2797.             break;
  2798.         case 'xml':
  2799.         case 'xsl':
  2800.             $img = 'fa fa-file-excel-o';
  2801.             break;
  2802.         case 'wav':
  2803.         case 'mp3':
  2804.         case 'mp2':
  2805.         case 'm4a':
  2806.         case 'aac':
  2807.         case 'ogg':
  2808.         case 'oga':
  2809.         case 'wma':
  2810.         case 'mka':
  2811.         case 'flac':
  2812.         case 'ac3':
  2813.         case 'tds':
  2814.             $img = 'fa fa-music';
  2815.             break;
  2816.         case 'm3u':
  2817.         case 'm3u8':
  2818.         case 'pls':
  2819.         case 'cue':
  2820.         case 'xspf':
  2821.             $img = 'fa fa-headphones';
  2822.             break;
  2823.         case 'avi':
  2824.         case 'mpg':
  2825.         case 'mpeg':
  2826.         case 'mp4':
  2827.         case 'm4v':
  2828.         case 'flv':
  2829.         case 'f4v':
  2830.         case 'ogm':
  2831.         case 'ogv':
  2832.         case 'mov':
  2833.         case 'mkv':
  2834.         case '3gp':
  2835.         case 'asf':
  2836.         case 'wmv':
  2837.         case 'webm':
  2838.             $img = 'fa fa-file-video-o';
  2839.             break;
  2840.         case 'eml':
  2841.         case 'msg':
  2842.             $img = 'fa fa-envelope-o';
  2843.             break;
  2844.         case 'xls':
  2845.         case 'xlsx':
  2846.         case 'ods':
  2847.             $img = 'fa fa-file-excel-o';
  2848.             break;
  2849.         case 'csv':
  2850.             $img = 'fa fa-file-text-o';
  2851.             break;
  2852.         case 'bak':
  2853.         case 'swp':
  2854.             $img = 'fa fa-clipboard';
  2855.             break;
  2856.         case 'doc':
  2857.         case 'docx':
  2858.         case 'odt':
  2859.             $img = 'fa fa-file-word-o';
  2860.             break;
  2861.         case 'ppt':
  2862.         case 'pptx':
  2863.             $img = 'fa fa-file-powerpoint-o';
  2864.             break;
  2865.         case 'ttf':
  2866.         case 'ttc':
  2867.         case 'otf':
  2868.         case 'woff':
  2869.         case 'woff2':
  2870.         case 'eot':
  2871.         case 'fon':
  2872.             $img = 'fa fa-font';
  2873.             break;
  2874.         case 'pdf':
  2875.             $img = 'fa fa-file-pdf-o';
  2876.             break;
  2877.         case 'psd':
  2878.         case 'ai':
  2879.         case 'eps':
  2880.         case 'fla':
  2881.         case 'swf':
  2882.             $img = 'fa fa-file-image-o';
  2883.             break;
  2884.         case 'exe':
  2885.         case 'msi':
  2886.             $img = 'fa fa-file-o';
  2887.             break;
  2888.         case 'bat':
  2889.             $img = 'fa fa-terminal';
  2890.             break;
  2891.         default:
  2892.             $img = 'fa fa-info-circle';
  2893.     }
  2894.  
  2895.     return $img;
  2896. }
  2897.  
  2898. /**
  2899.  * Get image files extensions
  2900.  * @return array
  2901.  */
  2902. function fm_get_image_exts()
  2903. {
  2904.     return array('ico', 'gif', 'jpg', 'jpeg', 'jpc', 'jp2', 'jpx', 'xbm', 'wbmp', 'png', 'bmp', 'tif', 'tiff', 'psd', 'svg', 'webp', 'avif');
  2905. }
  2906.  
  2907. /**
  2908.  * Get video files extensions
  2909.  * @return array
  2910.  */
  2911. function fm_get_video_exts()
  2912. {
  2913.     return array('avi', 'webm', 'wmv', 'mp4', 'm4v', 'ogm', 'ogv', 'mov', 'mkv');
  2914. }
  2915.  
  2916. /**
  2917.  * Get audio files extensions
  2918.  * @return array
  2919.  */
  2920. function fm_get_audio_exts()
  2921. {
  2922.     return array('wav', 'mp3', 'ogg', 'm4a');
  2923. }
  2924.  
  2925. /**
  2926.  * Get text file extensions
  2927.  * @return array
  2928.  */
  2929. function fm_get_text_exts()
  2930. {
  2931.     return array(
  2932.         'txt', 'css', 'ini', 'conf', 'log', 'htaccess', 'passwd', 'ftpquota', 'sql', 'js', 'ts', 'jsx', 'tsx', 'mjs', 'json', 'sh', 'config',
  2933.         'php', 'php4', 'php5', 'phps', 'phtml', 'htm', 'html', 'shtml', 'xhtml', 'xml', 'xsl', 'm3u', 'm3u8', 'pls', 'cue', 'bash', 'tpl', 'vue',
  2934.         'eml', 'msg', 'csv', 'bat', 'twig', 'tpl', 'md', 'gitignore', 'less', 'sass', 'scss', 'c', 'cpp', 'cs', 'py', 'go', 'zsh', 'swift', 'yml',
  2935.         'map', 'lock', 'dtd', 'svg', 'scss', 'asp', 'aspx', 'asx', 'asmx', 'ashx', 'jsp', 'jspx', 'cfm', 'cgi', 'dockerfile', 'ruby', 'twig',
  2936.         'yml', 'yaml', 'toml', 'md', 'vhost', 'scpt', 'applescript', 'c', 'cs', 'csx', 'cshtml', 'cpp', 'c++', 'coffee', 'cfm', 'rb',
  2937.         'graphql', 'mustache', 'jinja', 'phtml', 'http', 'handlebars', 'lock', 'java', 'es', 'es6', 'markdown', 'wiki', 'vhost', 'sql',
  2938.     );
  2939. }
  2940.  
  2941. /**
  2942.  * Get mime types of text files
  2943.  * @return array
  2944.  */
  2945. function fm_get_text_mimes()
  2946. {
  2947.     return array(
  2948.         'application/xml',
  2949.         'application/javascript',
  2950.         'application/x-javascript',
  2951.         'image/svg+xml',
  2952.         'message/rfc822',
  2953.         'application/json',
  2954.     );
  2955. }
  2956.  
  2957. /**
  2958.  * Get file names of text files w/o extensions
  2959.  * @return array
  2960.  */
  2961. function fm_get_text_names()
  2962. {
  2963.     return array(
  2964.         'license',
  2965.         'readme',
  2966.         'authors',
  2967.         'contributors',
  2968.         'changelog',
  2969.     );
  2970. }
  2971.  
  2972. /**
  2973.  * Get online docs viewer supported files extensions
  2974.  * @return array
  2975.  */
  2976. function fm_get_onlineViewer_exts()
  2977. {
  2978.     return array('doc', 'docx', 'xls', 'xlsx', 'pdf', 'ppt', 'pptx', 'ai', 'psd', 'dxf', 'xps', 'rar', 'odt', 'ods');
  2979. }
  2980.  
  2981. /**
  2982.  * It returns the mime type of a file based on its extension.
  2983.  * @param extension The file extension of the file you want to get the mime type for.
  2984.  * @return string|string[] The mime type of the file.
  2985.  */
  2986. function fm_get_file_mimes($extension)
  2987. {
  2988.     $fileTypes['swf'] = 'application/x-shockwave-flash';
  2989.     $fileTypes['pdf'] = 'application/pdf';
  2990.     $fileTypes['exe'] = 'application/octet-stream';
  2991.     $fileTypes['zip'] = 'application/zip';
  2992.     $fileTypes['doc'] = 'application/msword';
  2993.     $fileTypes['xls'] = 'application/vnd.ms-excel';
  2994.     $fileTypes['ppt'] = 'application/vnd.ms-powerpoint';
  2995.     $fileTypes['gif'] = 'image/gif';
  2996.     $fileTypes['png'] = 'image/png';
  2997.     $fileTypes['jpeg'] = 'image/jpg';
  2998.     $fileTypes['jpg'] = 'image/jpg';
  2999.     $fileTypes['webp'] = 'image/webp';
  3000.     $fileTypes['avif'] = 'image/avif';
  3001.     $fileTypes['rar'] = 'application/rar';
  3002.  
  3003.     $fileTypes['ra'] = 'audio/x-pn-realaudio';
  3004.     $fileTypes['ram'] = 'audio/x-pn-realaudio';
  3005.     $fileTypes['ogg'] = 'audio/x-pn-realaudio';
  3006.  
  3007.     $fileTypes['wav'] = 'video/x-msvideo';
  3008.     $fileTypes['wmv'] = 'video/x-msvideo';
  3009.     $fileTypes['avi'] = 'video/x-msvideo';
  3010.     $fileTypes['asf'] = 'video/x-msvideo';
  3011.     $fileTypes['divx'] = 'video/x-msvideo';
  3012.  
  3013.     $fileTypes['mp3'] = 'audio/mpeg';
  3014.     $fileTypes['mp4'] = 'audio/mpeg';
  3015.     $fileTypes['mpeg'] = 'video/mpeg';
  3016.     $fileTypes['mpg'] = 'video/mpeg';
  3017.     $fileTypes['mpe'] = 'video/mpeg';
  3018.     $fileTypes['mov'] = 'video/quicktime';
  3019.     $fileTypes['swf'] = 'video/quicktime';
  3020.     $fileTypes['3gp'] = 'video/quicktime';
  3021.     $fileTypes['m4a'] = 'video/quicktime';
  3022.     $fileTypes['aac'] = 'video/quicktime';
  3023.     $fileTypes['m3u'] = 'video/quicktime';
  3024.  
  3025.     $fileTypes['php'] = ['application/x-php'];
  3026.     $fileTypes['html'] = ['text/html'];
  3027.     $fileTypes['txt'] = ['text/plain'];
  3028.     //Unknown mime-types should be 'application/octet-stream'
  3029.     if(empty($fileTypes[$extension])) {
  3030.       $fileTypes[$extension] = ['application/octet-stream'];
  3031.     }
  3032.     return $fileTypes[$extension];
  3033. }
  3034.  
  3035. /**
  3036.  * This function scans the files and folder recursively, and return matching files
  3037.  * @param string $dir
  3038.  * @param string $filter
  3039.  * @return array|null
  3040.  */
  3041.  function scan($dir = '', $filter = '') {
  3042.     $path = FM_ROOT_PATH.'/'.$dir;
  3043.      if($path) {
  3044.          $ite = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path));
  3045.          $rii = new RegexIterator($ite, "/(" . $filter . ")/i");
  3046.  
  3047.          $files = array();
  3048.          foreach ($rii as $file) {
  3049.              if (!$file->isDir()) {
  3050.                  $fileName = $file->getFilename();
  3051.                  $location = str_replace(FM_ROOT_PATH, '', $file->getPath());
  3052.                  $files[] = array(
  3053.                      "name" => $fileName,
  3054.                      "type" => "file",
  3055.                      "path" => $location,
  3056.                  );
  3057.              }
  3058.          }
  3059.          return $files;
  3060.      }
  3061. }
  3062.  
  3063. /**
  3064. * Parameters: downloadFile(File Location, File Name,
  3065. * max speed, is streaming
  3066. * If streaming - videos will show as videos, images as images
  3067. * instead of download prompt
  3068. * https://stackoverflow.com/a/13821992/1164642
  3069. */
  3070. function fm_download_file($fileLocation, $fileName, $chunkSize  = 1024)
  3071. {
  3072.     if (connection_status() != 0)
  3073.         return (false);
  3074.     $extension = pathinfo($fileName, PATHINFO_EXTENSION);
  3075.  
  3076.     $contentType = fm_get_file_mimes($extension);
  3077.  
  3078.     if(is_array($contentType)) {
  3079.         $contentType = implode(' ', $contentType);
  3080.     }
  3081.  
  3082.     $size = filesize($fileLocation);
  3083.  
  3084.     if ($size == 0) {
  3085.         fm_set_msg(lng('Zero byte file! Aborting download'), 'error');
  3086.         $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
  3087.  
  3088.         return (false);
  3089.     }
  3090.  
  3091.     @ini_set('magic_quotes_runtime', 0);
  3092.     $fp = fopen("$fileLocation", "rb");
  3093.  
  3094.     if ($fp === false) {
  3095.         fm_set_msg(lng('Cannot open file! Aborting download'), 'error');
  3096.         $FM_PATH=FM_PATH; fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
  3097.         return (false);
  3098.     }
  3099.  
  3100.     // headers
  3101.     header('Content-Description: File Transfer');
  3102.     header('Expires: 0');
  3103.     header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
  3104.     header('Pragma: public');
  3105.     header("Content-Transfer-Encoding: binary");
  3106.     header("Content-Type: $contentType");
  3107.  
  3108.     $contentDisposition = 'attachment';
  3109.  
  3110.     if (strstr($_SERVER['HTTP_USER_AGENT'], "MSIE")) {
  3111.         $fileName = preg_replace('/\./', '%2e', $fileName, substr_count($fileName, '.') - 1);
  3112.         header("Content-Disposition: $contentDisposition;filename=\"$fileName\"");
  3113.     } else {
  3114.         header("Content-Disposition: $contentDisposition;filename=\"$fileName\"");
  3115.     }
  3116.  
  3117.     header("Accept-Ranges: bytes");
  3118.     $range = 0;
  3119.  
  3120.     if (isset($_SERVER['HTTP_RANGE'])) {
  3121.         list($a, $range) = explode("=", $_SERVER['HTTP_RANGE']);
  3122.         str_replace($range, "-", $range);
  3123.         $size2 = $size - 1;
  3124.         $new_length = $size - $range;
  3125.         header("HTTP/1.1 206 Partial Content");
  3126.         header("Content-Length: $new_length");
  3127.         header("Content-Range: bytes $range$size2/$size");
  3128.     } else {
  3129.         $size2 = $size - 1;
  3130.         header("Content-Range: bytes 0-$size2/$size");
  3131.         header("Content-Length: " . $size);
  3132.     }
  3133.     $fileLocation = realpath($fileLocation);
  3134.     while (ob_get_level()) ob_end_clean();
  3135.     readfile($fileLocation);
  3136.  
  3137.     fclose($fp);
  3138.  
  3139.     return ((connection_status() == 0) and !connection_aborted());
  3140. }
  3141.  
  3142. /**
  3143.  * If the theme is dark, return the text-white and bg-dark classes.
  3144.  * @return string the value of the  variable.
  3145.  */
  3146. function fm_get_theme() {
  3147.     $result = '';
  3148.     if(FM_THEME == "dark") {
  3149.         $result = "text-white bg-dark";
  3150.     }
  3151.     return $result;
  3152. }
  3153.  
  3154. /**
  3155.  * Class to work with zip files (using ZipArchive)
  3156.  */
  3157. class FM_Zipper
  3158. {
  3159.     private $zip;
  3160.  
  3161.     public function __construct()
  3162.     {
  3163.         $this->zip = new ZipArchive();
  3164.     }
  3165.  
  3166.     /**
  3167.      * Create archive with name $filename and files $files (RELATIVE PATHS!)
  3168.      * @param string $filename
  3169.      * @param array|string $files
  3170.      * @return bool
  3171.      */
  3172.     public function create($filename, $files)
  3173.     {
  3174.         $res = $this->zip->open($filename, ZipArchive::CREATE);
  3175.         if ($res !== true) {
  3176.             return false;
  3177.         }
  3178.         if (is_array($files)) {
  3179.             foreach ($files as $f) {
  3180.                 $f = fm_clean_path($f);
  3181.                 if (!$this->addFileOrDir($f)) {
  3182.                     $this->zip->close();
  3183.                     return false;
  3184.                 }
  3185.             }
  3186.             $this->zip->close();
  3187.             return true;
  3188.         } else {
  3189.             if ($this->addFileOrDir($files)) {
  3190.                 $this->zip->close();
  3191.                 return true;
  3192.             }
  3193.             return false;
  3194.         }
  3195.     }
  3196.  
  3197.     /**
  3198.      * Extract archive $filename to folder $path (RELATIVE OR ABSOLUTE PATHS)
  3199.      * @param string $filename
  3200.      * @param string $path
  3201.      * @return bool
  3202.      */
  3203.     public function unzip($filename, $path)
  3204.     {
  3205.         $res = $this->zip->open($filename);
  3206.         if ($res !== true) {
  3207.             return false;
  3208.         }
  3209.         if ($this->zip->extractTo($path)) {
  3210.             $this->zip->close();
  3211.             return true;
  3212.         }
  3213.         return false;
  3214.     }
  3215.  
  3216.     /**
  3217.      * Add file/folder to archive
  3218.      * @param string $filename
  3219.      * @return bool
  3220.      */
  3221.     private function addFileOrDir($filename)
  3222.     {
  3223.         if (is_file($filename)) {
  3224.             return $this->zip->addFile($filename);
  3225.         } elseif (is_dir($filename)) {
  3226.             return $this->addDir($filename);
  3227.         }
  3228.         return false;
  3229.     }
  3230.  
  3231.     /**
  3232.      * Add folder recursively
  3233.      * @param string $path
  3234.      * @return bool
  3235.      */
  3236.     private function addDir($path)
  3237.     {
  3238.         if (!$this->zip->addEmptyDir($path)) {
  3239.             return false;
  3240.         }
  3241.         $objects = scandir($path);
  3242.         if (is_array($objects)) {
  3243.             foreach ($objects as $file) {
  3244.                 if ($file != '.' && $file != '..') {
  3245.                     if (is_dir($path . '/' . $file)) {
  3246.                         if (!$this->addDir($path . '/' . $file)) {
  3247.                             return false;
  3248.                         }
  3249.                     } elseif (is_file($path . '/' . $file)) {
  3250.                         if (!$this->zip->addFile($path . '/' . $file)) {
  3251.                             return false;
  3252.                         }
  3253.                     }
  3254.                 }
  3255.             }
  3256.             return true;
  3257.         }
  3258.         return false;
  3259.     }
  3260. }
  3261.  
  3262. /**
  3263.  * Class to work with Tar files (using PharData)
  3264.  */
  3265. class FM_Zipper_Tar
  3266. {
  3267.     private $tar;
  3268.  
  3269.     public function __construct()
  3270.     {
  3271.         $this->tar = null;
  3272.     }
  3273.  
  3274.     /**
  3275.      * Create archive with name $filename and files $files (RELATIVE PATHS!)
  3276.      * @param string $filename
  3277.      * @param array|string $files
  3278.      * @return bool
  3279.      */
  3280.     public function create($filename, $files)
  3281.     {
  3282.         $this->tar = new PharData($filename);
  3283.         if (is_array($files)) {
  3284.             foreach ($files as $f) {
  3285.                 $f = fm_clean_path($f);
  3286.                 if (!$this->addFileOrDir($f)) {
  3287.                     return false;
  3288.                 }
  3289.             }
  3290.             return true;
  3291.         } else {
  3292.             if ($this->addFileOrDir($files)) {
  3293.                 return true;
  3294.             }
  3295.             return false;
  3296.         }
  3297.     }
  3298.  
  3299.     /**
  3300.      * Extract archive $filename to folder $path (RELATIVE OR ABSOLUTE PATHS)
  3301.      * @param string $filename
  3302.      * @param string $path
  3303.      * @return bool
  3304.      */
  3305.     public function unzip($filename, $path)
  3306.     {
  3307.         $res = $this->tar->open($filename);
  3308.         if ($res !== true) {
  3309.             return false;
  3310.         }
  3311.         if ($this->tar->extractTo($path)) {
  3312.             return true;
  3313.         }
  3314.         return false;
  3315.     }
  3316.  
  3317.     /**
  3318.      * Add file/folder to archive
  3319.      * @param string $filename
  3320.      * @return bool
  3321.      */
  3322.     private function addFileOrDir($filename)
  3323.     {
  3324.         if (is_file($filename)) {
  3325.             try {
  3326.                 $this->tar->addFile($filename);
  3327.                 return true;
  3328.             } catch (Exception $e) {
  3329.                 return false;
  3330.             }
  3331.         } elseif (is_dir($filename)) {
  3332.             return $this->addDir($filename);
  3333.         }
  3334.         return false;
  3335.     }
  3336.  
  3337.     /**
  3338.      * Add folder recursively
  3339.      * @param string $path
  3340.      * @return bool
  3341.      */
  3342.     private function addDir($path)
  3343.     {
  3344.         $objects = scandir($path);
  3345.         if (is_array($objects)) {
  3346.             foreach ($objects as $file) {
  3347.                 if ($file != '.' && $file != '..') {
  3348.                     if (is_dir($path . '/' . $file)) {
  3349.                         if (!$this->addDir($path . '/' . $file)) {
  3350.                             return false;
  3351.                         }
  3352.                     } elseif (is_file($path . '/' . $file)) {
  3353.                         try {
  3354.                             $this->tar->addFile($path . '/' . $file);
  3355.                         } catch (Exception $e) {
  3356.                             return false;
  3357.                         }
  3358.                     }
  3359.                 }
  3360.             }
  3361.             return true;
  3362.         }
  3363.         return false;
  3364.     }
  3365. }
  3366.  
  3367. /**
  3368.  * Save Configuration
  3369.  */
  3370.  class FM_Config
  3371. {
  3372.      var $data;
  3373.  
  3374.     function __construct()
  3375.     {
  3376.         global $root_path, $root_url, $CONFIG;
  3377.         $fm_url = $root_url.$_SERVER["PHP_SELF"];
  3378.         $this->data = array(
  3379.             'lang' => 'en',
  3380.             'error_reporting' => true,
  3381.             'show_hidden' => true
  3382.         );
  3383.         $data = false;
  3384.         if (strlen($CONFIG)) {
  3385.             $data = fm_object_to_array(json_decode($CONFIG));
  3386.         } else {
  3387.             $msg = 'Tiny File Manager<br>Error: Cannot load configuration';
  3388.             if (substr($fm_url, -1) == '/') {
  3389.                 $fm_url = rtrim($fm_url, '/');
  3390.                 $msg .= '<br>';
  3391.                 $msg .= '<br>Seems like you have a trailing slash on the URL.';
  3392.                 $msg .= '<br>Try this link: <a href="' . $fm_url . '">' . $fm_url . '</a>';
  3393.             }
  3394.             die($msg);
  3395.         }
  3396.         if (is_array($data) && count($data)) $this->data = $data;
  3397.         else $this->save();
  3398.     }
  3399.  
  3400.     function save()
  3401.     {
  3402.         $fm_file = __FILE__;
  3403.         $var_name = '$CONFIG';
  3404.         $var_value = var_export(json_encode($this->data), true);
  3405.         $config_string = "<?php" . chr(13) . chr(10) . "//Default Configuration".chr(13) . chr(10)."$var_name = $var_value;" . chr(13) . chr(10);
  3406.         if (is_writable($fm_file)) {
  3407.             $lines = file($fm_file);
  3408.             if ($fh = @fopen($fm_file, "w")) {
  3409.                 @fputs($fh, $config_string, strlen($config_string));
  3410.                 for ($x = 3; $x < count($lines); $x++) {
  3411.                     @fputs($fh, $lines[$x], strlen($lines[$x]));
  3412.                 }
  3413.                 @fclose($fh);
  3414.             }
  3415.         }
  3416.     }
  3417. }
  3418.  
  3419. //--- Templates Functions ---
  3420.  
  3421. /**
  3422.  * Show nav block
  3423.  * @param string $path
  3424.  */
  3425. function fm_show_nav_path($path)
  3426. {
  3427.     global $lang, $sticky_navbar, $editFile;
  3428.     $isStickyNavBar = $sticky_navbar ? 'fixed-top' : '';
  3429.     $getTheme = fm_get_theme();
  3430.     $getTheme .= " navbar-light";
  3431.     if(FM_THEME == "dark") {
  3432.         $getTheme .= " navbar-dark";
  3433.     } else {
  3434.         $getTheme .= " bg-white";
  3435.     }
  3436.     ?>
  3437.     <nav class="navbar navbar-expand-lg <?php echo $getTheme; ?> mb-4 main-nav <?php echo $isStickyNavBar ?>">
  3438.         <a class="navbar-brand"> <?php echo lng('AppTitle') ?> </a>
  3439.         <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
  3440.             <span class="navbar-toggler-icon"></span>
  3441.         </button>
  3442.         <div class="collapse navbar-collapse" id="navbarSupportedContent">
  3443.  
  3444.             <?php
  3445.             $path = fm_clean_path($path);
  3446.             $root_url = "<a href='?p='><i class='fa fa-home' aria-hidden='true' title='" . FM_ROOT_PATH . "'></i></a>";
  3447.             $sep = '<i class="bread-crumb"> / </i>';
  3448.             if ($path != '') {
  3449.                 $exploded = explode('/', $path);
  3450.                 $count = count($exploded);
  3451.                 $array = array();
  3452.                 $parent = '';
  3453.                 for ($i = 0; $i < $count; $i++) {
  3454.                     $parent = trim($parent . '/' . $exploded[$i], '/');
  3455.                     $parent_enc = urlencode($parent);
  3456.                     $array[] = "<a href='?p={$parent_enc}'>" . fm_enc(fm_convert_win($exploded[$i])) . "</a>";
  3457.                 }
  3458.                 $root_url .= $sep . implode($sep, $array);
  3459.             }
  3460.             echo '<div class="col-xs-6 col-sm-5">' . $root_url . $editFile . '</div>';
  3461.             ?>
  3462.  
  3463.             <div class="col-xs-6 col-sm-7">
  3464.                 <ul class="navbar-nav justify-content-end <?php echo fm_get_theme();  ?>">
  3465.                     <li class="nav-item mr-2">
  3466.                         <div class="input-group input-group-sm mr-1" style="margin-top:4px;">
  3467.                             <input type="text" class="form-control" placeholder="<?php echo lng('Filter') ?>" aria-label="<?php echo lng('Search') ?>" aria-describedby="search-addon2" id="search-addon">
  3468.                             <div class="input-group-append">
  3469.                                 <span class="input-group-text brl-0 brr-0" id="search-addon2"><i class="fa fa-search"></i></span>
  3470.                             </div>
  3471.                             <div class="input-group-append btn-group">
  3472.                                 <span class="input-group-text dropdown-toggle brl-0" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span>
  3473.                                   <div class="dropdown-menu dropdown-menu-right">
  3474.                                     <a class="dropdown-item" href="<?php echo $path2 = $path ? $path : '.'; ?>" id="js-search-modal" data-bs-toggle="modal" data-bs-target="#searchModal"><?php echo lng('Advanced Search') ?></a>
  3475.                                   </div>
  3476.                             </div>
  3477.                         </div>
  3478.                     </li>
  3479.                     <?php if (!FM_READONLY): ?>
  3480.                     <li class="nav-item">
  3481.                         <a title="<?php echo lng('Upload') ?>" class="nav-link" href="?p=<?php echo urlencode(FM_PATH) ?>&amp;upload"><i class="fa fa-cloud-upload" aria-hidden="true"></i> <?php echo lng('Upload') ?></a>
  3482.                     </li>
  3483.                     <li class="nav-item">
  3484.                         <a title="<?php echo lng('NewItem') ?>" class="nav-link" href="#createNewItem" data-bs-toggle="modal" data-bs-target="#createNewItem"><i class="fa fa-plus-square"></i> <?php echo lng('NewItem') ?></a>
  3485.                     </li>
  3486.                     <?php endif; ?>
  3487.                     <?php if (FM_USE_AUTH): ?>
  3488.                     <li class="nav-item avatar dropdown">
  3489.                         <a class="nav-link dropdown-toggle" id="navbarDropdownMenuLink-5" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <i class="fa fa-user-circle"></i> <?php if(isset($_SESSION[FM_SESSION_ID]['logged'])) { echo $_SESSION[FM_SESSION_ID]['logged']; } ?></a>
  3490.                         <div class="dropdown-menu text-small shadow <?php echo fm_get_theme(); ?>" aria-labelledby="navbarDropdownMenuLink-5">
  3491.                             <?php if (!FM_READONLY): ?>
  3492.                             <a title="<?php echo lng('Settings') ?>" class="dropdown-item nav-link" href="?p=<?php echo urlencode(FM_PATH) ?>&amp;settings=1"><i class="fa fa-cog" aria-hidden="true"></i> <?php echo lng('Settings') ?></a>
  3493.                             <?php endif ?>
  3494.                             <a title="<?php echo lng('Help') ?>" class="dropdown-item nav-link" href="?p=<?php echo urlencode(FM_PATH) ?>&amp;help=2"><i class="fa fa-exclamation-circle" aria-hidden="true"></i> <?php echo lng('Help') ?></a>
  3495.                             <a title="<?php echo lng('Logout') ?>" class="dropdown-item nav-link" href="?logout=1"><i class="fa fa-sign-out" aria-hidden="true"></i> <?php echo lng('Logout') ?></a>
  3496.                         </div>
  3497.                     </li>
  3498.                     <?php else: ?>
  3499.                         <?php if (!FM_READONLY): ?>
  3500.                             <li class="nav-item">
  3501.                                 <a title="<?php echo lng('Settings') ?>" class="dropdown-item nav-link" href="?p=<?php echo urlencode(FM_PATH) ?>&amp;settings=1"><i class="fa fa-cog" aria-hidden="true"></i> <?php echo lng('Settings') ?></a>
  3502.                             </li>
  3503.                         <?php endif; ?>
  3504.                     <?php endif; ?>
  3505.                 </ul>
  3506.             </div>
  3507.         </div>
  3508.     </nav>
  3509.     <?php
  3510. }
  3511.  
  3512. /**
  3513.  * Show alert message from session
  3514.  */
  3515. function fm_show_message()
  3516. {
  3517.     if (isset($_SESSION[FM_SESSION_ID]['message'])) {
  3518.         $class = isset($_SESSION[FM_SESSION_ID]['status']) ? $_SESSION[FM_SESSION_ID]['status'] : 'ok';
  3519.         echo '<p class="message ' . $class . '">' . $_SESSION[FM_SESSION_ID]['message'] . '</p>';
  3520.         unset($_SESSION[FM_SESSION_ID]['message']);
  3521.         unset($_SESSION[FM_SESSION_ID]['status']);
  3522.     }
  3523. }
  3524.  
  3525. /**
  3526.  * Show page header in Login Form
  3527.  */
  3528. function fm_show_header_login()
  3529. {
  3530. $sprites_ver = '20160315';
  3531. header("Content-Type: text/html; charset=utf-8");
  3532. header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");
  3533. header("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
  3534. header("Pragma: no-cache");
  3535.  
  3536. global $lang, $root_url, $favicon_path;
  3537. ?>
  3538. <!DOCTYPE html>
  3539. <html lang="en">
  3540. <head>
  3541.     <meta charset="utf-8">
  3542.     <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  3543.     <meta name="description" content="Web based File Manager in PHP, Manage your files efficiently and easily with Tiny File Manager">
  3544.     <meta name="author" content="CCP Programmers">
  3545.     <meta name="robots" content="noindex, nofollow">
  3546.     <meta name="googlebot" content="noindex">
  3547.     <?php if($favicon_path) { echo '<link rel="icon" href="'.fm_enc($favicon_path).'" type="image/png">'; } ?>
  3548.     <title><?php echo fm_enc(APP_TITLE) ?></title>
  3549.     <link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin/>
  3550.     <link rel="dns-prefetch" href="https://cdn.jsdelivr.net"/>
  3551.     <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
  3552.     <style>
  3553.         body.fm-login-page{ background-color:#f7f9fb;font-size:14px;background-color:#f7f9fb;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 304 304' width='304' height='304'%3E%3Cpath fill='%23e2e9f1' fill-opacity='0.4' d='M44.1 224a5 5 0 1 1 0 2H0v-2h44.1zm160 48a5 5 0 1 1 0 2H82v-2h122.1zm57.8-46a5 5 0 1 1 0-2H304v2h-42.1zm0 16a5 5 0 1 1 0-2H304v2h-42.1zm6.2-114a5 5 0 1 1 0 2h-86.2a5 5 0 1 1 0-2h86.2zm-256-48a5 5 0 1 1 0 2H0v-2h12.1zm185.8 34a5 5 0 1 1 0-2h86.2a5 5 0 1 1 0 2h-86.2zM258 12.1a5 5 0 1 1-2 0V0h2v12.1zm-64 208a5 5 0 1 1-2 0v-54.2a5 5 0 1 1 2 0v54.2zm48-198.2V80h62v2h-64V21.9a5 5 0 1 1 2 0zm16 16V64h46v2h-48V37.9a5 5 0 1 1 2 0zm-128 96V208h16v12.1a5 5 0 1 1-2 0V210h-16v-76.1a5 5 0 1 1 2 0zm-5.9-21.9a5 5 0 1 1 0 2H114v48H85.9a5 5 0 1 1 0-2H112v-48h12.1zm-6.2 130a5 5 0 1 1 0-2H176v-74.1a5 5 0 1 1 2 0V242h-60.1zm-16-64a5 5 0 1 1 0-2H114v48h10.1a5 5 0 1 1 0 2H112v-48h-10.1zM66 284.1a5 5 0 1 1-2 0V274H50v30h-2v-32h18v12.1zM236.1 176a5 5 0 1 1 0 2H226v94h48v32h-2v-30h-48v-98h12.1zm25.8-30a5 5 0 1 1 0-2H274v44.1a5 5 0 1 1-2 0V146h-10.1zm-64 96a5 5 0 1 1 0-2H208v-80h16v-14h-42.1a5 5 0 1 1 0-2H226v18h-16v80h-12.1zm86.2-210a5 5 0 1 1 0 2H272V0h2v32h10.1zM98 101.9V146H53.9a5 5 0 1 1 0-2H96v-42.1a5 5 0 1 1 2 0zM53.9 34a5 5 0 1 1 0-2H80V0h2v34H53.9zm60.1 3.9V66H82v64H69.9a5 5 0 1 1 0-2H80V64h32V37.9a5 5 0 1 1 2 0zM101.9 82a5 5 0 1 1 0-2H128V37.9a5 5 0 1 1 2 0V82h-28.1zm16-64a5 5 0 1 1 0-2H146v44.1a5 5 0 1 1-2 0V18h-26.1zm102.2 270a5 5 0 1 1 0 2H98v14h-2v-16h124.1zM242 149.9V160h16v34h-16v62h48v48h-2v-46h-48v-66h16v-30h-16v-12.1a5 5 0 1 1 2 0zM53.9 18a5 5 0 1 1 0-2H64V2H48V0h18v18H53.9zm112 32a5 5 0 1 1 0-2H192V0h50v2h-48v48h-28.1zm-48-48a5 5 0 0 1-9.8-2h2.07a3 3 0 1 0 5.66 0H178v34h-18V21.9a5 5 0 1 1 2 0V32h14V2h-58.1zm0 96a5 5 0 1 1 0-2H137l32-32h39V21.9a5 5 0 1 1 2 0V66h-40.17l-32 32H117.9zm28.1 90.1a5 5 0 1 1-2 0v-76.51L175.59 80H224V21.9a5 5 0 1 1 2 0V82h-49.59L146 112.41v75.69zm16 32a5 5 0 1 1-2 0v-99.51L184.59 96H300.1a5 5 0 0 1 3.9-3.9v2.07a3 3 0 0 0 0 5.66v2.07a5 5 0 0 1-3.9-3.9H185.41L162 121.41v98.69zm-144-64a5 5 0 1 1-2 0v-3.51l48-48V48h32V0h2v50H66v55.41l-48 48v2.69zM50 53.9v43.51l-48 48V208h26.1a5 5 0 1 1 0 2H0v-65.41l48-48V53.9a5 5 0 1 1 2 0zm-16 16V89.41l-34 34v-2.82l32-32V69.9a5 5 0 1 1 2 0zM12.1 32a5 5 0 1 1 0 2H9.41L0 43.41V40.6L8.59 32h3.51zm265.8 18a5 5 0 1 1 0-2h18.69l7.41-7.41v2.82L297.41 50H277.9zm-16 160a5 5 0 1 1 0-2H288v-71.41l16-16v2.82l-14 14V210h-28.1zm-208 32a5 5 0 1 1 0-2H64v-22.59L40.59 194H21.9a5 5 0 1 1 0-2H41.41L66 216.59V242H53.9zm150.2 14a5 5 0 1 1 0 2H96v-56.6L56.6 162H37.9a5 5 0 1 1 0-2h19.5L98 200.6V256h106.1zm-150.2 2a5 5 0 1 1 0-2H80v-46.59L48.59 178H21.9a5 5 0 1 1 0-2H49.41L82 208.59V258H53.9zM34 39.8v1.61L9.41 66H0v-2h8.59L32 40.59V0h2v39.8zM2 300.1a5 5 0 0 1 3.9 3.9H3.83A3 3 0 0 0 0 302.17V256h18v48h-2v-46H2v42.1zM34 241v63h-2v-62H0v-2h34v1zM17 18H0v-2h16V0h2v18h-1zm273-2h14v2h-16V0h2v16zm-32 273v15h-2v-14h-14v14h-2v-16h18v1zM0 92.1A5.02 5.02 0 0 1 6 97a5 5 0 0 1-6 4.9v-2.07a3 3 0 1 0 0-5.66V92.1zM80 272h2v32h-2v-32zm37.9 32h-2.07a3 3 0 0 0-5.66 0h-2.07a5 5 0 0 1 9.8 0zM5.9 0A5.02 5.02 0 0 1 0 5.9V3.83A3 3 0 0 0 3.83 0H5.9zm294.2 0h2.07A3 3 0 0 0 304 3.83V5.9a5 5 0 0 1-3.9-5.9zm3.9 300.1v2.07a3 3 0 0 0-1.83 1.83h-2.07a5 5 0 0 1 3.9-3.9zM97 100a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-48 32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 48a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-64a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 96a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-144a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-96 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm96 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-64a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-32 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM49 36a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-32 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM33 68a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-48a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 240a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-64a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm80-176a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 48a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm112 176a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM17 180a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM17 84a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 64a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6z'%3E%3C/path%3E%3C/svg%3E");}
  3554.         .fm-login-page .brand{ width:121px;overflow:hidden;margin:0 auto;position:relative;z-index:1}
  3555.         .fm-login-page .brand img{ width:100%}
  3556.         .fm-login-page .card-wrapper{ width:360px;margin-top:10%;margin-left:auto;margin-right:auto;}
  3557.         .fm-login-page .card{ border-color:transparent;box-shadow:0 4px 8px rgba(0,0,0,.05)}
  3558.         .fm-login-page .card-title{ margin-bottom:1.5rem;font-size:24px;font-weight:400;}
  3559.         .fm-login-page .form-control{ border-width:2.3px}
  3560.         .fm-login-page .form-group label{ width:100%}
  3561.         .fm-login-page .btn.btn-block{ padding:12px 10px}
  3562.         .fm-login-page .footer{ margin:40px 0;color:#888;text-align:center}
  3563.         @media screen and (max-width:425px){
  3564.             .fm-login-page .card-wrapper{ width:90%;margin:0 auto;margin-top:10%;}
  3565.         }
  3566.         @media screen and (max-width:320px){
  3567.             .fm-login-page .card.fat{ padding:0}
  3568.             .fm-login-page .card.fat .card-body{ padding:15px}
  3569.         }
  3570.         .message{ padding:4px 7px;border:1px solid #ddd;background-color:#fff}
  3571.         .message.ok{ border-color:green;color:green}
  3572.         .message.error{ border-color:red;color:red}
  3573.         .message.alert{ border-color:orange;color:orange}
  3574.         body.fm-login-page.theme-dark {background-color: #2f2a2a;}
  3575.         .theme-dark svg g, .theme-dark svg path {fill: #ffffff; }
  3576.     </style>
  3577. </head>
  3578. <body class="fm-login-page <?php echo (FM_THEME == "dark") ? 'theme-dark' : ''; ?>">
  3579. <div id="wrapper" class="container-fluid">
  3580.  
  3581.     <?php
  3582.     }
  3583.  
  3584.     /**
  3585.      * Show page footer in Login Form
  3586.      */
  3587.     function fm_show_footer_login()
  3588.     {
  3589.     ?>
  3590. </div>
  3591. <script src="https://code.jquery.com/jquery-3.6.1.min.js" integrity="sha256-o88AwQnZB+VDvE9tvIXrMQaPlFFSUTR+nldQm1LuPXQ=" crossorigin="anonymous"></script>
  3592. <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-OERcA2EqjJCMA+/3y+gxIOqMEjwtxJY7qPCqsdltbNJuaOe923+mo//f6V8Qbsw3" crossorigin="anonymous"></script>
  3593. </body>
  3594. </html>
  3595. <?php
  3596. }
  3597.  
  3598. /**
  3599.  * Show Header after login
  3600.  */
  3601. function fm_show_header()
  3602. {
  3603. $sprites_ver = '20160315';
  3604. header("Content-Type: text/html; charset=utf-8");
  3605. header("Expires: Sat, 26 Jul 1997 05:00:00 GMT");
  3606. header("Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
  3607. header("Pragma: no-cache");
  3608.  
  3609. global $lang, $root_url, $sticky_navbar, $favicon_path;
  3610. $isStickyNavBar = $sticky_navbar ? 'navbar-fixed' : 'navbar-normal';
  3611. ?>
  3612. <!DOCTYPE html>
  3613. <html>
  3614. <head>
  3615.     <meta charset="utf-8">
  3616.     <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  3617.     <meta name="description" content="Web based File Manager in PHP, Manage your files efficiently and easily with Tiny File Manager">
  3618.     <meta name="author" content="CCP Programmers">
  3619.     <meta name="robots" content="noindex, nofollow">
  3620.     <meta name="googlebot" content="noindex">
  3621.     <?php if($favicon_path) { echo '<link rel="icon" href="'.fm_enc($favicon_path).'" type="image/png">'; } ?>
  3622.     <title><?php echo fm_enc(APP_TITLE) ?></title>
  3623.     <link rel="preconnect" href="https://cdn.jsdelivr.net" crossorigin/>
  3624.     <link rel="dns-prefetch" href="https://cdn.jsdelivr.net"/>
  3625.     <link rel="preconnect" href="https://cdnjs.cloudflare.com" crossorigin/>
  3626.     <link rel="dns-prefetch" href="https://cdnjs.cloudflare.com"/>
  3627.     <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous">
  3628.     <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" crossorigin="anonymous">
  3629.     <?php if (FM_USE_HIGHLIGHTJS && isset($_GET['view'])): ?>
  3630.     <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/styles/<?php echo FM_HIGHLIGHTJS_STYLE ?>.min.css">
  3631.     <?php endif; ?>
  3632.     <script type="text/javascript">window.csrf = '<?php echo $_SESSION['token']; ?>';</script>
  3633.     <style>
  3634.         html { -moz-osx-font-smoothing: grayscale; -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; height: 100%; scroll-behavior: smooth;}
  3635.         *,*::before,*::after { box-sizing: border-box;}
  3636.         body { font-size:15px; color:#222;background:#F7F7F7; }
  3637.         body.navbar-fixed { margin-top:55px; }
  3638.         a, a:hover, a:visited, a:focus { text-decoration:none !important; }
  3639.         .filename, td, th { white-space:nowrap  }
  3640.         .navbar-brand { font-weight:bold; }
  3641.         .nav-item.avatar a { cursor:pointer;text-transform:capitalize; }
  3642.         .nav-item.avatar a > i { font-size:15px; }
  3643.         .nav-item.avatar .dropdown-menu a { font-size:13px; }
  3644.         #search-addon { font-size:12px;border-right-width:0; }
  3645.         .brl-0 { background:transparent;border-left:0; border-top-left-radius: 0; border-bottom-left-radius: 0; }
  3646.         .brr-0 { border-top-right-radius: 0; border-bottom-right-radius: 0; }
  3647.         .bread-crumb { color:#cccccc;font-style:normal; }
  3648.         #main-table { transition: transform .25s cubic-bezier(0.4, 0.5, 0, 1),width 0s .25s;}
  3649.         #main-table .filename a { color:#222222; }
  3650.         .table td, .table th { vertical-align:middle !important; }
  3651.         .table .custom-checkbox-td .custom-control.custom-checkbox, .table .custom-checkbox-header .custom-control.custom-checkbox { min-width:18px; display: flex;align-items: center; justify-content: center; }
  3652.         .table-sm td, .table-sm th { padding:.4rem; }
  3653.         .table-bordered td, .table-bordered th { border:1px solid #f1f1f1; }
  3654.         .hidden { display:none  }
  3655.         pre.with-hljs { padding:0; overflow: hidden;  }
  3656.         pre.with-hljs code { margin:0;border:0;overflow:scroll;  }
  3657.         code.maxheight, pre.maxheight { max-height:512px  }
  3658.         .fa.fa-caret-right { font-size:1.2em;margin:0 4px;vertical-align:middle;color:#ececec  }
  3659.         .fa.fa-home { font-size:1.3em;vertical-align:bottom  }
  3660.         .path { margin-bottom:10px  }
  3661.         form.dropzone { min-height:200px;border:2px dashed #007bff;line-height:6rem; }
  3662.         .right { text-align:right  }
  3663.         .center, .close, .login-form, .preview-img-container { text-align:center  }
  3664.         .message { padding:4px 7px;border:1px solid #ddd;background-color:#fff  }
  3665.         .message.ok { border-color:green;color:green  }
  3666.         .message.error { border-color:red;color:red  }
  3667.         .message.alert { border-color:orange;color:orange  }
  3668.         .preview-img { max-width:100%;max-height:80vh;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAKklEQVR42mL5//8/Azbw+PFjrOJMDCSCUQ3EABZc4S0rKzsaSvTTABBgAMyfCMsY4B9iAAAAAElFTkSuQmCC) }
  3669.         .inline-actions > a > i { font-size:1em;margin-left:5px;background:#3785c1;color:#fff;padding:3px 4px;border-radius:3px; }
  3670.         .preview-video { position:relative;max-width:100%;height:0;padding-bottom:62.5%;margin-bottom:10px  }
  3671.         .preview-video video { position:absolute;width:100%;height:100%;left:0;top:0;background:#000  }
  3672.         .compact-table { border:0;width:auto  }
  3673.         .compact-table td, .compact-table th { width:100px;border:0;text-align:center  }
  3674.         .compact-table tr:hover td { background-color:#fff  }
  3675.         .filename { max-width:420px;overflow:hidden;text-overflow:ellipsis  }
  3676.         .break-word { word-wrap:break-word;margin-left:30px  }
  3677.         .break-word.float-left a { color:#7d7d7d  }
  3678.         .break-word + .float-right { padding-right:30px;position:relative  }
  3679.         .break-word + .float-right > a { color:#7d7d7d;font-size:1.2em;margin-right:4px  }
  3680.         #editor { position:absolute;right:15px;top:100px;bottom:15px;left:15px  }
  3681.         @media (max-width:481px) {
  3682.             #editor { top:150px; }
  3683.         }
  3684.         #normal-editor { border-radius:3px;border-width:2px;padding:10px;outline:none; }
  3685.         .btn-2 { padding:4px 10px;font-size:small; }
  3686.         li.file:before,li.folder:before { font:normal normal normal 14px/1 FontAwesome;content:"\f016";margin-right:5px }
  3687.         li.folder:before { content:"\f114" }
  3688.         i.fa.fa-folder-o { color:#0157b3 }
  3689.         i.fa.fa-picture-o { color:#26b99a }
  3690.         i.fa.fa-file-archive-o { color:#da7d7d }
  3691.         .btn-2 i.fa.fa-file-archive-o { color:inherit }
  3692.         i.fa.fa-css3 { color:#f36fa0 }
  3693.         i.fa.fa-file-code-o { color:#007bff }
  3694.         i.fa.fa-code { color:#cc4b4c }
  3695.         i.fa.fa-file-text-o { color:#0096e6 }
  3696.         i.fa.fa-html5 { color:#d75e72 }
  3697.         i.fa.fa-file-excel-o { color:#09c55d }
  3698.         i.fa.fa-file-powerpoint-o { color:#f6712e }
  3699.         i.go-back { font-size:1.2em;color:#007bff; }
  3700.         .main-nav { padding:0.2rem 1rem;box-shadow:0 4px 5px 0 rgba(0, 0, 0, .14), 0 1px 10px 0 rgba(0, 0, 0, .12), 0 2px 4px -1px rgba(0, 0, 0, .2)  }
  3701.         .dataTables_filter { display:none; }
  3702.         table.dataTable thead .sorting { cursor:pointer;background-repeat:no-repeat;background-position:center right;background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAQAAADYWf5HAAAAkElEQVQoz7XQMQ5AQBCF4dWQSJxC5wwax1Cq1e7BAdxD5SL+Tq/QCM1oNiJidwox0355mXnG/DrEtIQ6azioNZQxI0ykPhTQIwhCR+BmBYtlK7kLJYwWCcJA9M4qdrZrd8pPjZWPtOqdRQy320YSV17OatFC4euts6z39GYMKRPCTKY9UnPQ6P+GtMRfGtPnBCiqhAeJPmkqAAAAAElFTkSuQmCC'); }
  3703.         table.dataTable thead .sorting_asc { cursor:pointer;background-repeat:no-repeat;background-position:center right;background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZ0lEQVQ4y2NgGLKgquEuFxBPAGI2ahhWCsS/gDibUoO0gPgxEP8H4ttArEyuQYxAPBdqEAxPBImTY5gjEL9DM+wTENuQahAvEO9DMwiGdwAxOymGJQLxTyD+jgWDxCMZRsEoGAVoAADeemwtPcZI2wAAAABJRU5ErkJggg=='); }
  3704.         table.dataTable thead .sorting_desc { cursor:pointer;background-repeat:no-repeat;background-position:center right;background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZUlEQVQ4y2NgGAWjYBSggaqGu5FA/BOIv2PBIPFEUgxjB+IdQPwfC94HxLykus4GiD+hGfQOiB3J8SojEE9EM2wuSJzcsFMG4ttQgx4DsRalkZENxL+AuJQaMcsGxBOAmGvopk8AVz1sLZgg0bsAAAAASUVORK5CYII='); }
  3705.         table.dataTable thead tr:first-child th.custom-checkbox-header:first-child { background-image:none; }
  3706.         .footer-action li { margin-bottom:10px; }
  3707.         .app-v-title { font-size:24px;font-weight:300;letter-spacing:-.5px;text-transform:uppercase; }
  3708.         hr.custom-hr { border-top:1px dashed #8c8b8b;border-bottom:1px dashed #fff; }
  3709.         #snackbar { visibility:hidden;min-width:250px;margin-left:-125px;background-color:#333;color:#fff;text-align:center;border-radius:2px;padding:16px;position:fixed;z-index:1;left:50%;bottom:30px;font-size:17px; }
  3710.         #snackbar.show { visibility:visible;-webkit-animation:fadein 0.5s, fadeout 0.5s 2.5s;animation:fadein 0.5s, fadeout 0.5s 2.5s; }
  3711.         @-webkit-keyframes fadein { from { bottom:0;opacity:0; }
  3712.         to { bottom:30px;opacity:1; }
  3713.         }
  3714.         @keyframes fadein { from { bottom:0;opacity:0; }
  3715.         to { bottom:30px;opacity:1; }
  3716.         }
  3717.         @-webkit-keyframes fadeout { from { bottom:30px;opacity:1; }
  3718.         to { bottom:0;opacity:0; }
  3719.         }
  3720.         @keyframes fadeout { from { bottom:30px;opacity:1; }
  3721.         to { bottom:0;opacity:0; }
  3722.         }
  3723.         #main-table span.badge { border-bottom:2px solid #f8f9fa }
  3724.         #main-table span.badge:nth-child(1) { border-color:#df4227 }
  3725.         #main-table span.badge:nth-child(2) { border-color:#f8b600 }
  3726.         #main-table span.badge:nth-child(3) { border-color:#00bd60 }
  3727.         #main-table span.badge:nth-child(4) { border-color:#4581ff }
  3728.         #main-table span.badge:nth-child(5) { border-color:#ac68fc }
  3729.         #main-table span.badge:nth-child(6) { border-color:#45c3d2 }
  3730.         @media only screen and (min-device-width:768px) and (max-device-width:1024px) and (orientation:landscape) and (-webkit-min-device-pixel-ratio:2) { .navbar-collapse .col-xs-6 { padding:0; }
  3731.         }
  3732.         .btn.active.focus,.btn.active:focus,.btn.focus,.btn.focus:active,.btn:active:focus,.btn:focus { outline:0!important;outline-offset:0!important;background-image:none!important;-webkit-box-shadow:none!important;box-shadow:none!important }
  3733.         .lds-facebook { display:none;position:relative;width:64px;height:64px }
  3734.         .lds-facebook div,.lds-facebook.show-me { display:inline-block }
  3735.         .lds-facebook div { position:absolute;left:6px;width:13px;background:#007bff;animation:lds-facebook 1.2s cubic-bezier(0,.5,.5,1) infinite }
  3736.         .lds-facebook div:nth-child(1) { left:6px;animation-delay:-.24s }
  3737.         .lds-facebook div:nth-child(2) { left:26px;animation-delay:-.12s }
  3738.         .lds-facebook div:nth-child(3) { left:45px;animation-delay:0s }
  3739.         @keyframes lds-facebook { 0% { top:6px;height:51px }
  3740.         100%,50% { top:19px;height:26px }
  3741.         }
  3742.         ul#search-wrapper { padding-left: 0;border: 1px solid #ecececcc; } ul#search-wrapper li { list-style: none; padding: 5px;border-bottom: 1px solid #ecececcc; }
  3743.         ul#search-wrapper li:nth-child(odd){ background: #f9f9f9cc;}
  3744.         .c-preview-img { max-width: 300px; }
  3745.         .border-radius-0 { border-radius: 0; }
  3746.         .float-right { float: right; }
  3747.         .table-hover>tbody>tr:hover>td:first-child { border-left: 1px solid #1b77fd; }
  3748.         #main-table tr.even { background-color: #F8F9Fa; }
  3749.         .filename>a>i {margin-right: 3px;}
  3750.     </style>
  3751.     <?php
  3752.     if (FM_THEME == "dark"): ?>
  3753.         <style>
  3754.             :root {
  3755.                 --bs-bg-opacity: 1;
  3756.                 --bg-color: #f3daa6;
  3757.                 --bs-dark-rgb: 28, 36, 41 !important;
  3758.                 --bs-bg-opacity: 1;
  3759.             }
  3760.             .table-dark { --bs-table-bg: 28, 36, 41 !important; }
  3761.             .btn-primary { --bs-btn-bg: #26566c; --bs-btn-border-color: #26566c; }
  3762.             body.theme-dark { background-image: linear-gradient(90deg, #1c2429, #263238); color: #CFD8DC; }
  3763.             .list-group .list-group-item { background: #343a40; }
  3764.             .theme-dark .navbar-nav i, .navbar-nav .dropdown-toggle, .break-word { color: #CFD8DC; }
  3765.             a, a:hover, a:visited, a:active, #main-table .filename a, i.fa.fa-folder-o, i.go-back { color: var(--bg-color); }
  3766.             ul#search-wrapper li:nth-child(odd) { background: #212a2f; }
  3767.             .theme-dark .btn-outline-primary { color: #b8e59c; border-color: #b8e59c; }
  3768.             .theme-dark .btn-outline-primary:hover, .theme-dark .btn-outline-primary:active { background-color: #2d4121;}
  3769.             .theme-dark input.form-control { background-color: #101518; color: #CFD8DC; }
  3770.             .theme-dark .dropzone { background: transparent; }
  3771.             .theme-dark .inline-actions > a > i { background: #79755e; }
  3772.             .theme-dark .text-white { color: #CFD8DC !important; }
  3773.             .theme-dark .table-bordered td, .table-bordered th { border-color: #343434; }
  3774.             .theme-dark .table-bordered td .custom-control-input, .theme-dark .table-bordered th .custom-control-input { opacity: 0.678; }
  3775.             .message { background-color: #212529; }
  3776.             .compact-table tr:hover td { background-color: #3d3d3d; }
  3777.             #main-table tr.even { background-color: #21292f; }
  3778.             form.dropzone { border-color: #79755e; }
  3779.         </style>
  3780.     <?php endif; ?>
  3781. </head>
  3782. <body class="<?php echo (FM_THEME == "dark") ? 'theme-dark' : ''; ?> <?php echo $isStickyNavBar; ?>">
  3783. <div id="wrapper" class="container-fluid">
  3784.     <!-- New Item creation -->
  3785.     <div class="modal fade" id="createNewItem" tabindex="-1" role="dialog" data-bs-backdrop="static" data-bs-keyboard="false" aria-labelledby="newItemModalLabel" aria-hidden="true">
  3786.         <div class="modal-dialog" role="document">
  3787.             <form class="modal-content <?php echo fm_get_theme(); ?>" method="post">
  3788.                 <div class="modal-header">
  3789.                     <h5 class="modal-title" id="newItemModalLabel"><i class="fa fa-plus-square fa-fw"></i><?php echo lng('CreateNewItem') ?></h5>
  3790.                     <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
  3791.                 </div>
  3792.                 <div class="modal-body">
  3793.                     <p><label for="newfile"><?php echo lng('ItemType') ?> </label></p>
  3794.                     <div class="form-check form-check-inline">
  3795.                       <input class="form-check-input" type="radio" name="newfile" id="customRadioInline1" name="newfile" value="file">
  3796.                       <label class="form-check-label" for="customRadioInline1"><?php echo lng('File') ?></label>
  3797.                     </div>
  3798.                     <div class="form-check form-check-inline">
  3799.                       <input class="form-check-input" type="radio" name="newfile" id="customRadioInline2" value="folder" checked>
  3800.                       <label class="form-check-label" for="customRadioInline2"><?php echo lng('Folder') ?></label>
  3801.                     </div>
  3802.  
  3803.                     <p class="mt-3"><label for="newfilename"><?php echo lng('ItemName') ?> </label></p>
  3804.                     <input type="text" name="newfilename" id="newfilename" value="" class="form-control" placeholder="<?php echo lng('Enter here...') ?>" required>
  3805.                 </div>
  3806.                 <div class="modal-footer">
  3807.                     <input type="hidden" name="token" value="<?php echo $_SESSION['token']; ?>">
  3808.                     <button type="button" class="btn btn-outline-primary" data-bs-dismiss="modal"><i class="fa fa-times-circle"></i> <?php echo lng('Cancel') ?></button>
  3809.                     <button type="submit" class="btn btn-success"><i class="fa fa-check-circle"></i> <?php echo lng('CreateNow') ?></button>
  3810.                 </div>
  3811.             </form>
  3812.         </div>
  3813.     </div>
  3814.  
  3815.     <!-- Advance Search Modal -->
  3816.     <div class="modal fade" id="searchModal" tabindex="-1" role="dialog" aria-labelledby="searchModalLabel" aria-hidden="true">
  3817.       <div class="modal-dialog modal-lg" role="document">
  3818.         <div class="modal-content <?php echo fm_get_theme(); ?>">
  3819.           <div class="modal-header">
  3820.             <h5 class="modal-title col-10" id="searchModalLabel">
  3821.                 <div class="input-group mb-3">
  3822.                   <input type="text" class="form-control" placeholder="<?php echo lng('Search') ?> <?php echo lng('a files') ?>" aria-label="<?php echo lng('Search') ?>" aria-describedby="search-addon3" id="advanced-search" autofocus required>
  3823.                   <span class="input-group-text" id="search-addon3"><i class="fa fa-search"></i></span>
  3824.                 </div>
  3825.             </h5>
  3826.             <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
  3827.           </div>
  3828.           <div class="modal-body">
  3829.             <form action="" method="post">
  3830.                 <div class="lds-facebook"><div></div><div></div><div></div></div>
  3831.                 <ul id="search-wrapper">
  3832.                     <p class="m-2"><?php echo lng('Search file in folder and subfolders...') ?></p>
  3833.                 </ul>
  3834.             </form>
  3835.           </div>
  3836.         </div>
  3837.       </div>
  3838.     </div>
  3839.  
  3840.     <!--Rename Modal -->
  3841.     <div class="modal modal-alert" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" role="dialog" id="renameDailog">
  3842.       <div class="modal-dialog" role="document">
  3843.         <form class="modal-content rounded-3 shadow <?php echo fm_get_theme(); ?>" method="post" autocomplete="off">
  3844.           <div class="modal-body p-4 text-center">
  3845.             <h5 class="mb-3"><?php echo lng('Are you sure want to rename?') ?></h5>
  3846.             <p class="mb-1">
  3847.                 <input type="text" name="rename_to" id="js-rename-to" class="form-control" placeholder="<?php echo lng('Enter new file name') ?>" required>
  3848.                 <input type="hidden" name="token" value="<?php echo $_SESSION['token']; ?>">
  3849.                 <input type="hidden" name="rename_from" id="js-rename-from">
  3850.             </p>
  3851.           </div>
  3852.           <div class="modal-footer flex-nowrap p-0">
  3853.             <button type="button" class="btn btn-lg btn-link fs-6 text-decoration-none col-6 m-0 rounded-0 border-end" data-bs-dismiss="modal"><?php echo lng('Cancel') ?></button>
  3854.             <button type="submit" class="btn btn-lg btn-link fs-6 text-decoration-none col-6 m-0 rounded-0"><strong><?php echo lng('Okay') ?></strong></button>
  3855.           </div>
  3856.         </form>
  3857.       </div>
  3858.     </div>
  3859.  
  3860.     <!-- Confirm Modal -->
  3861.     <script type="text/html" id="js-tpl-confirm">
  3862.         <div class="modal modal-alert confirmDailog" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" role="dialog" id="confirmDailog-<%this.id%>">
  3863.           <div class="modal-dialog" role="document">
  3864.             <form class="modal-content rounded-3 shadow <?php echo fm_get_theme(); ?>" method="post" autocomplete="off" action="<%this.action%>">
  3865.               <div class="modal-body p-4 text-center">
  3866.                 <h5 class="mb-2"><?php echo lng('Are you sure want to') ?> <%this.title%> ?</h5>
  3867.                 <p class="mb-1"><%this.content%></p>
  3868.               </div>
  3869.               <div class="modal-footer flex-nowrap p-0">
  3870.                 <button type="button" class="btn btn-lg btn-link fs-6 text-decoration-none col-6 m-0 rounded-0 border-end" data-bs-dismiss="modal"><?php echo lng('Cancel') ?></button>
  3871.                 <input type="hidden" name="token" value="<?php echo $_SESSION['token']; ?>">
  3872.                 <button type="submit" class="btn btn-lg btn-link fs-6 text-decoration-none col-6 m-0 rounded-0" data-bs-dismiss="modal"><strong><?php echo lng('Okay') ?></strong></button>
  3873.               </div>
  3874.             </form>
  3875.           </div>
  3876.         </div>
  3877.     </script>
  3878.  
  3879.     <?php
  3880.     }
  3881.  
  3882.     /**
  3883.      * Show page footer after login
  3884.      */
  3885.     function fm_show_footer()
  3886.     {
  3887.     ?>
  3888. </div>
  3889. <script src="https://code.jquery.com/jquery-3.6.1.min.js" integrity="sha256-o88AwQnZB+VDvE9tvIXrMQaPlFFSUTR+nldQm1LuPXQ=" crossorigin="anonymous"></script>
  3890. <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-OERcA2EqjJCMA+/3y+gxIOqMEjwtxJY7qPCqsdltbNJuaOe923+mo//f6V8Qbsw3" crossorigin="anonymous"></script>
  3891. <script src="https://cdn.datatables.net/1.13.1/js/jquery.dataTables.min.js" crossorigin="anonymous" defer></script>
  3892. <?php if (FM_USE_HIGHLIGHTJS && isset($_GET['view'])): ?>
  3893.     <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.6.0/highlight.min.js"></script>
  3894.     <script>hljs.highlightAll(); var isHighlightingEnabled = true;</script>
  3895. <?php endif; ?>
  3896. <script>
  3897.     function template(html,options){
  3898.         var re=/<\%([^\%>]+)?\%>/g,reExp=/(^( )?(if|for|else|switch|case|break|{|}))(.*)?/g,code='var r=[];\n',cursor=0,match;var add=function(line,js){js?(code+=line.match(reExp)?line+'\n':'r.push('+line+');\n'):(code+=line!=''?'r.push("'+line.replace(/"/g,'\\"')+'");\n':'');return add}
  3899.         while(match=re.exec(html)){add(html.slice(cursor,match.index))(match[1],!0);cursor=match.index+match[0].length}
  3900.         add(html.substr(cursor,html.length-cursor));code+='return r.join("");';return new Function(code.replace(/[\r\t\n]/g,'')).apply(options)
  3901.     }
  3902.     function rename(e, t) { if(t) { $("#js-rename-from").val(t);$("#js-rename-to").val(t); $("#renameDailog").modal('show'); } }
  3903.     function change_checkboxes(e, t) { for (var n = e.length - 1; n >= 0; n--) e[n].checked = "boolean" == typeof t ? t : !e[n].checked }
  3904.     function get_checkboxes() { for (var e = document.getElementsByName("file[]"), t = [], n = e.length - 1; n >= 0; n--) (e[n].type = "checkbox") && t.push(e[n]); return t }
  3905.     function select_all() { change_checkboxes(get_checkboxes(), !0) }
  3906.     function unselect_all() { change_checkboxes(get_checkboxes(), !1) }
  3907.     function invert_all() { change_checkboxes(get_checkboxes()) }
  3908.     function checkbox_toggle() { var e = get_checkboxes(); e.push(this), change_checkboxes(e) }
  3909.     function backup(e, t) { // Create file backup with .bck
  3910.         var n = new XMLHttpRequest,
  3911.             a = "path=" + e + "&file=" + t + "&token="+ window.csrf +"&type=backup&ajax=true";
  3912.         return n.open("POST", "", !0), n.setRequestHeader("Content-type", "application/x-www-form-urlencoded"), n.onreadystatechange = function () {
  3913.             4 == n.readyState && 200 == n.status && toast(n.responseText)
  3914.         }, n.send(a), !1
  3915.     }
  3916.     // Toast message
  3917.     function toast(txt) { var x = document.getElementById("snackbar");x.innerHTML=txt;x.className = "show";setTimeout(function(){ x.className = x.className.replace("show", ""); }, 3000); }
  3918.     // Save file
  3919.     function edit_save(e, t) {
  3920.         var n = "ace" == t ? editor.getSession().getValue() : document.getElementById("normal-editor").value;
  3921.         if (typeof n !== 'undefined' && n !== null) {
  3922.             if (true) {
  3923.                 var data = {ajax: true, content: n, type: 'save', token: window.csrf};
  3924.  
  3925.                 $.ajax({
  3926.                     type: "POST",
  3927.                     url: window.location,
  3928.                     data: JSON.stringify(data),
  3929.                     contentType: "application/json; charset=utf-8",
  3930.                     success: function(mes){toast("Saved Successfully"); window.onbeforeunload = function() {return}},
  3931.                     failure: function(mes) {toast("Error: try again");},
  3932.                     error: function(mes) {toast(`<p style="background-color:red">${mes.responseText}</p>`);}
  3933.                 });
  3934.             } else {
  3935.                 var a = document.createElement("form");
  3936.                 a.setAttribute("method", "POST"), a.setAttribute("action", "");
  3937.                 var o = document.createElement("textarea");
  3938.                 o.setAttribute("type", "textarea"), o.setAttribute("name", "savedata");
  3939.                 let cx = document.createElement("input"); cx.setAttribute("type", "hidden");cx.setAttribute("name", "token");cx.setAttribute("value", window.csrf);
  3940.                 var c = document.createTextNode(n);
  3941.                 o.appendChild(c), a.appendChild(o), a.appendChild(cx), document.body.appendChild(a), a.submit()
  3942.             }
  3943.         }
  3944.     }
  3945.     function show_new_pwd() { $(".js-new-pwd").toggleClass('hidden'); }
  3946.     // Save Settings
  3947.     function save_settings($this) {
  3948.         let form = $($this);
  3949.         $.ajax({
  3950.             type: form.attr('method'), url: form.attr('action'), data: form.serialize()+"&token="+ window.csrf +"&ajax="+true,
  3951.             success: function (data) {if(data) { window.location.reload();}}
  3952.         }); return false;
  3953.     }
  3954.     //Create new password hash
  3955.     function new_password_hash($this) {
  3956.         let form = $($this), $pwd = $("#js-pwd-result"); $pwd.val('');
  3957.         $.ajax({
  3958.             type: form.attr('method'), url: form.attr('action'), data: form.serialize()+"&token="+ window.csrf +"&ajax="+true,
  3959.             success: function (data) { if(data) { $pwd.val(data); } }
  3960.         }); return false;
  3961.     }
  3962.     // Upload files using URL @param {Object}
  3963.     function upload_from_url($this) {
  3964.         let form = $($this), resultWrapper = $("div#js-url-upload__list");
  3965.         $.ajax({
  3966.             type: form.attr('method'), url: form.attr('action'), data: form.serialize()+"&token="+ window.csrf +"&ajax="+true,
  3967.             beforeSend: function() { form.find("input[name=uploadurl]").attr("disabled","disabled"); form.find("button").hide(); form.find(".lds-facebook").addClass('show-me'); },
  3968.             success: function (data) {
  3969.                 if(data) {
  3970.                     data = JSON.parse(data);
  3971.                     if(data.done) {
  3972.                         resultWrapper.append('<div class="alert alert-success row">Uploaded Successful: '+data.done.name+'</div>'); form.find("input[name=uploadurl]").val('');
  3973.                     } else if(data['fail']) { resultWrapper.append('<div class="alert alert-danger row">Error: '+data.fail.message+'</div>'); }
  3974.                     form.find("input[name=uploadurl]").removeAttr("disabled");form.find("button").show();form.find(".lds-facebook").removeClass('show-me');
  3975.                 }
  3976.             },
  3977.             error: function(xhr) {
  3978.                 form.find("input[name=uploadurl]").removeAttr("disabled");form.find("button").show();form.find(".lds-facebook").removeClass('show-me');console.error(xhr);
  3979.             }
  3980.         }); return false;
  3981.     }
  3982.     // Search template
  3983.     function search_template(data) {
  3984.         var response = "";
  3985.         $.each(data, function (key, val) {
  3986.             response += `<li><a href="?p=${val.path}&view=${val.name}">${val.path}/${val.name}</a></li>`;
  3987.         });
  3988.         return response;
  3989.     }
  3990.     // Advance search
  3991.     function fm_search() {
  3992.         var searchTxt = $("input#advanced-search").val(), searchWrapper = $("ul#search-wrapper"), path = $("#js-search-modal").attr("href"), _html = "", $loader = $("div.lds-facebook");
  3993.         if(!!searchTxt && searchTxt.length > 2 && path) {
  3994.             var data = {ajax: true, content: searchTxt, path:path, type: 'search', token: window.csrf };
  3995.             $.ajax({
  3996.                 type: "POST",
  3997.                 url: window.location,
  3998.                 data: data,
  3999.                 beforeSend: function() {
  4000.                     searchWrapper.html('');
  4001.                     $loader.addClass('show-me');
  4002.                 },
  4003.                 success: function(data){
  4004.                     $loader.removeClass('show-me');
  4005.                     data = JSON.parse(data);
  4006.                     if(data && data.length) {
  4007.                         _html = search_template(data);
  4008.                         searchWrapper.html(_html);
  4009.                     } else { searchWrapper.html('<p class="m-2">No result found!<p>'); }
  4010.                 },
  4011.                 error: function(xhr) { $loader.removeClass('show-me'); searchWrapper.html('<p class="m-2">ERROR: Try again later!</p>'); },
  4012.                 failure: function(mes) { $loader.removeClass('show-me'); searchWrapper.html('<p class="m-2">ERROR: Try again later!</p>');}
  4013.             });
  4014.         } else { searchWrapper.html("OOPS: minimum 3 characters required!"); }
  4015.     }
  4016.  
  4017.     // action confirm dailog modal
  4018.     function confirmDailog(e, id = 0, title = "Action", content = "", action = null) {
  4019.         e.preventDefault();
  4020.         const tplObj = {id, title, content: decodeURIComponent(content.replace(/\+/g, ' ')), action};
  4021.         let tpl = $("#js-tpl-confirm").html();
  4022.         $(".modal.confirmDailog").remove();
  4023.         $('#wrapper').append(template(tpl,tplObj));
  4024.         $("#confirmDailog-"+tplObj.id).modal('show');
  4025.         return false;
  4026.     }
  4027.    
  4028.  
  4029.     // on mouse hover image preview
  4030.     !function(s){s.previewImage=function(e){var o=s(document),t=".previewImage",a=s.extend({xOffset:20,yOffset:-20,fadeIn:"fast",css:{padding:"5px",border:"1px solid #cccccc","background-color":"#fff"},eventSelector:"[data-preview-image]",dataKey:"previewImage",overlayId:"preview-image-plugin-overlay"},e);return o.off(t),o.on("mouseover"+t,a.eventSelector,function(e){s("p#"+a.overlayId).remove();var o=s("<p>").attr("id",a.overlayId).css("position","absolute").css("display","none").append(s('<img class="c-preview-img">').attr("src",s(this).data(a.dataKey)));a.css&&o.css(a.css),s("body").append(o),o.css("top",e.pageY+a.yOffset+"px").css("left",e.pageX+a.xOffset+"px").fadeIn(a.fadeIn)}),o.on("mouseout"+t,a.eventSelector,function(){s("#"+a.overlayId).remove()}),o.on("mousemove"+t,a.eventSelector,function(e){s("#"+a.overlayId).css("top",e.pageY+a.yOffset+"px").css("left",e.pageX+a.xOffset+"px")}),this},s.previewImage()}(jQuery);
  4031.  
  4032.     // Dom Ready Events
  4033.     $(document).ready( function () {
  4034.         // dataTable init
  4035.         var $table = $('#main-table'),
  4036.             tableLng = $table.find('th').length,
  4037.             _targets = (tableLng && tableLng == 7 ) ? [0, 4,5,6] : tableLng == 5 ? [0,4] : [3];
  4038.             mainTable = $('#main-table').DataTable({paging: false, info: false, order: [], columnDefs: [{targets: _targets, orderable: false}]
  4039.         });
  4040.         // filter table
  4041.         $('#search-addon').on( 'keyup', function () {
  4042.             mainTable.search( this.value ).draw();
  4043.         });
  4044.         $("input#advanced-search").on('keyup', function (e) {
  4045.             if (e.keyCode === 13) { fm_search(); }
  4046.         });
  4047.         $('#search-addon3').on( 'click', function () { fm_search(); });
  4048.         //upload nav tabs
  4049.         $(".fm-upload-wrapper .card-header-tabs").on("click", 'a', function(e){
  4050.             e.preventDefault();let target=$(this).data('target');
  4051.             $(".fm-upload-wrapper .card-header-tabs a").removeClass('active');$(this).addClass('active');
  4052.             $(".fm-upload-wrapper .card-tabs-container").addClass('hidden');$(target).removeClass('hidden');
  4053.         });
  4054.     });
  4055. </script>
  4056. <?php if (isset($_GET['edit']) && isset($_GET['env']) && FM_EDIT_FILE && !FM_READONLY):
  4057.        
  4058.         $ext = pathinfo($_GET["edit"], PATHINFO_EXTENSION);
  4059.         $ext =  $ext == "js" ? "javascript" :  $ext;
  4060.         ?>
  4061.     <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.13.1/ace.js"></script>
  4062.     <script>
  4063.         var editor = ace.edit("editor");
  4064.         editor.getSession().setMode( {path:"ace/mode/<?php echo $ext; ?>", inline:true} );
  4065.         //editor.setTheme("ace/theme/twilight"); //Dark Theme
  4066.         function ace_commend (cmd) { editor.commands.exec(cmd, editor); }
  4067.         editor.commands.addCommands([{
  4068.             name: 'save', bindKey: {win: 'Ctrl-S',  mac: 'Command-S'},
  4069.             exec: function(editor) { edit_save(this, 'ace'); }
  4070.         }]);
  4071.         function renderThemeMode() {
  4072.             var $modeEl = $("select#js-ace-mode"), $themeEl = $("select#js-ace-theme"), $fontSizeEl = $("select#js-ace-fontSize"), optionNode = function(type, arr){ var $Option = ""; $.each(arr, function(i, val) { $Option += "<option value='"+type+i+"'>" + val + "</option>"; }); return $Option; },
  4073.                 _data = {"aceTheme":{"bright":{"chrome":"Chrome","clouds":"Clouds","crimson_editor":"Crimson Editor","dawn":"Dawn","dreamweaver":"Dreamweaver","eclipse":"Eclipse","github":"GitHub","iplastic":"IPlastic","solarized_light":"Solarized Light","textmate":"TextMate","tomorrow":"Tomorrow","xcode":"XCode","kuroir":"Kuroir","katzenmilch":"KatzenMilch","sqlserver":"SQL Server"},"dark":{"ambiance":"Ambiance","chaos":"Chaos","clouds_midnight":"Clouds Midnight","dracula":"Dracula","cobalt":"Cobalt","gruvbox":"Gruvbox","gob":"Green on Black","idle_fingers":"idle Fingers","kr_theme":"krTheme","merbivore":"Merbivore","merbivore_soft":"Merbivore Soft","mono_industrial":"Mono Industrial","monokai":"Monokai","pastel_on_dark":"Pastel on dark","solarized_dark":"Solarized Dark","terminal":"Terminal","tomorrow_night":"Tomorrow Night","tomorrow_night_blue":"Tomorrow Night Blue","tomorrow_night_bright":"Tomorrow Night Bright","tomorrow_night_eighties":"Tomorrow Night 80s","twilight":"Twilight","vibrant_ink":"Vibrant Ink"}},"aceMode":{"javascript":"JavaScript","abap":"ABAP","abc":"ABC","actionscript":"ActionScript","ada":"ADA","apache_conf":"Apache Conf","asciidoc":"AsciiDoc","asl":"ASL","assembly_x86":"Assembly x86","autohotkey":"AutoHotKey","apex":"Apex","batchfile":"BatchFile","bro":"Bro","c_cpp":"C and C++","c9search":"C9Search","cirru":"Cirru","clojure":"Clojure","cobol":"Cobol","coffee":"CoffeeScript","coldfusion":"ColdFusion","csharp":"C#","csound_document":"Csound Document","csound_orchestra":"Csound","csound_score":"Csound Score","css":"CSS","curly":"Curly","d":"D","dart":"Dart","diff":"Diff","dockerfile":"Dockerfile","dot":"Dot","drools":"Drools","edifact":"Edifact","eiffel":"Eiffel","ejs":"EJS","elixir":"Elixir","elm":"Elm","erlang":"Erlang","forth":"Forth","fortran":"Fortran","fsharp":"FSharp","fsl":"FSL","ftl":"FreeMarker","gcode":"Gcode","gherkin":"Gherkin","gitignore":"Gitignore","glsl":"Glsl","gobstones":"Gobstones","golang":"Go","graphqlschema":"GraphQLSchema","groovy":"Groovy","haml":"HAML","handlebars":"Handlebars","haskell":"Haskell","haskell_cabal":"Haskell Cabal","haxe":"haXe","hjson":"Hjson","html":"HTML","html_elixir":"HTML (Elixir)","html_ruby":"HTML (Ruby)","ini":"INI","io":"Io","jack":"Jack","jade":"Jade","java":"Java","json":"JSON","jsoniq":"JSONiq","jsp":"JSP","jssm":"JSSM","jsx":"JSX","julia":"Julia","kotlin":"Kotlin","latex":"LaTeX","less":"LESS","liquid":"Liquid","lisp":"Lisp","livescript":"LiveScript","logiql":"LogiQL","lsl":"LSL","lua":"Lua","luapage":"LuaPage","lucene":"Lucene","makefile":"Makefile","markdown":"Markdown","mask":"Mask","matlab":"MATLAB","maze":"Maze","mel":"MEL","mixal":"MIXAL","mushcode":"MUSHCode","mysql":"MySQL","nix":"Nix","nsis":"NSIS","objectivec":"Objective-C","ocaml":"OCaml","pascal":"Pascal","perl":"Perl","perl6":"Perl 6","pgsql":"pgSQL","php_laravel_blade":"PHP (Blade Template)","php":"PHP","puppet":"Puppet","pig":"Pig","powershell":"Powershell","praat":"Praat","prolog":"Prolog","properties":"Properties","protobuf":"Protobuf","python":"Python","r":"R","razor":"Razor","rdoc":"RDoc","red":"Red","rhtml":"RHTML","rst":"RST","ruby":"Ruby","rust":"Rust","sass":"SASS","scad":"SCAD","scala":"Scala","scheme":"Scheme","scss":"SCSS","sh":"SH","sjs":"SJS","slim":"Slim","smarty":"Smarty","snippets":"snippets","soy_template":"Soy Template","space":"Space","sql":"SQL","sqlserver":"SQLServer","stylus":"Stylus","svg":"SVG","swift":"Swift","tcl":"Tcl","terraform":"Terraform","tex":"Tex","text":"Text","textile":"Textile","toml":"Toml","tsx":"TSX","twig":"Twig","typescript":"Typescript","vala":"Vala","vbscript":"VBScript","velocity":"Velocity","verilog":"Verilog","vhdl":"VHDL","visualforce":"Visualforce","wollok":"Wollok","xml":"XML","xquery":"XQuery","yaml":"YAML","django":"Django"},"fontSize":{8:8,10:10,11:11,12:12,13:13,14:14,15:15,16:16,17:17,18:18,20:20,22:22,24:24,26:26,30:30}};
  4074.             if(_data && _data.aceMode) { $modeEl.html(optionNode("ace/mode/", _data.aceMode)); }
  4075.             if(_data && _data.aceTheme) { var lightTheme = optionNode("ace/theme/", _data.aceTheme.bright), darkTheme = optionNode("ace/theme/", _data.aceTheme.dark); $themeEl.html("<optgroup label=\"Bright\">"+lightTheme+"</optgroup><optgroup label=\"Dark\">"+darkTheme+"</optgroup>");}
  4076.             if(_data && _data.fontSize) { $fontSizeEl.html(optionNode("", _data.fontSize)); }
  4077.             $modeEl.val( editor.getSession().$modeId );
  4078.             $themeEl.val( editor.getTheme() );
  4079.             $fontSizeEl.val(12).change(); //set default font size in drop down
  4080.         }
  4081.  
  4082.         $(function(){
  4083.             renderThemeMode();
  4084.             $(".js-ace-toolbar").on("click", 'button', function(e){
  4085.                 e.preventDefault();
  4086.                 let cmdValue = $(this).attr("data-cmd"), editorOption = $(this).attr("data-option");
  4087.                 if(cmdValue && cmdValue != "none") {
  4088.                     ace_commend(cmdValue);
  4089.                 } else if(editorOption) {
  4090.                     if(editorOption == "fullscreen") {
  4091.                         (void 0!==document.fullScreenElement&&null===document.fullScreenElement||void 0!==document.msFullscreenElement&&null===document.msFullscreenElement||void 0!==document.mozFullScreen&&!document.mozFullScreen||void 0!==document.webkitIsFullScreen&&!document.webkitIsFullScreen)
  4092.                         &&(editor.container.requestFullScreen?editor.container.requestFullScreen():editor.container.mozRequestFullScreen?editor.container.mozRequestFullScreen():editor.container.webkitRequestFullScreen?editor.container.webkitRequestFullScreen(Element.ALLOW_KEYBOARD_INPUT):editor.container.msRequestFullscreen&&editor.container.msRequestFullscreen());
  4093.                     } else if(editorOption == "wrap") {
  4094.                         let wrapStatus = (editor.getSession().getUseWrapMode()) ? false : true;
  4095.                         editor.getSession().setUseWrapMode(wrapStatus);
  4096.                     }
  4097.                 }
  4098.             });
  4099.             $("select#js-ace-mode, select#js-ace-theme, select#js-ace-fontSize").on("change", function(e){
  4100.                 e.preventDefault();
  4101.                 let selectedValue = $(this).val(), selectionType = $(this).attr("data-type");
  4102.                 if(selectedValue && selectionType == "mode") {
  4103.                     editor.getSession().setMode(selectedValue);
  4104.                 } else if(selectedValue && selectionType == "theme") {
  4105.                     editor.setTheme(selectedValue);
  4106.                 }else if(selectedValue && selectionType == "fontSize") {
  4107.                     editor.setFontSize(parseInt(selectedValue));
  4108.                 }
  4109.             });
  4110.         });
  4111.     </script>
  4112. <?php endif; ?>
  4113. <div id="snackbar"></div>
  4114. </body>
  4115. </html>
  4116. <?php
  4117. }
  4118.  
  4119. /**
  4120.  * Language Translation System
  4121.  * @param string $txt
  4122.  * @return string
  4123.  */
  4124. function lng($txt) {
  4125.     global $lang;
  4126.  
  4127.     // English Language
  4128.     $tr['en']['AppName']        = 'XmasCLOUD';      $tr['en']['AppTitle']           = 'XmasCLOUD';  // XmasCLOUD
  4129.     $tr['en']['Login']          = 'Sign in';                $tr['en']['Username']           = 'Username';
  4130.     $tr['en']['Password']       = 'Password';               $tr['en']['Logout']             = 'Sign Out';
  4131.     $tr['en']['Move']           = 'Move';                   $tr['en']['Copy']               = 'Copy';
  4132.     $tr['en']['Save']           = 'Save';                   $tr['en']['SelectAll']          = 'Select all';
  4133.     $tr['en']['UnSelectAll']    = 'Unselect all';           $tr['en']['File']               = 'File';
  4134.     $tr['en']['Back']           = 'Back';                   $tr['en']['Size']               = 'Size';
  4135.     $tr['en']['Perms']          = 'Perms';                  $tr['en']['Modified']           = 'Modified';
  4136.     $tr['en']['Owner']          = 'Owner';                  $tr['en']['Search']             = 'Search';
  4137.     $tr['en']['NewItem']        = 'New Item';               $tr['en']['Folder']             = 'Folder';
  4138.     $tr['en']['Delete']         = 'Delete';                 $tr['en']['Rename']             = 'Rename';
  4139.     $tr['en']['CopyTo']         = 'Copy to';                $tr['en']['DirectLink']         = 'Direct link';
  4140.     $tr['en']['UploadingFiles'] = 'Upload Files';           $tr['en']['ChangePermissions']  = 'Change Permissions';
  4141.     $tr['en']['Copying']        = 'Copying';                $tr['en']['CreateNewItem']      = 'Create New Item';
  4142.     $tr['en']['Name']           = 'Name';                   $tr['en']['AdvancedEditor']     = 'Advanced Editor';
  4143.     $tr['en']['Actions']        = 'Actions';                $tr['en']['Folder is empty']    = 'Folder is empty';
  4144.     $tr['en']['Upload']         = 'Upload';                 $tr['en']['Cancel']             = 'Cancel';
  4145.     $tr['en']['InvertSelection']= 'Invert Selection';       $tr['en']['DestinationFolder']  = 'Destination Folder';
  4146.     $tr['en']['ItemType']       = 'Item Type';              $tr['en']['ItemName']           = 'Item Name';
  4147.     $tr['en']['CreateNow']      = 'Create Now';             $tr['en']['Download']           = 'Download';
  4148.     $tr['en']['Open']           = 'Open';                   $tr['en']['UnZip']              = 'UnZip';
  4149.     $tr['en']['UnZipToFolder']  = 'UnZip to folder';        $tr['en']['Edit']               = 'Edit';
  4150.     $tr['en']['NormalEditor']   = 'Normal Editor';          $tr['en']['BackUp']             = 'Back Up';
  4151.     $tr['en']['SourceFolder']   = 'Source Folder';          $tr['en']['Files']              = 'Files';
  4152.     $tr['en']['Move']           = 'Move';                   $tr['en']['Change']             = 'Change';
  4153.     $tr['en']['Settings']       = 'Settings';               $tr['en']['Language']           = 'Language';        
  4154.     $tr['en']['ErrorReporting'] = 'Error Reporting';        $tr['en']['ShowHiddenFiles']    = 'Show Hidden Files';
  4155.     $tr['en']['Help']           = 'Help';                   $tr['en']['Created']            = 'Created';
  4156.     $tr['en']['Help Documents'] = 'Help Documents';         $tr['en']['Report Issue']       = 'Report Issue';
  4157.     $tr['en']['Generate']       = 'Generate';               $tr['en']['FullSize']           = 'Full Size';              
  4158.     $tr['en']['HideColumns']    = 'Hide Perms/Owner columns';$tr['en']['You are logged in'] = 'You are logged in';
  4159.     $tr['en']['Nothing selected']   = 'Nothing selected';   $tr['en']['Paths must be not equal']    = 'Paths must be not equal';
  4160.     $tr['en']['Renamed from']       = 'Renamed from';       $tr['en']['Archive not unpacked']       = 'Archive not unpacked';
  4161.     $tr['en']['Deleted']            = 'Deleted';            $tr['en']['Archive not created']        = 'Archive not created';
  4162.     $tr['en']['Copied from']        = 'Copied from';        $tr['en']['Permissions changed']        = 'Permissions changed';
  4163.     $tr['en']['to']                 = 'to';                 $tr['en']['Saved Successfully']         = 'Saved Successfully';
  4164.     $tr['en']['not found!']         = 'not found!';         $tr['en']['File Saved Successfully']    = 'File Saved Successfully';
  4165.     $tr['en']['Archive']            = 'Archive';            $tr['en']['Permissions not changed']    = 'Permissions not changed';
  4166.     $tr['en']['Select folder']      = 'Select folder';      $tr['en']['Source path not defined']    = 'Source path not defined';
  4167.     $tr['en']['already exists']     = 'already exists';     $tr['en']['Error while moving from']    = 'Error while moving from';
  4168.     $tr['en']['Create archive?']    = 'Create archive?';    $tr['en']['Invalid file or folder name']    = 'Invalid file or folder name';
  4169.     $tr['en']['Archive unpacked']   = 'Archive unpacked';   $tr['en']['File extension is not allowed']  = 'File extension is not allowed';
  4170.     $tr['en']['Root path']          = 'Root path';          $tr['en']['Error while renaming from']  = 'Error while renaming from';
  4171.     $tr['en']['File not found']     = 'File not found';     $tr['en']['Error while deleting items'] = 'Error while deleting items';
  4172.     $tr['en']['Moved from']         = 'Moved from';         $tr['en']['Generate new password hash'] = 'Generate new password hash';
  4173.     $tr['en']['Login failed. Invalid username or password'] = 'Login failed. Invalid username or password';
  4174.     $tr['en']['password_hash not supported, Upgrade PHP version'] = 'password_hash not supported, Upgrade PHP version';
  4175.     $tr['en']['Advanced Search']    = 'Advanced Search';    $tr['en']['Error while copying from']    = 'Error while copying from';
  4176.     $tr['en']['Invalid characters in file name']                = 'Invalid characters in file name';
  4177.     $tr['en']['FILE EXTENSION HAS NOT SUPPORTED']               = 'FILE EXTENSION HAS NOT SUPPORTED';
  4178.     $tr['en']['Selected files and folder deleted']              = 'Selected files and folder deleted';
  4179.     $tr['en']['Error while fetching archive info']              = 'Error while fetching archive info';
  4180.     $tr['en']['Delete selected files and folders?']             = 'Delete selected files and folders?';
  4181.     $tr['en']['Search file in folder and subfolders...']        = 'Search file in folder and subfolders...';
  4182.     $tr['en']['Access denied. IP restriction applicable']       = 'Access denied. IP restriction applicable';
  4183.     $tr['en']['Invalid characters in file or folder name']      = 'Invalid characters in file or folder name';
  4184.     $tr['en']['Operations with archives are not available']     = 'Operations with archives are not available';
  4185.     $tr['en']['File or folder with this path already exists']   = 'File or folder with this path already exists';
  4186.  
  4187.     $i18n = fm_get_translations($tr);
  4188.     $tr = $i18n ? $i18n : $tr;
  4189.  
  4190.     if (!strlen($lang)) $lang = 'en';
  4191.     if (isset($tr[$lang][$txt])) return fm_enc($tr[$lang][$txt]);
  4192.     else if (isset($tr['en'][$txt])) return fm_enc($tr['en'][$txt]);
  4193.     else return "$txt";
  4194. }
  4195.  
  4196. ?>

Quellcode

Hier kannst du den Code kopieren und ihn in deinen bevorzugten Editor einfügen. PASTEBIN_DOWNLOAD_SNIPPET_EXPLAIN