diff --git a/src/acl/UrlPath.cc b/src/acl/UrlPath.cc index ba5c7c19da4..8b894fbcc82 100644 --- a/src/acl/UrlPath.cc +++ b/src/acl/UrlPath.cc @@ -12,15 +12,19 @@ #include "acl/FilledChecklist.h" #include "acl/UrlPath.h" #include "HttpRequest.h" +#include "rfc1738.h" int Acl::UrlPathCheck::match(ACLChecklist * const ch) { const auto checklist = Filled(ch); - auto urlPath = checklist->request->url.path(); - if (urlPath.isEmpty()) + if (checklist->request->url.path().isEmpty()) return -1; - return data->match(urlPath.c_str()); + const auto esc_buf = SBufToCstring(checklist->request->url.path()); + rfc1738_unescape(esc_buf); + const auto result = data->match(esc_buf); + xfree(esc_buf); + return result; } diff --git a/src/anyp/Uri.cc b/src/anyp/Uri.cc index 5263ba5752e..904bdb58106 100644 --- a/src/anyp/Uri.cc +++ b/src/anyp/Uri.cc @@ -50,25 +50,6 @@ UserInfoChars() return userInfoValid; } -/// Characters which are valid within a URI path section -static const CharacterSet & -PathChars() -{ - /* - * RFC 3986 section 3.3 - * - * path = path-abempty ; begins with "/" or is empty - * ... - * path-abempty = *( "/" segment ) - * segment = *pchar - * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" - */ - static const auto pathValid = CharacterSet("path", "/:@-._~%!$&'()*+,;=") + - CharacterSet::ALPHA + - CharacterSet::DIGIT; - return pathValid; -} - /** * Governed by RFC 3986 section 2.1 */ @@ -776,7 +757,7 @@ AnyP::Uri::absolutePath() const { if (absolutePath_.isEmpty()) { // TODO: Encode each URI subcomponent in path_ as needed. - absolutePath_ = Encode(path(), PathChars()); + absolutePath_ = path(); } return absolutePath_; diff --git a/src/clients/FtpGateway.cc b/src/clients/FtpGateway.cc index 6352ce8c057..501f6c45c31 100644 --- a/src/clients/FtpGateway.cc +++ b/src/clients/FtpGateway.cc @@ -142,7 +142,6 @@ class Gateway : public Ftp::Client int checkAuth(const HttpHeader * req_hdr); void checkUrlpath(); - std::optional decodedRequestUriPath() const; void buildTitleUrl(); void writeReplyBody(const char *, size_t len); void completeForwarding() override; @@ -2304,15 +2303,7 @@ ftpReadQuit(Ftp::Gateway * ftpState) ftpState->serverComplete(); } -/// absolute request URI path after successful decoding of all pct-encoding sequences -std::optional -Ftp::Gateway::decodedRequestUriPath() const -{ - return AnyP::Uri::Decode(request->url.absolutePath()); -} - /// \prec !ftpState->flags.try_slash_hack -/// \prec ftpState->decodedRequestUriPath() static void ftpTrySlashHack(Ftp::Gateway * ftpState) { @@ -2325,9 +2316,10 @@ ftpTrySlashHack(Ftp::Gateway * ftpState) wordlistDestroy(&ftpState->pathcomps); /* Build the new path */ - // XXX: Conversion to c-string effectively truncates where %00 was decoded safe_free(ftpState->filepath); - ftpState->filepath = SBufToCstring(ftpState->decodedRequestUriPath().value()); + const auto path = SBufToCstring(ftpState->request->url.absolutePath()); + rfc1738_unescape(path); + ftpState->filepath = path; /* And off we go */ ftpGetFile(ftpState); @@ -2382,15 +2374,13 @@ ftpFail(Ftp::Gateway *ftpState) " reply code " << code << "flags(" << (ftpState->flags.isdir?"IS_DIR,":"") << (ftpState->flags.try_slash_hack?"TRY_SLASH_HACK":"") << "), " << - "decodable_filepath=" << bool(ftpState->decodedRequestUriPath()) << ' ' << "mdtm=" << ftpState->mdtm << ", size=" << ftpState->theSize << "slashhack=" << (slashHack? "T":"F")); /* Try the / hack to support "Netscape" FTP URL's for retrieving files */ if (!ftpState->flags.isdir && /* Not a directory */ !ftpState->flags.try_slash_hack && !slashHack && /* Not doing slash hack */ - ftpState->mdtm <= 0 && ftpState->theSize < 0 && /* Not known as a file */ - ftpState->decodedRequestUriPath()) { + ftpState->mdtm <= 0 && ftpState->theSize < 0) { /* Not known as a file */ switch (ftpState->state) {