diff --git a/src/HttpResponse.cc b/src/HttpResponse.cc index f310e083..264f9024 100644 --- a/src/HttpResponse.cc +++ b/src/HttpResponse.cc @@ -113,11 +113,11 @@ void HttpResponse::validateResponse() const } std::string HttpResponse::determineFilename( - bool content_disposition_default_utf8) const + bool contentDispositionUTF8) const { std::string contentDisposition = util::getContentDispositionFilename( httpHeader_->find(HttpHeader::CONTENT_DISPOSITION), - content_disposition_default_utf8); + 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 d513ac50..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(bool content_disposition_default_utf8) const; + std::string determineFilename(bool contentDispositionUTF8) const; void retrieveCookie(); diff --git a/src/usage_text.h b/src/usage_text.h index 0a124817..e6c18513 100644 --- a/src/usage_text.h +++ b/src/usage_text.h @@ -538,9 +538,10 @@ _(" --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 filename in\n" \ + _(" --content-disposition-default-utf8[=true|false] Handle quoted string in\n" \ " Content-Disposition header as UTF-8 instead of\n" \ - " ISO-8859-1.") + " 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 c4051e55..bbf6977a 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, bool default_utf8) + 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,7 +981,7 @@ ssize_t parse_content_disposition(char* dest, size_t destlen, if (*p == '"') { quoted_seen = 0; state = CD_QUOTED_STRING; - if(default_utf8){ + if(defaultUTF8){ dfa_state = UTF8_ACCEPT; dfa_code = 0; } @@ -1015,16 +1015,19 @@ 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. accept - ISO-8859-1 chars, or UTF-8 if content-disposition-default-utf8 is set */ + /* 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 (default_utf8){ + if (defaultUTF8){ if (utf8dfa(&dfa_state, &dfa_code, (unsigned char)*p) == UTF8_REJECT) { return -1; } @@ -1214,7 +1217,7 @@ ssize_t parse_content_disposition(char* dest, size_t destlen, } std::string getContentDispositionFilename(const std::string& header, - bool default_utf8) + bool defaultUTF8) { std::array cdval; size_t cdvallen = cdval.size(); @@ -1222,14 +1225,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(), default_utf8); + header.c_str(), header.size(), defaultUTF8); if (rv == -1) { return ""; } std::string res; if ((charset && strieq(charset, charset + charsetlen, "iso-8859-1")) - || (!charset && !default_utf8)){ + || (!charset && !defaultUTF8)){ res = iso8859p1ToUtf8(cdval.data(), rv); } else { diff --git a/src/util.h b/src/util.h index 314f7918..2fc8ca40 100644 --- a/src/util.h +++ b/src/util.h @@ -322,12 +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, bool default_utf8); + const char* in, size_t len, bool defaultUTF8); std::string getContentDispositionFilename(const std::string& header, - bool default_utf8); + bool defaultUTF8); std::string toUpper(std::string src);