From dc23a8f21332321f49ed4b69d812375f5ee259e6 Mon Sep 17 00:00:00 2001 From: infosave2007 Date: Sat, 24 Jan 2026 13:38:32 +0300 Subject: [PATCH] fix(qr): Use hybrid Chunked+Qt format for QR codes The format that likely works with Amnezia Android is: HEADER: 0x07C00100 (Magic 1984, Count 1, Id 0) PAYLOAD: [UncompressedLen (4b)] + [Zlib Data] This satisfies the Chunked QR check (magic 0x07C0) and then passes the payload to qUncompress, which expects the 4-byte uncompressed length prefix. Previous attempts failed because: 1. 12-byte header included compressedLen, which qUncompress interpreted as uncompressedLen (causing size mismatch error) 2. 4-byte header (Qt only) failed the Magic check --- inc/QrUtil.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/inc/QrUtil.php b/inc/QrUtil.php index a822240..6bb8f62 100644 --- a/inc/QrUtil.php +++ b/inc/QrUtil.php @@ -63,16 +63,15 @@ class QrUtil public static function encodeOldPayloadFromJson(string $jsonText): string { $json = self::normalizeJson($jsonText); - // Amnezia format: 12-byte header [version, compressed_len, uncompressed_len] + zlib compressed data - // Version 0x07C00100 is required for compatibility with Amnezia apps $compressed = gzcompress($json, 9); if ($compressed === false) { throw new RuntimeException('gzcompress failed'); } $uncompressedLen = strlen($json); - $compressedLen = strlen($compressed) + 4; // +4 for the uncompressed length field - $version = 0x07C00100; // Amnezia magic version number - $header = pack('N3', $version, $compressedLen, $uncompressedLen); + $version = 0x07C00100; // Magic 1984 (07C0), Count 1, Id 0 + // Pack version (4 bytes) and uncompressed length (4 bytes) + // Note: we skipped compressedLen which was present in old format but invalid for qUncompress + $header = pack('NN', $version, $uncompressedLen); return self::urlsafe_b64_encode($header . $compressed); }