forked from DiOS-Analysis/Worker
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathappImporter.py
143 lines (115 loc) · 4.06 KB
/
appImporter.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#!/usr/bin/python
import argparse
import sys
import os
import shutil
import tempfile
import biplist
# most plists reads will fail by using just plistlib
import logging
logging.basicConfig(level=logging.DEBUG)
import zipfile
from backend import Backend
METADATA_FILENAME='iTunesMetadata.plist'
METADATA_KV_MAP = {
'bundleId':'softwareVersionBundleId',
'version':'bundleShortVersionString',
'name':'itemName',
'trackId':'itemId',
'artworkUrl60':'softwareIcon57x57URL',
'artistName':'artistName',
'primaryGenreName':'genre',
'releaseDate':'releaseDate'
}
# + type + accountId
def is_present_at_backend(backend, appData):
version = None
if 'version' in appData:
version = appData['version']
if backend.get_app_bundleId(appData['bundleId'], version=version):
return True
return False
def add_app_to_backend(backend, appData, ipaFilename):
# required: 'bundleId', 'version', 'type', 'name', 'trackId', 'account'
appId = backend.post_app(appData)
if appId:
logging.debug('appInfo for %s succesfully added <%s>', appData['bundleId'], appId)
if backend.post_app_archive(appId, ipaFilename):
logging.info('%s succesfully added <%s>', appData['bundleId'], appId)
else:
logging.error('post appArchive for %s failed <%s>', appData['bundleId'], appId)
else:
logging.error('post appInfo for %s failed <%s>', appData['bundleId'], appId)
return appId
def accountId_from_appleId(backend, appleId):
accounts = backend.get_accounts()
for acc,accDict in accounts.iteritems():
if accDict['appleId'] == appleId:
return accDict['uniqueIdentifier']
#
# setip argparser
parser = argparse.ArgumentParser(description='Search for apps within the given folder and add it to the backend.')
parser.add_argument('-a','--app-folder', default='~/Music/iTunes/iTunes Media/Mobile Applications/', help='The folder containing the apps to import.')
parser.add_argument('-b','--backend', required=True, help='the backend url.')
args = parser.parse_args()
logging.debug(args)
# setup
backend = Backend(args.backend)
path = os.path.expanduser(unicode(args.app_folder))
if not os.path.exists(path):
logging.error('Path not found: %s', path)
sys.exit(1)
for filename in os.listdir(path):
logging.info('processing %s', filename)
filepath = "%s/%s" % (path, filename)
if not zipfile.is_zipfile(filepath):
logging.warning('%s is not a zipfile! - skipping', filename)
continue
appData = {
'type':'AppStoreApp'
}
with zipfile.ZipFile(filepath, 'r') as appachive:
if not METADATA_FILENAME in appachive.namelist():
logging.warning('%s has no %s file' % (filename, METADATA_FILENAME))
continue
metadatafile = appachive.open(METADATA_FILENAME)
# create a copy of the metadatafile
## biplist needs seek() - which requieres a real file
f = tempfile.TemporaryFile()
shutil.copyfileobj(metadatafile, f)
#
metadatafile.close()
plist = {}
try:
plist = biplist.readPlist(f)
except (biplist.InvalidPlistException, biplist.NotBinaryPlistException), e:
print "Not a plist:", e
logging.error('Reading plist failed for %s - skipping', filename)
continue
finally:
f.close()
for k,v in METADATA_KV_MAP.iteritems():
if v in plist:
appData[k] = plist[v]
# read old account format too
if 'appleId' in plist:
appData['account'] = accountId_from_appleId(backend, plist['appleId'])
else:
if 'com.apple.iTunesStore.downloadInfo' in plist:
dlInfo = plist['com.apple.iTunesStore.downloadInfo']
if 'accountInfo' in dlInfo:
accInfo = dlInfo['accountInfo']
if 'DSPersonID' in accInfo:
appData['account'] = accInfo['DSPersonID']
# check verison
if not 'version' in appData and 'bundleVersion' in plist:
appData['version'] = plist['bundleVersion']
if not 'version' in appData and 'releaseDate' in plist:
appData['version'] = plist['releaseDate']
# add if not already present
if not is_present_at_backend(backend, appData):
logging.info('aading app to backend: %s', appData['bundleId'])
if add_app_to_backend(backend, appData, filepath):
print '\n### DONE: %s\n' % appData['bundleId']
else:
print '\n### FAILED: %s\n' % appData['bundleId']