Mercurial > hg > orthanc
changeset 4453:4f8e77c650e8
new function MultipartStreamReader::ParseHeaderArguments()
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 19 Jan 2021 10:02:46 +0100 |
parents | a86fd55c4df0 |
children | f20a7655fb1c |
files | NEWS OrthancFramework/Sources/HttpServer/MultipartStreamReader.cpp OrthancFramework/Sources/HttpServer/MultipartStreamReader.h OrthancFramework/UnitTestsSources/RestApiTests.cpp |
diffstat | 4 files changed, 126 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/NEWS Mon Jan 18 15:04:36 2021 +0100 +++ b/NEWS Tue Jan 19 10:02:46 2021 +0100 @@ -24,6 +24,7 @@ Maintenance ----------- +* Partial fix of issue #48 (Windows service not stopped properly), cf. comment 4 * Upgraded dependencies for static builds (notably on Windows): - jsoncpp 1.9.4
--- a/OrthancFramework/Sources/HttpServer/MultipartStreamReader.cpp Mon Jan 18 15:04:36 2021 +0100 +++ b/OrthancFramework/Sources/HttpServer/MultipartStreamReader.cpp Tue Jan 19 10:02:46 2021 +0100 @@ -23,6 +23,7 @@ #include "../PrecompiledHeaders.h" #include "MultipartStreamReader.h" +#include "../Logging.h" #include "../OrthancException.h" #include "../Toolbox.h" @@ -332,7 +333,7 @@ bool valid = false; subType.clear(); - for (size_t i = 0; i < tokens.size(); i++) + for (size_t i = 1; i < tokens.size(); i++) { std::vector<std::string> items; Toolbox::TokenizeString(items, tokens[i], '='); @@ -362,4 +363,66 @@ return valid; } + + + bool MultipartStreamReader::ParseHeaderArguments(std::string& main, + std::map<std::string, std::string>& arguments, + const std::string& header) + { + std::vector<std::string> tokens; + Toolbox::TokenizeString(tokens, header, ';'); + + if (tokens.empty()) + { + return false; + } + + main = Toolbox::StripSpaces(tokens[0]); + Toolbox::ToLowerCase(main); + if (main.empty()) + { + return false; + } + + arguments.clear(); + + for (size_t i = 1; i < tokens.size(); i++) + { + std::vector<std::string> items; + Toolbox::TokenizeString(items, tokens[i], '='); + + if (items.size() > 2) + { + return false; + } + else if (!items.empty()) + { + std::string key = Toolbox::StripSpaces(items[0]); + Toolbox::ToLowerCase(key); + + if (arguments.find(key) != arguments.end()) + { + LOG(ERROR) << "The same argument was provided twice in an HTTP header: \"" + << key << "\" in \"" << header << "\""; + return false; + } + else if (!key.empty()) + { + if (items.size() == 1) + { + arguments[key] = ""; + } + else + { + assert(items.size() == 2); + std::string value = Toolbox::StripSpaces(items[1]); + RemoveSurroundingQuotes(value); + arguments[key] = value; + } + } + } + } + + return true; + } }
--- a/OrthancFramework/Sources/HttpServer/MultipartStreamReader.h Mon Jan 18 15:04:36 2021 +0100 +++ b/OrthancFramework/Sources/HttpServer/MultipartStreamReader.h Tue Jan 19 10:02:46 2021 +0100 @@ -86,5 +86,9 @@ std::string& subType, // Possibly empty std::string& boundary, const std::string& contentTypeHeader); + + static bool ParseHeaderArguments(std::string& main, + std::map<std::string, std::string>& arguments, + const std::string& header); }; }
--- a/OrthancFramework/UnitTestsSources/RestApiTests.cpp Mon Jan 18 15:04:36 2021 +0100 +++ b/OrthancFramework/UnitTestsSources/RestApiTests.cpp Tue Jan 19 10:02:46 2021 +0100 @@ -836,6 +836,63 @@ } +TEST(MultipartStreamReader, ParseHeaders2) +{ + std::string main; + std::map<std::string, std::string> args; + + ASSERT_FALSE(MultipartStreamReader::ParseHeaderArguments(main, args, "")); + ASSERT_FALSE(MultipartStreamReader::ParseHeaderArguments(main, args, " ")); + ASSERT_FALSE(MultipartStreamReader::ParseHeaderArguments(main, args, " ; ")); + + ASSERT_TRUE(MultipartStreamReader::ParseHeaderArguments(main, args, "hello")); + ASSERT_EQ("hello", main); + ASSERT_TRUE(args.empty()); + + ASSERT_TRUE(MultipartStreamReader::ParseHeaderArguments(main, args, "hello ; a = \" b \";c=d ; e=f;")); + ASSERT_EQ("hello", main); + ASSERT_EQ(3u, args.size()); + ASSERT_EQ(" b ", args["a"]); + ASSERT_EQ("d", args["c"]); + ASSERT_EQ("f", args["e"]); + + ASSERT_TRUE(MultipartStreamReader::ParseHeaderArguments(main, args, " hello ;;;; ; ")); + ASSERT_EQ("hello", main); + ASSERT_TRUE(args.empty()); + + ASSERT_FALSE(MultipartStreamReader::ParseHeaderArguments(main, args, "hello;a=b;c=d;a=f")); + + ASSERT_TRUE(MultipartStreamReader::ParseHeaderArguments(main, args, "multipart/related; dummy=value; boundary=1234; hello=world")); + ASSERT_EQ("multipart/related", main); + ASSERT_EQ(3u, args.size()); + ASSERT_EQ("value", args["dummy"]); + ASSERT_EQ("1234", args["boundary"]); + ASSERT_EQ("world", args["hello"]); + + ASSERT_TRUE(MultipartStreamReader::ParseHeaderArguments(main, args, "multipart/related; boundary=")); + ASSERT_EQ("multipart/related", main); + ASSERT_EQ(1u, args.size()); + ASSERT_EQ("", args["boundary"]); + + ASSERT_TRUE(MultipartStreamReader::ParseHeaderArguments(main, args, "multipart/related; boundary")); + ASSERT_EQ("multipart/related", main); + ASSERT_EQ(1u, args.size()); + ASSERT_EQ("", args["boundary"]); + + ASSERT_TRUE(MultipartStreamReader::ParseHeaderArguments(main, args, "Multipart/Related; TYPE=Application/Dicom; Boundary=heLLO")); + ASSERT_EQ("multipart/related", main); + ASSERT_EQ(2u, args.size()); + ASSERT_EQ("Application/Dicom", args["type"]); + ASSERT_EQ("heLLO", args["boundary"]); + + ASSERT_TRUE(MultipartStreamReader::ParseHeaderArguments(main, args, "Multipart/Related; type=\"application/DICOM\"; Boundary=a")); + ASSERT_EQ("multipart/related", main); + ASSERT_EQ(2u, args.size()); + ASSERT_EQ("application/DICOM", args["type"]); + ASSERT_EQ("a", args["boundary"]); +} + + TEST(MultipartStreamReader, BytePerByte) { std::string stream = "GARBAGE";