Escape the database path in the SQLite connection string (closes #518) #523

Merged
clawbot merged 1 commits from issue-518-escape-sqlite-path into next 2026-10-13 09:30:25 +02:00
Collaborator

Fixes #518.

SQLiteDSN now builds the file: URI with url.URL, which escapes the path. SQLite reads a file: URI's path only up to the first ? or # and decodes %XX escapes in it, so a data directory such as /srv/hooks#1 sent every database to the one file /srv/hooks. The driver also splits its own settings off at the first ? anywhere in the string, so a ? in the path lost the busy timeout as well.

What the diff does not show:

  • OmitHost is what keeps a relative DATA_DIR working. Without it a relative path is written file://data/... and SQLite rejects data as the URI's authority. TestOpenSQLiteOpensARelativePath opens a database at a relative path so that this cannot break unnoticed.
  • The tests read PRAGMA database_list, which names the file SQLite actually opened. They compare that file with os.SameFile rather than comparing names, because SQLite resolves symlinks in the name it reports.
  • A comment in delivery_attempts_test.go said a # in the temporary directory's path broke the database path. That is no longer true, so the comment is gone.
  • Judgement call: a path that starts with // is still rejected by SQLite as carrying an authority, as it was before. Out of scope here.

Model: opus-5-5

Fixes https://git.eeqj.de/sneak/webhooker/issues/518. `SQLiteDSN` now builds the `file:` URI with `url.URL`, which escapes the path. SQLite reads a `file:` URI's path only up to the first `?` or `#` and decodes `%XX` escapes in it, so a data directory such as `/srv/hooks#1` sent every database to the one file `/srv/hooks`. The driver also splits its own settings off at the first `?` anywhere in the string, so a `?` in the path lost the busy timeout as well. What the diff does not show: - `OmitHost` is what keeps a relative `DATA_DIR` working. Without it a relative path is written `file://data/...` and SQLite rejects `data` as the URI's authority. `TestOpenSQLiteOpensARelativePath` opens a database at a relative path so that this cannot break unnoticed. - The tests read `PRAGMA database_list`, which names the file SQLite actually opened. They compare that file with `os.SameFile` rather than comparing names, because SQLite resolves symlinks in the name it reports. - A comment in `delivery_attempts_test.go` said a `#` in the temporary directory's path broke the database path. That is no longer true, so the comment is gone. - Judgement call: a path that starts with `//` is still rejected by SQLite as carrying an authority, as it was before. Out of scope here. Model: opus-5-5
clawbot added the needs-review label 2026-10-13 07:26:43 +02:00
clawbot self-assigned this 2026-10-13 07:26:43 +02:00
Author
Collaborator

Review: changes needed.

  1. internal/database/sqlite_open.go, the OmitHost: true line in SQLiteDSN: this line is what keeps a relative DATA_DIR working, including the README's own DATA_DIR=../webhooker-data make dev, but no test opens a database at a relative path. Without it every relative DATA_DIR fails to open and no test notices. Acceptable: a test that opens a database through OpenSQLite at a relative path (using t.Chdir, as internal/config/dotenv_test.go does) and checks that SQLite opened the file asked for.

  2. internal/handlers/delivery_attempts_test.go, lines 45-47: the comment still says a # in the temporary directory's path cuts short the path SQLiteDSN gives SQLite. After this change it no longer does, so the comment is false. Acceptable: drop that clause (or the whole comment).

Model: opus-5-5

Review: changes needed. 1. `internal/database/sqlite_open.go`, the `OmitHost: true` line in `SQLiteDSN`: this line is what keeps a relative `DATA_DIR` working, including the README's own `DATA_DIR=../webhooker-data make dev`, but no test opens a database at a relative path. Without it every relative `DATA_DIR` fails to open and no test notices. Acceptable: a test that opens a database through `OpenSQLite` at a relative path (using `t.Chdir`, as `internal/config/dotenv_test.go` does) and checks that SQLite opened the file asked for. 2. `internal/handlers/delivery_attempts_test.go`, lines 45-47: the comment still says a `#` in the temporary directory's path cuts short the path `SQLiteDSN` gives SQLite. After this change it no longer does, so the comment is false. Acceptable: drop that clause (or the whole comment). Model: opus-5-5
clawbot added needs-rework and removed needs-review labels 2026-10-13 08:25:41 +02:00
clawbot added 1 commit 2026-10-13 08:59:46 +02:00
SQLite reads a file: URI's path only up to the first ? or #, and
decodes %XX escapes in it. With a data directory such as
/srv/hooks#1, every database opened the one file /srv/hooks. The
connection string is now built with url.URL, which escapes the path,
and OmitHost keeps a relative path relative.

Tests open databases in a directory whose name holds #, ? and %, and
at a relative path, and check through PRAGMA database_list that each
opened the file asked for. A handlers test comment that blamed # in
the temporary directory's path is dropped, as that is no longer true.

Model: opus-5-5
clawbot force-pushed issue-518-escape-sqlite-path from a2f6bc17f6 to 0ef53a4e15 2026-10-13 08:59:46 +02:00 Compare
clawbot changed title from Escape the database path in the SQLite connection string to Escape the database path in the SQLite connection string (closes #518) 2026-10-13 08:59:52 +02:00
clawbot added needs-review and removed needs-rework labels 2026-10-13 09:00:01 +02:00
Author
Collaborator
  1. Added TestOpenSQLiteOpensARelativePath, which changes into a temporary directory with t.Chdir, opens data/webhooker.db through OpenSQLite, and checks with PRAGMA database_list that SQLite opened that file. It fails when OmitHost is removed.
  2. Removed the comment.

Model: opus-5-5

1. Added `TestOpenSQLiteOpensARelativePath`, which changes into a temporary directory with `t.Chdir`, opens `data/webhooker.db` through `OpenSQLite`, and checks with `PRAGMA database_list` that SQLite opened that file. It fails when `OmitHost` is removed. 2. Removed the comment. Model: opus-5-5
Author
Collaborator

Review passed.

Model: opus-5-5

Review passed. Model: opus-5-5
clawbot merged commit 267d5b12f2 into next 2026-10-13 09:30:25 +02:00
clawbot deleted branch issue-518-escape-sqlite-path 2026-10-13 09:30:25 +02:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/webhooker#523