From 491a82cd67d9d15f45c956b197386f438a9c2b01 Mon Sep 17 00:00:00 2001 From: n1474335 Date: Fri, 19 May 2017 11:15:48 +0000 Subject: [PATCH] Added 'Render Image' operation --- src/core/config/Categories.js | 1 + src/core/config/OperationConfig.js | 13 ++++++ src/core/operations/FileType.js | 7 ++- src/core/operations/Image.js | 52 +++++++++++++++++++++++ src/web/stylesheets/layout/_structure.css | 4 ++ test/index.js | 2 +- test/tests/operations/Image.js | 34 +++++++++++++++ 7 files changed, 108 insertions(+), 5 deletions(-) diff --git a/src/core/config/Categories.js b/src/core/config/Categories.js index 64418cea..64e71394 100755 --- a/src/core/config/Categories.js +++ b/src/core/config/Categories.js @@ -285,6 +285,7 @@ const Categories = [ "Detect File Type", "Scan for Embedded Files", "Generate UUID", + "Render Image", "Numberwang", ] }, diff --git a/src/core/config/OperationConfig.js b/src/core/config/OperationConfig.js index 9c34b58f..a16d820d 100755 --- a/src/core/config/OperationConfig.js +++ b/src/core/config/OperationConfig.js @@ -3353,6 +3353,19 @@ const OperationConfig = { outputType: "string", args: [], }, + "Render Image": { + description: "Displays the input as an image. Supports the following formats:

", + run: Image.runRenderImage, + inputType: "string", + outputType: "html", + args: [ + { + name: "Input format", + type: "option", + value: Image.INPUT_FORMAT + } + ] + }, }; export default OperationConfig; diff --git a/src/core/operations/FileType.js b/src/core/operations/FileType.js index 90a449eb..ad3e5ba7 100755 --- a/src/core/operations/FileType.js +++ b/src/core/operations/FileType.js @@ -20,7 +20,7 @@ const FileType = { * @returns {string} */ runDetect: function(input, args) { - const type = FileType._magicType(input); + const type = FileType.magicType(input); if (!type) { return "Unknown file type. Have you tried checking the entropy of this data to determine whether it might be encrypted or compressed?"; @@ -59,7 +59,7 @@ const FileType = { numCommonFound = 0; for (let i = 0; i < input.length; i++) { - type = FileType._magicType(input.slice(i)); + type = FileType.magicType(input.slice(i)); if (type) { if (ignoreCommon && commonExts.indexOf(type.ext) > -1) { numCommonFound++; @@ -96,14 +96,13 @@ const FileType = { * Given a buffer, detects magic byte sequences at specific positions and returns the * extension and mime type. * - * @private * @param {byteArray} buf * @returns {Object} type * @returns {string} type.ext - File extension * @returns {string} type.mime - Mime type * @returns {string} [type.desc] - Description */ - _magicType: function (buf) { + magicType: function (buf) { if (!(buf && buf.length > 1)) { return null; } diff --git a/src/core/operations/Image.js b/src/core/operations/Image.js index ef35918b..9ebafaf0 100644 --- a/src/core/operations/Image.js +++ b/src/core/operations/Image.js @@ -1,5 +1,6 @@ import * as ExifParser from "exif-parser"; import Utils from "../Utils.js"; +import FileType from "./FileType.js"; /** @@ -42,6 +43,57 @@ const Image = { } }, + + /** + * @constant + * @default + */ + INPUT_FORMAT: ["Raw", "Base64", "Hex"], + + /** + * Render Image operation. + * + * @author n1474335 [n1474335@gmail.com] + * @param {string} input + * @param {Object[]} args + * @returns {html} + */ + runRenderImage(input, args) { + const inputFormat = args[0]; + let dataURI = "data:"; + + if (!input.length) return ""; + + // Convert input to raw bytes + switch (inputFormat) { + case "Hex": + input = Utils.fromHex(input); + break; + case "Base64": + // Don't trust the Base64 entered by the user. + // Unwrap it first, then re-encode later. + input = Utils.fromBase64(input, null, "byteArray"); + break; + case "Raw": + default: + input = Utils.strToByteArray(input); + break; + } + + // Determine file type + const type = FileType.magicType(input); + if (type && type.mime.indexOf("image") === 0) { + dataURI += type.mime + ";"; + } else { + throw "Invalid file type"; + } + + // Add image data to URI + dataURI += "base64," + Utils.toBase64(input); + + return ""; + }, + }; export default Image; diff --git a/src/web/stylesheets/layout/_structure.css b/src/web/stylesheets/layout/_structure.css index b6ef0da2..77902d09 100644 --- a/src/web/stylesheets/layout/_structure.css +++ b/src/web/stylesheets/layout/_structure.css @@ -6,6 +6,10 @@ * @license Apache-2.0 */ +body { + overflow: hidden; +} + #content-wrapper { position: absolute; top: 0; diff --git a/test/index.js b/test/index.js index 9533fd6c..94b95e63 100644 --- a/test/index.js +++ b/test/index.js @@ -75,7 +75,7 @@ function handleTestResult(testResult) { setTimeout(function() { console.log("Tests took longer than 10 seconds to run, returning."); process.exit(1); -}, 1 * 1000); +}, 10 * 1000); TestRegister.runTests() diff --git a/test/tests/operations/Image.js b/test/tests/operations/Image.js index cf6572a2..c9ec9f84 100644 --- a/test/tests/operations/Image.js +++ b/test/tests/operations/Image.js @@ -2,6 +2,7 @@ * Image operation tests. * * @author tlwr [toby@toby.codes] + * @author n1474335 [n1474335@gmail.com] * * @copyright Crown Copyright 2017 * @license Apache-2.0 @@ -9,6 +10,39 @@ import TestRegister from "../../TestRegister.js"; TestRegister.addTests([ + { + name: "Render Image: nothing", + input: "", + expectedOutput: "", + recipeConfig: [ + { op: "Render Image", args: ["Raw"] } + ] + }, + { + name: "Render Image: raw gif", + input: "4749463839610f000f00b30b00424242ffe700ffef00ffce00000000ffb500ff9c00ffff94ffff10ffffc6ffffefffffff00000000000000000000000021ff0b4e45545343415045322e30030100000021f9040532000b002c000000000f000f0000045a7049096a9d785595ce19170670081204c2600013d09de899aed411108480e229eb9a38194f553998044854725028c6623a14b3727cea7453c0404090790944cdb6abe40e40943317170ca7cff082bb0528d80b2b568662d14f220021f904050a000b002c030009000900010000040530483165040021f904050a000b002c04000a000700010000040530ac3943040021f904050a000b002c040004000700010000040550042943040021f904050a000b002c030004000900020000040a3010228298575c5949040021f904050a000b002c03000400090002000004093008492921415e11010021f9040532000b002c040004000700010000040590904565040021f9040519000b002c030004000800020000040990acb0960c52d41b010021f9040519000b002c030004000900020000040930084264a0128b49220021f904050a000b002c04000400080002000004097005b1ea24b26211010021f904050a000b002c030004000900020000040a3010228298575c5949040021f904050a000b002c03000400090002000004093008492921415e11010021f9040532000b002c040004000700010000040590904565040021f9040519000b002c040003000700030000040a90904525bd54882b42040021f9040519000b002c030003000800020000040990acb0961492da19010021f9040519000b002c030003000900020000040af0044244982408aa71040021f9040519000b002c050003000700030000040a308445c5a098128277040021f904051e000b002c0400040008000200000409902cb1961432d41b010021f904050a000b002c04000a000700010000040590ac3949040021f904050a000b002c030009000900010000040590ac491789003b", + expectedOutput: "", + recipeConfig: [ + { op: "From Hex", args: ["Space"] }, + { op: "Render Image", args: ["Raw"] } + ] + }, + { + name: "Render Image: hex png", + input: "89504e470d0a1a0a0000000d4948445200000020000000200806000000737a7af400000006624b474400ff00ff00ffa0bda793000000097048597300000dd700000dd70142289b78000005184944415458c3c5575d6c145514feeeccecccacdbddb6e096a5dbcdb6d06d80d06090466d6953454ab52ad0a65589840ac1d02a313c989af062820fa66210130d9a68b0363c34610135690b188b7183c13f44506c8115ba535ab6ddd2617f667f66ae0fb41596ddee2eadf13c4de69e7bcf77cff9cecf25b83f613b3b3b975b2c96f25028c47a3c9e1f5a5a5a7e05a0016000d0c9ef9442d23448a60edeb973a769c78e1d077272721a65594620106000505996bf1a1f1f3f67369bebc2e1f0ef6bd7aedd0a409d2d00e2743a1f2929296915046199a66901007aa3d1580600131313da24000000a594124288aaaab72a2b2bed1d1d1d8f8ba2386fc3860d9f25f3c84c0088cbe56a2d2c2cdc4708d12552880770a7288a3228088215003c1ecfd68d1b377e9e488f4b66dde974aeb2dbed498da71251146d538ed1b4e4746092dddee170b4300ca3c32c251c0edfd8bc79f3d164de4e0680110461794a02119292c482202c387efcf86f3d3d3d7b13814816024a2955e62a8b4451b4abaafad8e485d5743ca005028153699c4dd30c83140a857e4c9409c900a0bbbbfbc368343a34a3754a693a1c58b76eddf2dadada5d89002705b07bf7eee13367ce3cab284aff6c482808425e6767e70bc9ea0033d3e6c6c6c65fd6ac5953a1695a3453c3a150c84d295529a59aa669914cd3705adc6eb7926eaca74455d5605555d5c3030303f59224bd525f5f7f30992e87ff40344d5328a5caa64d9bbe4ca5cbe07f1666ae522dae40a5dd8ed30941c8e5727d63341a9f8a5f181a1ac2f0f07022029e02109d2b00bae2e26207cbb2f72cf03c8f9c9c9c441c580c804dc70b330258b6c020beb87ac9abecb59f8b087377b4f4f30a68b6de482549a29224ddb5168bc51cd5d5d54ff6f5f575cfa69633edeb971c78e2d195db055e77cfb6a2eaadb816e5b59ffafb19a7d3095555e3ab64341a8d96f6f6f6fe755f247c69d542abd9c0bd3c70f90a628c30fd5f56542c5c550fc3837600406e6e2eca9e2e433837fcefc0c8b2e079fe7b9fcfe7aba9a9296613c52f55084acc864a027013b28c828a2d30e805bcbe670fac4b5740f5a9285b18c6a0db4da8c180fdc6fdb035d850c555a174a4148410b85cae7293c97442a7d395363434347775757d91b6075a2a6c45d66ce18369258685de644659d96af45ff80345f9f908c932821313c4eff7639b6d1b06838358242c82d96c86288abe582ce6e6797e052184701c9797910796e61976b10c991fff7f7b5313b6373541d5340426d36f747414e5c67294679503a1e90634e6f57adbac56ebb14020f0e9a14387decf84038c8e232b53b45888dc6dec63636389d290c9caca5a3d09a6a2a6a6a628130054d33092a2c52272bbe4515996113f16288ab2c86432bd01001cc72db5582caf651202eaf5473e7e80d7af270409d9cb320c0c66331ca5a5602c1624180d492412392bcbf2db46a3f1394992f665c481b77a2f9f78e719476b5e16ff2e00d31dae8524cb30e8f560390ee72e5e243d7d7d34168bc16030a87575752ccbb20400a2d1e8b7478e1c390ce0f0fd5442fae6d7039f343d643956345f5fcbf1fafd00b219868145afc78d4b97101a1b833a32426d361bcdcfcf87cd6663a7a6649ee70725497a6faede86e4c2c993cf171716eee5753aeb9d0b7f5ebfae5df67a99b86164e8e6cd9badcdcdcdc7d27ae5a6a3f45147c7794dd30e2e59bcf896c0f3851ccbe602c0a8df4fc783413269d8130c06f79d3e7d7a4b5b5bdbd9b45b77c60304c3f0df75752db31714acf8dbe7cbbee2f5fafd7efff9f6f6f6b357af5e8d647ade3fa1780bad734c65970000000049454e44ae426082", + expectedOutput: "", + recipeConfig: [ + { op: "Render Image", args: ["Hex"] } + ] + }, + { + name: "Render Image: base64 jpg", + input: "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", + expectedOutput: "", + recipeConfig: [ + { op: "Render Image", args: ["Base64"] } + ] + }, { name: "Extract EXIF: nothing", input: "",