gabefromsimplebit commited on
Commit
4dcf967
·
verified ·
1 Parent(s): 30f1d28

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +45 -41
app.py CHANGED
@@ -16,6 +16,9 @@ CORS(app)
16
  BASE_URL = "https://gabefromsimplebit-simplebit-signer.hf.space"
17
 
18
 
 
 
 
19
  @app.route("/")
20
  def home():
21
  return jsonify({
@@ -25,22 +28,19 @@ def home():
25
 
26
 
27
  # -------------------------------------------------
28
- # Extract main bundle ID
29
  # -------------------------------------------------
30
  def get_actual_bundle_id(ipa_path):
 
31
  try:
32
  with zipfile.ZipFile(ipa_path, "r") as ipa:
33
 
34
  for name in ipa.namelist():
35
 
36
- if (
37
- name.startswith("Payload/")
38
- and name.count("/") == 2
39
- and name.endswith(".app/Info.plist")
40
- ):
41
  with ipa.open(name) as f:
42
  plist_data = plistlib.load(f)
43
- return plist_data.get("CFBundleIdentifier")
44
 
45
  except Exception as e:
46
  print("Bundle error:", e)
@@ -49,22 +49,21 @@ def get_actual_bundle_id(ipa_path):
49
 
50
 
51
  # -------------------------------------------------
52
- # Save / load bundle ID
53
  # -------------------------------------------------
54
- def save_bundle_id(job_dir, bundle_id):
55
- with open(job_dir / "bundle_id.txt", "w") as f:
56
- f.write(bundle_id)
57
 
 
58
 
59
- def load_bundle_id(job_dir):
60
- try:
61
- return (job_dir / "bundle_id.txt").read_text().strip()
62
- except:
63
- return "com.simplebit.dynamic"
64
 
65
 
66
  # -------------------------------------------------
67
- # SIGN IPA
68
  # -------------------------------------------------
69
  @app.route("/sign", methods=["POST"])
70
  def sign():
@@ -103,33 +102,27 @@ def sign():
103
  bundle_id = get_actual_bundle_id(ipa_path) or "com.simplebit.dynamic"
104
 
105
  # -------------------------------------------------
106
- # Extract IPA manually
107
  # -------------------------------------------------
108
  temp_dir = tempfile.mkdtemp()
109
 
110
  with zipfile.ZipFile(ipa_path, "r") as zip_ref:
111
  zip_ref.extractall(temp_dir)
112
 
113
- payload_path = Path(temp_dir) / "Payload"
114
-
115
- if not payload_path.exists():
116
- shutil.rmtree(temp_dir)
117
- return jsonify({"error": "Payload missing"}), 500
118
 
119
- app_folder = None
120
- for item in payload_path.iterdir():
121
- if item.suffix == ".app":
122
- app_folder = item
123
- break
124
 
125
- if not app_folder:
126
  shutil.rmtree(temp_dir)
127
- return jsonify({"error": ".app not found"}), 500
 
 
128
 
129
- print("APP:", app_folder)
130
 
131
  # -------------------------------------------------
132
- # Sign extracted app
133
  # -------------------------------------------------
134
  command = [
135
  zsign_path,
@@ -137,7 +130,7 @@ def sign():
137
  "-k", str(p12_path),
138
  "-p", password,
139
  "-m", str(prov_path),
140
- str(app_folder)
141
  ]
142
 
143
  result = subprocess.run(
@@ -158,7 +151,7 @@ def sign():
158
  }), 500
159
 
160
  # -------------------------------------------------
161
- # Rebuild IPA manually
162
  # -------------------------------------------------
163
  shutil.make_archive(
164
  str(job_dir / "signed"),
@@ -170,10 +163,10 @@ def sign():
170
 
171
  shutil.rmtree(temp_dir)
172
 
173
- save_bundle_id(job_dir, bundle_id)
 
174
 
175
  plist_url = f"{BASE_URL}/plist/{job_id}"
176
-
177
  install_url = f"itms-services://?action=download-manifest&url={plist_url}"
178
 
179
  return redirect(install_url)
@@ -190,13 +183,17 @@ def plist(job_id):
190
 
191
  job_dir = Path(job_id)
192
 
193
- bundle_id = load_bundle_id(job_dir)
 
 
 
194
 
195
  ipa_url = f"{BASE_URL}/download/{job_id}"
196
 
197
  plist_content = f"""<?xml version="1.0" encoding="UTF-8"?>
198
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
199
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 
200
  <plist version="1.0">
201
  <dict>
202
  <key>items</key>
@@ -225,17 +222,17 @@ def plist(job_id):
225
  </dict>
226
  </array>
227
  </dict>
228
- </plist>"""
 
229
 
230
  plist_path = job_dir / "manifest.plist"
231
-
232
  plist_path.write_text(plist_content)
233
 
234
  return send_file(plist_path, mimetype="application/xml")
235
 
236
 
237
  # -------------------------------------------------
238
- # DOWNLOAD IPA (IMPORTANT FOR iOS OTA)
239
  # -------------------------------------------------
240
  @app.route("/download/<job_id>")
241
  def download(job_id):
@@ -245,7 +242,11 @@ def download(job_id):
245
  if not ipa_path.exists():
246
  return jsonify({"error": "IPA not found"}), 404
247
 
248
- response = send_file(ipa_path, mimetype="application/octet-stream")
 
 
 
 
249
  response.headers["Content-Disposition"] = "inline; filename=signed.ipa"
250
  return response
251
 
@@ -261,5 +262,8 @@ def health():
261
  })
262
 
263
 
 
 
 
264
  if __name__ == "__main__":
265
  app.run(host="0.0.0.0", port=7860, debug=True)
 
16
  BASE_URL = "https://gabefromsimplebit-simplebit-signer.hf.space"
17
 
18
 
19
+ # -------------------------------------------------
20
+ # HOME
21
+ # -------------------------------------------------
22
  @app.route("/")
23
  def home():
24
  return jsonify({
 
28
 
29
 
30
  # -------------------------------------------------
31
+ # GET BUNDLE ID (safe)
32
  # -------------------------------------------------
33
  def get_actual_bundle_id(ipa_path):
34
+
35
  try:
36
  with zipfile.ZipFile(ipa_path, "r") as ipa:
37
 
38
  for name in ipa.namelist():
39
 
40
+ if name.endswith("Info.plist") and ".app/" in name:
 
 
 
 
41
  with ipa.open(name) as f:
42
  plist_data = plistlib.load(f)
43
+ return plist_data.get("CFBundleIdentifier")
44
 
45
  except Exception as e:
46
  print("Bundle error:", e)
 
49
 
50
 
51
  # -------------------------------------------------
52
+ # FIND APP BUNDLE ANYWHERE (FIXED)
53
  # -------------------------------------------------
54
+ def find_app_bundle(temp_dir):
 
 
55
 
56
+ temp_dir = Path(temp_dir)
57
 
58
+ for item in temp_dir.rglob("*.app"):
59
+ if item.is_dir():
60
+ return item
61
+
62
+ return None
63
 
64
 
65
  # -------------------------------------------------
66
+ # SIGN ROUTE
67
  # -------------------------------------------------
68
  @app.route("/sign", methods=["POST"])
69
  def sign():
 
102
  bundle_id = get_actual_bundle_id(ipa_path) or "com.simplebit.dynamic"
103
 
104
  # -------------------------------------------------
105
+ # Extract IPA
106
  # -------------------------------------------------
107
  temp_dir = tempfile.mkdtemp()
108
 
109
  with zipfile.ZipFile(ipa_path, "r") as zip_ref:
110
  zip_ref.extractall(temp_dir)
111
 
112
+ print("EXTRACTED FILES:", list(Path(temp_dir).rglob("*")))
 
 
 
 
113
 
114
+ app_bundle = find_app_bundle(temp_dir)
 
 
 
 
115
 
116
+ if not app_bundle:
117
  shutil.rmtree(temp_dir)
118
+ return jsonify({
119
+ "error": "No .app bundle found in IPA"
120
+ }), 500
121
 
122
+ print("FOUND APP:", app_bundle)
123
 
124
  # -------------------------------------------------
125
+ # SIGN APP
126
  # -------------------------------------------------
127
  command = [
128
  zsign_path,
 
130
  "-k", str(p12_path),
131
  "-p", password,
132
  "-m", str(prov_path),
133
+ str(app_bundle)
134
  ]
135
 
136
  result = subprocess.run(
 
151
  }), 500
152
 
153
  # -------------------------------------------------
154
+ # REPACK IPA
155
  # -------------------------------------------------
156
  shutil.make_archive(
157
  str(job_dir / "signed"),
 
163
 
164
  shutil.rmtree(temp_dir)
165
 
166
+ # Save bundle ID
167
+ (job_dir / "bundle_id.txt").write_text(bundle_id)
168
 
169
  plist_url = f"{BASE_URL}/plist/{job_id}"
 
170
  install_url = f"itms-services://?action=download-manifest&url={plist_url}"
171
 
172
  return redirect(install_url)
 
183
 
184
  job_dir = Path(job_id)
185
 
186
+ bundle_id = "com.simplebit.dynamic"
187
+
188
+ if (job_dir / "bundle_id.txt").exists():
189
+ bundle_id = (job_dir / "bundle_id.txt").read_text().strip()
190
 
191
  ipa_url = f"{BASE_URL}/download/{job_id}"
192
 
193
  plist_content = f"""<?xml version="1.0" encoding="UTF-8"?>
194
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
195
  "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
196
+
197
  <plist version="1.0">
198
  <dict>
199
  <key>items</key>
 
222
  </dict>
223
  </array>
224
  </dict>
225
+ </plist>
226
+ """
227
 
228
  plist_path = job_dir / "manifest.plist"
 
229
  plist_path.write_text(plist_content)
230
 
231
  return send_file(plist_path, mimetype="application/xml")
232
 
233
 
234
  # -------------------------------------------------
235
+ # DOWNLOAD IPA (iOS SAFE)
236
  # -------------------------------------------------
237
  @app.route("/download/<job_id>")
238
  def download(job_id):
 
242
  if not ipa_path.exists():
243
  return jsonify({"error": "IPA not found"}), 404
244
 
245
+ response = send_file(
246
+ ipa_path,
247
+ mimetype="application/octet-stream"
248
+ )
249
+
250
  response.headers["Content-Disposition"] = "inline; filename=signed.ipa"
251
  return response
252
 
 
262
  })
263
 
264
 
265
+ # -------------------------------------------------
266
+ # RUN
267
+ # -------------------------------------------------
268
  if __name__ == "__main__":
269
  app.run(host="0.0.0.0", port=7860, debug=True)