files.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. const fs = require('fs-extra')
  2. const path = require('path')
  3. const log = require('../../util/log')
  4. const manifestMBDBParse = require('../../util/manifest_mbdb_parse')
  5. module.exports = {
  6. version: 4,
  7. name: 'backup.files',
  8. description: `Gets a backup's file list`,
  9. requiresBackup: true,
  10. // Run on a v3 lib / backup object.
  11. run (lib, { backup, extract, filter }) {
  12. return new Promise(async (resolve, reject) => {
  13. getManifest(backup)
  14. .then(files => {
  15. // Possibly extract objects.
  16. if (extract) {
  17. extractFiles(backup, extract, filter, files)
  18. }
  19. resolve(files)
  20. })
  21. .catch(reject)
  22. })
  23. },
  24. // Available fields.
  25. output: {
  26. id: el => el.fileID,
  27. domain: el => el.domain,
  28. path: el => el.filename,
  29. size: el => el.filelen || 0
  30. }
  31. }
  32. /// Get the manifest for an sqlite database if available
  33. function getSqliteFileManifest (backup) {
  34. return new Promise(async (resolve, reject) => {
  35. backup.openDatabase('Manifest.db', true)
  36. .then(db => {
  37. db.all('SELECT fileID, domain, relativePath as filename from FILES', async function (err, rows) {
  38. if (err) reject(err)
  39. resolve(rows)
  40. })
  41. })
  42. .catch(reject)
  43. })
  44. }
  45. /// Get the manifest from the mbdb file
  46. function getMBDBFileManifest (backup) {
  47. return new Promise((resolve, reject) => {
  48. let mbdbPath = backup.getFileName('Manifest.mbdb', true)
  49. manifestMBDBParse.process(mbdbPath, resolve, reject)
  50. })
  51. }
  52. /// Try to load both of the manifest files
  53. function getManifest (backup) {
  54. return new Promise(async (resolve, reject) => {
  55. // Try the new sqlite file database.
  56. try {
  57. log.verbose('Trying sqlite manifest...')
  58. let item = await getSqliteFileManifest(backup)
  59. return resolve(item)
  60. } catch (e) {
  61. log.verbose('Trying sqlite manifest... [failed]', e)
  62. }
  63. // Try the mbdb file database
  64. try {
  65. log.verbose('Trying mbdb manifest...')
  66. let item = await getMBDBFileManifest(backup)
  67. return resolve(item)
  68. } catch (e) {
  69. log.verbose('Trying mbdb manifest...[failed]', e)
  70. }
  71. reject(new Error('Could not find a manifest.'))
  72. })
  73. }
  74. /// Filter exclusion check
  75. function isIncludedByFilter (filter, item) {
  76. return filter === 'all' ||
  77. filter === undefined ||
  78. (filter && item.domain.indexOf(filter) > -1) ||
  79. (filter && item.filename.indexOf(filter) > -1)
  80. }
  81. /// Extract files
  82. /// - backup: the backup api object
  83. /// - destination: file system location
  84. /// - filter: contains check filter for files
  85. /// - items: list of files.
  86. function extractFiles (backup, destination, filter, items) {
  87. for (var item of items) {
  88. // Filter by the domain.
  89. // Simple "Contains" Search
  90. if (!isIncludedByFilter(filter, item)) {
  91. // Skip to the next iteration of the loop.
  92. log.action('skipped', item.filename)
  93. continue
  94. }
  95. try {
  96. let sourceFile = backup.getFileName(item.fileID)
  97. var stat = fs.lstatSync(sourceFile)
  98. // Only process files that exist.
  99. if (stat.isFile() && fs.existsSync(sourceFile)) {
  100. log.action('export', item.filename)
  101. // Calculate the output dir.
  102. var outDir = path.join(destination, item.domain, item.filename)
  103. // Create the directory and copy
  104. fs.ensureDirSync(path.dirname(outDir))
  105. fs.copySync(sourceFile, outDir)
  106. // Save output info to the data item.
  107. item.output_dir = outDir
  108. } else if (stat.isDirectory()) {
  109. // Do nothing..
  110. } else {
  111. log.error('not found', sourceFile)
  112. }
  113. } catch (e) {
  114. log.error(item.fileID, item.filename, e.toString())
  115. }
  116. }
  117. }