diff --git a/assets/css/terminal.css b/assets/css/terminal.css index ca5f7be..faee263 100644 --- a/assets/css/terminal.css +++ b/assets/css/terminal.css @@ -30,7 +30,7 @@ html, body {width: 100%; height: 100%} .output {position: absolute; display: block; top: 0; padding: 15px 18px 8px 13px; width: 100%; min-height: 100%; border: 0; background: rgba(0,0,0,0.92); color: #ccc} .commandLine {width: 100%; padding: 8px 2px 8px 0; color: #fff} .commandLine .user {display: inline-block; height: 24px; margin-top: -4px; margin-left: -13px; padding: 5px 5px 5px 0; margin-bottom: 5px; background: #b58901; color: #000} -.commandLine .path {display: inline-block; height: 24px; margin-top: -4px; padding: 5px 5px 5px 0; margin-bottom: 5px; background: #278bd2; color: #fff} +.commandLine .cwd {display: inline-block; height: 24px; margin-top: -4px; padding: 5px 5px 5px 0; margin-bottom: 5px; background: #278bd2; color: #fff} .commandLine .promptVLine {display: inline-block; width: 1px; height: 12px; margin-top: -5px; margin-left: 3px; background: #b58901} .commandLine .promptHLine {display: inline-block; color: #b58901} .commandLine .promptArrow {display: inline-block; margin-left:-1px} diff --git a/lib/terminal-xhr.php b/lib/terminal-xhr.php index 117c337..ee0b369 100644 --- a/lib/terminal-xhr.php +++ b/lib/terminal-xhr.php @@ -1,67 +1,95 @@ Sorry but you can't use this terminal if your proc_open is disabled\n\n"); -} +include dirname(__FILE__) . "/headers.php"; +include dirname(__FILE__) . "/settings.php"; +// Set some common aliases $aliases = array( - 'la' => 'ls -la', - 'll' => 'ls -lvhF', + 'la' => 'ls -la', + 'll' => 'ls -lvhF', ); -// Get current working dir -$user = str_replace("\n","",shell_exec("whoami")); -$cwd = getcwd(); +// If we have a current working dir in session, change to that dir +if (true === isset($_SESSION['cwd'])) { + chdir($_SESSION['cwd']); +} -// If we have a command -if(!empty($_REQUEST['command'])) { - // Strip any slashes from it - if(get_magic_quotes_gpc()) { - $_REQUEST['command'] = stripslashes($_REQUEST['command']); - } +// Get current user and cwd +$user = str_replace("\n", "", shell_exec("whoami")); +$cwd = str_replace("\n", "", shell_exec("pwd")); - // Begin output with prompt and user command - $output = '
  '.$user.' 
'. - '
 '.$cwd.' 
: '.date("H:m:s"). - '
'. - '
'.$_REQUEST['command'].'


'; +// Check if we have proc_open_enabled +// (Used later to handle commands) +function proc_open_enabled() { + $disabled = explode(',', ini_get('disable_functions')); + return false === in_array('proc_open', $disabled); +} + +// Return HTML prompt plus the command the user provided last +function returnHTMLPromptCommand($cmd) { + global $user, $cwd; + // Begin output with prompt and user command + return '
  ' . $user . ' 
'. + '
 ' . $cwd . ' 
: ' . date("H:m:s") . + '
' . + '
' . $cmd . '

'; +} + +// If proc_open isn't enabled, display prompt, command and a message re needing this enabled +if (false === proc_open_enabled()) { + echo json_encode([ + "output" => returnHTMLPromptCommand($_REQUEST['command'] . "

Sorry but you can't use this terminal if your proc_open is disabled"), + "user" => $user, + "cwd" => $cwd + ]); + exit; } // If in demo mode, display message and go no further -if ($demoMode) { - $output .= "Sorry, shell usage not enabled in demo mode\n\n"; - echo $output; - exit; +if (true === $demoMode) { + echo json_encode([ + "output" => returnHTMLPromptCommand($_REQUEST['command'] . "

Sorry, shell usage not enabled in demo mode"), + "user" => $user, + "cwd" => $cwd + ]); + exit; } +// If in demo mode, display message and go no further +if (false === isset($_REQUEST['command'])) { + echo json_encode([ + "output" => returnHTMLPromptCommand($_REQUEST['command'] . "

Sorry, no command received"), + "user" => $user, + "cwd" => $cwd + ]); + exit; +} + +// Strip any slashes from command +$_REQUEST['command'] = stripslashes($_REQUEST['command']); + +// Start output with the prompt and command they provided last +$output = returnHTMLPromptCommand($_REQUEST['command']); + // If command contains cd but no dir -if (preg_match('/^[[:blank:]]*cd[[:blank:]]*$/', @$_REQUEST['command'])) { - $_SESSION['cwd'] = getcwd(); //dirname(__FILE__); +if (preg_match('/^[[:blank:]]*cd[[:blank:]]*$/', $_REQUEST['command'])) { + $_SESSION['cwd'] = $cwd; + $output .= returnHTMLPromptCommand("cd"); // Else cd to a dir -} elseif (preg_match('/^[[:blank:]]*cd[[:blank:]]+([^;]+)$/', @$_REQUEST['command'], $regs)) { +} elseif (preg_match('/^[[:blank:]]*cd[[:blank:]]+([^;]+)$/', $_REQUEST['command'], $regs)) { // The current command is 'cd', which we have to handle as an internal shell command - // Absolute/relative path ? - ($regs[1][0] == '/') ? $newDir = $regs[1] : $newDir = $_SESSION['cwd'].'/'.$regs[1]; + $newDir = "/" === $regs[1][0] ? $regs[1] : $_SESSION['cwd'] . "/" . $regs[1]; // Tidy up appearance on /./ - while (strpos($newDir, '/./') !== false) { + while (false !== strpos($newDir, '/./')) { $newDir = str_replace('/./', '/', $newDir); } // Tidy up appearance on // - while (strpos($newDir, '//') !== false) { + while (false !== strpos($newDir, '//')) { $newDir = str_replace('//', '/', $newDir); } // Tidy up appearance on other variations - while (preg_match('|/\.\.(?!\.)|', $newDir)) { - $newDir = preg_replace('|/?[^/]+/\.\.(?!\.)|', '', $newDir); + while (preg_match('/\/\.\.(?!\.)/', $newDir)) { + $newDir = preg_replace('/\/?[^\/]+\/\.\.(?!\.)/', '', $newDir); } // Empty dir @@ -70,36 +98,35 @@ if (preg_match('/^[[:blank:]]*cd[[:blank:]]*$/', @$_REQUEST['command'])) { } // Test if we could change to that dir, else display error - (@chdir($newDir)) ? $_SESSION['cwd'] = $newDir : $output .= "\n\nCould not change to: $newDir\n\n"; + (@chdir($newDir)) ? $_SESSION['cwd'] = $newDir : $output .= "Could not change to: $newDir\n\n"; } else { - // The command is not a 'cd' command, so we execute it after - // changing the directory and save the output. - chdir($_SESSION['cwd']); + // The command is not a 'cd' command // Alias expansion - $length = strcspn(@$_REQUEST['command'], " \t"); - $token = substr(@$_REQUEST['command'], 0, $length); - if (isset($aliases[$token])) { - $_REQUEST['command'] = $aliases[$token].substr($_REQUEST['command'], $length); + $length = strcspn($_REQUEST['command'], " \t"); + $token = substr($_REQUEST['command'], 0, $length); + if (true === isset($aliases[$token])) { + $_REQUEST['command'] = $aliases[$token] . substr($_REQUEST['command'], $length); } // Open a proc with array and $io return $p = proc_open( - @$_REQUEST['command'], + $_REQUEST['command'], array( 1 => array('pipe', 'w'), 2 => array('pipe', 'w') ), $io ); - + // Read output sent to stdout - while (!feof($io[1])) { /// this will return always false ... and will loop forever until "fork: retry: no child processes" will show if proc_open is disabled; - $output .= htmlspecialchars(fgets($io[1]),ENT_COMPAT, 'UTF-8'); + while (false === feof($io[1])) { + // this will return always false ... and will loop forever until "fork: retry: no child processes" will show if proc_open is disabled; + $output .= htmlspecialchars(fgets($io[1]), ENT_COMPAT, 'UTF-8'); } // Read output sent to stderr - while (!feof($io[2])) { - $output .= htmlspecialchars(fgets($io[2]),ENT_COMPAT, 'UTF-8'); + while (false === feof($io[2])) { + $output .= htmlspecialchars(fgets($io[2]), ENT_COMPAT, 'UTF-8'); } $output .= "\n"; @@ -109,6 +136,16 @@ if (preg_match('/^[[:blank:]]*cd[[:blank:]]*$/', @$_REQUEST['command'])) { proc_close($p); } -// Finally, output our string -echo $output; +// Change to the cwd in session +chdir($_SESSION['cwd']); +// and again ask for current user and working dir +$user = str_replace("\n","",shell_exec("whoami")); +$cwd = str_replace("\n","",shell_exec("pwd")); + +// Finally, output our JSON data +echo json_encode([ + "output" => $output, + "user" => $user, + "cwd" => $cwd +]); diff --git a/terminal.php b/terminal.php index 6703c12..445c916 100644 --- a/terminal.php +++ b/terminal.php @@ -60,10 +60,15 @@ sendCmd = function(command) { if (xhr.status==200) { // Set the output to also include our response and scroll down to bottom var newOutput = document.createElement("DIV"); - newOutput.innerHTML = xhr.responseText; + responseText = xhr.responseText; + responseJSON = JSON.parse(responseText); + newOutput.innerHTML = responseJSON.output; + document.getElementById("user").innerHTML = "  " + responseJSON.user + " "; + document.getElementById("user").innerHTML = "  " + responseJSON.user + " "; + document.getElementById("cwd").innerHTML = " " + responseJSON.cwd + " "; var cmdElem = document.getElementById("commandLine"); cmdElem.parentNode.insertBefore(newOutput, cmdElem); - document.getElementById("terminal").contentWindow.document.documentElement.scrollTop = document.getElementById('output').scrollHeight; + parent.document.getElementById("terminal").contentWindow.document.documentElement.scrollTop = document.getElementById('output').scrollHeight; // Add command onto end of history array or set as last item in array if (currentLine == 0 || commandHistory[commandHistory.length-1].indexOf("[[ICEcoder]]:") !== 0) { @@ -86,10 +91,11 @@ sendCmd = function(command) { - +
@@ -97,8 +103,7 @@ $cwd = getcwd(); This is a full powered terminal, but will have the permissions of the '' user. The more access rights you give that user, the more this terminal has. -
   
  
-
+
   
  
: