Skip to content

Expose the handle constructors and fix multiline response parsing - #5

Merged
onslaughtq merged 5 commits into
mainfrom
pr-2-multiline-and-handle-exports
Sep 1, 2026
Merged

onslaughtq merged 5 commits into
mainfrom
pr-2-multiline-and-handle-exports

Conversation

@onslaughtq

@onslaughtq onslaughtq commented Aug 22, 2026 •

Copy link
Copy Markdown

@pucsdian's three commits from #2, cherry-picked so the authorship stays theirs, plus tests and one correction.

The diagnosis in #2 is right. RFC 959 ends a multiline reply with the code followed by a space and continues it with the code followed by a hyphen, so the old three byte comparison stopped at the first continuation line that happened to repeat the code. 220-First / 220-Second / 220 Third came back as two lines.

Two things needed adding. The suite has had a multiline test since 2019, but its continuation line doesn't repeat the code, so it passes under both the old and the new logic and never covered this. And requiring the code followed by a space regresses servers whose final line is the bare code with no trailing text — those terminated under the old comparison but would now loop until the socket closed. Both forms are accepted.

Three new examples, twelve in the suite. The RFC case fails against the old check, and the bare code case fails against the unhardened fix.

Two notes for whoever merges this:

Please use a merge commit or a rebase rather than a squash, or the three commits collapse into one authored by whoever pressed the button.

This supersedes #2, but GitHub's closing keywords only work on issues, so #2 needs closing by hand afterwards.

Stacked: add-ci-multi-ghc → fix-response-line-partiality → pr-2-multiline-and-handle-exports → add-ci-flag → add-henforcer-fourmolu → fix-audit-findings. Merge bottom-up.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Exposes lower-level connection constructors and corrects FTP multiline response termination.

Changes:

  • Exports handle and TLS connection constructors.
  • Implements RFC 959-compatible multiline parsing with regression tests.
  • Bumps the package version and updates the changelog.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/Network/FTP/Client.hs Exports constructors and fixes multiline parsing.
test/test.hs Adds multiline response regression tests.
package.yaml Bumps version to 0.5.2.0.
ftp-client.cabal Synchronizes the generated package version.
CHANGELOG.md Documents the release changes.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread ftp-client/src/Network/FTP/Client.hs
Comment thread ftp-client/src/Network/FTP/Client.hs
pucsdian and others added 5 commits August 24, 2026 20:38
Adds the cases that distinguish the new terminator check from the old one.
The multiline test that has been here since 277d621 passes either way, so
it never covered this: its continuation line does not repeat the code.

Requiring the code followed by a space is what RFC 959 specifies, but it
regressed servers whose final line is the bare code with no trailing
space. Those terminated under the old prefix comparison and would now
loop until the socket closed. Accept both forms.
The three newly exported functions are an additive API change, so PVP asks
for a minor bump. This stays inside the ftp-client == 0.5.* bound that
ftp-client-conduit depends on, which therefore needs no bump of its own.

The package has never carried a changelog. Seed one covering this release
and point at git history for anything earlier.
@onslaughtq
onslaughtq force-pushed the pr-2-multiline-and-handle-exports branch from 02cd84a to 1fbc526 Compare August 25, 2026 00:59
Base automatically changed from fix-response-line-partiality to main August 27, 2026 16:21
@onslaughtq
onslaughtq marked this pull request as ready for review August 31, 2026 13:11
@onslaughtq

Copy link
Copy Markdown
Author

@pucsdian — this is the PR I mentioned on #2, and it's going in now. Thanks for the fix, and sorry it sat so long.

Your three commits are here as-is, so the authorship stays yours, and you're credited in the new ftp-client 0.5.2.0 changelog entry for both halves of the change.

Your diagnosis was right, and the RFC 959 reference was exactly the right one to reach for. The old three-byte comparison ended the reply at the first continuation line that happened to repeat the code, so 220-First / 220-Second / 220 Third came back truncated to two lines with the real terminator left unread.

Two things were added on top rather than merged directly, which is why this landed as a new PR instead of a merge of #2.

Tests. Answering @ysangkok's question on #2: there is a suite, at ftp-client/test/test.hs. It has been there since 2019 (277d621) and builds a fake Handle out of scripted responses, so it needs no network. It simply wasn't covering this — its multiline case uses a bare line2 as the continuation line, which never repeats the code, so it passes under both the old and the new logic. Three examples were added for the RFC 959 shape from your report, and those do fail against the old check.

One correction. C.isPrefixOf (code <> " ") on its own never matches a final line that is the bare code with no trailing space, so a server answering 226 rather than 226 would have looped until the socket closed — where the old three-byte comparison terminated. The terminator now accepts both forms:

isLastLine = nextLine == code || C.isPrefixOf (code <> " ") nextLine

Thanks again — the bug was real, and the report was clear enough to fix from directly.

@onslaughtq
onslaughtq merged commit 1fbc526 into main Sep 1, 2026
15 checks passed
@onslaughtq
onslaughtq deleted the pr-2-multiline-and-handle-exports branch September 1, 2026 20:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants