gabefromsimplebit commited on
Commit
ca0dca4
·
verified ·
1 Parent(s): b7a588e

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. app.py +35 -12
app.py CHANGED
@@ -1,24 +1,25 @@
1
- from flask import Flask, request, send_file, redirect
2
  from flask_cors import CORS
3
  import subprocess
4
  import os
5
  import uuid
6
  import re
7
- import shutil
8
 
9
  app = Flask(__name__)
10
  CORS(app)
11
 
 
12
  BASE_URL = "https://gabefromsimplebit-simplebit-signer.hf.space"
13
 
14
  @app.route('/')
15
  def home():
16
- return "SimpleBit Engine is Online and Ready!"
17
 
18
  @app.route('/sign', methods=['POST'])
19
  def sign():
20
  job_id = str(uuid.uuid4())[:8]
21
  os.makedirs(job_id, exist_ok=True)
 
22
 
23
  ipa = request.files['ipa']
24
  p12 = request.files['p12']
@@ -34,27 +35,43 @@ def sign():
34
  p12.save(p12_path)
35
  prov.save(prov_path)
36
 
37
- # Use shell=True and quotes around the password to handle special characters
38
- # This is the most compatible way to run zsign on Linux
39
  command = f"zsign -k '{p12_path}' -p '{password}' -m '{prov_path}' -o '{out_path}' -z 0 '{ipa_path}'"
40
 
41
  try:
42
- # We capture everything to see the REAL error
43
  result = subprocess.run(command, shell=True, capture_output=True, text=True)
44
 
45
  if result.returncode != 0:
46
- # If it fails, we show you the exact console output from zsign
47
- return f"Zsign Error (Code {result.returncode}): {result.stdout} {result.stderr}", 500
48
 
49
- # Success! Now get the Bundle ID
50
  match = re.search(r"Bundle Id:\s+([\w\.-]+)", result.stdout)
51
  bundle_id = match.group(1) if match else "com.simplebit.dynamic"
52
 
 
53
  with open(os.path.join(job_id, "bundle_id.txt"), "w") as f:
54
  f.write(bundle_id)
55
 
56
  plist_url = f"{BASE_URL}/plist/{job_id}"
57
- return redirect(f"itms-services://?action=download-manifest&url={plist_url}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
 
59
  except Exception as e:
60
  return f"System Error: {str(e)}", 500
@@ -101,11 +118,17 @@ def serve_plist(job_id):
101
  </dict>
102
  </plist>"""
103
 
104
- return send_file(os.path.join(job_id, "manifest.plist"), mimetype='text/xml')
 
105
 
106
  @app.route('/download/<job_id>')
107
  def download_ipa(job_id):
108
- return send_file(os.path.join(job_id, "signed.ipa"), mimetype='application/octet-stream')
 
 
 
 
 
109
 
110
  if __name__ == "__main__":
111
  app.run(host="0.0.0.0", port=7860)
 
1
+ from flask import Flask, request, send_file, Response
2
  from flask_cors import CORS
3
  import subprocess
4
  import os
5
  import uuid
6
  import re
 
7
 
8
  app = Flask(__name__)
9
  CORS(app)
10
 
11
+ # Base URL for your Hugging Face Space - Ensure this is the direct 'hf.space' link
12
  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
  job_id = str(uuid.uuid4())[:8]
21
  os.makedirs(job_id, exist_ok=True)
22
+ os.chmod(job_id, 0o777) # Ensure the folder is writable for signing
23
 
24
  ipa = request.files['ipa']
25
  p12 = request.files['p12']
 
35
  p12.save(p12_path)
36
  prov.save(prov_path)
37
 
38
+ # Optimized zsign command for speed and compatibility
 
39
  command = f"zsign -k '{p12_path}' -p '{password}' -m '{prov_path}' -o '{out_path}' -z 0 '{ipa_path}'"
40
 
41
  try:
42
+ # Run zsign and capture output to extract the real Bundle ID
43
  result = subprocess.run(command, shell=True, capture_output=True, text=True)
44
 
45
  if result.returncode != 0:
46
+ return f"Zsign Failed (Code {result.returncode}): {result.stderr}", 500
 
47
 
48
+ # Extract the real Bundle ID so the itms-services handshake doesn't fail
49
  match = re.search(r"Bundle Id:\s+([\w\.-]+)", result.stdout)
50
  bundle_id = match.group(1) if match else "com.simplebit.dynamic"
51
 
52
+ # Save the Bundle ID to a file for the /plist route
53
  with open(os.path.join(job_id, "bundle_id.txt"), "w") as f:
54
  f.write(bundle_id)
55
 
56
  plist_url = f"{BASE_URL}/plist/{job_id}"
57
+
58
+ # User-facing landing page to prevent "Silent Failure" on Safari
59
+ return f'''
60
+ <html>
61
+ <head><meta name="viewport" content="width=device-width, initial-scale=1"></head>
62
+ <body style="display:flex; flex-direction:column; align-items:center; justify-content:center; height:100vh; font-family:-apple-system, sans-serif; background-color:#f2f2f7;">
63
+ <div style="background:white; padding:30px; border-radius:20px; box-shadow:0 10px 25px rgba(0,0,0,0.1); text-align:center;">
64
+ <h2 style="color:#1c1c1e; margin-bottom:10px;">Ready to Install</h2>
65
+ <p style="color:#8e8e93; margin-bottom:25px;">Bundle ID: <b>{bundle_id}</b></p>
66
+ <a href="itms-services://?action=download-manifest&url={plist_url}"
67
+ style="background:#007AFF; color:white; padding:15px 40px; text-decoration:none; border-radius:12px; font-weight:600; display:inline-block;">
68
+ Install App
69
+ </a>
70
+ </div>
71
+ <p style="margin-top:20px; color:#8e8e93; font-size:12px;">Make sure you are using Safari on iOS.</p>
72
+ </body>
73
+ </html>
74
+ '''
75
 
76
  except Exception as e:
77
  return f"System Error: {str(e)}", 500
 
118
  </dict>
119
  </plist>"""
120
 
121
+ # Return with correct XML mimetype for iOS recognition
122
+ return Response(plist_content, mimetype='application/xml')
123
 
124
  @app.route('/download/<job_id>')
125
  def download_ipa(job_id):
126
+ # Serve as octet-stream to ensure binary download
127
+ return send_file(
128
+ os.path.join(job_id, "signed.ipa"),
129
+ mimetype='application/octet-stream',
130
+ as_attachment=True
131
+ )
132
 
133
  if __name__ == "__main__":
134
  app.run(host="0.0.0.0", port=7860)