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
27 from .exception import FDroidException
30 def extract_signature(apkpath):
32 if not os.path.exists(apkpath):
33 raise FDroidException("file APK does not exists '{}'".format(apkpath))
34 if not common.verify_apk_signature(apkpath):
35 raise FDroidException("no valid signature in '{}'".format(apkpath))
36 logging.debug('signature okay: %s', apkpath)
38 appid, vercode, _ = common.get_apk_id_aapt(apkpath)
39 sigdir = common.metadata_get_sigdir(appid, vercode)
40 if not os.path.exists(sigdir):
42 common.apk_extract_signatures(apkpath, sigdir)
47 def extract(config, options):
49 # Create tmp dir if missing...
51 if not os.path.exists(tmp_dir):
54 if not options.APK or len(options.APK) <= 0:
55 logging.critical('no APK supplied')
58 # iterate over supplied APKs downlaod and extract them...
59 httpre = re.compile('https?:\/\/')
60 for apk in options.APK:
62 if os.path.isfile(apk):
63 sigdir = extract_signature(apk)
64 logging.info('fetched singatures for %s -> %s', apk, sigdir)
65 elif httpre.match(apk):
66 if apk.startswith('https') or options.no_check_https:
68 tmp_apk = os.path.join(tmp_dir, 'signed.apk')
69 net.download_file(apk, tmp_apk)
70 sigdir = extract_signature(tmp_apk)
71 logging.info('fetched singatures for %s -> %s', apk, sigdir)
73 if tmp_apk and os.path.exists(tmp_apk):
76 logging.warn('refuse downloading via insecure http connection (use https or specify --no-https-check): %s', apk)
77 except FDroidException as e:
78 logging.warning("failed fetching signatures for '%s': %s", apk, e)
80 logging.debug(e.detail)
85 global config, options
87 # Parse command line...
88 parser = ArgumentParser(usage="%(prog)s [options] APK [APK...]")
89 common.setup_global_opts(parser)
90 parser.add_argument("APK", nargs='*',
91 help="signed APK, either a file-path or Https-URL are fine here.")
92 parser.add_argument("--no-check-https", action="store_true", default=False)
93 options = parser.parse_args()
96 config = common.read_config(options)
98 extract(config, options)