v1.7.12: codesign identifier coerente per TCC subprocess + skip quota su Annual
Bug: codesign --deep ad-hoc dava a ffmpeg un identifier auto-generato (ffmpeg-<hash>) diverso da com.djluza.musictools del bundle, quindi macOS trattava ffmpeg come app distinta per TCC -> permesso microfono del main NON ereditato dal subprocess -> registrazione muta o errore. Fix: in adhoc_codesign() ora firmiamo OGNI Mach-O nested con --identifier com.djluza.musictools (stesso del bundle), poi firmiamo il bundle .app. Cosi' TCC vede un unico "team" coerente e il permesso microfono si propaga a ffmpeg/ffprobe/yt-dlp. Verificato in dev mode: registrazione BlackHole funziona quando ffmpeg eredita correttamente il TCC. Anche fix collaterale: bridge._gate() salta la chiamata consume_quota al server quando il piano corrente ha daily_limit=None (Annual). Per i piani unlimited non c'e' motivo di chiamare il server -> niente piu' errori online se il server e' temporaneamente irraggiungibile durante una registrazione su un piano Annual.
This commit is contained in:
1 parent
b74a0a53ec
commit
5771d631fd
3 files changed
+71
-28
No files matched your search
+6
-1
@@ -229,7 +229,12 @@ class Api:
|
||||
),
|
||||
"plan": plan,
|
||||
}
|
||||
# 2) Quota gate server-side
|
||||
# 2) Quota gate server-side: skippato per i piani senza limite
|
||||
# giornaliero (Annual) — evita una chiamata HTTP inutile e fa
|
||||
# funzionare l'app anche offline per quei piani.
|
||||
plan = license_mod.get_plan()
|
||||
if plan.get("daily_limit") is None:
|
||||
return None
|
||||
try:
|
||||
res = license_mod.consume_quota(feature)
|
||||
except license_mod.LicenseNetworkError as e:
|
||||
|
||||
+64
-26
@@ -293,40 +293,78 @@ def patch_info_plist(app_path):
|
||||
log("Info.plist aggiornato.")
|
||||
|
||||
|
||||
_BUNDLE_ID = "com.djluza.musictools"
|
||||
|
||||
|
||||
def adhoc_codesign(app_path):
|
||||
"""Ad-hoc codesign dell'intero bundle .app.
|
||||
"""Ad-hoc codesign dell'intero bundle .app con identifier coerente.
|
||||
|
||||
Senza una firma coerente, macOS tratta ffmpeg (subprocess bundled)
|
||||
come binario separato dal main MusicTools per TCC: ffmpeg apre il
|
||||
dispositivo audio senza errore ma riceve solo silenzio perche' il
|
||||
sistema non gli concede il permesso microfono ereditato.
|
||||
macOS tratta ogni binario Mach-O firmato come una "app" distinta per
|
||||
le decisioni TCC (microfono, camera, ecc.). Con `codesign --deep`
|
||||
standard, i nested binary (ffmpeg, ffprobe, yt-dlp) ricevono ognuno
|
||||
un identifier auto-generato del tipo `<nome>-<hash>`, diverso da
|
||||
quello del bundle principale -> TCC NEGA al subprocess.
|
||||
|
||||
`codesign --force --deep --sign -` applica una firma ad-hoc (gratis,
|
||||
senza Developer ID) a tutti i binari nested. Per macOS questo rende
|
||||
l'app un singolo "team" coerente, e il permesso TCC concesso al
|
||||
main si propaga anche a ffmpeg/ffprobe/yt-dlp.
|
||||
Soluzione: firmiamo PRIMA ogni binario interno con `--identifier
|
||||
com.djluza.musictools`, poi il bundle .app intero. Cosi' TCC vede
|
||||
tutti i Mach-O come parte dello stesso "team" e propaga il permesso
|
||||
del main ai subprocess.
|
||||
"""
|
||||
log("Ad-hoc codesign del bundle (per TCC microfono ereditato)...")
|
||||
log("Ad-hoc codesign del bundle (identifier coerente per TCC)...")
|
||||
try:
|
||||
# Rimuovi vecchie firme che potrebbero confondere codesign --deep
|
||||
subprocess.run(
|
||||
["xattr", "-cr", str(app_path)],
|
||||
capture_output=True,
|
||||
)
|
||||
subprocess.run(
|
||||
["codesign", "--remove-signature", "--deep", str(app_path)],
|
||||
capture_output=True,
|
||||
)
|
||||
result = subprocess.run(
|
||||
["codesign", "--force", "--deep", "--sign", "-",
|
||||
"--timestamp=none", str(app_path)],
|
||||
# 1) Pulisci attributi estesi (rimuove quarantine residui dal build)
|
||||
subprocess.run(["xattr", "-cr", str(app_path)], capture_output=True)
|
||||
|
||||
# 2) Trova tutti i Mach-O nested (binari ed eventuali .dylib).
|
||||
# Li firmiamo uno a uno con identifier coerente, dal piu' profondo
|
||||
# al piu' esterno (richiesta da codesign).
|
||||
nested_machos = []
|
||||
for p in sorted(app_path.rglob("*"), key=lambda x: -len(x.parts)):
|
||||
if not p.is_file():
|
||||
continue
|
||||
# Skip risorse non eseguibili
|
||||
if p.suffix in (".plist", ".nib", ".png", ".icns", ".svg",
|
||||
".html", ".css", ".js", ".json", ".md", ".txt"):
|
||||
continue
|
||||
try:
|
||||
with open(p, "rb") as f:
|
||||
magic = f.read(4)
|
||||
except Exception:
|
||||
continue
|
||||
# Mach-O magic numbers (32/64-bit, big/little endian, fat)
|
||||
if magic in (b"\xcf\xfa\xed\xfe", b"\xce\xfa\xed\xfe",
|
||||
b"\xfe\xed\xfa\xce", b"\xfe\xed\xfa\xcf",
|
||||
b"\xca\xfe\xba\xbe", b"\xbe\xba\xfe\xca"):
|
||||
nested_machos.append(p)
|
||||
|
||||
log(f"Trovati {len(nested_machos)} binari Mach-O da firmare.")
|
||||
|
||||
for p in nested_machos:
|
||||
r = subprocess.run(
|
||||
["codesign", "--force", "--sign", "-",
|
||||
"--identifier", _BUNDLE_ID,
|
||||
"--timestamp=none",
|
||||
str(p)],
|
||||
capture_output=True, text=True,
|
||||
)
|
||||
if result.returncode != 0:
|
||||
log(f"ATTENZIONE: codesign fallito: {result.stderr.strip()}")
|
||||
if r.returncode != 0:
|
||||
log(f" warn: firma {p.name} fallita: {r.stderr.strip()}")
|
||||
|
||||
# 3) Firma del bundle .app principale (l'identifier corretto viene
|
||||
# letto dall'Info.plist - CFBundleIdentifier che gia' settiamo).
|
||||
r = subprocess.run(
|
||||
["codesign", "--force", "--sign", "-",
|
||||
"--identifier", _BUNDLE_ID,
|
||||
"--timestamp=none",
|
||||
str(app_path)],
|
||||
capture_output=True, text=True,
|
||||
)
|
||||
if r.returncode != 0:
|
||||
log(f"ATTENZIONE: firma bundle fallita: {r.stderr.strip()}")
|
||||
else:
|
||||
log("Codesign ad-hoc completato.")
|
||||
# Verifica
|
||||
|
||||
# 4) Verifica finale
|
||||
verify = subprocess.run(
|
||||
["codesign", "--verify", "--deep", "--strict", str(app_path)],
|
||||
capture_output=True, text=True,
|
||||
@@ -334,7 +372,7 @@ def adhoc_codesign(app_path):
|
||||
if verify.returncode == 0:
|
||||
log("Verifica firma OK.")
|
||||
else:
|
||||
log(f"NOTA: verifica firma con warning: {verify.stderr.strip()}")
|
||||
log(f"NOTA verifica firma: {verify.stderr.strip()}")
|
||||
except FileNotFoundError:
|
||||
log("ATTENZIONE: 'codesign' non trovato nel PATH, skip ad-hoc signing")
|
||||
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
VERSION = "v1.7.11"
|
||||
VERSION = "v1.7.12"
|
||||
|
||||
|
||||
APP_NAME = "MusicTools"
|
||||
|
||||
Reference in new issue
Block a user