|
@@ -25,6 +25,7 @@ const databases = {
|
|
|
Notes: fileHash('Library/Notes/notes.sqlite'),
|
|
|
Notes2: fileHash('NoteStore.sqlite', 'AppDomainGroup-group.com.apple.notes'),
|
|
|
AddressBook: fileHash('Library/AddressBook/AddressBook.sqlitedb'),
|
|
|
+ AddressBookImages: fileHash('Library/AddressBook/AddressBookImages.sqlitedb'),
|
|
|
'Cookies.binarycookies': '69b1865768101bacde5b77ccc44445cea9ce1261',
|
|
|
Calls: '2b2b0084a1bc3a5ac8c27afdf14afb42c61a19ca',
|
|
|
Calls2: fileHash('Library/CallHistoryDB/CallHistory.storedata'),
|
|
@@ -593,8 +594,10 @@ class IPhoneBackup {
|
|
|
|
|
|
getAddressBook () {
|
|
|
return new Promise((resolve, reject) => {
|
|
|
- var addressbookdb = this.getDatabase(databases.AddressBook)
|
|
|
+ let addressbookdb = this.getDatabase(databases.AddressBook)
|
|
|
+ const self = this
|
|
|
try {
|
|
|
+ // Query basic Address Book fields
|
|
|
const query = `
|
|
|
select ABPerson.ROWID
|
|
|
, ABPerson.first
|
|
@@ -604,7 +607,8 @@ class IPhoneBackup {
|
|
|
, ABPerson.Department as department
|
|
|
, ABPerson.Birthday as birthday
|
|
|
, ABPerson.JobTitle as jobtitle
|
|
|
-
|
|
|
+ , datetime(ABPerson.CreationDate + 978307200, 'unixepoch') as created_date
|
|
|
+ , datetime(ABPerson.ModificationDate + 978307200, 'unixepoch') as updated_date
|
|
|
, (select value from ABMultiValue where property = 3 and record_id = ABPerson.ROWID and label = (select ROWID from ABMultiValueLabel where value = '_$!<Work>!$_')) as phone_work
|
|
|
, (select value from ABMultiValue where property = 3 and record_id = ABPerson.ROWID and label = (select ROWID from ABMultiValueLabel where value = '_$!<Mobile>!$_')) as phone_mobile
|
|
|
, (select value from ABMultiValue where property = 3 and record_id = ABPerson.ROWID and label = (select ROWID from ABMultiValueLabel where value = '_$!<Home>!$_')) as phone_home
|
|
@@ -613,13 +617,56 @@ class IPhoneBackup {
|
|
|
|
|
|
, (select value from ABMultiValueEntry where parent_id in (select ROWID from ABMultiValue where record_id = ABPerson.ROWID) and key = (select ROWID from ABMultiValueEntryKey where lower(value) = 'street')) as address
|
|
|
, (select value from ABMultiValueEntry where parent_id in (select ROWID from ABMultiValue where record_id = ABPerson.ROWID) and key = (select ROWID from ABMultiValueEntryKey where lower(value) = 'city')) as city
|
|
|
+ , ABPerson.Note as note
|
|
|
from ABPerson
|
|
|
order by ABPerson.ROWID
|
|
|
`
|
|
|
addressbookdb.all(query, async function (err, rows) {
|
|
|
if (err) reject(err)
|
|
|
-
|
|
|
- resolve(rows)
|
|
|
+ const iterateElements = (elements, index, callback) => {
|
|
|
+ if (index === elements.length) { return callback() }
|
|
|
+ // do parse call with element
|
|
|
+ let ele = elements[index]
|
|
|
+ //Query username and profile links for other services (facebook etc)
|
|
|
+ const query = `
|
|
|
+ select (select value from ABMultiValue where property = 22 and record_id = ABPerson.ROWID and label = (select ROWID from ABMultiValueLabel where value = 'PROFILE')) as google_profile
|
|
|
+ , (select value from ABMultiValue where property = 22 and record_id = ABPerson.ROWID and label = (select ROWID from ABMultiValueLabel where value = 'profile')) as google_profile1
|
|
|
+ , (select value from ABMultiValue where property = 4 and record_id = ABPerson.ROWID and label = (select ROWID from ABMultiValueLabel where value = 'iCloud')) as icloud
|
|
|
+
|
|
|
+ , (select value from ABMultiValueEntry where parent_id in (select ROWID from ABMultiValue where record_id = ABPerson.ROWID) and key = (select ROWID from ABMultiValueEntryKey where lower(value) = 'service')) as service
|
|
|
+ , (select value from ABMultiValueEntry where parent_id in (select ROWID from ABMultiValue where record_id = ABPerson.ROWID) and key = (select ROWID from ABMultiValueEntryKey where lower(value) = 'username')) as username
|
|
|
+ , (select value from ABMultiValueEntry where parent_id in (select ROWID from ABMultiValue where record_id = ABPerson.ROWID) and key = (select ROWID from ABMultiValueEntryKey where lower(value) = 'url')) as url
|
|
|
+ from ABPerson
|
|
|
+ where ABPerson.ROWID = ${ele.ROWID}
|
|
|
+ order by ABPerson.ROWID
|
|
|
+ `
|
|
|
+ addressbookdb.all(query, async function (err, rows1) {
|
|
|
+ if (err) reject(err)
|
|
|
+ rows1[0].google_profile = rows1[0].google_profile || rows1[0].google_profile1
|
|
|
+ delete rows1[0].google_profile1
|
|
|
+ ele.services = rows1[0]
|
|
|
+
|
|
|
+ const addressbookimagesdb = self.getDatabase(databases.AddressBookImages)
|
|
|
+ //Query profile picture extraction from /Library/AddressBook/AddressBookImages.sqlitedb
|
|
|
+ const query = `
|
|
|
+ select data
|
|
|
+ from ABFullSizeImage
|
|
|
+ where ABFullSizeImage.record_id = ${ele.ROWID}
|
|
|
+ `
|
|
|
+ addressbookimagesdb.get(query, async function (err, row) {
|
|
|
+ if (err) reject(err)
|
|
|
+ ele.profile_picture = null
|
|
|
+ if (row) {
|
|
|
+ ele.profile_picture = row.data.toString('base64')
|
|
|
+ }
|
|
|
+ iterateElements(elements, index + 1, callback)
|
|
|
+ })
|
|
|
+
|
|
|
+ })
|
|
|
+ }
|
|
|
+ iterateElements(rows, 0, () => {
|
|
|
+ resolve(rows)
|
|
|
+ })
|
|
|
})
|
|
|
} catch (e) {
|
|
|
reject(e)
|