Ripara ora
- Trascina il file
- La riparazione avviene in locale
- Scarica il risultato
WhatsApp su Android conserva ogni conversazione in un unico database SQLite chiamato msgstore.db: il testo dei messaggi, le marche temporali e i riferimenti a chat e contatti vivono tutti al suo interno. Quando un arresto anomalo dell'app, una copia interrotta mentre lo si estrae dal telefono o una sincronizzazione lasciata a metà lo danneggiano, WhatsApp e qualsiasi altro strumento SQLite rifiutano l'intero file con "database disk image is malformed". Trascina qui sopra il msgstore.db già decifrato e lo strumento ne percorre le pagine in locale, ricostruisce lo schema e reinserisce ogni riga che riesce ancora a decodificare in un database nuovo e apribile; il database della chat, che contiene tutta la cronologia dei messaggi, non viene mai caricato online.
Cosa c'è dentro msgstore.db: pagine, tabelle e il file -wal
Un database di WhatsApp è un normale file SQLite, quindi è un array piatto di pagine di dimensione fissa (il valore predefinito di SQLite è spesso 4 KB). I primi 16 byte sono la stringa magica SQLite format 3\0; il resto della pagina 1 contiene l'intestazione del file e lo sqlite_schema, che elenca ogni tabella. Ogni tabella è un albero-b (b-tree): le pagine interne contengono puntatori che scendono verso le pagine foglia, e le pagine foglia contengono le tue righe vere e proprie.
Le tabelle che contano per la cronologia delle chat sono prevedibili. Le versioni moderne di WhatsApp conservano i messaggi in una tabella message (le versioni più vecchie usavano messages), l'elenco delle conversazioni in chat e gli identificatori di numero di telefono/gruppo in jid. Il testo del messaggio vive in una colonna di testo (text_data nello schema moderno, data in quello vecchio), e ogni riga porta una marca temporale in millisecondi dall'epoca Unix. Tabelle di supporto come message_media, message_thumbnail, message_quoted e call_log completano il quadro. E un dettaglio fondamentale: le foto, i video e le note vocali in sé non sono nel database; sono file separati nella cartella Media di WhatsApp, e il database conserva solo i loro percorsi e piccole miniature.
WhatsApp esegue il database in modalità WAL (write-ahead logging), quindi sul telefono vedrai due file fratelli accanto a esso: msgstore.db-wal e msgstore.db-shm. I messaggi recenti già confermati (committed) possono vivere solo nel file -wal finché non vengono consolidati (checkpoint) nel .db principale. Se hai quel file affiancato, conservalo: i suoi frame confermati sono le righe più recenti.
Perché segnala "malformed" e la trappola del .crypt
SQLite lancia SQLITE_CORRUPT (codice di risultato 11) —che appare come "database disk image is malformed"— non appena segue un puntatore e atterra su qualcosa che non è una pagina b-tree valida: una pagina azzerata, un offset di cella errato, un conteggio di pagine che non torna con la dimensione del file. Si ferma alla prima incongruenza, ed è per questo che una singola pagina interna danneggiata fa cadere l'intero file mentre le pagine foglia intatte che stanno dietro continuano a conservare i tuoi messaggi. Un errore imparentato, "file is not a database," significa che la stringa magica di 16 byte dell'intestazione è stata alterata; le pagine che stanno dietro di solito sono a posto.
Il danno arriva quasi sempre da una scrittura interrotta. Estrarre il msgstore.db dal telefono via USB o con un gestore di file mentre WhatsApp lo tiene ancora aperto può copiare un file rotto, con il checkpoint a metà; un bit invertito su una scheda SD che sta cedendo o durante una sincronizzazione, oppure un dispositivo rimasto senza batteria a metà scrittura, producono lo stesso effetto. Una copia troncata perde semplicemente le pagine che si trovavano in coda.
C'è una trappola che frega quasi tutti per prima cosa: il file nella cartella dei backup di WhatsApp non è un database normale. I backup si chiamano msgstore.db.crypt14 o msgstore.db.crypt15 e sono cifrati con AES-GCM (la chiave si trova in /data/data/com.whatsapp/files/key oppure, per crypt15, dietro la tua password di backup cifrato end-to-end). Un file .crypt14/.crypt15 si legge come rumore ad alta entropia: non ha alcuna intestazione SQLite, quindi il recupero per pagine non può toccarlo finché non viene decifrato e ritorna a essere un msgstore.db normale. Questo strumento lavora sul database già decifrato, non sul backup cifrato.
Cosa recupera e perché non devi mai caricare online il database di una chat
Invece di fidarsi dei puntatori rotti, lo strumento legge il file pagina per pagina: ricostruisce lo schema, percorre il b-tree di ogni tabella e, per tutto ciò che la catena di puntatori non riesce più a raggiungere, ricorre a una scansione grezza delle pagine che decodifica i record autodescrittivi direttamente dalle pagine foglia. Ricostruisce i b-tree da zero attorno alle righe che trova e le scrive in un database nuovo che scarichi: la stessa strategia del comando .recover di SQLite stesso. Le righe che non possono essere attribuite a una tabella nota finiscono in una tabella lost_and_found invece di essere scartate, e se fornisci il file affiancato msgstore.db-wal, i suoi frame confermati vengono sovrapposti per primi in modo che il risultato rifletta i tuoi ultimi messaggi confermati, non solo l'ultimo checkpoint.
I limiti onesti: i byte sovrascritti fisicamente o troncati alla fine del file sono persi, e nessuno strumento può inventarli. I valori tornano con la loro classe di archiviazione su disco, quindi l'affinità di una colonna può cambiare. Poiché la scansione legge anche le pagine della lista libera (freelist) e quelle non compattate, alcuni messaggi cancellati in precedenza possono riaffiorare. I dati recuperati sono sempre da considerare sospetti —lo dice la stessa documentazione di SQLite—, quindi verificali contro una fonte attendibile prima di fidarti. E i file multimediali restano nella cartella Media separata; il database ti dà il testo e i riferimenti, non le immagini in sé.
Perché farlo nel browser? Il database di una chat è il peggior file che tu possa consegnare a un server che non controlli: può contenere ogni messaggio, numero di telefono e marca temporale che hai mai scambiato. Gli strumenti di "riparazione" che caricano il file lo copiano su un'infrastruttura che non puoi ispezionare, con termini di conservazione che non hai scritto tu. Qui il file viene letto dal tuo disco e ricostruito nella tua scheda; puoi aprire il pannello Rete (Network) e verificare che 0 byte del database escono dal tuo dispositivo.
Cosa può e cosa non può riparare
Può riparare
- "Database disk image is malformed" (SQLITE_CORRUPT 11) da una pagina danneggiata o da un puntatore b-tree rotto
- "File is not a database" quando è stata alterata solo la stringa magica di 16 byte dell'intestazione e le pagine dietro sopravvivono
- Un msgstore.db rotto o con il checkpoint a metà per averlo copiato dal telefono mentre WhatsApp era ancora aperto
- Database troncati: viene estratta ogni riga di messaggio dalle pagine sopravvissute, più le righe non consolidate da un file affiancato -wal fornito
- Righe su pagine che la catena di puntatori non raggiunge più, recuperate con una scansione grezza delle pagine verso lost_and_found
Non può riparare
- Backup cifrati .crypt14 / .crypt15 senza la chiave: sono testo cifrato senza intestazione SQLite e vanno decifrati prima
- Messaggi sovrascritti fisicamente o troncati alla fine del file: quei byte non esistono più
- Le foto, i video e le note vocali in sé (sono file separati nella cartella Media, non stanno nel database)
- Una garanzia che ogni messaggio recuperato sia completo o corretto: verifica i dati recuperati contro una fonte attendibile
- File da 0 byte, o un database la cui intestazione e le cui pagine sono tutto rumore (quello è prima di tutto un problema di recupero dello storage)
Se una riparazione fallisce, ti diciamo perché (dati mancanti rispetto a struttura danneggiata), e non ti viene mai addebitato nulla per una riparazione fallita.