OutputWaiter.js 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /**
  2. * Waiter to handle events related to the output.
  3. *
  4. * @author n1474335 [n1474335@gmail.com]
  5. * @copyright Crown Copyright 2016
  6. * @license Apache-2.0
  7. *
  8. * @constructor
  9. * @param {HTMLApp} app - The main view object for CyberChef.
  10. * @param {Manager} manager - The CyberChef event manager.
  11. */
  12. var OutputWaiter = function(app, manager) {
  13. this.app = app;
  14. this.manager = manager;
  15. };
  16. /**
  17. * Gets the output string from the output textarea.
  18. *
  19. * @returns {string}
  20. */
  21. OutputWaiter.prototype.get = function() {
  22. return document.getElementById("output-text").value;
  23. };
  24. /**
  25. * Sets the output in the output textarea.
  26. *
  27. * @param {string} dataStr - The output string/HTML
  28. * @param {string} type - The data type of the output
  29. * @param {number} duration - The length of time (ms) it took to generate the output
  30. */
  31. OutputWaiter.prototype.set = function(dataStr, type, duration) {
  32. var outputText = document.getElementById("output-text"),
  33. outputHtml = document.getElementById("output-html"),
  34. outputHighlighter = document.getElementById("output-highlighter"),
  35. inputHighlighter = document.getElementById("input-highlighter");
  36. if (type === "html") {
  37. outputText.style.display = "none";
  38. outputHtml.style.display = "block";
  39. outputHighlighter.display = "none";
  40. inputHighlighter.display = "none";
  41. outputText.value = "";
  42. outputHtml.innerHTML = dataStr;
  43. // Execute script sections
  44. var scriptElements = outputHtml.querySelectorAll("script");
  45. for (var i = 0; i < scriptElements.length; i++) {
  46. try {
  47. eval(scriptElements[i].innerHTML); // eslint-disable-line no-eval
  48. } catch (err) {
  49. console.error(err);
  50. }
  51. }
  52. } else {
  53. outputText.style.display = "block";
  54. outputHtml.style.display = "none";
  55. outputHighlighter.display = "block";
  56. inputHighlighter.display = "block";
  57. outputText.value = Utils.printable(dataStr, true);
  58. outputHtml.innerHTML = "";
  59. }
  60. this.manager.highlighter.removeHighlights();
  61. var lines = dataStr.count("\n") + 1;
  62. this.setOutputInfo(dataStr.length, lines, duration);
  63. };
  64. /**
  65. * Displays information about the output.
  66. *
  67. * @param {number} length - The length of the current output string
  68. * @param {number} lines - The number of the lines in the current output string
  69. * @param {number} duration - The length of time (ms) it took to generate the output
  70. */
  71. OutputWaiter.prototype.setOutputInfo = function(length, lines, duration) {
  72. var width = length.toString().length;
  73. width = width < 4 ? 4 : width;
  74. var lengthStr = Utils.pad(length.toString(), width, " ").replace(/ /g, "&nbsp;");
  75. var linesStr = Utils.pad(lines.toString(), width, " ").replace(/ /g, "&nbsp;");
  76. var timeStr = Utils.pad(duration.toString() + "ms", width, " ").replace(/ /g, "&nbsp;");
  77. document.getElementById("output-info").innerHTML = "time: " + timeStr +
  78. "<br>length: " + lengthStr +
  79. "<br>lines: " + linesStr;
  80. document.getElementById("input-selection-info").innerHTML = "";
  81. document.getElementById("output-selection-info").innerHTML = "";
  82. };
  83. /**
  84. * Adjusts the display properties of the output buttons so that they fit within the current width
  85. * without wrapping or overflowing.
  86. */
  87. OutputWaiter.prototype.adjustWidth = function() {
  88. var output = document.getElementById("output"),
  89. saveToFile = document.getElementById("save-to-file"),
  90. switchIO = document.getElementById("switch"),
  91. undoSwitch = document.getElementById("undo-switch"),
  92. maximiseOutput = document.getElementById("maximise-output");
  93. if (output.clientWidth < 680) {
  94. saveToFile.childNodes[1].nodeValue = "";
  95. switchIO.childNodes[1].nodeValue = "";
  96. undoSwitch.childNodes[1].nodeValue = "";
  97. maximiseOutput.childNodes[1].nodeValue = "";
  98. } else {
  99. saveToFile.childNodes[1].nodeValue = " Save to file";
  100. switchIO.childNodes[1].nodeValue = " Move output to input";
  101. undoSwitch.childNodes[1].nodeValue = " Undo";
  102. maximiseOutput.childNodes[1].nodeValue =
  103. maximiseOutput.getAttribute("title") === "Maximise" ? " Max" : " Restore";
  104. }
  105. };
  106. /**
  107. * Handler for save click events.
  108. * Saves the current output to a file, downloaded as a URL octet stream.
  109. */
  110. OutputWaiter.prototype.saveClick = function() {
  111. var data = Utils.toBase64(this.app.dishStr),
  112. filename = window.prompt("Please enter a filename:", "download.dat");
  113. if (filename) {
  114. var el = document.createElement("a");
  115. el.setAttribute("href", "data:application/octet-stream;base64;charset=utf-8," + data);
  116. el.setAttribute("download", filename);
  117. // Firefox requires that the element be added to the DOM before it can be clicked
  118. el.style.display = "none";
  119. document.body.appendChild(el);
  120. el.click();
  121. el.remove();
  122. }
  123. };
  124. /**
  125. * Handler for switch click events.
  126. * Moves the current output into the input textarea.
  127. */
  128. OutputWaiter.prototype.switchClick = function() {
  129. this.switchOrigData = this.manager.input.get();
  130. document.getElementById("undo-switch").disabled = false;
  131. this.app.setInput(this.app.dishStr);
  132. };
  133. /**
  134. * Handler for undo switch click events.
  135. * Removes the output from the input and replaces the input that was removed.
  136. */
  137. OutputWaiter.prototype.undoSwitchClick = function() {
  138. this.app.setInput(this.switchOrigData);
  139. document.getElementById("undo-switch").disabled = true;
  140. };
  141. /**
  142. * Handler for maximise output click events.
  143. * Resizes the output frame to be as large as possible, or restores it to its original size.
  144. */
  145. OutputWaiter.prototype.maximiseOutputClick = function(e) {
  146. var el = e.target.id === "maximise-output" ? e.target : e.target.parentNode;
  147. if (el.getAttribute("title") === "Maximise") {
  148. this.app.columnSplitter.collapse(0);
  149. this.app.columnSplitter.collapse(1);
  150. this.app.ioSplitter.collapse(0);
  151. el.setAttribute("title", "Restore");
  152. el.innerHTML = "<img src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAlUlEQVQ4y93RwQpBQRQG4C9ba1fxBteGPIj38BTejFJKLFnwCJIiCsW1mcV0k9yx82/OzGK+OXMGOpiiLTFjFNiilQI0sQ7IJiAjLKsgGVYB2YdaVO0kwy46/BVQi9ZDNPyQWen2ub/KufS8y7shfkq9tF9U7SC+/YluKvAI9YZeFeCECXJcA3JHP2WgMXJM/ZUcBwxeM+YuSWTgMtUAAAAASUVORK5CYII='> Restore";
  153. this.adjustWidth();
  154. } else {
  155. el.setAttribute("title", "Maximise");
  156. el.innerHTML = "<img src='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAi0lEQVQ4y83TMQrCQBCF4S+5g4rJEdJ7KE+RQ1lrIQQCllroEULuoM0Ww3a7aXwwLAzMPzDvLcz4hnooUItT1rsoVNy+4lgLWNL7RlcCmDBij2eCfNCrUITc0dRCrhj8m5otw0O6SV8LuAV3uhrAAa8sJ2Np7KPFawhgscVLjH9bCDhjt8WNKft88w/HjCvuVqu53QAAAABJRU5ErkJggg=='> Max";
  157. this.app.resetLayout();
  158. }
  159. };