Browse Source

Output files can be viewed in slices

n1474335 7 years ago
parent
commit
bad0816115

+ 3 - 1
src/web/Manager.js

@@ -142,7 +142,7 @@ Manager.prototype.initialiseEventListeners = function() {
     document.getElementById("input-text").addEventListener("mouseup", this.highlighter.inputMouseup.bind(this.highlighter));
     document.getElementById("input-text").addEventListener("mousemove", this.highlighter.inputMousemove.bind(this.highlighter));
     this.addMultiEventListener("#input-text", "mousedown dblclick select",  this.highlighter.inputMousedown, this.highlighter);
-    document.querySelector("#input-file .close").addEventListener("click", this.input.closeFile.bind(this.input));
+    document.querySelector("#input-file .close").addEventListener("click", this.input.clearIoClick.bind(this.input));
 
     // Output
     document.getElementById("save-to-file").addEventListener("click", this.output.saveClick.bind(this.output));
@@ -159,6 +159,8 @@ Manager.prototype.initialiseEventListeners = function() {
     this.addMultiEventListener("#output-html", "mousedown dblclick select",  this.highlighter.outputHtmlMousedown, this.highlighter);
     this.addDynamicListener(".file-switch", "click", this.output.fileSwitch, this.output);
     this.addDynamicListener("#output-file-download", "click", this.output.downloadFile, this.output);
+    this.addDynamicListener("#output-file-slice", "click", this.output.displayFile, this.output);
+    document.getElementById("show-file-overlay").addEventListener("click", this.output.showFileOverlayClick.bind(this.output));
 
     // Options
     document.getElementById("options").addEventListener("click", this.options.optionsClick.bind(this.options));

+ 46 - 12
src/web/OutputWaiter.js

@@ -17,7 +17,7 @@ const OutputWaiter = function(app, manager) {
     this.app = app;
     this.manager = manager;
 
-    this.file = null;
+    this.dishBuffer = null;
 };
 
 
@@ -37,8 +37,9 @@ OutputWaiter.prototype.get = function() {
  * @param {string|ArrayBuffer} data - The output string/HTML/ArrayBuffer
  * @param {string} type - The data type of the output
  * @param {number} duration - The length of time (ms) it took to generate the output
+ * @param {boolean} [preserveBuffer=false] - Whether to preserve the dishBuffer
  */
-OutputWaiter.prototype.set = function(data, type, duration) {
+OutputWaiter.prototype.set = function(data, type, duration, preserveBuffer) {
     const outputText = document.getElementById("output-text");
     const outputHtml = document.getElementById("output-html");
     const outputFile = document.getElementById("output-file");
@@ -46,7 +47,7 @@ OutputWaiter.prototype.set = function(data, type, duration) {
     const inputHighlighter = document.getElementById("input-highlighter");
     let scriptElements, lines, length;
 
-    this.closeFile();
+    if (!preserveBuffer) this.closeFile();
 
     switch (type) {
         case "html":
@@ -80,7 +81,7 @@ OutputWaiter.prototype.set = function(data, type, duration) {
             outputHtml.innerHTML = "";
             length = data.byteLength;
 
-            this.setFile(new File([data], "output.dat"));
+            this.setFile(data);
             break;
         case "string":
         default:
@@ -106,10 +107,11 @@ OutputWaiter.prototype.set = function(data, type, duration) {
 /**
  * Shows file details.
  *
- * @param {File} file
+ * @param {ArrayBuffer} buf
  */
-OutputWaiter.prototype.setFile = function(file) {
-    this.file = file;
+OutputWaiter.prototype.setFile = function(buf) {
+    this.dishBuffer = buf;
+    const file = new File([buf], "output.dat");
 
     // Display file overlay in output area with details
     const fileOverlay = document.getElementById("output-file"),
@@ -124,7 +126,7 @@ OutputWaiter.prototype.setFile = function(file) {
  * Removes the output file and nulls its memory.
  */
 OutputWaiter.prototype.closeFile = function() {
-    this.file = null;
+    this.dishBuffer = null;
     document.getElementById("output-file").style.display = "none";
 };
 
@@ -134,8 +136,40 @@ OutputWaiter.prototype.closeFile = function() {
  */
 OutputWaiter.prototype.downloadFile = function() {
     const filename = window.prompt("Please enter a filename:", "download.dat");
+    const file = new File([this.dishBuffer], filename);
 
-    if (filename) FileSaver.saveAs(this.file, filename, false);
+    if (filename) FileSaver.saveAs(file, filename, false);
+};
+
+
+/**
+ * Handler for file display events.
+ */
+OutputWaiter.prototype.displayFile = function() {
+    const startTime = new Date().getTime(),
+        showFileOverlay = document.getElementById("show-file-overlay"),
+        sliceFromEl = document.getElementById("output-file-slice-from"),
+        sliceToEl = document.getElementById("output-file-slice-to"),
+        sliceFrom = parseInt(sliceFromEl.value, 10),
+        sliceTo = parseInt(sliceToEl.value, 10),
+        str = Utils.arrayBufferToStr(this.dishBuffer.slice(sliceFrom, sliceTo));
+
+    showFileOverlay.style.display = "block";
+    this.set(str, "string", new Date().getTime() - startTime, true);
+};
+
+
+/**
+ * Handler for show file overlay events.
+ * 
+ * @param {Event} e
+ */
+OutputWaiter.prototype.showFileOverlayClick = function(e) {
+    const outputFile = document.getElementById("output-file"),
+        showFileOverlay = e.target;
+
+    outputFile.style.display = "block";
+    showFileOverlay.style.display = "none";
 };
 
 
@@ -198,8 +232,8 @@ OutputWaiter.prototype.adjustWidth = function() {
  * Saves the current output to a file.
  */
 OutputWaiter.prototype.saveClick = function() {
-    if (!this.file) {
-        this.file = new File([new Uint8Array(Utils.strToCharcode(this.app.dishStr))], "");
+    if (!this.dishBuffer) {
+        this.dishBuffer = new Uint8Array(Utils.strToCharcode(this.app.dishStr)).buffer;
     }
     this.downloadFile();
 };
@@ -227,7 +261,7 @@ OutputWaiter.prototype.copyClick = function() {
     let success = false;
     try {
         textarea.select();
-        success = document.execCommand("copy");
+        success = textarea.value && document.execCommand("copy");
     } catch (err) {
         success = false;
     }

+ 12 - 5
src/web/html/index.html

@@ -184,7 +184,7 @@
                             <div id="input-file">
                                 <div style="position: relative; height: 100%;">
                                     <div class="card">
-                                        <img aria-hidden="true" src="<%- require('../static/images/cyberchef-256x256.png') %>" alt="File icon"/>
+                                        <img aria-hidden="true" src="<%- require('../static/images/file-128x128.png') %>" alt="File icon"/>
                                         <div class="card-body">
                                             <button type="button" class="close" id="input-file-close">&times;</button>
                                             Name: <span id="input-file-name"></span><br>
@@ -216,15 +216,22 @@
                             <div id="output-highlighter" class="no-select"></div>
                             <div id="output-html"></div>
                             <textarea id="output-text" readonly="readonly"></textarea>
+                            <img id="show-file-overlay" aria-hidden="true" src="<%- require('../static/images/file-32x32.png') %>" alt="Show file overlay" title="Show file overlay"/>
                             <div id="output-file">
                                 <div style="position: relative; height: 100%;">
                                     <div class="card">
-                                        <img aria-hidden="true" src="<%- require('../static/images/cyberchef-256x256.png') %>" alt="File icon"/>
+                                        <img aria-hidden="true" src="<%- require('../static/images/file-128x128.png') %>" alt="File icon"/>
                                         <div class="card-body">
                                             Size: <span id="output-file-size"></span><br>
-                                            <button id="output-file-download" type="button" class="btn btn-primary btn-sm">Download</button><br>
-                                            Display in output<br>
-                                            Options for how much to display
+                                            <button id="output-file-download" type="button" class="btn btn-primary">Download</button>
+                                            <div class="input-group">
+                                                <span class="input-group-btn">
+                                                    <button id="output-file-slice" type="button" class="btn btn-default" title="View">&#x1f50d;</button>
+                                                </span>
+                                                <input type="number" class="form-control" id="output-file-slice-from" placeholder="From" value="0" step="1024" min="0">
+                                                <div class="input-group-addon">to</div>
+                                                <input type="number" class="form-control" id="output-file-slice-to" placeholder="To" value="1024" step="1024" min="0">
+                                            </div>
                                         </div>
                                     </div>
                                 </div>

BIN
src/web/static/images/file-128x128.png


BIN
src/web/static/images/file-32x32.png


+ 15 - 3
src/web/stylesheets/components/_pane.css

@@ -50,8 +50,10 @@
 
 .card>img {
     float: left;
-    width: 150px;
-    height: 150px;
+    width: 128px;
+    height: 128px;
+    margin-left: 10px;
+    margin-top: 11px;
 }
 
 .card-body .close {
@@ -68,4 +70,14 @@
     overflow: hidden;
     text-overflow: ellipsis;
     user-select: text;
-}
+}
+
+.card-body>.btn {
+    margin-bottom: 15px;
+    margin-top: 5px;
+}
+
+.card input[type=number] {
+    padding-right: 6px;
+    padding-left: 6px;
+}

+ 8 - 0
src/web/stylesheets/layout/_io.css

@@ -88,6 +88,14 @@
     display: none;
 }
 
+#show-file-overlay {
+    position: absolute;
+    right: 15px;
+    top: 15px;
+    cursor: pointer;
+    display: none;
+}
+
 .io-btn-group {
     float: right;
     margin-top: -4px;

+ 11 - 1
src/web/stylesheets/utils/_overrides.css

@@ -64,7 +64,8 @@ a:focus {
 .alert,
 .modal-content,
 .tooltip-inner,
-.dropdown-menu {
+.dropdown-menu,
+.input-group-addon {
     border-radius: 0 !important;
 }
 
@@ -187,6 +188,15 @@ optgroup {
     color: var(--primary-font-colour);
 }
 
+.input-group-addon:not(:first-child):not(:last-child) {
+    border-left: 0;
+    border-right: 0;
+}
+
+.input-group-btn:first-child>.btn {
+    border-right: 0;
+}
+
 
 /* Bootstrap-switch */