From d95bf69be0c4af4c61b422f3c0bb34dc2d8118c5 Mon Sep 17 00:00:00 2001 From: Carlos Date: Sun, 26 Apr 2026 13:17:11 -0400 Subject: [PATCH] Fix CSV export crash on filenames with embedded newlines Use QUOTE_ALL + sanitise NUL/CR/LF in path/filename/exif fields. Default csv dialect rejected fields containing line terminators with 'need to escape, but no escapechar set'. Co-Authored-By: Claude Opus 4.7 --- app/main.py | 16 +++++++++++++--- debian/build-deb.sh | 2 +- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/app/main.py b/app/main.py index 31fc31e..23598ce 100644 --- a/app/main.py +++ b/app/main.py @@ -689,17 +689,27 @@ def export_csv(): con.close() output = io.StringIO() - writer = csv.writer(output) + # QUOTE_ALL + explicit lineterminator handles paths/filenames containing + # embedded \r, \n, quotes, or NULs — which the default dialect refuses. + writer = csv.writer(output, quoting=csv.QUOTE_ALL, lineterminator="\n") writer.writerow([ "group_id", "method", "file_id", "path", "filename", "size", "width", "height", "exif_date", "device", "is_keeper", "is_redundant", "reviewed", ]) + + def _clean(v): + # Strip NULs (csv writer rejects them) and normalise embedded line breaks + if isinstance(v, str): + return v.replace("\x00", "").replace("\r\n", " ").replace("\r", " ").replace("\n", " ") + return v + for r in rows: writer.writerow([ r["group_id"], r["method"], r["file_id"], - r["path"], r["filename"], r["file_size"], - r["width"], r["height"], r["exif_datetime"], r["exif_device"], + _clean(r["path"]), _clean(r["filename"]), r["file_size"], + r["width"], r["height"], _clean(r["exif_datetime"]), + _clean(r["exif_device"]), r["is_keeper"], r["is_redundant"], r["reviewed"], ]) diff --git a/debian/build-deb.sh b/debian/build-deb.sh index 8ed8ab6..2a66680 100644 --- a/debian/build-deb.sh +++ b/debian/build-deb.sh @@ -13,7 +13,7 @@ BUILD_DIR="$REPO_ROOT/build/deb" # ── Config ──────────────────────────────────────────────────────────────────── PKG_NAME="dupfinder" -PKG_VERSION="1.0.3" +PKG_VERSION="1.0.4" PKG_ARCH="amd64" DEB_FILE="${PKG_NAME}_${PKG_VERSION}_${PKG_ARCH}.deb"