123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- const fs = require('fs')
- const sqlite3 = require('sqlite3')
- const path = require('path')
- const log = require('./util/log')
- const filehash = require('./util/backup_filehash')
- const manifestMBDBParse = require('./util/manifest_mbdb_parse')
- class Backup {
-
- constructor (base, id) {
- log.verbose(`create backup with base=${base}, id=${id}`)
- id = id || ''
- base = base || ''
-
- if (id.constructor === Backup) {
- id = id.id
- log.verbose(`unwrapping backup to id=${id}`)
- }
- this.id = id
- this.base = base
-
- if (base) {
- this.path = path.join(base, id)
- } else {
- this.path = path.join(process.env.HOME, '/Library/Application Support/MobileSync/Backup/', id)
- }
- }
-
- getFileID (path, domain) {
- return Backup.getFileID(path, domain)
- }
-
- static getFileID (path, domain) {
- return filehash(path, domain)
- }
-
- getFileName (fileID, isAbsoulte) {
-
- isAbsoulte = isAbsoulte || false
-
- let possibilities
- if (isAbsoulte) {
-
- possibilities = [
- path.join(this.path, fileID)
- ]
- } else {
-
- possibilities = [
- path.join(this.path, fileID),
- path.join(this.path, fileID.substr(0, 2), fileID)
- ]
- }
-
- for (let path of possibilities) {
- log.verbose('trying', path, fs.existsSync(path))
-
- if (fs.existsSync(path)) {
- log.verbose('trying', path, '[found]')
-
- return path
- }
- }
-
- throw new Error(`Could not find a file needed for this report. It may not be compatibile with this specific backup or iOS Version.`)
- }
-
- getSqliteFileManifest () {
- return new Promise(async (resolve, reject) => {
- this.openDatabase('Manifest.db', true)
- .then(db => {
- db.all('SELECT fileID, domain, relativePath as filename from FILES', async function (err, rows) {
- if (err) reject(err)
-
- resolve(rows)
- })
- })
- .catch(reject)
- })
- }
-
- getMBDBFileManifest () {
- return new Promise((resolve, reject) => {
- let mbdbPath = this.getFileName('Manifest.mbdb', true)
- manifestMBDBParse.process(mbdbPath, resolve, reject)
- })
- }
-
-
- getManifest () {
- return new Promise(async (resolve, reject) => {
-
- try {
- log.verbose('Trying sqlite manifest...')
- let item = await this.getSqliteFileManifest(this)
- return resolve(item)
- } catch (e) {
- log.verbose('Trying sqlite manifest... [failed]', e)
- }
-
-
- try {
- log.verbose('Trying mbdb manifest...')
- let item = await this.getMBDBFileManifest(this)
- return resolve(item)
- } catch (e) {
- log.verbose('Trying mbdb manifest...[failed]', e)
- }
-
- reject(new Error('Could not find a manifest.'))
- })
- }
-
-
- openDatabase (fileID, isAbsoulte) {
- return new Promise((resolve, reject) => {
- try {
-
- let file = this.getFileName(fileID, isAbsoulte)
-
- let db = new sqlite3.Database(file, sqlite3.OPEN_READONLY, (err) => {
- if (err) { return reject(err) }
- if (db != null) {
- resolve(db)
- } else {
- reject(new Error('did not get a database instance.'))
- }
- })
- } catch (e) {
- return reject(e)
- }
- })
- }
- }
- module.exports = Backup
|