Skip to content

Commit 7a443df

Browse files
author
Ali
committed
Temp
1 parent 99c8a72 commit 7a443df

19 files changed

+829
-317
lines changed
+226
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
import json
2+
import os
3+
import sys
4+
import shutil
5+
import tempfile
6+
import plistlib
7+
8+
from BuildEnvironment import run_executable_with_output
9+
10+
class BuildConfiguration:
11+
def __init__(self,
12+
bundle_id,
13+
api_id,
14+
api_hash,
15+
team_id,
16+
app_center_id,
17+
is_internal_build,
18+
is_appstore_build,
19+
appstore_id,
20+
app_specific_url_scheme,
21+
premium_iap_product_id,
22+
enable_siri,
23+
enable_icloud
24+
):
25+
self.bundle_id = bundle_id
26+
self.api_id = api_id
27+
self.api_hash = api_hash
28+
self.team_id = team_id
29+
self.app_center_id = app_center_id
30+
self.is_internal_build = is_internal_build
31+
self.is_appstore_build = is_appstore_build
32+
self.appstore_id = appstore_id
33+
self.app_specific_url_scheme = app_specific_url_scheme
34+
self.premium_iap_product_id = premium_iap_product_id
35+
self.enable_siri = enable_siri
36+
self.enable_icloud = enable_icloud
37+
38+
def write_to_variables_file(self, aps_environment, path):
39+
string = ''
40+
string += 'telegram_bundle_id = "{}"\n'.format(self.bundle_id)
41+
string += 'telegram_api_id = "{}"\n'.format(self.api_id)
42+
string += 'telegram_api_hash = "{}"\n'.format(self.api_hash)
43+
string += 'telegram_team_id = "{}"\n'.format(self.team_id)
44+
string += 'telegram_app_center_id = "{}"\n'.format(self.app_center_id)
45+
string += 'telegram_is_internal_build = "{}"\n'.format(self.is_internal_build)
46+
string += 'telegram_is_appstore_build = "{}"\n'.format(self.is_appstore_build)
47+
string += 'telegram_appstore_id = "{}"\n'.format(self.appstore_id)
48+
string += 'telegram_app_specific_url_scheme = "{}"\n'.format(self.app_specific_url_scheme)
49+
string += 'telegram_premium_iap_product_id = "{}"\n'.format(self.premium_iap_product_id)
50+
string += 'telegram_aps_environment = "{}"\n'.format(aps_environment)
51+
string += 'telegram_enable_siri = {}\n'.format(self.enable_siri)
52+
string += 'telegram_enable_icloud = {}\n'.format(self.enable_icloud)
53+
string += 'telegram_enable_watch = True\n'
54+
55+
if os.path.exists(path):
56+
os.remove(path)
57+
with open(path, 'w+') as file:
58+
file.write(string)
59+
60+
61+
def build_configuration_from_json(path):
62+
if not os.path.exists(path):
63+
print('Could not load build configuration from {}'.format(path))
64+
sys.exit(1)
65+
with open(path) as file:
66+
configuration_dict = json.load(file)
67+
required_keys = [
68+
'bundle_id',
69+
'api_id',
70+
'api_hash',
71+
'team_id',
72+
'app_center_id',
73+
'is_internal_build',
74+
'is_appstore_build',
75+
'appstore_id',
76+
'app_specific_url_scheme',
77+
'premium_iap_product_id',
78+
'enable_siri',
79+
'enable_icloud'
80+
]
81+
for key in required_keys:
82+
if key not in configuration_dict:
83+
print('Configuration at {} does not contain {}'.format(path, key))
84+
return BuildConfiguration(
85+
bundle_id=configuration_dict['bundle_id'],
86+
api_id=configuration_dict['api_id'],
87+
api_hash=configuration_dict['api_hash'],
88+
team_id=configuration_dict['team_id'],
89+
app_center_id=configuration_dict['app_center_id'],
90+
is_internal_build=configuration_dict['is_internal_build'],
91+
is_appstore_build=configuration_dict['is_appstore_build'],
92+
appstore_id=configuration_dict['appstore_id'],
93+
app_specific_url_scheme=configuration_dict['app_specific_url_scheme'],
94+
premium_iap_product_id=configuration_dict['premium_iap_product_id'],
95+
enable_siri=configuration_dict['enable_siri'],
96+
enable_icloud=configuration_dict['enable_icloud']
97+
)
98+
99+
100+
def decrypt_codesigning_directory_recursively(source_base_path, destination_base_path, password):
101+
for file_name in os.listdir(source_base_path):
102+
source_path = source_base_path + '/' + file_name
103+
destination_path = destination_base_path + '/' + file_name
104+
if os.path.isfile(source_path):
105+
os.system('openssl aes-256-cbc -md md5 -k "{password}" -in "{source_path}" -out "{destination_path}" -a -d'.format(
106+
password=password,
107+
source_path=source_path,
108+
destination_path=destination_path
109+
))
110+
elif os.path.isdir(source_path):
111+
os.makedirs(destination_path, exist_ok=True)
112+
decrypt_codesigning_directory_recursively(source_path, destination_path, password)
113+
114+
115+
def load_provisioning_profiles_from_git(working_dir, repo_url, branch, password, always_fetch):
116+
if not os.path.exists(working_dir):
117+
os.makedirs(working_dir, exist_ok=True)
118+
119+
encrypted_working_dir = working_dir + '/encrypted'
120+
if os.path.exists(encrypted_working_dir):
121+
if always_fetch:
122+
original_working_dir = os.getcwd()
123+
os.chdir(encrypted_working_dir)
124+
os.system('git fetch')
125+
os.system('git checkout "{branch}"'.format(branch=branch))
126+
os.system('git pull')
127+
os.chdir(original_working_dir)
128+
else:
129+
os.makedirs(encrypted_working_dir, exist_ok=True)
130+
original_working_dir = os.getcwd()
131+
os.chdir(working_dir)
132+
os.system('git clone {repo_url} -b "{branch}" "{target_path}"'.format(
133+
repo_url=repo_url,
134+
branch=branch,
135+
target_path=encrypted_working_dir
136+
))
137+
os.chdir(original_working_dir)
138+
139+
decrypted_working_dir = working_dir + '/decrypted'
140+
if os.path.exists(decrypted_working_dir):
141+
shutil.rmtree(decrypted_working_dir)
142+
os.makedirs(decrypted_working_dir, exist_ok=True)
143+
144+
decrypt_codesigning_directory_recursively(encrypted_working_dir + '/profiles', decrypted_working_dir + '/profiles', password)
145+
decrypt_codesigning_directory_recursively(encrypted_working_dir + '/certs', decrypted_working_dir + '/certs', password)
146+
147+
148+
def copy_profiles_from_directory(source_path, destination_path, team_id, bundle_id):
149+
profile_name_mapping = {
150+
'.SiriIntents': 'Intents',
151+
'.NotificationContent': 'NotificationContent',
152+
'.NotificationService': 'NotificationService',
153+
'.Share': 'Share',
154+
'': 'Telegram',
155+
'.watchkitapp': 'WatchApp',
156+
'.watchkitapp.watchkitextension': 'WatchExtension',
157+
'.Widget': 'Widget',
158+
'.BroadcastUpload': 'BroadcastUpload'
159+
}
160+
161+
for file_name in os.listdir(source_path):
162+
file_path = source_path + '/' + file_name
163+
if os.path.isfile(file_path):
164+
if not file_path.endswith('.mobileprovision'):
165+
continue
166+
167+
profile_data = run_executable_with_output('openssl', arguments=[
168+
'smime',
169+
'-inform',
170+
'der',
171+
'-verify',
172+
'-noverify',
173+
'-in',
174+
file_path
175+
], decode=False, stderr_to_stdout=False, check_result=True)
176+
177+
profile_dict = plistlib.loads(profile_data)
178+
profile_name = profile_dict['Entitlements']['application-identifier']
179+
180+
if profile_name.startswith(team_id + '.' + bundle_id):
181+
profile_base_name = profile_name[len(team_id + '.' + bundle_id):]
182+
if profile_base_name in profile_name_mapping:
183+
shutil.copyfile(file_path, destination_path + '/' + profile_name_mapping[profile_base_name] + '.mobileprovision')
184+
else:
185+
print('Warning: skipping provisioning profile at {} with bundle_id {} (base_name {})'.format(file_path, profile_name, profile_base_name))
186+
187+
188+
class ProvisioningProfileSource:
189+
def __init__(self):
190+
pass
191+
192+
def copy_profiles_to_destination(self, destination_path):
193+
raise Exception('Not implemented')
194+
195+
196+
class GitProvisioningProfileSource(ProvisioningProfileSource):
197+
def __init__(self, working_dir, repo_url, team_id, bundle_id, profile_type, password, always_fetch):
198+
self.working_dir = working_dir
199+
self.repo_url = repo_url
200+
self.team_id = team_id
201+
self.bundle_id = bundle_id
202+
self.profile_type = profile_type
203+
self.password = password
204+
self.always_fetch = always_fetch
205+
206+
def copy_profiles_to_destination(self, destination_path):
207+
load_provisioning_profiles_from_git(working_dir=self.working_dir, repo_url=self.repo_url, branch=self.team_id, password=self.password, always_fetch=self.always_fetch)
208+
copy_profiles_from_directory(source_path=self.working_dir + '/decrypted/profiles/{}'.format(self.profile_type), destination_path=destination_path, team_id=self.team_id, bundle_id=self.bundle_id)
209+
210+
211+
class DirectoryProvisioningProfileSource(ProvisioningProfileSource):
212+
def __init__(self, directory_path, team_id, bundle_id):
213+
self.directory_path = directory_path
214+
self.team_id = team_id
215+
self.bundle_id = bundle_id
216+
217+
def copy_profiles_to_destination(self, destination_path):
218+
profiles_path = self.directory_path
219+
if not os.path.exists(profiles_path):
220+
print('{} does not exist'.format(profiles_path))
221+
sys.exit(1)
222+
copy_profiles_from_directory(source_path=profiles_path, destination_path=destination_path, team_id=self.team_id, bundle_id=self.bundle_id)
223+
224+
225+
def generate_configuration_repository(path, profile_source):
226+
pass

‎build-system/Make/BuildEnvironment.py

+23-5
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import os
33
import platform
44
import subprocess
5-
5+
import sys
66

77
def is_apple_silicon():
88
if platform.processor() == 'arm':
@@ -28,20 +28,38 @@ def is_executable(fpath):
2828
return None
2929

3030

31-
def run_executable_with_output(path, arguments):
31+
def run_executable_with_output(path, arguments, decode=True, input=None, stderr_to_stdout=True, check_result=False):
3232
executable_path = resolve_executable(path)
3333
if executable_path is None:
3434
raise Exception('Could not resolve {} to a valid executable file'.format(path))
3535

36+
stderr_assignment = subprocess.DEVNULL
37+
if stderr_to_stdout:
38+
stderr_assignment = subprocess.STDOUT
39+
3640
process = subprocess.Popen(
3741
[executable_path] + arguments,
3842
stdout=subprocess.PIPE,
39-
stderr=subprocess.STDOUT,
43+
stderr=stderr_assignment,
44+
stdin=subprocess.PIPE,
4045
env=get_clean_env()
4146
)
42-
output_data, _ = process.communicate()
47+
if input is not None:
48+
output_data, _ = process.communicate(input=input)
49+
else:
50+
output_data, _ = process.communicate()
51+
4352
output_string = output_data.decode('utf-8')
44-
return output_string
53+
54+
if check_result:
55+
if process.returncode != 0:
56+
print('Command {} {} finished with non-zero return code and output:\n{}'.format(executable_path, arguments, output_string))
57+
sys.exit(1)
58+
59+
if decode:
60+
return output_string
61+
else:
62+
return output_data
4563

4664

4765
def call_executable(arguments, use_clean_environment=True, check_result=True):
+95
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import os
2+
import sys
3+
import argparse
4+
5+
from BuildEnvironment import run_executable_with_output
6+
7+
def import_certificates(certificatesPath):
8+
if not os.path.exists(certificatesPath):
9+
print('{} does not exist'.format(certificatesPath))
10+
sys.exit(1)
11+
12+
keychain_name = 'temp.keychain'
13+
keychain_password = 'secret'
14+
15+
existing_keychains = run_executable_with_output('security', arguments=['list-keychains'], check_result=True)
16+
if keychain_name in existing_keychains:
17+
run_executable_with_output('security', arguments=['delete-keychain'], check_result=True)
18+
19+
run_executable_with_output('security', arguments=[
20+
'create-keychain',
21+
'-p',
22+
keychain_password,
23+
keychain_name
24+
], check_result=True)
25+
26+
existing_keychains = run_executable_with_output('security', arguments=['list-keychains', '-d', 'user'])
27+
existing_keychains.replace('"', '')
28+
29+
run_executable_with_output('security', arguments=[
30+
'list-keychains',
31+
'-d',
32+
'user',
33+
'-s',
34+
keychain_name,
35+
existing_keychains
36+
], check_result=True)
37+
38+
run_executable_with_output('security', arguments=['set-keychain-settings', keychain_name])
39+
run_executable_with_output('security', arguments=['unlock-keychain', '-p', keychain_password, keychain_name])
40+
41+
for file_name in os.listdir(certificatesPath):
42+
file_path = certificatesPath + '/' + file_name
43+
if file_path.endwith('.p12') or file_path.endwith('.cer'):
44+
run_executable_with_output('security', arguments=[
45+
'import',
46+
file_path,
47+
'-k',
48+
keychain_name,
49+
'-P',
50+
'',
51+
'-T',
52+
'/usr/bin/codesign',
53+
'-T',
54+
'/usr/bin/security'
55+
], check_result=True)
56+
57+
run_executable_with_output('security', arguments=[
58+
'import',
59+
'build-system/AppleWWDRCAG3.cer',
60+
'-k',
61+
keychain_name,
62+
'-P',
63+
'',
64+
'-T',
65+
'/usr/bin/codesign',
66+
'-T',
67+
'/usr/bin/security'
68+
], check_result=True)
69+
70+
run_executable_with_output('security', arguments=[
71+
'set-key-partition-list',
72+
'-S',
73+
'apple-tool:,apple:',
74+
'-k',
75+
keychain_password,
76+
keychain_name
77+
], check_result=True)
78+
79+
80+
if __name__ == '__main__':
81+
parser = argparse.ArgumentParser(prog='build')
82+
83+
parser.add_argument(
84+
'--path',
85+
required=True,
86+
help='Path to certificates.'
87+
)
88+
89+
if len(sys.argv) < 2:
90+
parser.print_help()
91+
sys.exit(1)
92+
93+
args = parser.parse_args()
94+
95+
import_certificates(args.path)

0 commit comments

Comments
 (0)