RawInflate.mjs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. /**
  2. * @author n1474335 [n1474335@gmail.com]
  3. * @copyright Crown Copyright 2016
  4. * @license Apache-2.0
  5. */
  6. import Operation from "../Operation.mjs";
  7. import {INFLATE_BUFFER_TYPE} from "../lib/Zlib.mjs";
  8. import rawinflate from "zlibjs/bin/rawinflate.min.js";
  9. import OperationError from "../errors/OperationError.mjs";
  10. const Zlib = rawinflate.Zlib;
  11. const RAW_BUFFER_TYPE_LOOKUP = {
  12. "Adaptive": Zlib.RawInflate.BufferType.ADAPTIVE,
  13. "Block": Zlib.RawInflate.BufferType.BLOCK,
  14. };
  15. /**
  16. * Raw Inflate operation
  17. */
  18. class RawInflate extends Operation {
  19. /**
  20. * RawInflate constructor
  21. */
  22. constructor() {
  23. super();
  24. this.name = "Raw Inflate";
  25. this.module = "Compression";
  26. this.description = "Decompresses data which has been compressed using the deflate algorithm with no headers.";
  27. this.infoURL = "https://wikipedia.org/wiki/DEFLATE";
  28. this.inputType = "ArrayBuffer";
  29. this.outputType = "ArrayBuffer";
  30. this.args = [
  31. {
  32. name: "Start index",
  33. type: "number",
  34. value: 0
  35. },
  36. {
  37. name: "Initial output buffer size",
  38. type: "number",
  39. value: 0
  40. },
  41. {
  42. name: "Buffer expansion type",
  43. type: "option",
  44. value: INFLATE_BUFFER_TYPE
  45. },
  46. {
  47. name: "Resize buffer after decompression",
  48. type: "boolean",
  49. value: false
  50. },
  51. {
  52. name: "Verify result",
  53. type: "boolean",
  54. value: false
  55. }
  56. ];
  57. this.checks = {
  58. input: {
  59. entropy: {
  60. input: [7.5, 8],
  61. args: [0, 0, INFLATE_BUFFER_TYPE, false, false]
  62. }
  63. }
  64. };
  65. }
  66. /**
  67. * @param {ArrayBuffer} input
  68. * @param {Object[]} args
  69. * @returns {ArrayBuffer}
  70. */
  71. run(input, args) {
  72. const inflate = new Zlib.RawInflate(new Uint8Array(input), {
  73. index: args[0],
  74. bufferSize: args[1],
  75. bufferType: RAW_BUFFER_TYPE_LOOKUP[args[2]],
  76. resize: args[3],
  77. verify: args[4]
  78. }),
  79. result = new Uint8Array(inflate.decompress());
  80. // Raw Inflate sometimes messes up and returns nonsense like this:
  81. // ]....]....]....]....]....]....]....]....]....]....]....]....]....]...
  82. // e.g. Input data of [8b, 1d, dc, 44]
  83. // Look for the first two square brackets:
  84. if (result.length > 158 && result[0] === 93 && result[5] === 93) {
  85. // If the first two square brackets are there, check that the others
  86. // are also there. If they are, throw an error. If not, continue.
  87. let valid = false;
  88. for (let i = 0; i < 155; i += 5) {
  89. if (result[i] !== 93) {
  90. valid = true;
  91. }
  92. }
  93. if (!valid) {
  94. throw new OperationError("Error: Unable to inflate data");
  95. }
  96. }
  97. // This seems to be the easiest way...
  98. return result.buffer;
  99. }
  100. }
  101. export default RawInflate;