manifest.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. const fs = require('fs-extra')
  2. const log = require('../util/log')
  3. const path = require('path')
  4. module.exports.name = 'manifest'
  5. module.exports.description = 'List all the files contained in the backup (iOS 5+)'
  6. // Specify this reporter requires a backup.
  7. // The second parameter to func() is now a backup instead of the path to one.
  8. module.exports.requiresBackup = true
  9. // Specify this reporter supports the promises API for allowing chaining of reports.
  10. module.exports.usesPromises = true
  11. // Specify this only works for iOS 5+
  12. module.exports.supportedVersions = '>=5.0'
  13. function isIncludedByFilter (program, item) {
  14. return program.filter === 'all' ||
  15. program.filter === undefined ||
  16. (program.filter && item.domain.indexOf(program.filter) > -1)
  17. }
  18. // You can also provide an array of functions instead of using `module.exports.func`.
  19. // These functions *should* be independent ranges to ensure reliable execution
  20. module.exports.functions = {
  21. '>=10.0': function (program, backup, resolve, reject) {
  22. // This function would be called for iOS 10+
  23. backup.getFileManifest()
  24. .then((items) => {
  25. // Extract items for analysis on-disk.
  26. if (program.extract) {
  27. for (var item of items) {
  28. // Filter by the domain.
  29. // Simple "Contains" Search
  30. if (isIncludedByFilter(program, item)) {
  31. // Do nothing, we'll process later.
  32. } else {
  33. // Skip to the next iteration of the loop.
  34. log.action('skipped', item.relativePath)
  35. continue
  36. }
  37. try {
  38. var sourceFile = backup.getFileName(item.fileID)
  39. var stat = fs.lstatSync(sourceFile)
  40. // Only process files that exist.
  41. if (stat.isFile() && fs.existsSync(sourceFile)) {
  42. log.action('export', item.relativePath)
  43. // Calculate the output dir.
  44. var outDir = path.join(program.extract, item.domain, item.relativePath)
  45. // Create the directory and copy
  46. fs.ensureDirSync(path.dirname(outDir))
  47. fs.copySync(sourceFile, outDir)
  48. // Save output info to the data item.
  49. item.output_dir = outDir
  50. } else if (stat.isDirectory()) {
  51. // Do nothing..
  52. } else {
  53. log.error('not found', item.relativePath)
  54. }
  55. } catch (e) {
  56. log.error(item.relativePath, e.toString())
  57. }
  58. }
  59. resolve([])
  60. } else {
  61. var result = program.formatter.format(items, {
  62. program: program,
  63. columns: {
  64. 'ID': el => el.fileID,
  65. 'Domain/Path': el => el.domain + ': ' + el.relativePath
  66. }
  67. })
  68. resolve(result)
  69. }
  70. })
  71. .catch((e) => {
  72. console.log('[!] Encountered an Error:', e)
  73. })
  74. },
  75. '>=5.0,<10.0': function (program, backup, resolve, reject) {
  76. // This function would be called for all iOS 5 up to iOS 9.x.
  77. backup.getOldFileManifest()
  78. .then((items) => {
  79. // Extract items for analysis on-disk.
  80. if (program.extract) {
  81. for (var item of items) {
  82. // Filter by the domain.
  83. // Simple "Contains" Search
  84. if (isIncludedByFilter(program, item)) {
  85. // Do nothing, we'll process later.
  86. } else {
  87. // Skip to the next iteration of the loop.
  88. log.action('skipped', item.filename)
  89. continue
  90. }
  91. try {
  92. var sourceFile = backup.getFileName(item.fileID)
  93. var stat = fs.lstatSync(sourceFile)
  94. // Only process files that exist.
  95. if (stat.isFile() && fs.existsSync(sourceFile)) {
  96. log.action(item.filename)
  97. // Calculate the output dir.
  98. var outDir = path.join(program.extract, item.domain, item.filename)
  99. // Create the directory and copy
  100. fs.ensureDirSync(path.dirname(outDir))
  101. fs.copySync(sourceFile, outDir)
  102. // Save output info to the data item.
  103. item.output_dir = outDir
  104. } else if (stat.isDirectory()) {
  105. // Do nothing..
  106. } else {
  107. log.error('not found', item.filename)
  108. }
  109. } catch (e) {
  110. log.error(item.filename, e.toString())
  111. }
  112. }
  113. resolve([])
  114. } else {
  115. var result = program.formatter.format(items, {
  116. program: program,
  117. columns: {
  118. 'ID': el => el.fileID,
  119. 'Domain/Path': el => (el.domain + ': ' + el.filename).substr(0, 70),
  120. 'Size': el => el.filelen
  121. }
  122. })
  123. resolve(result)
  124. }
  125. })
  126. .catch(reject)
  127. }
  128. }