From da730478af0cdae2936053d6f9789cee12c95b7d Mon Sep 17 00:00:00 2001 From: JimmyZ Date: Wed, 28 Dec 2016 00:44:46 +0800 Subject: [PATCH 1/2] new option content-disposition-default-utf8 --- src/HttpResponse.cc | 5 +- src/HttpResponse.h | 2 +- src/HttpResponseCommand.cc | 4 +- src/OptionHandlerFactory.cc | 12 + src/prefs.cc | 3 + src/prefs.h | 2 + src/usage_text.h | 5 + src/util.cc | 31 +- src/util.h | 8 +- test/HttpResponseTest.cc | 6 +- test/UtilTest1.cc | 601 +++++++++++++++++++----------------- 11 files changed, 373 insertions(+), 306 deletions(-) diff --git a/src/HttpResponse.cc b/src/HttpResponse.cc index f009ecae..230041d9 100644 --- a/src/HttpResponse.cc +++ b/src/HttpResponse.cc @@ -112,10 +112,11 @@ void HttpResponse::validateResponse() const error_code::HTTP_PROTOCOL_ERROR); } -std::string HttpResponse::determineFilename() const +std::string HttpResponse::determineFilename(bool contentDispositionUTF8) const { std::string contentDisposition = util::getContentDispositionFilename( - httpHeader_->find(HttpHeader::CONTENT_DISPOSITION)); + httpHeader_->find(HttpHeader::CONTENT_DISPOSITION), + contentDispositionUTF8); if (contentDisposition.empty()) { auto file = httpRequest_->getFile(); file = util::percentDecode(file.begin(), file.end()); diff --git a/src/HttpResponse.h b/src/HttpResponse.h index 38bfa342..2caffaf1 100644 --- a/src/HttpResponse.h +++ b/src/HttpResponse.h @@ -70,7 +70,7 @@ public: * this function returns the filename from it. * If it is not there, returns the part of filename from the request URL. */ - std::string determineFilename() const; + std::string determineFilename(bool contentDispositionUTF8) const; void retrieveCookie(); diff --git a/src/HttpResponseCommand.cc b/src/HttpResponseCommand.cc index 18972575..d0e44803 100644 --- a/src/HttpResponseCommand.cc +++ b/src/HttpResponseCommand.cc @@ -261,8 +261,8 @@ bool HttpResponseCommand::executeInternal() int64_t totalLength = httpResponse->getEntityLength(); fe->setLength(totalLength); if (fe->getPath().empty()) { - auto suffixPath = util::createSafePath(httpResponse->determineFilename()); - + auto suffixPath = util::createSafePath(httpResponse->determineFilename( + getOption()->getAsBool(PREF_CONTENT_DISPOSITION_DEFAULT_UTF8))); fe->setPath(util::applyDir(getOption()->get(PREF_DIR), suffixPath)); fe->setSuffixPath(suffixPath); } diff --git a/src/OptionHandlerFactory.cc b/src/OptionHandlerFactory.cc index fd963613..b8f07770 100644 --- a/src/OptionHandlerFactory.cc +++ b/src/OptionHandlerFactory.cc @@ -1054,6 +1054,18 @@ std::vector OptionHandlerFactory::createOptionHandlers() op->addTag(TAG_HTTPS); handlers.push_back(op); } + { + OptionHandler* op( + new BooleanOptionHandler(PREF_CONTENT_DISPOSITION_DEFAULT_UTF8, + TEXT_CONTENT_DISPOSITION_DEFAULT_UTF8, + A2_V_FALSE, OptionHandler::OPT_ARG)); + op->addTag(TAG_ADVANCED); + op->addTag(TAG_HTTP); + op->setInitialOption(true); + op->setChangeGlobalOption(true); + op->setChangeOptionForReserved(true); + handlers.push_back(op); + } { OptionHandler* op(new BooleanOptionHandler( PREF_ENABLE_HTTP_KEEP_ALIVE, TEXT_ENABLE_HTTP_KEEP_ALIVE, A2_V_TRUE, diff --git a/src/prefs.cc b/src/prefs.cc index c0e1af6d..4f213f2c 100644 --- a/src/prefs.cc +++ b/src/prefs.cc @@ -427,6 +427,9 @@ PrefPtr PREF_HTTP_AUTH_CHALLENGE = makePref("http-auth-challenge"); PrefPtr PREF_HTTP_NO_CACHE = makePref("http-no-cache"); // value: true | false PrefPtr PREF_HTTP_ACCEPT_GZIP = makePref("http-accept-gzip"); +// value: true | false +PrefPtr PREF_CONTENT_DISPOSITION_DEFAULT_UTF8 = + makePref("content-disposition-default-utf8"); /** * Proxy related preferences diff --git a/src/prefs.h b/src/prefs.h index fb064727..91fa8769 100644 --- a/src/prefs.h +++ b/src/prefs.h @@ -380,6 +380,8 @@ extern PrefPtr PREF_HTTP_AUTH_CHALLENGE; extern PrefPtr PREF_HTTP_NO_CACHE; // value: true | false extern PrefPtr PREF_HTTP_ACCEPT_GZIP; +// value: true | false +extern PrefPtr PREF_CONTENT_DISPOSITION_DEFAULT_UTF8; /**; * Proxy related preferences diff --git a/src/usage_text.h b/src/usage_text.h index 3bd835eb..19817bcd 100644 --- a/src/usage_text.h +++ b/src/usage_text.h @@ -537,6 +537,11 @@ #define TEXT_USE_HEAD \ _(" --use-head[=true|false] Use HEAD method for the first request to the HTTP\n" \ " server.") +#define TEXT_CONTENT_DISPOSITION_DEFAULT_UTF8 \ + _(" --content-disposition-default-utf8[=true|false] Handle quoted string in\n" \ + " Content-Disposition header as UTF-8 instead of\n" \ + " ISO-8859-1, for example, the filename parameter,\n" \ + " but not the extended version filename*.") #define TEXT_EVENT_POLL \ _(" --event-poll=POLL Specify the method for polling events.") #define TEXT_BT_EXTERNAL_IP \ diff --git a/src/util.cc b/src/util.cc index 8229f98b..4d9b5fd0 100644 --- a/src/util.cc +++ b/src/util.cc @@ -879,7 +879,7 @@ typedef enum { ssize_t parse_content_disposition(char* dest, size_t destlen, const char** charsetp, size_t* charsetlenp, - const char* in, size_t len) + const char* in, size_t len, bool defaultUTF8) { const char *p = in, *eop = in + len, *mark_first = nullptr, *mark_last = nullptr; @@ -891,7 +891,7 @@ ssize_t parse_content_disposition(char* dest, size_t destlen, /* To suppress warnings */ char* dp = dest; size_t dlen = destlen; - uint32_t dfa_state = 0; + uint32_t dfa_state = UTF8_ACCEPT; uint32_t dfa_code = 0; uint8_t pctval = 0; @@ -981,6 +981,10 @@ ssize_t parse_content_disposition(char* dest, size_t destlen, if (*p == '"') { quoted_seen = 0; state = CD_QUOTED_STRING; + if (defaultUTF8) { + dfa_state = UTF8_ACCEPT; + dfa_code = 0; + } } else if (inRFC2616HttpToken(*p)) { if (in_file_parm) { @@ -1011,16 +1015,25 @@ ssize_t parse_content_disposition(char* dest, size_t destlen, quoted_seen = 1; } else if (*p == '"' && quoted_seen == 0) { + if (defaultUTF8 && dfa_state != UTF8_ACCEPT) { + return -1; + } if (in_file_parm) { flags |= CD_FILENAME_FOUND; } state = CD_AFTER_VALUE; } else { - /* TEXT which is OCTET except CTLs, but including LWS. We only - accept ISO-8859-1 chars. */ + /* TEXT which is OCTET except CTLs, but including LWS. Accept + ISO-8859-1 chars, or UTF-8 if defaultUTF8 is set */ quoted_seen = 0; - if (!isIso8859p1(*p)) { + if (defaultUTF8) { + if (utf8dfa(&dfa_state, &dfa_code, (unsigned char)*p) == + UTF8_REJECT) { + return -1; + } + } + else if (!isIso8859p1(*p)) { return -1; } if (in_file_parm) { @@ -1204,7 +1217,8 @@ ssize_t parse_content_disposition(char* dest, size_t destlen, } } -std::string getContentDispositionFilename(const std::string& header) +std::string getContentDispositionFilename(const std::string& header, + bool defaultUTF8) { std::array cdval; size_t cdvallen = cdval.size(); @@ -1212,13 +1226,14 @@ std::string getContentDispositionFilename(const std::string& header) size_t charsetlen; ssize_t rv = parse_content_disposition(cdval.data(), cdvallen, &charset, &charsetlen, - header.c_str(), header.size()); + header.c_str(), header.size(), defaultUTF8); if (rv == -1) { return ""; } std::string res; - if (!charset || strieq(charset, charset + charsetlen, "iso-8859-1")) { + if ((charset && strieq(charset, charset + charsetlen, "iso-8859-1")) || + (!charset && !defaultUTF8)) { res = iso8859p1ToUtf8(cdval.data(), rv); } else { diff --git a/src/util.h b/src/util.h index 76ecb549..2fc8ca40 100644 --- a/src/util.h +++ b/src/util.h @@ -322,11 +322,15 @@ std::string iso8859p1ToUtf8(const std::string& src); // succeeds, or -1. If there is enough room to store filename in // |dest|, this function returns -1. If this function returns -1, the // |dest|, |*charsetp| and |*charsetlenp| are undefined. +// +// It will handle quoted string(as in RFC 7230 section 3.2.6) as +// ISO-8859-1 by default, or UTF-8 if defaultUTF8 == true. ssize_t parse_content_disposition(char* dest, size_t destlen, const char** charsetp, size_t* charsetlenp, - const char* in, size_t len); + const char* in, size_t len, bool defaultUTF8); -std::string getContentDispositionFilename(const std::string& header); +std::string getContentDispositionFilename(const std::string& header, + bool defaultUTF8); std::string toUpper(std::string src); diff --git a/test/HttpResponseTest.cc b/test/HttpResponseTest.cc index f34e1219..ab1e5a8f 100644 --- a/test/HttpResponseTest.cc +++ b/test/HttpResponseTest.cc @@ -148,7 +148,7 @@ void HttpResponseTest::testDetermineFilename_without_ContentDisposition() httpResponse.setHttpRequest(std::move(httpRequest)); CPPUNIT_ASSERT_EQUAL(std::string("aria2-1.0.0.tar.bz2"), - httpResponse.determineFilename()); + httpResponse.determineFilename(false)); } void HttpResponseTest:: @@ -166,7 +166,7 @@ void HttpResponseTest:: httpResponse.setHttpRequest(std::move(httpRequest)); CPPUNIT_ASSERT_EQUAL(std::string("aria2-1.0.0.tar.bz2"), - httpResponse.determineFilename()); + httpResponse.determineFilename(false)); } void HttpResponseTest::testDetermineFilename_with_ContentDisposition() @@ -184,7 +184,7 @@ void HttpResponseTest::testDetermineFilename_with_ContentDisposition() httpResponse.setHttpRequest(std::move(httpRequest)); CPPUNIT_ASSERT_EQUAL(std::string("aria2-current.tar.bz2"), - httpResponse.determineFilename()); + httpResponse.determineFilename(false)); } void HttpResponseTest::testGetRedirectURI_without_Location() diff --git a/test/UtilTest1.cc b/test/UtilTest1.cc index 08ac13d4..554b3905 100644 --- a/test/UtilTest1.cc +++ b/test/UtilTest1.cc @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -751,68 +752,78 @@ void UtilTest1::testGetContentDispositionFilename() val = "attachment; filename=\"aria2.tar.bz2\""; CPPUNIT_ASSERT_EQUAL(std::string("aria2.tar.bz2"), - util::getContentDispositionFilename(val)); + util::getContentDispositionFilename(val, false)); val = "attachment; filename=\"\""; CPPUNIT_ASSERT_EQUAL(std::string(""), - util::getContentDispositionFilename(val)); + util::getContentDispositionFilename(val, false)); val = "attachment; filename=\""; CPPUNIT_ASSERT_EQUAL(std::string(""), - util::getContentDispositionFilename(val)); + util::getContentDispositionFilename(val, false)); val = "attachment; filename= \" aria2.tar.bz2 \""; CPPUNIT_ASSERT_EQUAL(std::string(" aria2.tar.bz2 "), - util::getContentDispositionFilename(val)); + util::getContentDispositionFilename(val, false)); val = "attachment; filename=dir/file"; CPPUNIT_ASSERT_EQUAL(std::string(""), - util::getContentDispositionFilename(val)); + util::getContentDispositionFilename(val, false)); val = "attachment; filename=dir\\file"; CPPUNIT_ASSERT_EQUAL(std::string(""), - util::getContentDispositionFilename(val)); + util::getContentDispositionFilename(val, false)); val = "attachment; filename=\"dir/file\""; CPPUNIT_ASSERT_EQUAL(std::string(""), - util::getContentDispositionFilename(val)); + util::getContentDispositionFilename(val, false)); val = "attachment; filename=\"dir\\\\file\""; CPPUNIT_ASSERT_EQUAL(std::string(""), - util::getContentDispositionFilename(val)); + util::getContentDispositionFilename(val, false)); val = "attachment; filename=\"/etc/passwd\""; CPPUNIT_ASSERT_EQUAL(std::string(""), - util::getContentDispositionFilename(val)); + util::getContentDispositionFilename(val, false)); val = "attachment; filename=\"..\""; CPPUNIT_ASSERT_EQUAL(std::string(""), - util::getContentDispositionFilename(val)); + util::getContentDispositionFilename(val, false)); val = "attachment; filename=.."; CPPUNIT_ASSERT_EQUAL(std::string(""), - util::getContentDispositionFilename(val)); + util::getContentDispositionFilename(val, false)); // Unescaping %2E%2E%2F produces "../". But since we won't unescape, // we just accept it as is. val = "attachment; filename=\"%2E%2E%2Ffoo.html\""; CPPUNIT_ASSERT_EQUAL(std::string("%2E%2E%2Ffoo.html"), - util::getContentDispositionFilename(val)); + util::getContentDispositionFilename(val, false)); // iso-8859-1 string will be converted to utf-8. val = "attachment; filename*=iso-8859-1''foo-%E4.html"; CPPUNIT_ASSERT_EQUAL(std::string("foo-ä.html"), - util::getContentDispositionFilename(val)); + util::getContentDispositionFilename(val, false)); val = "attachment; filename*= UTF-8''foo-%c3%a4.html"; CPPUNIT_ASSERT_EQUAL(std::string("foo-ä.html"), - util::getContentDispositionFilename(val)); + util::getContentDispositionFilename(val, false)); // iso-8859-1 string will be converted to utf-8. val = "attachment; filename=\"foo-%E4.html\""; val = util::percentDecode(val.begin(), val.end()); CPPUNIT_ASSERT_EQUAL(std::string("foo-ä.html"), - util::getContentDispositionFilename(val)); + util::getContentDispositionFilename(val, false)); + + // allow utf-8 in filename if default_utf8 is set. + val = "attachment; filename=\"foo-ä.html\""; + CPPUNIT_ASSERT_EQUAL(std::string("foo-ä.html"), + util::getContentDispositionFilename(val, true)); + + // return empty if default_utf8 is set but invalid utf8. + val = "attachment; filename=\"foo-\xc2\x02.html\""; + CPPUNIT_ASSERT_EQUAL(std::string(""), + util::getContentDispositionFilename(val, true)); } void UtilTest1::testParseContentDisposition1() @@ -826,140 +837,140 @@ void UtilTest1::testParseContentDisposition1() // test cases from http://greenbytes.de/tech/tc2231/ // inlonly val = "inline"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)0, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)0, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // inlonlyquoted val = "\"inline\""; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)-1, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // inlwithasciifilename val = "inline; filename=\"foo.html\""; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)8, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)8, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("foo.html"), std::string(&dest[0], &dest[8])); // inlwithfnattach val = "inline; filename=\"Not an attachment!\""; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)18, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)18, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("Not an attachment!"), std::string(&dest[0], &dest[18])); // inlwithasciifilenamepdf val = "inline; filename=\"foo.pdf\""; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)7, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)7, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("foo.pdf"), std::string(&dest[0], &dest[7])); // attwithasciifilename25 val = "attachment; filename=\"0000000000111111111122222\""; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)25, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)25, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("0000000000111111111122222"), std::string(&dest[0], &dest[25])); // attwithasciifilename35 val = "attachment; filename=\"00000000001111111111222222222233333\""; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)35, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)35, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("00000000001111111111222222222233333"), std::string(&dest[0], &dest[35])); // attwithasciifnescapedchar val = "attachment; filename=\"f\\oo.html\""; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)8, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)8, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("foo.html"), std::string(&dest[0], &dest[8])); // attwithasciifnescapedquote val = "attachment; filename=\"\\\"quoting\\\" tested.html\""; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)21, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)21, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("\"quoting\" tested.html"), std::string(&dest[0], &dest[21])); // attwithquotedsemicolon val = "attachment; filename=\"Here's a semicolon;.html\""; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)24, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)24, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("Here's a semicolon;.html"), std::string(&dest[0], &dest[24])); // attwithfilenameandextparam val = "attachment; foo=\"bar\"; filename=\"foo.html\""; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)8, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)8, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("foo.html"), std::string(&dest[0], &dest[8])); // attwithfilenameandextparamescaped val = "attachment; foo=\"\\\"\\\\\";filename=\"foo.html\""; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)8, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)8, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("foo.html"), std::string(&dest[0], &dest[8])); // attwithasciifilenameucase val = "attachment; FILENAME=\"foo.html\""; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)8, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)8, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("foo.html"), std::string(&dest[0], &dest[8])); // attwithasciifilenamenq val = "attachment; filename=foo.html"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)8, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)8, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("foo.html"), std::string(&dest[0], &dest[8])); // attwithtokfncommanq val = "attachment; filename=foo,bar.html"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)-1, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // attwithasciifilenamenqs val = "attachment; filename=foo.html ;"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)-1, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // attemptyparam val = "attachment; ;filename=foo"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)-1, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // attwithasciifilenamenqws val = "attachment; filename=foo bar.html"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)-1, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // attwithfntokensq val = "attachment; filename='foo.bar'"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)9, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)9, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("'foo.bar'"), std::string(&dest[0], &dest[9])); @@ -967,9 +978,9 @@ void UtilTest1::testParseContentDisposition1() // attachment; filename="foo-ä.html" val = "attachment; filename=\"foo-%E4.html\""; val = util::percentDecode(val.begin(), val.end()); - CPPUNIT_ASSERT_EQUAL( - (ssize_t)10, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)10, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("foo-ä.html"), util::iso8859p1ToUtf8(std::string(&dest[0], &dest[10]))); @@ -977,165 +988,165 @@ void UtilTest1::testParseContentDisposition1() // attachment; filename="foo-ä.html" val = "attachment; filename=\"foo-%C3%A4.html\""; val = util::percentDecode(val.begin(), val.end()); - CPPUNIT_ASSERT_EQUAL( - (ssize_t)11, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)11, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("foo-ä.html"), util::iso8859p1ToUtf8(std::string(&dest[0], &dest[11]))); // attwithfnrawpctenca val = "attachment; filename=\"foo-%41.html\""; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)12, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)12, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("foo-%41.html"), std::string(&dest[0], &dest[12])); // attwithfnusingpct val = "attachment; filename=\"50%.html\""; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)8, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)8, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("50%.html"), std::string(&dest[0], &dest[8])); // attwithfnrawpctencaq val = "attachment; filename=\"foo-%\\41.html\""; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)12, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)12, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("foo-%41.html"), std::string(&dest[0], &dest[12])); // attwithnamepct val = "attachment; name=\"foo-%41.html\""; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)0, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)0, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // attwithfilenamepctandiso // attachment; filename="ä-%41.html" val = "attachment; filename=\"%E4-%2541.html\""; val = util::percentDecode(val.begin(), val.end()); - CPPUNIT_ASSERT_EQUAL( - (ssize_t)10, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)10, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("ä-%41.html"), util::iso8859p1ToUtf8(std::string(&dest[0], &dest[10]))); // attwithfnrawpctenclong val = "attachment; filename=\"foo-%c3%a4-%e2%82%ac.html\""; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)25, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)25, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("foo-%c3%a4-%e2%82%ac.html"), std::string(&dest[0], &dest[25])); // attwithasciifilenamews1 val = "attachment; filename =\"foo.html\""; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)8, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)8, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("foo.html"), std::string(&dest[0], &dest[8])); // attwith2filenames val = "attachment; filename=\"foo.html\"; filename=\"bar.html\""; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)-1, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // attfnbrokentoken val = "attachment; filename=foo[1](2).html"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)-1, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // attfnbrokentokeniso val = "attachment; filename=foo-%E4.html"; val = util::percentDecode(val.begin(), val.end()); - CPPUNIT_ASSERT_EQUAL( - (ssize_t)-1, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // attfnbrokentokenutf // attachment; filename=foo-ä.html val = "attachment; filename=foo-ä.html"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)-1, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // attmissingdisposition val = "filename=foo.html"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)-1, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // attmissingdisposition2 val = "x=y; filename=foo.html"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)-1, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // attmissingdisposition3 val = "\"foo; filename=bar;baz\"; filename=qux"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)-1, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // attmissingdisposition4 val = "filename=foo.html, filename=bar.html"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)-1, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // emptydisposition val = "; filename=foo.html"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)-1, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // doublecolon val = ": inline; attachment; filename=foo.html"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)-1, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // attandinline val = "inline; attachment; filename=foo.html"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)-1, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // attandinline2 val = "attachment; inline; filename=foo.html"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)-1, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // attbrokenquotedfn val = "attachment; filename=\"foo.html\".txt"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)-1, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // attbrokenquotedfn2 val = "attachment; filename=\"bar"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)-1, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // attbrokenquotedfn3 val = "attachment; filename=foo\"bar;baz\"qux"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)-1, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // attmultinstances val = "attachment; filename=foo.html, attachment; filename=bar.html"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)-1, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); } void UtilTest1::testParseContentDisposition2() @@ -1149,228 +1160,228 @@ void UtilTest1::testParseContentDisposition2() // test cases from http://greenbytes.de/tech/tc2231/ // attmissingdelim val = "attachment; foo=foo filename=bar"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)-1, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // attmissingdelim2 val = "attachment; filename=bar foo=foo "; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)-1, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // attmissingdelim3 val = "attachment filename=bar"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)-1, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // attreversed val = "filename=foo.html; attachment"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)-1, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // attconfusedparam val = "attachment; xfilename=foo.html"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)0, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)0, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // attabspath val = "attachment; filename=\"/foo.html\""; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)9, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)9, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("/foo.html"), std::string(&dest[0], &dest[9])); // attabspathwin val = "attachment; filename=\"\\\\foo.html\""; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)9, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)9, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("\\foo.html"), std::string(&dest[0], &dest[9])); // attcdate val = "attachment; creation-date=\"Wed, 12 Feb 1997 16:29:51 -0500\""; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)0, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)0, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // dispext val = "foobar"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)0, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)0, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // dispextbadfn val = "attachment; example=\"filename=example.txt\""; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)0, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)0, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // attwithisofn2231iso val = "attachment; filename*=iso-8859-1''foo-%E4.html"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)10, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)10, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("iso-8859-1"), std::string(cs, cslen)); CPPUNIT_ASSERT_EQUAL(std::string("foo-ä.html"), util::iso8859p1ToUtf8(std::string(&dest[0], &dest[10]))); // attwithfn2231utf8 val = "attachment; filename*=UTF-8''foo-%c3%a4-%e2%82%ac.html"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)15, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)15, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("UTF-8"), std::string(cs, cslen)); CPPUNIT_ASSERT_EQUAL(std::string("foo-ä-€.html"), std::string(&dest[0], &dest[15])); // attwithfn2231noc val = "attachment; filename*=''foo-%c3%a4-%e2%82%ac.html"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)-1, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // attwithfn2231utf8comp val = "attachment; filename*=UTF-8''foo-a%cc%88.html"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)12, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)12, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); val = "foo-a%cc%88.html"; CPPUNIT_ASSERT_EQUAL(std::string(util::percentDecode(val.begin(), val.end())), std::string(&dest[0], &dest[12])); // attwithfn2231utf8-bad val = "attachment; filename*=iso-8859-1''foo-%c3%a4-%e2%82%ac.html"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)-1, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // attwithfn2231iso-bad val = "attachment; filename*=utf-8''foo-%E4.html"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)-1, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // attwithfn2231ws1 val = "attachment; filename *=UTF-8''foo-%c3%a4.html"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)-1, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // attwithfn2231ws2 val = "attachment; filename*= UTF-8''foo-%c3%a4.html"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)11, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)11, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("foo-ä.html"), std::string(&dest[0], &dest[11])); // attwithfn2231ws3 val = "attachment; filename* =UTF-8''foo-%c3%a4.html"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)11, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)11, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("foo-ä.html"), std::string(&dest[0], &dest[11])); // attwithfn2231quot val = "attachment; filename*=\"UTF-8''foo-%c3%a4.html\""; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)-1, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // attwithfn2231quot2 val = "attachment; filename*=\"foo%20bar.html\""; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)-1, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // attwithfn2231singleqmissing val = "attachment; filename*=UTF-8'foo-%c3%a4.html"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)-1, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // attwithfn2231nbadpct1 val = "attachment; filename*=UTF-8''foo%"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)-1, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // attwithfn2231nbadpct2 val = "attachment; filename*=UTF-8''f%oo.html"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)-1, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // attwithfn2231dpct val = "attachment; filename*=UTF-8''A-%2541.html"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)10, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)10, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("A-%41.html"), std::string(&dest[0], &dest[10])); // attwithfn2231abspathdisguised val = "attachment; filename*=UTF-8''%5cfoo.html"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)9, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)9, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("\\foo.html"), std::string(&dest[0], &dest[9])); // attfnboth val = "attachment; filename=\"foo-ae.html\"; filename*=UTF-8''foo-%c3%a4.html"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)11, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)11, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("foo-ä.html"), std::string(&dest[0], &dest[11])); // attfnboth2 val = "attachment; filename*=UTF-8''foo-%c3%a4.html; filename=\"foo-ae.html\""; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)11, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)11, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("foo-ä.html"), std::string(&dest[0], &dest[11])); // attfnboth3 val = "attachment; filename*0*=ISO-8859-15''euro-sign%3d%a4; " "filename*=ISO-8859-1''currency-sign%3d%a4"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)15, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)15, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("ISO-8859-1"), std::string(cs, cslen)); CPPUNIT_ASSERT_EQUAL(std::string("currency-sign=¤"), util::iso8859p1ToUtf8(std::string(&dest[0], &dest[15]))); // attnewandfn val = "attachment; foobar=x; filename=\"foo.html\""; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)8, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)8, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("foo.html"), std::string(&dest[0], &dest[8])); // attrfc2047token val = "attachment; filename==?ISO-8859-1?Q?foo-=E4.html?="; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)-1, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // attrfc2047quoted val = "attachment; filename=\"=?ISO-8859-1?Q?foo-=E4.html?=\""; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)29, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)29, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("=?ISO-8859-1?Q?foo-=E4.html?="), std::string(&dest[0], &dest[29])); @@ -1378,108 +1389,122 @@ void UtilTest1::testParseContentDisposition2() // zero-length filename. token cannot be empty, so this is invalid. val = "attachment; filename="; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)-1, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // zero-length filename. quoted-string can be empty string, so this // is ok. val = "attachment; filename=\"\""; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)0, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)0, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // empty value is not allowed val = "attachment; filename=;"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)-1, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // / is not valid char in token. val = "attachment; filename=dir/file"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)-1, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); // value-chars is *(pct-encoded / attr-char), so empty string is // allowed. val = "attachment; filename*=UTF-8''"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)0, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)0, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("UTF-8"), std::string(cs, cslen)); val = "attachment; filename*=UTF-8''; filename=foo"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)0, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)0, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("UTF-8"), std::string(cs, cslen)); val = "attachment; filename*=UTF-8'' ; filename=foo"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)0, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)0, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("UTF-8"), std::string(cs, cslen)); // with language val = "attachment; filename*=UTF-8'japanese'konnichiwa"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)10, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)10, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("konnichiwa"), std::string(&dest[0], &dest[10])); // lws before and after "=" val = "attachment; filename = foo.html"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)8, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)8, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("foo.html"), std::string(&dest[0], &dest[8])); // lws before and after "=" with quoted-string val = "attachment; filename = \"foo.html\""; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)8, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)8, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("foo.html"), std::string(&dest[0], &dest[8])); // lws after parm val = "attachment; filename=foo.html "; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)8, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)8, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("foo.html"), std::string(&dest[0], &dest[8])); val = "attachment; filename=foo.html ; hello=world"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)8, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)8, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("foo.html"), std::string(&dest[0], &dest[8])); val = "attachment; filename=\"foo.html\" "; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)8, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)8, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("foo.html"), std::string(&dest[0], &dest[8])); val = "attachment; filename=\"foo.html\" ; hello=world"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)8, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)8, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("foo.html"), std::string(&dest[0], &dest[8])); val = "attachment; filename*=UTF-8''foo.html ; hello=world"; - CPPUNIT_ASSERT_EQUAL( - (ssize_t)8, util::parse_content_disposition(dest, destlen, &cs, &cslen, - val.c_str(), val.size())); + CPPUNIT_ASSERT_EQUAL((ssize_t)8, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), false)); CPPUNIT_ASSERT_EQUAL(std::string("foo.html"), std::string(&dest[0], &dest[8])); + + // allow utf8 if content-disposition-default-utf8 is set + val = "attachment; filename=\"foo-ä.html\""; + CPPUNIT_ASSERT_EQUAL((ssize_t)11, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), true)); + CPPUNIT_ASSERT_EQUAL(std::string("foo-ä.html"), + std::string(&dest[0], &dest[11])); + + // incomplete utf8 sequence must be rejected + val = "attachment; filename=\"foo-\xc3.html\""; + CPPUNIT_ASSERT_EQUAL((ssize_t)-1, util::parse_content_disposition( + dest, destlen, &cs, &cslen, val.c_str(), + val.size(), true)); } } // namespace aria2 From 2efc5a9288bd208e58372a66c79ac7f04d649a36 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Sat, 31 Dec 2016 14:10:14 +0900 Subject: [PATCH 2/2] Document --content-disposition-default-utf8 opiton --- doc/manual-src/en/aria2c.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/doc/manual-src/en/aria2c.rst b/doc/manual-src/en/aria2c.rst index 992dd7dd..f419b039 100644 --- a/doc/manual-src/en/aria2c.rst +++ b/doc/manual-src/en/aria2c.rst @@ -1211,6 +1211,12 @@ Advanced Options Set log level to output to console. LEVEL is either ``debug``, ``info``, ``notice``, ``warn`` or ``error``. Default: ``notice`` +.. option:: --content-disposition-default-utf8[=true|false] + + Handle quoted string in Content-Disposition header as UTF-8 instead + of ISO-8859-1, for example, the filename parameter, but not the + extended version filename*. Default: ``false`` + .. option:: -D, --daemon[=true|false] Run as daemon. The current working directory will be changed to ``/`` @@ -2104,6 +2110,7 @@ of URIs. These optional lines must start with white space(s). * :option:`checksum <--checksum>` * :option:`conditional-get <--conditional-get>` * :option:`connect-timeout <--connect-timeout>` + * :option:`content-disposition-default-utf8 <--content-disposition-default-utf8>` * :option:`continue <-c>` * :option:`dir <-d>` * :option:`dry-run <--dry-run>`