From 083d2d1cc41533182ddcc650897d82ae2668cfdf Mon Sep 17 00:00:00 2001 From: n1474335 Date: Mon, 2 Apr 2018 20:46:55 +0100 Subject: [PATCH] ESM: Added Zlib ops and created a Zlib library. --- Gruntfile.js | 4 +- src/core/config/Categories.js | 26 +- src/core/config/OperationConfig.json | 220 ++++++++++++++++ src/core/config/modules/Compression.mjs | 30 +++ src/core/config/modules/OpModules.mjs | 2 + src/core/lib/Zlib.mjs | 19 ++ src/core/operations/Gunzip.mjs | 46 ++++ src/core/operations/Gzip.mjs | 85 ++++++ src/core/operations/RawDeflate.mjs | 58 ++++ src/core/operations/RawInflate.mjs | 105 ++++++++ src/core/operations/Unzip.mjs | 80 ++++++ src/core/operations/Zip.mjs | 101 +++++++ src/core/operations/ZlibDeflate.mjs | 52 ++++ src/core/operations/ZlibInflate.mjs | 84 ++++++ src/core/operations/index.mjs | 16 ++ src/core/operations/legacy/Compress.js | 335 ------------------------ 16 files changed, 913 insertions(+), 350 deletions(-) create mode 100644 src/core/config/modules/Compression.mjs create mode 100644 src/core/lib/Zlib.mjs create mode 100644 src/core/operations/Gunzip.mjs create mode 100644 src/core/operations/Gzip.mjs create mode 100644 src/core/operations/RawDeflate.mjs create mode 100644 src/core/operations/RawInflate.mjs create mode 100644 src/core/operations/Unzip.mjs create mode 100644 src/core/operations/Zip.mjs create mode 100644 src/core/operations/ZlibDeflate.mjs create mode 100644 src/core/operations/ZlibInflate.mjs diff --git a/Gruntfile.js b/Gruntfile.js index f81d508b..eb66cd95 100755 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -22,7 +22,7 @@ module.exports = function (grunt) { // Tasks grunt.registerTask("dev", "A persistent task which creates a development build whenever source files are modified.", - ["clean:dev", "clean:config", "webpack-dev-server:start"]); + ["clean:dev", "webpack-dev-server:start"]); grunt.registerTask("node", "Compiles CyberChef into a single NodeJS module.", @@ -38,7 +38,7 @@ module.exports = function (grunt) { grunt.registerTask("prod", "Creates a production-ready build. Use the --msg flag to add a compile message.", - ["eslint", "clean:prod", "clean:config", "webpack:web", "inline", "chmod"]); + ["eslint", "clean:prod", "webpack:web", "inline", "chmod"]); grunt.registerTask("default", "Lints the code base", diff --git a/src/core/config/Categories.js b/src/core/config/Categories.js index 47ebf9d6..77eafb4b 100755 --- a/src/core/config/Categories.js +++ b/src/core/config/Categories.js @@ -238,22 +238,22 @@ const Categories = [ // "Extract EXIF", // ] // }, - // { - // name: "Compression", - // ops: [ - // "Raw Deflate", - // "Raw Inflate", - // "Zlib Deflate", - // "Zlib Inflate", - // "Gzip", - // "Gunzip", - // "Zip", - // "Unzip", + { + name: "Compression", + ops: [ + "Raw Deflate", + "Raw Inflate", + "Zlib Deflate", + "Zlib Inflate", + "Gzip", + "Gunzip", + "Zip", + "Unzip", // "Bzip2 Decompress", // "Tar", // "Untar", - // ] - // }, + ] + }, // { // name: "Hashing", // ops: [ diff --git a/src/core/config/OperationConfig.json b/src/core/config/OperationConfig.json index 881da0d6..1486c66d 100644 --- a/src/core/config/OperationConfig.json +++ b/src/core/config/OperationConfig.json @@ -114,6 +114,102 @@ } ] }, + "Gunzip": { + "module": "Compression", + "description": "Decompresses data which has been compressed using the deflate algorithm with gzip headers.", + "inputType": "byteArray", + "outputType": "byteArray", + "flowControl": false, + "args": [] + }, + "Gzip": { + "module": "Compression", + "description": "Compresses data using the deflate algorithm with gzip headers.", + "inputType": "byteArray", + "outputType": "byteArray", + "flowControl": false, + "args": [ + { + "name": "Compression type", + "type": "option", + "value": [ + "Dynamic Huffman Coding", + "Fixed Huffman Coding", + "None (Store)" + ] + }, + { + "name": "Filename (optional)", + "type": "string", + "value": "" + }, + { + "name": "Comment (optional)", + "type": "string", + "value": "" + }, + { + "name": "Include file checksum", + "type": "boolean", + "value": false + } + ] + }, + "Raw Deflate": { + "module": "Compression", + "description": "Compresses data using the deflate algorithm with no headers.", + "inputType": "byteArray", + "outputType": "byteArray", + "flowControl": false, + "args": [ + { + "name": "Compression type", + "type": "option", + "value": [ + "Dynamic Huffman Coding", + "Fixed Huffman Coding", + "None (Store)" + ] + } + ] + }, + "Raw Inflate": { + "module": "Compression", + "description": "Decompresses data which has been compressed using the deflate algorithm with no headers.", + "inputType": "byteArray", + "outputType": "byteArray", + "flowControl": false, + "args": [ + { + "name": "Start index", + "type": "number", + "value": 0 + }, + { + "name": "Initial output buffer size", + "type": "number", + "value": 0 + }, + { + "name": "Buffer expansion type", + "type": "option", + "value": [ + "Adaptive", + "Block" + ] + }, + { + "name": "Resize buffer after decompression", + "type": "boolean", + "value": false + }, + { + "name": "Verify result", + "type": "boolean", + "value": false + } + ] + }, "Show Base64 offsets": { "module": "Default", "description": "When a string is within a block of data and the whole block is Base64'd, the string itself could be represented in Base64 in three distinct ways depending on its offset within the block.

This operation shows all possible offsets for a given string so that each possible encoding can be considered.", @@ -237,5 +333,129 @@ ] } ] + }, + "Unzip": { + "module": "Compression", + "description": "Decompresses data using the PKZIP algorithm and displays it per file, with support for passwords.", + "inputType": "byteArray", + "outputType": "byteArray", + "flowControl": false, + "args": [ + { + "name": "Password", + "type": "binaryString", + "value": "" + }, + { + "name": "Verify result", + "type": "boolean", + "value": false + } + ] + }, + "Zip": { + "module": "Compression", + "description": "Compresses data using the PKZIP algorithm with the given filename.

No support for multiple files at this time.", + "inputType": "byteArray", + "outputType": "byteArray", + "flowControl": false, + "args": [ + { + "name": "Filename", + "type": "string", + "value": "file.txt" + }, + { + "name": "Comment", + "type": "string", + "value": "" + }, + { + "name": "Password", + "type": "binaryString", + "value": "" + }, + { + "name": "Compression method", + "type": "option", + "value": [ + "Deflate", + "None (Store)" + ] + }, + { + "name": "Operating system", + "type": "option", + "value": [ + "MSDOS", + "Unix", + "Macintosh" + ] + }, + { + "name": "Compression type", + "type": "option", + "value": [ + "Dynamic Huffman Coding", + "Fixed Huffman Coding", + "None (Store)" + ] + } + ] + }, + "Zlib Deflate": { + "module": "Compression", + "description": "Compresses data using the deflate algorithm adding zlib headers.", + "inputType": "byteArray", + "outputType": "byteArray", + "flowControl": false, + "args": [ + { + "name": "Compression type", + "type": "option", + "value": [ + "Dynamic Huffman Coding", + "Fixed Huffman Coding", + "None (Store)" + ] + } + ] + }, + "Zlib Inflate": { + "module": "Compression", + "description": "Decompresses data which has been compressed using the deflate algorithm with zlib headers.", + "inputType": "byteArray", + "outputType": "byteArray", + "flowControl": false, + "args": [ + { + "name": "Start index", + "type": "number", + "value": 0 + }, + { + "name": "Initial output buffer size", + "type": "number", + "value": 0 + }, + { + "name": "Buffer expansion type", + "type": "option", + "value": [ + "Adaptive", + "Block" + ] + }, + { + "name": "Resize buffer after decompression", + "type": "boolean", + "value": false + }, + { + "name": "Verify result", + "type": "boolean", + "value": false + } + ] } } \ No newline at end of file diff --git a/src/core/config/modules/Compression.mjs b/src/core/config/modules/Compression.mjs new file mode 100644 index 00000000..61b2ed2d --- /dev/null +++ b/src/core/config/modules/Compression.mjs @@ -0,0 +1,30 @@ +/** +* THIS FILE IS AUTOMATICALLY GENERATED BY src/core/config/scripts/generateConfig.mjs +* +* @author n1474335 [n1474335@gmail.com] +* @copyright Crown Copyright 2018 +* @license Apache-2.0 +*/ +import Gunzip from "../../operations/Gunzip"; +import Gzip from "../../operations/Gzip"; +import RawDeflate from "../../operations/RawDeflate"; +import RawInflate from "../../operations/RawInflate"; +import Unzip from "../../operations/Unzip"; +import Zip from "../../operations/Zip"; +import ZlibDeflate from "../../operations/ZlibDeflate"; +import ZlibInflate from "../../operations/ZlibInflate"; + +const OpModules = typeof self === "undefined" ? {} : self.OpModules || {}; + +OpModules.Compression = { + "Gunzip": Gunzip, + "Gzip": Gzip, + "Raw Deflate": RawDeflate, + "Raw Inflate": RawInflate, + "Unzip": Unzip, + "Zip": Zip, + "Zlib Deflate": ZlibDeflate, + "Zlib Inflate": ZlibInflate, +}; + +export default OpModules; diff --git a/src/core/config/modules/OpModules.mjs b/src/core/config/modules/OpModules.mjs index 8ac4ac6d..7c3f3b5e 100644 --- a/src/core/config/modules/OpModules.mjs +++ b/src/core/config/modules/OpModules.mjs @@ -8,12 +8,14 @@ * @license Apache-2.0 */ import DefaultModule from "./Default"; +import CompressionModule from "./Compression"; const OpModules = {}; Object.assign( OpModules, DefaultModule, + CompressionModule, ); export default OpModules; diff --git a/src/core/lib/Zlib.mjs b/src/core/lib/Zlib.mjs new file mode 100644 index 00000000..7cfb4c2f --- /dev/null +++ b/src/core/lib/Zlib.mjs @@ -0,0 +1,19 @@ +/** + * Zlib exports. + * + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + */ + +import zlibAndGzip from "zlibjs/bin/zlib_and_gzip.min"; + +const Zlib = zlibAndGzip.Zlib; + +export const COMPRESSION_TYPE = ["Dynamic Huffman Coding", "Fixed Huffman Coding", "None (Store)"]; +export const INFLATE_BUFFER_TYPE = ["Adaptive", "Block"]; +export const ZLIB_COMPRESSION_TYPE_LOOKUP = { + "Fixed Huffman Coding": Zlib.Deflate.CompressionType.FIXED, + "Dynamic Huffman Coding": Zlib.Deflate.CompressionType.DYNAMIC, + "None (Store)": Zlib.Deflate.CompressionType.NONE, +}; diff --git a/src/core/operations/Gunzip.mjs b/src/core/operations/Gunzip.mjs new file mode 100644 index 00000000..60e29d6f --- /dev/null +++ b/src/core/operations/Gunzip.mjs @@ -0,0 +1,46 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + */ + +import Operation from "../Operation"; +import Utils from "../Utils"; +import zlibAndGzip from "zlibjs/bin/zlib_and_gzip.min"; + +const Zlib = zlibAndGzip.Zlib; + +/** + * Gunzip operation + */ +class Gunzip extends Operation { + + /** + * Gunzip constructor + */ + constructor() { + super(); + + this.name = "Gunzip"; + this.module = "Compression"; + this.description = "Decompresses data which has been compressed using the deflate algorithm with gzip headers."; + this.inputType = "byteArray"; + this.outputType = "byteArray"; + this.args = []; + } + + /** + * @param {byteArray} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + // Deal with character encoding issues + input = Utils.strToByteArray(Utils.byteArrayToUtf8(input)); + const gunzip = new Zlib.Gunzip(input); + return Array.prototype.slice.call(gunzip.decompress()); + } + +} + +export default Gunzip; diff --git a/src/core/operations/Gzip.mjs b/src/core/operations/Gzip.mjs new file mode 100644 index 00000000..86a96763 --- /dev/null +++ b/src/core/operations/Gzip.mjs @@ -0,0 +1,85 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + */ + +import Operation from "../Operation"; +import {COMPRESSION_TYPE, ZLIB_COMPRESSION_TYPE_LOOKUP} from "../lib/Zlib"; +import zlibAndGzip from "zlibjs/bin/zlib_and_gzip.min"; + +const Zlib = zlibAndGzip.Zlib; + +/** + * Gzip operation + */ +class Gzip extends Operation { + + /** + * Gzip constructor + */ + constructor() { + super(); + + this.name = "Gzip"; + this.module = "Compression"; + this.description = "Compresses data using the deflate algorithm with gzip headers."; + this.inputType = "byteArray"; + this.outputType = "byteArray"; + this.args = [ + { + name: "Compression type", + type: "option", + value: COMPRESSION_TYPE + }, + { + name: "Filename (optional)", + type: "string", + value: "" + }, + { + name: "Comment (optional)", + type: "string", + value: "" + }, + { + name: "Include file checksum", + type: "boolean", + value: false + } + ]; + } + + /** + * @param {byteArray} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + const filename = args[1], + comment = args[2], + options = { + deflateOptions: { + compressionType: ZLIB_COMPRESSION_TYPE_LOOKUP[args[0]] + }, + flags: { + fhcrc: args[3] + } + }; + + if (filename.length) { + options.flags.fname = true; + options.filename = filename; + } + if (comment.length) { + options.flags.fcommenct = true; + options.comment = comment; + } + + const gzip = new Zlib.Gzip(input, options); + return Array.prototype.slice.call(gzip.compress()); + } + +} + +export default Gzip; diff --git a/src/core/operations/RawDeflate.mjs b/src/core/operations/RawDeflate.mjs new file mode 100644 index 00000000..a1a30981 --- /dev/null +++ b/src/core/operations/RawDeflate.mjs @@ -0,0 +1,58 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + */ + +import Operation from "../Operation"; +import {COMPRESSION_TYPE} from "../lib/Zlib"; +import rawdeflate from "zlibjs/bin/rawdeflate.min"; + +const Zlib = rawdeflate.Zlib; + +const RAW_COMPRESSION_TYPE_LOOKUP = { + "Fixed Huffman Coding": Zlib.RawDeflate.CompressionType.FIXED, + "Dynamic Huffman Coding": Zlib.RawDeflate.CompressionType.DYNAMIC, + "None (Store)": Zlib.RawDeflate.CompressionType.NONE, +}; + +/** + * Raw Deflate operation + */ +class RawDeflate extends Operation { + + /** + * RawDeflate constructor + */ + constructor() { + super(); + + this.name = "Raw Deflate"; + this.module = "Compression"; + this.description = "Compresses data using the deflate algorithm with no headers."; + this.inputType = "byteArray"; + this.outputType = "byteArray"; + this.args = [ + { + name: "Compression type", + type: "option", + value: COMPRESSION_TYPE + } + ]; + } + + /** + * @param {byteArray} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + const deflate = new Zlib.RawDeflate(input, { + compressionType: RAW_COMPRESSION_TYPE_LOOKUP[args[0]] + }); + return Array.prototype.slice.call(deflate.compress()); + } + +} + +export default RawDeflate; diff --git a/src/core/operations/RawInflate.mjs b/src/core/operations/RawInflate.mjs new file mode 100644 index 00000000..5ec74649 --- /dev/null +++ b/src/core/operations/RawInflate.mjs @@ -0,0 +1,105 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + */ + +import Operation from "../Operation"; +import Utils from "../Utils"; +import {INFLATE_BUFFER_TYPE} from "../lib/Zlib"; +import rawinflate from "zlibjs/bin/rawinflate.min"; + +const Zlib = rawinflate.Zlib; + +const RAW_BUFFER_TYPE_LOOKUP = { + "Adaptive": Zlib.RawInflate.BufferType.ADAPTIVE, + "Block": Zlib.RawInflate.BufferType.BLOCK, +}; + +/** + * Raw Inflate operation + */ +class RawInflate extends Operation { + + /** + * RawInflate constructor + */ + constructor() { + super(); + + this.name = "Raw Inflate"; + this.module = "Compression"; + this.description = "Decompresses data which has been compressed using the deflate algorithm with no headers."; + this.inputType = "byteArray"; + this.outputType = "byteArray"; + this.args = [ + { + name: "Start index", + type: "number", + value: 0 + }, + { + name: "Initial output buffer size", + type: "number", + value: 0 + }, + { + name: "Buffer expansion type", + type: "option", + value: INFLATE_BUFFER_TYPE + }, + { + name: "Resize buffer after decompression", + type: "boolean", + value: false + }, + { + name: "Verify result", + type: "boolean", + value: false + } + ]; + } + + /** + * @param {byteArray} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + // Deal with character encoding issues + input = Utils.strToByteArray(Utils.byteArrayToUtf8(input)); + const inflate = new Zlib.RawInflate(input, { + index: args[0], + bufferSize: args[1], + bufferType: RAW_BUFFER_TYPE_LOOKUP[args[2]], + resize: args[3], + verify: args[4] + }), + result = Array.prototype.slice.call(inflate.decompress()); + + // Raw Inflate somethimes messes up and returns nonsense like this: + // ]....]....]....]....]....]....]....]....]....]....]....]....]....]... + // e.g. Input data of [8b, 1d, dc, 44] + // Look for the first two square brackets: + if (result.length > 158 && result[0] === 93 && result[5] === 93) { + // If the first two square brackets are there, check that the others + // are also there. If they are, throw an error. If not, continue. + let valid = false; + for (let i = 0; i < 155; i += 5) { + if (result[i] !== 93) { + valid = true; + } + } + + if (!valid) { + throw "Error: Unable to inflate data"; + } + } + // This seems to be the easiest way... + return result; + } + +} + +export default RawInflate; diff --git a/src/core/operations/Unzip.mjs b/src/core/operations/Unzip.mjs new file mode 100644 index 00000000..1444551a --- /dev/null +++ b/src/core/operations/Unzip.mjs @@ -0,0 +1,80 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + */ + +import Operation from "../Operation"; +import Utils from "../Utils"; +import unzip from "zlibjs/bin/unzip.min"; + +const Zlib = unzip.Zlib; + +/** + * Unzip operation + */ +class Unzip extends Operation { + + /** + * Unzip constructor + */ + constructor() { + super(); + + this.name = "Unzip"; + this.module = "Compression"; + this.description = "Decompresses data using the PKZIP algorithm and displays it per file, with support for passwords."; + this.inputType = "byteArray"; + this.outputType = "html"; + this.args = [ + { + name: "Password", + type: "binaryString", + value: "" + }, + { + name: "Verify result", + type: "boolean", + value: false + } + ]; + } + + /** + * @param {byteArray} input + * @param {Object[]} args + * @returns {html} + */ + run(input, args) { + const options = { + password: Utils.strToByteArray(args[0]), + verify: args[1] + }, + unzip = new Zlib.Unzip(input, options), + filenames = unzip.getFilenames(), + files = []; + + filenames.forEach(function(fileName) { + const bytes = unzip.decompress(fileName); + const contents = Utils.byteArrayToUtf8(bytes); + + const file = { + fileName: fileName, + size: contents.length, + }; + + const isDir = contents.length === 0 && fileName.endsWith("/"); + if (!isDir) { + file.bytes = bytes; + file.contents = contents; + } + + files.push(file); + }); + + return Utils.displayFilesAsHTML(files); + } + +} + +export default Unzip; diff --git a/src/core/operations/Zip.mjs b/src/core/operations/Zip.mjs new file mode 100644 index 00000000..c487ccbb --- /dev/null +++ b/src/core/operations/Zip.mjs @@ -0,0 +1,101 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + */ + +import Operation from "../Operation"; +import Utils from "../Utils"; +import {COMPRESSION_TYPE, ZLIB_COMPRESSION_TYPE_LOOKUP} from "../lib/Zlib"; +import zip from "zlibjs/bin/zip.min"; + +const Zlib = zip.Zlib; + +const ZIP_COMPRESSION_METHOD_LOOKUP = { + "Deflate": Zlib.Zip.CompressionMethod.DEFLATE, + "None (Store)": Zlib.Zip.CompressionMethod.STORE +}; + +const ZIP_OS_LOOKUP = { + "MSDOS": Zlib.Zip.OperatingSystem.MSDOS, + "Unix": Zlib.Zip.OperatingSystem.UNIX, + "Macintosh": Zlib.Zip.OperatingSystem.MACINTOSH +}; + +/** + * Zip operation + */ +class Zip extends Operation { + + /** + * Zip constructor + */ + constructor() { + super(); + + this.name = "Zip"; + this.module = "Compression"; + this.description = "Compresses data using the PKZIP algorithm with the given filename.

No support for multiple files at this time."; + this.inputType = "byteArray"; + this.outputType = "byteArray"; + this.args = [ + { + name: "Filename", + type: "string", + value: "file.txt" + }, + { + name: "Comment", + type: "string", + value: "" + }, + { + name: "Password", + type: "binaryString", + value: "" + }, + { + name: "Compression method", + type: "option", + value: ["Deflate", "None (Store)"] + }, + { + name: "Operating system", + type: "option", + value: ["MSDOS", "Unix", "Macintosh"] + }, + { + name: "Compression type", + type: "option", + value: COMPRESSION_TYPE + } + ]; + } + + /** + * @param {byteArray} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + const password = Utils.strToByteArray(args[2]), + options = { + filename: Utils.strToByteArray(args[0]), + comment: Utils.strToByteArray(args[1]), + compressionMethod: ZIP_COMPRESSION_METHOD_LOOKUP[args[3]], + os: ZIP_OS_LOOKUP[args[4]], + deflateOption: { + compressionType: ZLIB_COMPRESSION_TYPE_LOOKUP[args[5]] + }, + }, + zip = new Zlib.Zip(); + + if (password.length) + zip.setPassword(password); + zip.addFile(input, options); + return Array.prototype.slice.call(zip.compress()); + } + +} + +export default Zip; diff --git a/src/core/operations/ZlibDeflate.mjs b/src/core/operations/ZlibDeflate.mjs new file mode 100644 index 00000000..99948f93 --- /dev/null +++ b/src/core/operations/ZlibDeflate.mjs @@ -0,0 +1,52 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + */ + +import Operation from "../Operation"; +import {COMPRESSION_TYPE, ZLIB_COMPRESSION_TYPE_LOOKUP} from "../lib/Zlib"; +import zlibAndGzip from "zlibjs/bin/zlib_and_gzip.min"; + +const Zlib = zlibAndGzip.Zlib; + +/** + * Zlib Deflate operation + */ +class ZlibDeflate extends Operation { + + /** + * ZlibDeflate constructor + */ + constructor() { + super(); + + this.name = "Zlib Deflate"; + this.module = "Compression"; + this.description = "Compresses data using the deflate algorithm adding zlib headers."; + this.inputType = "byteArray"; + this.outputType = "byteArray"; + this.args = [ + { + name: "Compression type", + type: "option", + value: COMPRESSION_TYPE + } + ]; + } + + /** + * @param {byteArray} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + const deflate = new Zlib.Deflate(input, { + compressionType: ZLIB_COMPRESSION_TYPE_LOOKUP[args[0]] + }); + return Array.prototype.slice.call(deflate.compress()); + } + +} + +export default ZlibDeflate; diff --git a/src/core/operations/ZlibInflate.mjs b/src/core/operations/ZlibInflate.mjs new file mode 100644 index 00000000..bb7d95ba --- /dev/null +++ b/src/core/operations/ZlibInflate.mjs @@ -0,0 +1,84 @@ +/** + * @author n1474335 [n1474335@gmail.com] + * @copyright Crown Copyright 2016 + * @license Apache-2.0 + */ + +import Operation from "../Operation"; +import Utils from "../Utils"; +import {INFLATE_BUFFER_TYPE} from "../lib/Zlib"; +import zlibAndGzip from "zlibjs/bin/zlib_and_gzip.min"; + +const Zlib = zlibAndGzip.Zlib; + +const ZLIB_BUFFER_TYPE_LOOKUP = { + "Adaptive": Zlib.Inflate.BufferType.ADAPTIVE, + "Block": Zlib.Inflate.BufferType.BLOCK, +}; + +/** + * Zlib Inflate operation + */ +class ZlibInflate extends Operation { + + /** + * ZlibInflate constructor + */ + constructor() { + super(); + + this.name = "Zlib Inflate"; + this.module = "Compression"; + this.description = "Decompresses data which has been compressed using the deflate algorithm with zlib headers."; + this.inputType = "byteArray"; + this.outputType = "byteArray"; + this.args = [ + { + name: "Start index", + type: "number", + value: 0 + }, + { + name: "Initial output buffer size", + type: "number", + value: 0 + }, + { + name: "Buffer expansion type", + type: "option", + value: INFLATE_BUFFER_TYPE + }, + { + name: "Resize buffer after decompression", + type: "boolean", + value: false + }, + { + name: "Verify result", + type: "boolean", + value: false + } + ]; + } + + /** + * @param {byteArray} input + * @param {Object[]} args + * @returns {byteArray} + */ + run(input, args) { + // Deal with character encoding issues + input = Utils.strToByteArray(Utils.byteArrayToUtf8(input)); + const inflate = new Zlib.Inflate(input, { + index: args[0], + bufferSize: args[1], + bufferType: ZLIB_BUFFER_TYPE_LOOKUP[args[2]], + resize: args[3], + verify: args[4] + }); + return Array.prototype.slice.call(inflate.decompress()); + } + +} + +export default ZlibInflate; diff --git a/src/core/operations/index.mjs b/src/core/operations/index.mjs index 81c24acc..55a8e79a 100644 --- a/src/core/operations/index.mjs +++ b/src/core/operations/index.mjs @@ -8,17 +8,33 @@ import FromBase32 from "./FromBase32"; import FromBase64 from "./FromBase64"; import FromHex from "./FromHex"; +import Gunzip from "./Gunzip"; +import Gzip from "./Gzip"; +import RawDeflate from "./RawDeflate"; +import RawInflate from "./RawInflate"; import ShowBase64Offsets from "./ShowBase64Offsets"; import ToBase32 from "./ToBase32"; import ToBase64 from "./ToBase64"; import ToHex from "./ToHex"; +import Unzip from "./Unzip"; +import Zip from "./Zip"; +import ZlibDeflate from "./ZlibDeflate"; +import ZlibInflate from "./ZlibInflate"; export { FromBase32, FromBase64, FromHex, + Gunzip, + Gzip, + RawDeflate, + RawInflate, ShowBase64Offsets, ToBase32, ToBase64, ToHex, + Unzip, + Zip, + ZlibDeflate, + ZlibInflate, }; diff --git a/src/core/operations/legacy/Compress.js b/src/core/operations/legacy/Compress.js index 972a6e08..2313541d 100755 --- a/src/core/operations/legacy/Compress.js +++ b/src/core/operations/legacy/Compress.js @@ -1,22 +1,6 @@ import Utils from "../Utils.js"; -import rawdeflate from "zlibjs/bin/rawdeflate.min"; -import rawinflate from "zlibjs/bin/rawinflate.min"; -import zlibAndGzip from "zlibjs/bin/zlib_and_gzip.min"; -import zip from "zlibjs/bin/zip.min"; -import unzip from "zlibjs/bin/unzip.min"; import bzip2 from "exports-loader?bzip2!../vendor/bzip2.js"; -const Zlib = { - RawDeflate: rawdeflate.Zlib.RawDeflate, - RawInflate: rawinflate.Zlib.RawInflate, - Deflate: zlibAndGzip.Zlib.Deflate, - Inflate: zlibAndGzip.Zlib.Inflate, - Gzip: zlibAndGzip.Zlib.Gzip, - Gunzip: zlibAndGzip.Zlib.Gunzip, - Zip: zip.Zlib.Zip, - Unzip: unzip.Zlib.Unzip, -}; - /** * Compression operations. @@ -29,325 +13,6 @@ const Zlib = { */ const Compress = { - /** - * @constant - * @default - */ - COMPRESSION_TYPE: ["Dynamic Huffman Coding", "Fixed Huffman Coding", "None (Store)"], - /** - * @constant - * @default - */ - INFLATE_BUFFER_TYPE: ["Adaptive", "Block"], - /** - * @constant - * @default - */ - COMPRESSION_METHOD: ["Deflate", "None (Store)"], - /** - * @constant - * @default - */ - OS: ["MSDOS", "Unix", "Macintosh"], - /** - * @constant - * @default - */ - RAW_COMPRESSION_TYPE_LOOKUP: { - "Fixed Huffman Coding": Zlib.RawDeflate.CompressionType.FIXED, - "Dynamic Huffman Coding": Zlib.RawDeflate.CompressionType.DYNAMIC, - "None (Store)": Zlib.RawDeflate.CompressionType.NONE, - }, - - /** - * Raw Deflate operation. - * - * @param {byteArray} input - * @param {Object[]} args - * @returns {byteArray} - */ - runRawDeflate: function(input, args) { - const deflate = new Zlib.RawDeflate(input, { - compressionType: Compress.RAW_COMPRESSION_TYPE_LOOKUP[args[0]] - }); - return Array.prototype.slice.call(deflate.compress()); - }, - - - /** - * @constant - * @default - */ - INFLATE_INDEX: 0, - /** - * @constant - * @default - */ - INFLATE_BUFFER_SIZE: 0, - /** - * @constant - * @default - */ - INFLATE_RESIZE: false, - /** - * @constant - * @default - */ - INFLATE_VERIFY: false, - /** - * @constant - * @default - */ - RAW_BUFFER_TYPE_LOOKUP: { - "Adaptive": Zlib.RawInflate.BufferType.ADAPTIVE, - "Block": Zlib.RawInflate.BufferType.BLOCK, - }, - - /** - * Raw Inflate operation. - * - * @param {byteArray} input - * @param {Object[]} args - * @returns {byteArray} - */ - runRawInflate: function(input, args) { - // Deal with character encoding issues - input = Utils.strToByteArray(Utils.byteArrayToUtf8(input)); - let inflate = new Zlib.RawInflate(input, { - index: args[0], - bufferSize: args[1], - bufferType: Compress.RAW_BUFFER_TYPE_LOOKUP[args[2]], - resize: args[3], - verify: args[4] - }), - result = Array.prototype.slice.call(inflate.decompress()); - - // Raw Inflate somethimes messes up and returns nonsense like this: - // ]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]....]... - // e.g. Input data of [8b, 1d, dc, 44] - // Look for the first two square brackets: - if (result.length > 158 && result[0] === 93 && result[5] === 93) { - // If the first two square brackets are there, check that the others - // are also there. If they are, throw an error. If not, continue. - let valid = false; - for (let i = 0; i < 155; i += 5) { - if (result[i] !== 93) { - valid = true; - } - } - - if (!valid) { - throw "Error: Unable to inflate data"; - } - } - // Trust me, this is the easiest way... - return result; - }, - - - /** - * @constant - * @default - */ - ZLIB_COMPRESSION_TYPE_LOOKUP: { - "Fixed Huffman Coding": Zlib.Deflate.CompressionType.FIXED, - "Dynamic Huffman Coding": Zlib.Deflate.CompressionType.DYNAMIC, - "None (Store)": Zlib.Deflate.CompressionType.NONE, - }, - - /** - * Zlib Deflate operation. - * - * @param {byteArray} input - * @param {Object[]} args - * @returns {byteArray} - */ - runZlibDeflate: function(input, args) { - const deflate = new Zlib.Deflate(input, { - compressionType: Compress.ZLIB_COMPRESSION_TYPE_LOOKUP[args[0]] - }); - return Array.prototype.slice.call(deflate.compress()); - }, - - - /** - * @constant - * @default - */ - ZLIB_BUFFER_TYPE_LOOKUP: { - "Adaptive": Zlib.Inflate.BufferType.ADAPTIVE, - "Block": Zlib.Inflate.BufferType.BLOCK, - }, - - /** - * Zlib Inflate operation. - * - * @param {byteArray} input - * @param {Object[]} args - * @returns {byteArray} - */ - runZlibInflate: function(input, args) { - // Deal with character encoding issues - input = Utils.strToByteArray(Utils.byteArrayToUtf8(input)); - const inflate = new Zlib.Inflate(input, { - index: args[0], - bufferSize: args[1], - bufferType: Compress.ZLIB_BUFFER_TYPE_LOOKUP[args[2]], - resize: args[3], - verify: args[4] - }); - return Array.prototype.slice.call(inflate.decompress()); - }, - - - /** - * @constant - * @default - */ - GZIP_CHECKSUM: false, - - /** - * Gzip operation. - * - * @param {byteArray} input - * @param {Object[]} args - * @returns {byteArray} - */ - runGzip: function(input, args) { - let filename = args[1], - comment = args[2], - options = { - deflateOptions: { - compressionType: Compress.ZLIB_COMPRESSION_TYPE_LOOKUP[args[0]] - }, - flags: { - fhcrc: args[3] - } - }; - - if (filename.length) { - options.flags.fname = true; - options.filename = filename; - } - if (comment.length) { - options.flags.fcommenct = true; - options.comment = comment; - } - - const gzip = new Zlib.Gzip(input, options); - return Array.prototype.slice.call(gzip.compress()); - }, - - - /** - * Gunzip operation. - * - * @param {byteArray} input - * @param {Object[]} args - * @returns {byteArray} - */ - runGunzip: function(input, args) { - // Deal with character encoding issues - input = Utils.strToByteArray(Utils.byteArrayToUtf8(input)); - const gunzip = new Zlib.Gunzip(input); - return Array.prototype.slice.call(gunzip.decompress()); - }, - - - /** - * @constant - * @default - */ - PKZIP_FILENAME: "file.txt", - /** - * @constant - * @default - */ - ZIP_COMPRESSION_METHOD_LOOKUP: { - "Deflate": Zlib.Zip.CompressionMethod.DEFLATE, - "None (Store)": Zlib.Zip.CompressionMethod.STORE - }, - /** - * @constant - * @default - */ - ZIP_OS_LOOKUP: { - "MSDOS": Zlib.Zip.OperatingSystem.MSDOS, - "Unix": Zlib.Zip.OperatingSystem.UNIX, - "Macintosh": Zlib.Zip.OperatingSystem.MACINTOSH - }, - - /** - * Zip operation. - * - * @param {byteArray} input - * @param {Object[]} args - * @returns {byteArray} - */ - runPkzip: function(input, args) { - let password = Utils.strToByteArray(args[2]), - options = { - filename: Utils.strToByteArray(args[0]), - comment: Utils.strToByteArray(args[1]), - compressionMethod: Compress.ZIP_COMPRESSION_METHOD_LOOKUP[args[3]], - os: Compress.ZIP_OS_LOOKUP[args[4]], - deflateOption: { - compressionType: Compress.ZLIB_COMPRESSION_TYPE_LOOKUP[args[5]] - }, - }, - zip = new Zlib.Zip(); - - if (password.length) - zip.setPassword(password); - zip.addFile(input, options); - return Array.prototype.slice.call(zip.compress()); - }, - - - /** - * @constant - * @default - */ - PKUNZIP_VERIFY: false, - - /** - * Unzip operation. - * - * @param {byteArray} input - * @param {Object[]} args - * @returns {string} - */ - runPkunzip: function(input, args) { - let options = { - password: Utils.strToByteArray(args[0]), - verify: args[1] - }, - unzip = new Zlib.Unzip(input, options), - filenames = unzip.getFilenames(), - files = []; - - filenames.forEach(function(fileName) { - const bytes = unzip.decompress(fileName); - const contents = Utils.byteArrayToUtf8(bytes); - - const file = { - fileName: fileName, - size: contents.length, - }; - - const isDir = contents.length === 0 && fileName.endsWith("/"); - if (!isDir) { - file.bytes = bytes; - file.contents = contents; - } - - files.push(file); - }); - - return Utils.displayFilesAsHTML(files); - }, - - /** * Bzip2 Decompress operation. *