ExtractFiles.mjs 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. /**
  2. * @author n1474335 [n1474335@gmail.com]
  3. * @copyright Crown Copyright 2018
  4. * @license Apache-2.0
  5. */
  6. import Operation from "../Operation";
  7. import OperationError from "../errors/OperationError";
  8. import Utils from "../Utils";
  9. import {scanForFileTypes, extractFile} from "../lib/FileType";
  10. import {FILE_SIGNATURES} from "../lib/FileSignatures";
  11. /**
  12. * Extract Files operation
  13. */
  14. class ExtractFiles extends Operation {
  15. /**
  16. * ExtractFiles constructor
  17. */
  18. constructor() {
  19. super();
  20. this.name = "Extract Files";
  21. this.module = "Default";
  22. this.description = "TODO";
  23. this.infoURL = "https://forensicswiki.org/wiki/File_Carving";
  24. this.inputType = "ArrayBuffer";
  25. this.outputType = "List<File>";
  26. this.presentType = "html";
  27. this.args = Object.keys(FILE_SIGNATURES).map(cat => {
  28. return {
  29. name: cat,
  30. type: "boolean",
  31. value: cat === "Miscellaneous" ? false : true
  32. };
  33. }).concat([
  34. {
  35. name: "Ignore failed extractions",
  36. type: "boolean",
  37. value: "true"
  38. }
  39. ]);
  40. }
  41. /**
  42. * @param {ArrayBuffer} input
  43. * @param {Object[]} args
  44. * @returns {List<File>}
  45. */
  46. run(input, args) {
  47. const bytes = new Uint8Array(input),
  48. categories = [],
  49. ignoreFailedExtractions = args.pop(1);
  50. args.forEach((cat, i) => {
  51. if (cat) categories.push(Object.keys(FILE_SIGNATURES)[i]);
  52. });
  53. // Scan for embedded files
  54. const detectedFiles = scanForFileTypes(bytes, categories);
  55. // Extract each file that we support
  56. const files = [];
  57. const errors = [];
  58. detectedFiles.forEach(detectedFile => {
  59. try {
  60. files.push(extractFile(bytes, detectedFile.fileDetails, detectedFile.offset));
  61. } catch (err) {
  62. if (!ignoreFailedExtractions && err.message.indexOf("No extraction algorithm available") < 0) {
  63. errors.push(
  64. `Error while attempting to extract ${detectedFile.fileDetails.name} ` +
  65. `at offset ${detectedFile.offset}:\n` +
  66. `${err.message}`
  67. );
  68. }
  69. }
  70. });
  71. if (errors.length) {
  72. throw new OperationError(errors.join("\n\n"));
  73. }
  74. return files;
  75. }
  76. /**
  77. * Displays the files in HTML for web apps.
  78. *
  79. * @param {File[]} files
  80. * @returns {html}
  81. */
  82. async present(files) {
  83. return await Utils.displayFilesAsHTML(files);
  84. }
  85. }
  86. export default ExtractFiles;