From 33426e90e5e9c1ef1f676642dd55d8e3cbd474d8 Mon Sep 17 00:00:00 2001 From: CyberMind-FR Date: Wed, 25 Feb 2026 12:51:15 +0100 Subject: [PATCH] fix(streamlit): Fix ZIP extraction - except catches SystemExit The bare `except:` clause catches SystemExit which is raised by sys.exit(0), causing the script to fall through to sys.exit(1). Changed to `except Exception:` which doesn't catch SystemExit, allowing proper exit code propagation. Also: - Simplified Python extraction script - Use double quotes for string literals (shell compatibility) - Write Python script to temp file instead of heredoc (RPCD stdin conflict) Co-Authored-By: Claude Opus 4.5 --- .../root/usr/libexec/rpcd/luci.streamlit | 115 +++++++++--------- 1 file changed, 58 insertions(+), 57 deletions(-) diff --git a/package/secubox/luci-app-streamlit/root/usr/libexec/rpcd/luci.streamlit b/package/secubox/luci-app-streamlit/root/usr/libexec/rpcd/luci.streamlit index 496b89a0..9045c1b5 100755 --- a/package/secubox/luci-app-streamlit/root/usr/libexec/rpcd/luci.streamlit +++ b/package/secubox/luci-app-streamlit/root/usr/libexec/rpcd/luci.streamlit @@ -564,8 +564,8 @@ upload_app() { # KISS: Auto-detect ZIP by magic bytes (PK = 0x504B) local is_zip_file=0 - local magic=$(head -c2 "$tmpfile" 2>/dev/null | od -An -tx1 | tr -d ' ') - [ "$magic" = "504b" ] && is_zip_file=1 + local magic=$(head -c2 "$tmpfile" 2>/dev/null) + [ "$magic" = "PK" ] && is_zip_file=1 local app_file="$data_path/apps/${name}.py" @@ -574,39 +574,42 @@ upload_app() { local tmpdir="/tmp/extract_${name}_$$" mkdir -p "$tmpdir" - python3 -c " -import zipfile, sys + # Use Python to extract (write script to file to avoid stdin conflict with RPCD) + local pyscript="/tmp/extract_$$.py" + cat > "$pyscript" << 'PYEOF' +import zipfile, sys, os +tmpfile, app_file, tmpdir = sys.argv[1], sys.argv[2], sys.argv[3] try: - z = zipfile.ZipFile('$tmpfile') - names = z.namelist() + z = zipfile.ZipFile(tmpfile) app_py = None req_txt = None - for n in names: - bn = n.split('/')[-1] - if bn == 'app.py': + for n in z.namelist(): + bn = os.path.basename(n) + if bn == "app.py": app_py = n - elif bn == 'requirements.txt': + elif bn == "requirements.txt": req_txt = n - elif bn.endswith('.py') and app_py is None: + elif bn.endswith(".py") and not app_py: app_py = n - if app_py: - content = z.read(app_py).decode('utf-8', errors='replace') - if not content.startswith('# -*- coding'): - content = '# -*- coding: utf-8 -*-\n' + content - with open('$app_file', 'w') as f: - f.write(content) - if req_txt: - z.extract(req_txt, '$tmpdir') - import shutil - shutil.move('$tmpdir/' + req_txt, '$tmpdir/requirements.txt') - sys.exit(0) - else: + if not app_py: sys.exit(1) -except: + content = z.read(app_py).decode("utf-8", errors="replace") + if not content.startswith("# -*- coding"): + content = "# -*- coding: utf-8 -*-\n" + content + with open(app_file, "w") as f: + f.write(content) + if req_txt: + try: + z.extract(req_txt, tmpdir) + except: + pass + sys.exit(0) +except Exception: sys.exit(1) -" 2>/dev/null +PYEOF + python3 "$pyscript" "$tmpfile" "$app_file" "$tmpdir" 2>/dev/null rc=$? - rm -f "$tmpfile" + rm -f "$tmpfile" "$pyscript" if [ $rc -ne 0 ] || [ ! -s "$app_file" ]; then rm -rf "$tmpdir" @@ -1686,8 +1689,8 @@ upload_and_deploy() { # KISS: Auto-detect ZIP by magic bytes (PK = 0x504B) local is_zip_file=0 - local magic=$(head -c2 "$tmpfile" 2>/dev/null | od -An -tx1 | tr -d ' ') - [ "$magic" = "504b" ] && is_zip_file=1 + local magic=$(head -c2 "$tmpfile" 2>/dev/null) + [ "$magic" = "PK" ] && is_zip_file=1 local app_file="$data_path/apps/${name}.py" @@ -1696,44 +1699,42 @@ upload_and_deploy() { local tmpdir="/tmp/extract_${name}_$$" mkdir -p "$tmpdir" - # Use Python to extract (unzip may not be available) - python3 -c " -import zipfile, sys + # Use Python to extract (write script to file to avoid stdin conflict with RPCD) + local pyscript="/tmp/extract_$$.py" + cat > "$pyscript" << 'PYEOF' +import zipfile, sys, os +tmpfile, app_file, tmpdir = sys.argv[1], sys.argv[2], sys.argv[3] try: - z = zipfile.ZipFile('$tmpfile') - names = z.namelist() - # Find app.py or main .py file + z = zipfile.ZipFile(tmpfile) app_py = None req_txt = None - for n in names: - bn = n.split('/')[-1] - if bn == 'app.py': + for n in z.namelist(): + bn = os.path.basename(n) + if bn == "app.py": app_py = n - elif bn == 'requirements.txt': + elif bn == "requirements.txt": req_txt = n - elif bn.endswith('.py') and app_py is None: + elif bn.endswith(".py") and not app_py: app_py = n - if app_py: - content = z.read(app_py).decode('utf-8', errors='replace') - # Add UTF-8 encoding if not present - if not content.startswith('# -*- coding'): - content = '# -*- coding: utf-8 -*-\n' + content - with open('$app_file', 'w') as f: - f.write(content) - # Extract requirements.txt if present - if req_txt: - z.extract(req_txt, '$tmpdir') - import shutil - shutil.move('$tmpdir/' + req_txt, '$tmpdir/requirements.txt') - sys.exit(0) - else: + if not app_py: sys.exit(1) -except Exception as e: - print(str(e), file=sys.stderr) + content = z.read(app_py).decode("utf-8", errors="replace") + if not content.startswith("# -*- coding"): + content = "# -*- coding: utf-8 -*-\n" + content + with open(app_file, "w") as f: + f.write(content) + if req_txt: + try: + z.extract(req_txt, tmpdir) + except: + pass + sys.exit(0) +except Exception: sys.exit(1) -" 2>/dev/null +PYEOF + python3 "$pyscript" "$tmpfile" "$app_file" "$tmpdir" 2>/dev/null rc=$? - rm -f "$tmpfile" + rm -f "$tmpfile" "$pyscript" if [ $rc -ne 0 ] || [ ! -s "$app_file" ]; then rm -rf "$tmpdir"