3 # Copyright (C) 2017, Michael Poehn <michael.poehn@fsfe.org>
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU Affero General Public License for more details.
15 # You should have received a copy of the GNU Affero General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18 from argparse import ArgumentParser
28 from .exception import FDroidException
31 def extract_signature(apkpath):
33 if not os.path.exists(apkpath):
34 raise FDroidException("file APK does not exists '{}'".format(apkpath))
35 if not common.verify_apk_signature(apkpath):
36 raise FDroidException("no valid signature in '{}'".format(apkpath))
37 logging.debug('signature okay: %s', apkpath)
39 appid, vercode, _ = common.get_apk_id_aapt(apkpath)
40 sigdir = common.metadata_get_sigdir(appid, vercode)
41 if not os.path.exists(sigdir):
43 common.apk_extract_signatures(apkpath, sigdir)
48 def extract(config, options):
50 # Create tmp dir if missing...
52 if not os.path.exists(tmp_dir):
55 if not options.APK or len(options.APK) <= 0:
56 logging.critical(_('no APK supplied'))
59 # iterate over supplied APKs downlaod and extract them...
60 httpre = re.compile('https?:\/\/')
61 for apk in options.APK:
63 if os.path.isfile(apk):
64 sigdir = extract_signature(apk)
65 logging.info(_('fetched signatures for %s -> %s'), apk, sigdir)
66 elif httpre.match(apk):
67 if apk.startswith('https') or options.no_check_https:
69 tmp_apk = os.path.join(tmp_dir, 'signed.apk')
70 net.download_file(apk, tmp_apk)
71 sigdir = extract_signature(tmp_apk)
72 logging.info(_('fetched signatures for %s -> %s'), apk, sigdir)
74 if tmp_apk and os.path.exists(tmp_apk):
77 logging.warn(_('refuse downloading via insecure http connection (use https or specify --no-https-check): %s'), apk)
78 except FDroidException as e:
79 logging.warning(_("failed fetching signatures for '%s': %s"), apk, e)
81 logging.debug(e.detail)
86 global config, options
88 # Parse command line...
89 parser = ArgumentParser(usage="%(prog)s [options] APK [APK...]")
90 common.setup_global_opts(parser)
91 parser.add_argument("APK", nargs='*',
92 help=_("signed APK, either a file-path or HTTPS URL."))
93 parser.add_argument("--no-check-https", action="store_true", default=False)
94 options = parser.parse_args()
97 config = common.read_config(options)
99 extract(config, options)