From 3232f6f163f35fba5852e8c54fdc75f4e0a29682 Mon Sep 17 00:00:00 2001 From: r-zakarya <82443831+r-zakarya@users.noreply.github.com> Date: Sat, 15 Aug 2026 06:04:43 +0100 Subject: [PATCH] fix(android): the ETag dies with the plaintext it describes Unlock, lock, download again: the app sent If-None-Match, got 304, and had nothing to show - on Windows there is no local cache to fall back on, so the only way back in was restarting. FETag outlived the vault it belonged to; LockVault now clears it. The 304 branch also stopped re-reading the cache file (which can fail on an expired authentication) and serves the plaintext it already holds - in memory, or the copy read at the start of the call. Co-Authored-By: Claude Opus 5 --- mainApk.pas | 42 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/mainApk.pas b/mainApk.pas index f193d8e..56d7368 100644 --- a/mainApk.pas +++ b/mainApk.pas @@ -499,6 +499,12 @@ procedure TForm8.LockVault; begin // Le clair dispararait de la memoire ET de l'ecran. Le fichier local reste : // il est chiffre par le materiel, c'est tout l'interet du cache. + // + // L'ETAG PART AVEC LUI. Il decrit le clair detenu, pas un telechargement : + // le garder ferait repondre 304 au serveur alors qu'on n'a plus rien a + // afficher - et sur un poste sans cache local (hors Android), plus aucun + // moyen de rouvrir le coffre sans relancer l'application. + FETag := ''; FVault.Clear; FList.Clear; FCurrent := Default(TVaultEntry); @@ -628,12 +634,36 @@ begin begin // C'est ICI que le cache paie : pas de telechargement, pas de // derivation, le coffre vient du fichier local. - Log(' 304 : inchange, coffre servi depuis le cache'); - // SetBusy AVANT l'ouverture : la file est FIFO, et celui du - // bloc finally passerait apres - DoOpenLocal sortirait aussitot - // sur son garde-fou "occupe". - TThread.Queue(nil, procedure - begin SetBusy(False); DoOpenLocal(nil); end); + // Rien n'a change cote serveur : le clair est deja quelque part, + // soit en memoire, soit dans le cache lu en debut de procedure. + // Surtout PAS de relecture du fichier ici - elle peut echouer + // (authentification expiree) et laisserait l'utilisateur sans + // rien apres un appel pourtant reussi. + TThread.Queue(nil, + procedure + begin + if FVault.Count > 0 then + begin + Log(' 304 : inchange, coffre deja ouvert'); + ShowList; + end + else if LCached <> '' then + begin + Log(' 304 : inchange, coffre servi depuis le cache'); + try + AdoptVault(LCached); + except + on E: Exception do Status('Cache illisible : ' + E.Message); + end; + end + else + begin + // Un ETag sans clair correspondant : l'invariant est rompu. + // On le jette pour que l'appel suivant retelecharge. + FETag := ''; + Status('Cache absent - appuyer a nouveau pour telecharger'); + end; + end); Exit; end; ssNoSnapshot: