Markdown-export kan ongemerkt het geopende brondocument overschrijven #1671

Closed
opened 2026-08-21 12:02:06 +00:00 by brenno · 1 comment
Owner

Probleem

Bij export naar .md mag de gebruiker als uitvoerpad exact het momenteel geopende bronbestand kiezen. writeDocumentExport schrijft daar vervolgens de geprojecteerde/geredigeerde export atomisch overheen, terwijl de exportdialoog een kopie belooft en de in-memory editor niet als extern gewijzigd wordt bijgewerkt. Dit kan originele inhoud en metadata verliezen.

Reproductie

  1. Open een bestaand document.
  2. Kies Document exporteren → Markdown.
  3. Selecteer hetzelfde bestand als het geopende document en bevestig overschrijven.
  4. Controleer het bestand op schijf en de nog geopende editorstate.

Verwacht

Export naar het bronpad wordt geblokkeerd of vraagt expliciet om een afzonderlijke, destructieve handeling; een gewone export verandert de bron niet.

Technische aanwijzing

_documentExport kent filePath/projectPath, maar _pickDocumentExportPath en writeDocumentExport vergelijken outputPath nergens met de bronlocatie.

Gevonden bij audit van commit d439638c6b.

## Probleem Bij export naar .md mag de gebruiker als uitvoerpad exact het momenteel geopende bronbestand kiezen. writeDocumentExport schrijft daar vervolgens de geprojecteerde/geredigeerde export atomisch overheen, terwijl de exportdialoog een kopie belooft en de in-memory editor niet als extern gewijzigd wordt bijgewerkt. Dit kan originele inhoud en metadata verliezen. ## Reproductie 1. Open een bestaand document. 2. Kies Document exporteren → Markdown. 3. Selecteer hetzelfde bestand als het geopende document en bevestig overschrijven. 4. Controleer het bestand op schijf en de nog geopende editorstate. ## Verwacht Export naar het bronpad wordt geblokkeerd of vraagt expliciet om een afzonderlijke, destructieve handeling; een gewone export verandert de bron niet. ## Technische aanwijzing _documentExport kent filePath/projectPath, maar _pickDocumentExportPath en writeDocumentExport vergelijken outputPath nergens met de bronlocatie. Gevonden bij audit van commit d439638c6bd1b519d68d87680cb022b7d5eddc85.
Author
Owner

Triage: accepted

Bevestigd tegen main (e93ef205c). writeDocumentExport (lib/services/document_export_service.dart) kent alleen outputPath en schrijft daar via writeStringAtomic naartoe; voor md is dat _projectedMarkdown(bundle, …). _pickDocumentExportPath (lib/widgets/document_editor_screen.dart) vergelijkt het gekozen pad nergens met state.filePath, terwijl de aanroeper dat pad wél in handen heeft (_writeDocumentExport in hetzelfde bestand).

Wat er dan gebeurt is erger dan "een bestand overschrijven": de export is de geprojecteerde body. In het geredigeerde profiel schrijft de gebruiker dus een geredigeerde versie over zijn eigen bron heen, terwijl de editor de oude tekst blijft vasthouden alsof er niets is — de volgende opslag maakt het definitief of draait het terug, maar hoe dan ook zonder dat iemand het zag.

Oplossingsrichting

Het brondocumentpad meegeven aan _pickDocumentExportPath en aan writeDocumentExport, en een uitvoerpad dat daarnaar wijst weigeren met een melding die zegt waarom ("een export is een kopie; kies een andere naam"). Vergelijken op het gecanoniseerde pad — symlinks opgelost, hoofdletterongevoelig waar het bestandssysteem dat is — en niet op stringgelijkheid.

Weigeren, niet waarschuwen-en-doorgaan: er is geen geval waarin "exporteer over mijn eigen document heen" is wat iemand bedoelde. Wie zijn document wil normaliseren doet dat met Opslaan, en dat is een andere handeling.

Neem in dezelfde pas mee of de deck-export dit gat ook heeft; zo ja, apart issue, niet hier verbreden.

Regressietest (verplicht)

test/document_export_write_test.dart: export met outputPath gelijk aan het bronpad → geweigerd (null), bronbestand byte-identiek. Plus een variant via een symlink of een andere schrijfwijze van hetzelfde pad, want dáár faalt een naïeve stringvergelijking.

Kosten

Service + scherm + één nieuwe l10n.d('…') ⇒ 31 vertalingen (make add-l10n, zie taalbouwer). Halve dag.

Prioriteit

Hoog binnen deze reeks: stil, onomkeerbaar verlies van het eigen document van de gebruiker.

## Triage: accepted **Bevestigd tegen `main` (e93ef205c).** `writeDocumentExport` (`lib/services/document_export_service.dart`) kent alleen `outputPath` en schrijft daar via `writeStringAtomic` naartoe; voor `md` is dat `_projectedMarkdown(bundle, …)`. `_pickDocumentExportPath` (`lib/widgets/document_editor_screen.dart`) vergelijkt het gekozen pad nergens met `state.filePath`, terwijl de aanroeper dat pad wél in handen heeft (`_writeDocumentExport` in hetzelfde bestand). Wat er dan gebeurt is erger dan "een bestand overschrijven": de export is de *geprojecteerde* body. In het geredigeerde profiel schrijft de gebruiker dus een geredigeerde versie over zijn eigen bron heen, terwijl de editor de oude tekst blijft vasthouden alsof er niets is — de volgende opslag maakt het definitief of draait het terug, maar hoe dan ook zonder dat iemand het zag. ## Oplossingsrichting Het brondocumentpad meegeven aan `_pickDocumentExportPath` en aan `writeDocumentExport`, en een uitvoerpad dat daarnaar wijst weigeren met een melding die zegt waarom ("een export is een kopie; kies een andere naam"). Vergelijken op het gecanoniseerde pad — symlinks opgelost, hoofdletterongevoelig waar het bestandssysteem dat is — en niet op stringgelijkheid. Weigeren, niet waarschuwen-en-doorgaan: er is geen geval waarin "exporteer over mijn eigen document heen" is wat iemand bedoelde. Wie zijn document wil normaliseren doet dat met Opslaan, en dat is een andere handeling. Neem in dezelfde pas mee of de deck-export dit gat ook heeft; zo ja, apart issue, niet hier verbreden. ## Regressietest (verplicht) `test/document_export_write_test.dart`: export met `outputPath` gelijk aan het bronpad → geweigerd (`null`), bronbestand byte-identiek. Plus een variant via een symlink of een andere schrijfwijze van hetzelfde pad, want dáár faalt een naïeve stringvergelijking. ## Kosten Service + scherm + één nieuwe `l10n.d('…')` ⇒ 31 vertalingen (`make add-l10n`, zie `taalbouwer`). Halve dag. ## Prioriteit Hoog binnen deze reeks: stil, onomkeerbaar verlies van het eigen document van de gebruiker.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
LibreKAT/Ocideck#1671
No description provided.