gabefromsimplebit commited on
Commit
11c4812
·
verified ·
1 Parent(s): dc82579

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. app.py +32 -34
app.py CHANGED
@@ -13,33 +13,49 @@ BASE_URL = "https://gabefromsimplebit-simplebit-signer.hf.space"
13
 
14
  @app.route('/')
15
  def home():
16
- return "SimpleBit Engine is Online!"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
17
 
18
  @app.route('/sign', methods=['POST'])
19
  def sign():
20
- # 1. Create a unique folder for this signing job
21
  job_id = str(uuid.uuid4())[:8]
22
  os.makedirs(job_id, exist_ok=True)
23
 
24
- # 2. Get files from the form
25
  ipa = request.files['ipa']
26
  p12 = request.files['p12']
27
  prov = request.files['provision']
28
  password = request.form.get('password', '1234')
29
 
30
- # 3. Define paths
31
  ipa_path = os.path.join(job_id, "app.ipa")
32
  p12_path = os.path.join(job_id, "cert.p12")
33
  prov_path = os.path.join(job_id, "prov.mobileprovision")
34
  out_path = os.path.join(job_id, "signed.ipa")
35
 
36
- # 4. Save uploaded files
37
  ipa.save(ipa_path)
38
  p12.save(p12_path)
39
  prov.save(prov_path)
40
 
41
- # 5. Run zsign command
42
- # -z 0: No compression for instant speed on MacBook Air/HF
 
 
43
  command = [
44
  "zsign",
45
  "-k", p12_path,
@@ -51,47 +67,34 @@ def sign():
51
  ]
52
 
53
  try:
54
- # We capture both stdout and stderr because zsign logs vary
55
  result = subprocess.run(command, capture_output=True, text=True, check=True)
56
- combined_output = result.stdout + result.stderr
57
-
58
- # 6. Improved Regex to prevent the "com.simplebit.dynamic" mismatch in image.png
59
- match = re.search(r"Bundle\s?Id:\s+([a-zA-Z0-9\.-]+)", combined_output, re.IGNORECASE)
60
 
61
- if match:
62
- bundle_id = match.group(1).strip()
63
- else:
64
- # Fallback search for any string matching a standard reverse-DNS bundle ID
65
- fallback_match = re.search(r"([a-zA-Z]{2,}\.[a-zA-Z0-9-]+\.[a-zA-Z0-9.-]+)", combined_output)
66
- bundle_id = fallback_match.group(1) if fallback_match else "com.simplebit.dynamic"
67
 
68
- # Save the confirmed ID to ensure the /plist route uses the right one
69
  with open(os.path.join(job_id, "bundle_id.txt"), "w") as f:
70
  f.write(bundle_id)
71
 
72
- # 7. Redirect to the itms-services protocol for iOS installation
73
  plist_url = f"{BASE_URL}/plist/{job_id}"
74
  return redirect(f"itms-services://?action=download-manifest&url={plist_url}")
75
 
76
  except subprocess.CalledProcessError as e:
77
- # Captures specific zsign errors (like wrong password) for debugging
78
- error_logs = e.stderr if e.stderr else e.stdout
79
- return f"Signing failed. Zsign output: {error_logs}", 500
80
- except Exception as e:
81
- return f"System Error: {str(e)}", 500
82
 
83
  @app.route('/plist/<job_id>')
84
  def serve_plist(job_id):
85
- # Retrieve the dynamic bundle ID extracted during the sign phase
86
  try:
87
  with open(os.path.join(job_id, "bundle_id.txt"), "r") as f:
88
  bundle_id = f.read().strip()
89
  except:
90
- bundle_id = "com.simplebit.fallback"
91
 
92
  ipa_direct_url = f"{BASE_URL}/download/{job_id}"
93
 
94
- # Manifest required by iOS to install apps over-the-air
95
  plist_content = f"""<?xml version="1.0" encoding="UTF-8"?>
96
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
97
  <plist version="1.0">
@@ -132,12 +135,7 @@ def serve_plist(job_id):
132
 
133
  @app.route('/download/<job_id>')
134
  def download_ipa(job_id):
135
- # Sends the final binary to the iPhone
136
- return send_file(
137
- os.path.join(job_id, "signed.ipa"),
138
- mimetype='application/octet-stream',
139
- as_attachment=True
140
- )
141
 
142
  if __name__ == "__main__":
143
  app.run(host="0.0.0.0", port=7860)
 
13
 
14
  @app.route('/')
15
  def home():
16
+ return "SimpleBit Signer is Online!"
17
+
18
+ def get_actual_bundle_id(ipa_path):
19
+ """ Extracts the actual Bundle ID from the IPA's Info.plist """
20
+ try:
21
+ # Use unzip to peek at the Info.plist and grep for the ID
22
+ # This is more reliable than parsing zsign logs
23
+ cmd = f"unzip -p {ipa_path} Payload/*.app/Info.plist | grep -A1 'CFBundleIdentifier' | grep 'string' | sed 's/<[^>]*>//g' | str.strip()"
24
+ # Using a more robust subprocess call for the same logic:
25
+ result = subprocess.run(
26
+ f"unzip -p {ipa_path} Payload/*.app/Info.plist | grep -A1 'CFBundleIdentifier'",
27
+ shell=True, capture_output=True, text=True
28
+ )
29
+ match = re.search(r"<string>(.*)</string>", result.stdout)
30
+ if match:
31
+ return match.group(1).strip()
32
+ except Exception:
33
+ pass
34
+ return None
35
 
36
  @app.route('/sign', methods=['POST'])
37
  def sign():
 
38
  job_id = str(uuid.uuid4())[:8]
39
  os.makedirs(job_id, exist_ok=True)
40
 
 
41
  ipa = request.files['ipa']
42
  p12 = request.files['p12']
43
  prov = request.files['provision']
44
  password = request.form.get('password', '1234')
45
 
 
46
  ipa_path = os.path.join(job_id, "app.ipa")
47
  p12_path = os.path.join(job_id, "cert.p12")
48
  prov_path = os.path.join(job_id, "prov.mobileprovision")
49
  out_path = os.path.join(job_id, "signed.ipa")
50
 
 
51
  ipa.save(ipa_path)
52
  p12.save(p12_path)
53
  prov.save(prov_path)
54
 
55
+ # STEP 1: Get the REAL Bundle ID first
56
+ bundle_id = get_actual_bundle_id(ipa_path)
57
+
58
+ # STEP 2: Sign the app
59
  command = [
60
  "zsign",
61
  "-k", p12_path,
 
67
  ]
68
 
69
  try:
 
70
  result = subprocess.run(command, capture_output=True, text=True, check=True)
 
 
 
 
71
 
72
+ # If extraction failed earlier, try one last time from zsign logs
73
+ if not bundle_id:
74
+ combined_output = result.stdout + result.stderr
75
+ match = re.search(r"Bundle\s?Id:\s+([a-zA-Z0-9\.-]+)", combined_output, re.IGNORECASE)
76
+ bundle_id = match.group(1).strip() if match else "com.simplebit.dynamic"
 
77
 
78
+ # Save the confirmed ID for the /plist route
79
  with open(os.path.join(job_id, "bundle_id.txt"), "w") as f:
80
  f.write(bundle_id)
81
 
 
82
  plist_url = f"{BASE_URL}/plist/{job_id}"
83
  return redirect(f"itms-services://?action=download-manifest&url={plist_url}")
84
 
85
  except subprocess.CalledProcessError as e:
86
+ return f"Signing failed: {e.stderr}", 500
 
 
 
 
87
 
88
  @app.route('/plist/<job_id>')
89
  def serve_plist(job_id):
 
90
  try:
91
  with open(os.path.join(job_id, "bundle_id.txt"), "r") as f:
92
  bundle_id = f.read().strip()
93
  except:
94
+ bundle_id = "com.simplebit.dynamic"
95
 
96
  ipa_direct_url = f"{BASE_URL}/download/{job_id}"
97
 
 
98
  plist_content = f"""<?xml version="1.0" encoding="UTF-8"?>
99
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
100
  <plist version="1.0">
 
135
 
136
  @app.route('/download/<job_id>')
137
  def download_ipa(job_id):
138
+ return send_file(os.path.join(job_id, "signed.ipa"), as_attachment=True)
 
 
 
 
 
139
 
140
  if __name__ == "__main__":
141
  app.run(host="0.0.0.0", port=7860)