From c5effe9c511a17d0367e9a08094389d8c5745ae1 Mon Sep 17 00:00:00 2001 From: Bertrand Darbon Date: Sun, 26 Sep 2021 02:51:13 +0200 Subject: [PATCH] fix(MutliPart): Does not respect quotes in Content-Disposition header (#1031) * fix(MutliPart): Does not respect quotes in Content-Disposition header Currently, Drogon MultiPart parser expects quotes for name and filename in the Content-Disposition header. The builtin HTTP library for .NET Core (System.Net.Http.HttpClient) leaves the quotes in this header, which means that by default, .NET Core applications cannot upload files to drogon. The related RFC https://datatracker.ietf.org/doc/html/rfc6266 allows for both usages. This contribution aims to fix this and handle both cases (with or without quotes) --- lib/src/MultiPart.cc | 44 +++++++++++++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/lib/src/MultiPart.cc b/lib/src/MultiPart.cc index 73cdce58..50a57d01 100644 --- a/lib/src/MultiPart.cc +++ b/lib/src/MultiPart.cc @@ -76,20 +76,28 @@ int MultiPartParser::parse(const HttpRequestPtr &req) int MultiPartParser::parseEntity(const char *begin, const char *end) { - static const char entityName[] = "name=\""; - static const char quotationMark[] = "\""; - static const char fileName[] = "filename=\""; + static const char entityName[] = "name="; + static const char semiColon[] = ";"; + static const char fileName[] = "filename="; static const char CRLF[] = "\r\n\r\n"; - auto pos = std::search(begin, end, entityName, entityName + 6); + auto pos = std::search(begin, end, entityName, entityName + 5); if (pos == end) return -1; - pos += 6; - auto pos1 = std::search(pos, end, quotationMark, quotationMark + 1); + pos += 5; + auto pos1 = std::search(pos, end, semiColon, semiColon + 1); if (pos1 == end) - return -1; + { + pos1 = std::search(pos, end, CRLF, CRLF + 2); + if (pos1 == end) + return -1; + } + if (*pos == '"') + pos++; + if (*(pos1 - 1) == '"') + pos1--; std::string name(pos, pos1); - pos = std::search(pos1, end, fileName, fileName + 10); + pos = std::search(pos1, end, fileName, fileName + 9); if (pos == end) { pos1 = std::search(pos1, end, CRLF, CRLF + 4); @@ -100,10 +108,24 @@ int MultiPartParser::parseEntity(const char *begin, const char *end) } else { - pos += 10; - auto pos1 = std::search(pos, end, quotationMark, quotationMark + 1); + pos += 9; + pos1 = std::search(pos, end, semiColon, semiColon + 1); if (pos1 == end) - return -1; + { + pos1 = std::search(pos, end, CRLF, CRLF + 2); + if (pos1 == end) + return -1; + } + else + { + auto pos2 = std::search(pos, pos1, CRLF, CRLF + 2); + if (pos2 != end) + pos1 = pos2; + } + if (*pos == '"') + pos++; + if (*(pos1 - 1) == '"') + pos1--; auto filePtr = std::make_shared(); filePtr->setRequest(requestPtr_); filePtr->setItemName(name);