Explorar el Código

Merge branch 'totable-operation' of https://github.com/JustAnotherMark/CyberChef into JustAnotherMark-totable-operation

n1474335 hace 7 años
padre
commit
8fc5f59647

+ 1 - 0
src/core/config/Categories.js

@@ -67,6 +67,7 @@ const Categories = [
             "Encode text",
             "Decode text",
             "Swap endianness",
+            "To Table",
         ]
     },
     {

+ 33 - 0
src/core/config/OperationConfig.js

@@ -37,6 +37,7 @@ import SeqUtils from "../operations/SeqUtils.js";
 import Shellcode from "../operations/Shellcode.js";
 import StrUtils from "../operations/StrUtils.js";
 import Tidy from "../operations/Tidy.js";
+import ToTable from "../operations/ToTable.js";
 import Unicode from "../operations/Unicode.js";
 import URL_ from "../operations/URL.js";
 
@@ -613,6 +614,38 @@ const OperationConfig = {
             }
         ]
     },
+    "To Table": {
+        module: "Default",
+        description: "Renders data as a table. Data can be split on different characters and output as a HTML or ASCII table with optional header row.",
+        inputType: "string",
+        outputType: "html",
+        highlight: false,
+        highlightReverse: false,
+        manualBake: false,
+        args: [
+            {
+                name: "Select separator",
+                type: "populateOption",
+                value: ToTable.SEPARATORS,
+                target: 1
+            },
+            {
+                name: "Separator",
+                type: "string",
+                value: ","
+            },
+            {
+                name: "First row header?",
+                type: "boolean",
+                value: false
+            },
+            {
+                name: "Format",
+                type: "option",
+                value: ToTable.FORMATS
+            }
+        ]
+    },
     "From Hex": {
         module: "Default",
         description: "Converts a hexadecimal byte string back into its raw value.<br><br>e.g. <code>ce 93 ce b5 ce b9 ce ac 20 cf 83 ce bf cf 85 0a</code> becomes the UTF-8 encoded string <code>Γειά σου</code>",

+ 2 - 0
src/core/config/modules/Default.js

@@ -27,6 +27,7 @@ import Rotate from "../../operations/Rotate.js";
 import SeqUtils from "../../operations/SeqUtils.js";
 import StrUtils from "../../operations/StrUtils.js";
 import Tidy from "../../operations/Tidy.js";
+import ToTable from "../../operations/ToTable.js";
 import Unicode from "../../operations/Unicode.js";
 import UUID from "../../operations/UUID.js";
 import XKCD from "../../operations/XKCD.js";
@@ -163,6 +164,7 @@ OpModules.Default = {
     "Mean":                 Arithmetic.runMean,
     "Median":               Arithmetic.runMedian,
     "Standard Deviation":   Arithmetic.runStdDev,
+    "To Table":             ToTable.runToTable,
     "Windows Filetime to UNIX Timestamp": Filetime.runFromFiletimeToUnix,
     "UNIX Timestamp to Windows Filetime": Filetime.runToFiletimeFromUnix,
     "XKCD Random Number":  XKCD.runRandomNumber,

+ 181 - 0
src/core/operations/ToTable.js

@@ -0,0 +1,181 @@
+/**
+ * ToTable operations.
+ *
+ * @author Mark Jones [github.com/justanothermark]
+ * @namespace
+ */
+const ToTable = {
+    /**
+     * @constant
+     * @default
+     */
+    SEPARATORS: [
+        {name: "Comma", value: ","},
+        {name: "Tab", value: "\\t"},
+        {name: "Pipe", value: "|"},
+        {name: "Custom", value: ""}
+    ],
+
+    /**
+     * @constant
+     * @default
+     */
+    FORMATS: [
+        "ASCII",
+        "HTML"
+    ],
+
+    /**
+     * To Table operation.
+     *
+     * @param {string} input
+     * @param {Object[]} args
+     * @returns {html}
+     */
+    runToTable: function (input, args) {
+        let separator = args[1];
+        let firstRowHeader = args[2];
+        let format = args[3];
+        let tableData = [];
+
+        // If the separator contains any tabs, convert them to tab characters.
+        separator = separator.replace("\\t", "\t");
+
+        // Process the input into a nested array of elements.
+        let rows = input.split("\n");
+        rows.forEach(function(element) {
+            if (separator === "") {
+                tableData.push([element]);
+            } else {
+                tableData.push(element.split(separator));
+            }
+        });
+
+        // Render the data in the requested format.
+        let output = "";
+        switch (format) {
+            case "ASCII":
+                output = asciiOutput(tableData);
+                break;
+
+            default:
+                output = htmlOutput(tableData);
+                break;
+        }
+
+        return output;
+
+        /**
+         * Outputs an array of data as an ASCII table.
+         *
+         * @param {Array[]} tableData
+         * @returns {string}
+         */
+        function asciiOutput(tableData) {
+            const horizontalBorder = "-";
+            const verticalBorder = "|";
+            const crossBorder = "+";
+
+            let output = "";
+            let longestCells = [];
+
+            // Find longestCells value per column to pad cells equally.
+            tableData.forEach(function(row, index) {
+                row.forEach(function(cell, cellIndex) {
+                    if (longestCells[cellIndex] === undefined || cell.length > longestCells[cellIndex]) {
+                        longestCells[cellIndex] = cell.length;
+                    }
+                });
+            });
+
+            // Add the top border of the table to the output.
+            output += outputHorizontalBorder(longestCells);
+
+            // If the first row is a header, remove the row from the data and
+            // add it to the output with another horizontal border.
+            if (firstRowHeader) {
+                let row = tableData.shift();
+                output += outputRow(row, longestCells);
+                output += outputHorizontalBorder(longestCells);
+            }
+
+            // Add the rest of the table rows.
+            tableData.forEach(function(row, index) {
+                output += outputRow(row, longestCells);
+            });
+
+            // Close the table with a final horizontal border.
+            output += outputHorizontalBorder(longestCells);
+
+            return output;
+
+            /**
+             * Outputs a row of correctly padded cells.
+             */
+            function outputRow(row, longestCells) {
+                let rowOutput = verticalBorder;
+                row.forEach(function(cell, index) {
+                    rowOutput += " " + cell + " ".repeat(longestCells[index] - cell.length) + " " + verticalBorder;
+                });
+                rowOutput += "\n";
+                return rowOutput;
+            }
+
+            /**
+             * Outputs a horizontal border with a different character where
+             * the horizontal border meets a vertical border.
+             */
+            function outputHorizontalBorder(longestCells) {
+                let rowOutput = crossBorder;
+                longestCells.forEach(function(cellLength) {
+                    rowOutput += horizontalBorder.repeat(cellLength + 2) + crossBorder;
+                });
+                rowOutput += "\n";
+                return rowOutput;
+            }
+        }
+
+        /**
+         * Outputs a table of data as a HTML table.
+         */
+        function htmlOutput(tableData) {
+            // Start the HTML output with suitable classes for styling.
+            let output = "<table class='table table-hover table-condensed table-bordered table-nonfluid'>";
+
+            // If the first row is a header then put it in <thead> with <th> cells.
+            if (firstRowHeader) {
+                let row = tableData.shift();
+                output += "<thead>";
+                output += outputRow(row, "th");
+                output += "</thead>";
+            }
+
+            // Output the rest of the rows in the <tbody>.
+            output += "<tbody>";
+            tableData.forEach(function(row, index) {
+                output += outputRow(row, "td");
+            });
+
+            // Close the body and table elements.
+            output += "</tbody></table>";
+            return output;
+
+          /**
+           * Outputs a table row.
+           *
+           * @param {string[]} row
+           * @param {string} cellType
+           */
+            function outputRow(row, cellType) {
+                let output = "<tr>";
+                row.forEach(function(cell) {
+                    output += "<" + cellType + ">" + cell + "</" + cellType + ">";
+                });
+                output += "</tr>";
+                return output;
+            }
+        }
+    }
+};
+
+export default ToTable;