index.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. #!/usr/bin/env node
  2. const program = require('commander')
  3. const path = require('path')
  4. const chalk = require('chalk')
  5. const version = require('./util/version_compare')
  6. const iPhoneBackup = require('./util/iphone_backup.js').iPhoneBackup
  7. var base = path.join(process.env.HOME, '/Library/Application Support/MobileSync/Backup/')
  8. var reportTypes = {
  9. 'apps': require('./reports/apps'),
  10. 'calls': require('./reports/calls'),
  11. 'conversations': require('./reports/conversations'),
  12. 'list': require('./reports/list'),
  13. 'manifest': require('./reports/manifest'),
  14. 'messages': require('./reports/messages'),
  15. 'notes': require('./reports/notes'),
  16. 'oldnotes': require('./reports/oldnotes'),
  17. 'photolocations': require('./reports/photolocations'),
  18. 'voicemail-files': require('./reports/voicemail-files'),
  19. 'voicemail': require('./reports/voicemail'),
  20. 'webhistory': require('./reports/webhistory'),
  21. 'wifi': require('./reports/wifi')
  22. }
  23. var formatters = {
  24. 'json': require('./formatters/json'),
  25. 'table': require('./formatters/table'),
  26. 'raw': require('./formatters/raw'),
  27. 'csv': require('./formatters/csv')
  28. }
  29. program
  30. .version('2.0.5')
  31. .option('-l, --list', 'List Backups')
  32. .option(`-b, --backup <backup>`, 'Backup ID')
  33. .option('-r, --report <report_type>', 'Select a report type. see below for a full list.')
  34. .option(`-d, --dir <directory>`, `Backup Directory (default: ${base})`)
  35. .option(`-v, --verbose`, 'Verbose debugging output')
  36. .option(`-x, --no-color`, 'Disable colorized output')
  37. .option('-f, --formatter <type>', 'Specify output format. default: table')
  38. .option(`-e, --extract <dir>`, 'Extract data for commands. supported by: voicemail-files')
  39. program.on('--help', function () {
  40. console.log('')
  41. console.log('Supported Report Types:')
  42. for (var i in reportTypes) {
  43. if (program.isTTY) {
  44. console.log(' ', reportTypes[i].name, '-', reportTypes[i].description)
  45. } else {
  46. console.log(' ', chalk.green(reportTypes[i].name), '-', reportTypes[i].description)
  47. }
  48. }
  49. console.log('')
  50. console.log("If you're interested to know how this works, check out my post:")
  51. console.log('https://www.richinfante.com/2017/3/16/reverse-engineering-the-ios-backup')
  52. console.log('')
  53. console.log('Issue tracker:')
  54. console.log('https://github.com/richinfante/iphonebackuptools/issues')
  55. console.log('')
  56. })
  57. program.parse(process.argv)
  58. // Global verbose output flag.
  59. // This is bad
  60. global.verbose = program.verbose
  61. // Save the formatter
  62. program.formatter = formatters[program.formatter] || formatters.table
  63. if (!process.stdout.isTTY) { program.color = false }
  64. base = program.dir || base
  65. if (program.verbose) console.log('Using source:', base)
  66. if (program.list) {
  67. // Shortcut for list report
  68. reportTypes.list.func(program, base)
  69. } else if (program.conversations) {
  70. // Legacy shortcut for conversations report
  71. reportTypes.conversations.func(program, base)
  72. } else if (program.messages) {
  73. // Legacy shortcut for messages report
  74. reportTypes.messages.func(program, base)
  75. } else if (program.report) {
  76. // If the report is valid
  77. if (reportTypes[program.report]) {
  78. var report = reportTypes[program.report]
  79. if (report.requiresBackup) {
  80. if (!program.backup) {
  81. console.log('use -b or --backup <id> to specify backup.')
  82. process.exit(1)
  83. }
  84. }
  85. // Try to use it
  86. if (report.func) {
  87. try {
  88. report.func(program, base)
  89. } catch (e) {
  90. console.log('[!] Encountered an error', e)
  91. }
  92. } else if (report.functions) {
  93. // New type of reports
  94. var backup = iPhoneBackup.fromID(program.backup, base)
  95. var flag = false
  96. // Check for a compatible reporting tool.
  97. for (var key in report.functions) {
  98. if (version.versionCheck(backup.iOSVersion, key)) {
  99. report.functions[key](program, backup)
  100. flag = true
  101. break
  102. }
  103. }
  104. if (!flag) {
  105. console.log('[!] No compatible reporter for', backup.iOSVersion, 'and type', program.report)
  106. console.log('')
  107. console.log(' If you think one should exist, file an issue here:')
  108. console.log(' https://github.com/richinfante/iphonebackuptools/issues')
  109. console.log('')
  110. process.exit(1)
  111. }
  112. }
  113. } else {
  114. console.log('')
  115. console.log(' [!] Unknown Option type:', program.report)
  116. console.log(' [!] It\'s possible this tool is out-of date.')
  117. console.log(' https://github.com/richinfante/iphonebackuptools/issues')
  118. console.log('')
  119. program.outputHelp()
  120. }
  121. } else {
  122. program.outputHelp()
  123. }