IBO Pro Ultra — Reseller Bundle v18 panel/ + apk/IBO_Pro_Ultra.apk (generic — placeholder URL baked in) What's new in v18 ----------------- One belt-and-suspenders fix on top of v17 for a real buyer install that broke Quick URL Encrypt. 0. api/quick_url_encrypt.php now reads crypto constants DIRECTLY from includes/apksec_constants.php, bypassing db_config() ----------------------------------------------------------------- Previously the endpoint went through db_config() which reads panel.db config row and falls back to apksec_constants.php only if the DB value is empty. If the DB was readonly (perm mismatch), had a partial init, or had a legacy non-empty seed value that later became invalid, the endpoint could produce a bad literal (or throw "working_key_hex must be 16 raw bytes"). No DB state can now cause a crypto misconfiguration — the endpoint reads the file straight. Same applies to the verify path. What's new in v17 ----------------- Same as v16 (see below), minus one install-day headache: 0. data/panel.db is no longer shipped in the zip ----------------------------------------------- Previously the zip contained a 0-byte `panel/data/panel.db` placeholder. On many shared-hosting setups the extract left it owned by root (or whatever user did the extract) while Apache ran as www-data — so Apache couldn't overwrite the file, panel_db() failed with `SQLSTATE[HY000]: General error: 8 attempt to write a readonly database`, schema never initialized, addaplaylist never registered, and Quick URL Encrypt threw. Fix was previously "delete the file so PHP recreates it"; now v17 just doesn't ship it. `panel/data/` is still shipped as an empty directory. PHP creates panel.db on first hit with the correct owner and permissions. (Same reasoning for `panel/uploads/slideshows/` — the slideshow upload code auto-mkdirs it, and the empty dir ships without any file inside.) What's new in v16 (kept for reference) -------------------------------------- This release is mostly quality-of-life on top of v15, plus one silent-fatal schema bug that would break Quick URL Encrypt on every fresh install. 1. Schema seed no longer poisons Quick URL Encrypt on new installs ----------------------------------------------------------------- includes/db.php CREATE TABLE config had a hardcoded default value for `target_server_key_hex` (`0370dd1afec23dabd2639452ca6a4099`). Because the column wasn't empty on fresh installs, `db_config()`'s fallback to `apksec_constants.php` never fired — the panel encrypted URLs using the seeded garbage instead of the reseller working key. Symptom: buyer runs Quick URL Encrypt, bakes the literal into the APK, installs, and gets `Bad URL /auth`. Fix: default cleared to `''` in the schema, the INSERT, and the ALTER TABLE. Fresh installs now hit the apksec_constants fallback as intended. If you already deployed v15 to a customer: fix in-place with UPDATE config SET target_server_key_hex = '' WHERE id = 1; 2. Quick URL Encrypt now forces a trailing slash before encrypting --------------------------------------------------------------- The IBO app's GlassVpnPicker builds fetch URLs as `_panelUrl + "vpns.php"` — no leading slash on the endpoint side. If the buyer pasted a URL without a trailing slash, the app fetched `.../slugvpns.php` and threw "Could not load VPN list". Fix: `api/quick_url_encrypt.php` appends a `/` before encryption if one isn't present. Buyers can't paste a URL that breaks half the app. 3. Verify a literal — new tool on the Quick URL Encrypt page -------------------------------------------------------- Paste any `ct_hex|iv_hex` string from an APK's PanelUrl.smali line 14; panel decrypts it locally with the reseller constants and reports the URL it will decode to on-device. Three outcomes: ✓ Decrypts cleanly → URL shown, safe to install ⚠ Decrypts but no trailing slash → yellow warning ✗ Decrypts to garbage → specific reason (customer format, wrong keys, non-hex characters, etc.) Answers "was this literal generated by THIS panel?" in one click. 4. VPN URL-fetch now handles Dropbox and Google Drive share links --------------------------------------------------------------- The Add VPN Config modal's URL field auto-rewrites two common share-URL formats so paste-and-go works: Dropbox dropbox.com/s/… or /scl/… → forces ?dl=1 G. Drive drive.google.com/file/d/ID/view → uc?export=download&id=ID Any other host is fetched as-is. If it returns HTML (login page, error), the panel's `remote` directive check rejects it with a human-readable toast so the buyer knows the URL was bad. 5. Framed View — Layout 0 (fullscreen 1 slot) + backdrop toggle ------------------------------------------------------------ Framed View gains a new "Layout 0 — Fullscreen (1 slot)" option and a top-level checkbox "Use this as the home backdrop". When the toggle is on, the panel resolves `home_url1` in /auth to `api/webview/frameview.php` instead of the TMDB backdrop. End-to-end flow: upload slideshow images → Framed View → Layout 0 → drop Slideshow in the only slot → toggle on → save → next /auth on the box swaps the backdrop. Fully reversible. 6. Media Slideshow — new Image Fit dropdown ----------------------------------------- "Fit" (default; whole image visible, letterbox if aspect differs) vs "Fill" (edge-to-edge, may crop). Portrait / square photos no longer zoom-crop on the TV. Setting persists in webview_settings under `slide_fit_mode`. 7. Slideshow upload no longer requires the fileinfo extension ----------------------------------------------------------- `finfo_open()` on a host without the fileinfo extension threw a 500. Now the panel falls back to `getimagesize()` (always available with GD, standard on cPanel). Still rejects renamed PHP/HTML because getimagesize returns false for non-images. 8. New Support Tools sidebar section ---------------------------------- Two buyer-facing pages under Diagnostics: Health Check pass/fail per requirement — PHP version, required + optional extensions, ini limits, file permissions, apksec+crypto variant, addaplaylist registration, outbound HTTPS test. Buyer self-diagnoses without needing the support token. Self Test one-click probe of every panel endpoint the app depends on (auth, has_playlist, vpns, webview endpoints), plus outbound HTTPS. Reports HTTP code + pass/fail + ms per endpoint. 9. Hidden debug.php — support-mode diagnostic dump ------------------------------------------------ /debug.php returns 404 unless the support token is passed as ?key=. Token lives in includes/debug_constants.php (rotate the string to invalidate). With the right token, the page shows in one screen: - Sticky action bar (Copy report, Download .txt, Open plain text, Export panel state .zip, Clear errors, Clear requests, Clear BOTH) - Overall HEALTHY / MINOR ISSUES / ATTENTION status pill - Auto-refresh checkbox (10 s) - PHP + Reseller sanity + Extensions + ini + config + File perms + panel.db counts + Recent request log + Recent error log — all with green/amber/red status per section, per-section Copy button, and helpful empty states Also supports ?format=txt for plain-text output the buyer can paste into chat with one click. Filename is dynamic (panel-state--.zip / .txt) — nothing hardcoded. Everything from v15 still in place ---------------------------------- - Fully redacted panel — no apk_builder, no builder.php, no master.db refs, no proprietary paths - RESELLER-VARIANT apksec_constants.php + crypto.php - .htaccess with all rewrite rules - vpn.php + api/vpns.php URL-fetch feature - vpns.php empty-cred filter - add.php returns public_id - delete.php accepts playlist_id + row-PK fallback - APK AndroidManifest — foregroundServiceType="specialUse" (Android 14) - APK res/layout/userpass.xml — real fields with @id/username etc. - APK signed with reseller keystore (cert SHA 9210b240…d283d7); installs upgrade in place on end-user devices If you already deployed v15 to a customer's host ------------------------------------------------ Overwrite these files from the v16 zip: panel/includes/db.php (schema seed fix) panel/api/quick_url_encrypt.php (trailing slash + verify) panel/api/vpns.php (Dropbox/Drive rewriting) panel/quick_url_encrypt.php (verifier UI) panel/frameview_settings.php (Layout 0 + backdrop toggle) panel/api/webview/frameview.php (Layout 0 rendering) panel/api/webview/frames.php (backdrop toggle save) panel/includes/client_common.php (home_url1 resolution) panel/api/webview/slideshow.php (fit mode) panel/api/webview/slideshows.php (fileinfo fallback + fit mode API) panel/slideshow_settings.php (fit mode UI) panel/health.php (new) panel/selftest.php (new) panel/debug.php (new) panel/includes/debug_constants.php (new) panel/modules/support/module.php (new sidebar section) And on their live DB, one row to clear the stale schema default: sqlite3 data/panel.db \ "UPDATE config SET target_server_key_hex = '' WHERE id = 1;" Prior fixes still in place (rollup) ----------------------------------- v15: proper reseller-variant crypto.php restored (was clobbered in v11–v14); .htaccess restored to the panel/ root v14: proprietary APK builder infrastructure stripped from the zip v13: restored reseller-variant apksec_constants.php that v12 clobbered v12: api/vpns.php + vpn.php — URL fetch for external OVPN v11: AndroidManifest — foregroundServiceType="specialUse" (Android 14 fix) + api/vpns.php filter for empty-creds profiles + /add.php returns public_id (contract match with /auth) + /delete.php accepts playlist_id + row-PK fallback v10: languages editor — full 217-key manual editor, Save preserves all v9: TMDB dropdowns — added pl-PL metadata + PL region v8: VPN Add form (u/p optional, enabled checkbox honored) + 8-language seed (1736 translations) v7: delete_user_row atomic action (playlist + mac-if-orphan) v6: services_clients Edit / Lock buttons wired v5: generic placeholder-URL APK v4: full addaplaylist integration v3: quick_url_encrypt auto-detect keeps trailing slash v2: server-side trailing-slash enforcement v1: libapksec_reseller.so + apksec_constants.php as source of truth Common questions ---------------- Q: A customer's QR code says "Device code expired or invalid" A: The addaplaylist auto-register call may have failed during first-load (network timeout, blocked outbound). Re-run manually via SSH: cd /path/to/panel ADDAPLAYLIST_REGISTER_SECRET= \ PANEL_DOMAIN='/' \ php cron/addaplaylist_register.php Q: How do I access the debug page? A: /debug.php?key= Change the token by editing that file. The default token is baked in this bundle — rotate it if you're worried it's leaked.