1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3# Copyright (c) 2023 Huawei Device Co., Ltd.
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#     http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16
17import subprocess
18import argparse
19import os
20import sys
21
22from util import build_utils
23from util import file_utils
24
25
26def parse_args(args):
27    parser = argparse.ArgumentParser()
28    build_utils.add_depfile_option(parser)
29
30    parser.add_argument('--keyPwd', help='')
31    parser.add_argument('--sign-algo', help='')
32    parser.add_argument('--keyalias', help='')
33    parser.add_argument('--keystoreFile', help='')
34    parser.add_argument('--keystorePwd', help='')
35    parser.add_argument('--profileFile', help='')
36    parser.add_argument('--hapsigner', help='')
37    parser.add_argument('--unsigned-hap-path-list', help='')
38    parser.add_argument('--compatible_version', help='compatible_version')
39    parser.add_argument('--hap-out-dir', help='')
40    parser.add_argument('--inFile', help='')
41    parser.add_argument('--outFile', help='')
42    parser.add_argument('--profileSigned', help='')
43    parser.add_argument('--inForm', help='')
44    parser.add_argument('--certificate-file', help='')
45    parser.add_argument('--hap-name', help='')
46    parser.add_argument('--hap-list', help='')
47    options = parser.parse_args(args)
48    return options
49
50
51def sign_app(options, unsigned_hap_path: str, signed_hap_path: str):
52    cmd = ['java', '-jar', options.hapsigner, 'sign-app']
53    cmd.extend(['-mode', 'localsign'])
54    cmd.extend(['-signAlg', options.sign_algo])
55    cmd.extend(['-keyAlias', options.keyalias])
56    cmd.extend(['-inFile', unsigned_hap_path])
57    cmd.extend(['-outFile', signed_hap_path])
58    cmd.extend(['-profileFile', options.profileFile])
59    cmd.extend(['-keystoreFile', options.keystoreFile])
60    cmd.extend(['-keystorePwd', options.keystorePwd])
61    cmd.extend(['-keyPwd', options.keyPwd])
62    cmd.extend(['-appCertFile', options.certificate_file])
63    cmd.extend(['-profileSigned', (options.profileSigned or '1')])
64    cmd.extend(['-inForm', (options.inForm or 'zip')])
65    child = subprocess.Popen(cmd,
66                             stdout=subprocess.PIPE,
67                             stderr=subprocess.PIPE)
68    stdout, stderr = child.communicate()
69    if child.returncode:
70        print(stdout.decode(), stderr.decode())
71        raise Exception("Failed to sign hap")
72
73
74def main(args):
75    options = parse_args(args)
76    if not options.hap_out_dir:
77        sign_app(options, options.inFile, options.outFile)
78    else:
79        if not os.path.exists(options.hap_out_dir):
80            os.makedirs(options.hap_out_dir, exist_ok=True)
81        unsigned_hap_path_list = file_utils.read_json_file(options.unsigned_hap_path_list)
82        signed_hap_names = {}
83        if os.path.isfile(options.hap_list):
84            hap_list = file_utils.read_json_file(options.hap_list)
85            signed_hap_names['do_filter'] = hap_list.get('do_filter')
86            for unsigned_to_signed in hap_list.get('hap_list'):
87                names = unsigned_to_signed.split(':')
88                if len(names) == 2:
89                    signed_hap_names[f'{names[0]}.hsp'] = f'{names[1]}.hsp'
90                    signed_hap_names[f'{names[0]}.hap'] = f'{names[1]}.hap'
91                else:
92                    raise ValueError(f'Value hap_list {hap_list} not compliant with format')
93        for unsigned_hap_path in unsigned_hap_path_list.get('unsigned_hap_path_list'):
94            signed_hap_path = unsigned_hap_path.replace('unsigned', 'signed')
95            output_hap_name = f'{options.hap_name}-{os.path.basename(signed_hap_path)}'
96            unsigned_hap_name = f'{options.hap_name}-{os.path.basename(unsigned_hap_path)}'
97            if len(unsigned_hap_path_list.get('unsigned_hap_path_list')) == 1 and options.hap_name:
98                if unsigned_hap_path_list.get('unsigned_hap_path_list')[0].endswith('.hsp'):
99                    output_hap_name = f'{options.hap_name}.hsp'
100                    unsigned_hap_name = output_hap_name
101                else:
102                    output_hap_name = f'{options.hap_name}.hap'
103                    unsigned_hap_name = output_hap_name
104            if signed_hap_names.get('do_filter'):
105                if signed_hap_names.get(unsigned_hap_name):
106                    output_hap_name = signed_hap_names.get(unsigned_hap_name)
107            output_hap = os.path.join(options.hap_out_dir, output_hap_name)
108            sign_app(options, unsigned_hap_path, output_hap)
109
110
111if __name__ == '__main__':
112    sys.exit(main(sys.argv[1:]))
113