aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarlson2k <k2k@narod.ru>2013-11-21 23:34:03 +0400
committerKarlson2k <k2k@narod.ru>2013-12-09 18:52:21 +0400
commite0a06abc4267bf1724f8c0713a272c035a0be254 (patch)
tree23b240ba183caedc4723d529eb4539574a5fc1b6
parenta9e149117f3b014f5d26e232e34630776bcea6e3 (diff)
HttpHeader::GetCharset: fix: properly find charset according to RFC 2616
* detect more than one whitespace * use 'tab' as whitespace * allow charset to be quoted
-rw-r--r--xbmc/utils/HttpHeader.cpp53
1 files changed, 40 insertions, 13 deletions
diff --git a/xbmc/utils/HttpHeader.cpp b/xbmc/utils/HttpHeader.cpp
index f98605d518..511c02bace 100644
--- a/xbmc/utils/HttpHeader.cpp
+++ b/xbmc/utils/HttpHeader.cpp
@@ -185,20 +185,47 @@ std::string CHttpHeader::GetCharset(void) const
if (strValue.empty())
return strValue;
- const size_t semicolonPos = strValue.find(';');
- if (semicolonPos == std::string::npos)
- return "";
-
StringUtils::ToUpper(strValue);
- size_t posCharset;
- if ((posCharset = strValue.find("; CHARSET=", semicolonPos)) != std::string::npos)
- posCharset += 10;
- else if ((posCharset = strValue.find(";CHARSET=", semicolonPos)) != std::string::npos)
- posCharset += 9;
- else
- return "";
-
- return strValue.substr(posCharset, strValue.find(';', posCharset) - posCharset);
+ const size_t len = strValue.length();
+ const char* const strValueC = strValue.c_str();
+
+ // extract charset value from 'contenttype/contentsubtype;pram1=param1Val ; charset=XXXX\t;param2=param2Val'
+ // most common form: 'text/html; charset=XXXX'
+ // charset value can be in double quotes: 'text/xml; charset="XXX XX"'
+
+ size_t pos = strValue.find(';');
+ while (pos < len)
+ {
+ // move to the next non-whitespace character
+ pos = strValue.find_first_not_of(m_whitespaceChars, pos + 1);
+
+ if (pos != std::string::npos)
+ {
+ if (strValue.compare(pos, 8, "CHARSET=", 8) == 0)
+ {
+ std::string charset(strValue, pos, strValue.find(';', pos)); // intentionally ignoring possible ';' inside quoted string
+ // as we don't support any charset with ';' in name
+ StringUtils::Trim(charset, m_whitespaceChars);
+ if (!charset.empty())
+ {
+ if (charset[0] != '"')
+ return charset;
+ else
+ { // charset contains quoted string (allowed according to RFC 2616)
+ StringUtils::Replace(charset, "\\", ""); // unescape chars, ignoring possible '\"' and '\\'
+ const size_t closingQ = charset.find('"', 1);
+ if (closingQ == std::string::npos)
+ return ""; // no closing quote
+
+ return charset.substr(1, closingQ - 1);
+ }
+ }
+ }
+ pos = strValue.find(';', pos); // find next parameter
+ }
+ }
+
+ return ""; // no charset is detected
}
void CHttpHeader::Clear()