bool SPDYUtil::hasGzipAndDeflate(const std::string& value, bool& hasGzip, bool& hasDeflate) { static folly::ThreadLocal<std::vector<RFC2616::TokenQPair>> output; output->clear(); hasGzip = false; hasDeflate = false; RFC2616::parseQvalues(value, *output); for (const auto& encodingQ: *output) { std::string lower(encodingQ.first.str()); std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower); // RFC says 3 sig figs if (lower == "gzip" && encodingQ.second >= 0.001) { hasGzip = true; } else if (lower == "deflate" && encodingQ.second >= 0.001) { hasDeflate = true; } } return hasGzip && hasDeflate; }
bool parseQvalues(folly::StringPiece value, std::vector<TokenQPair> &output) { bool result = true; static folly::ThreadLocal<std::vector<folly::StringPiece>> tokens; tokens->clear(); folly::split(",", value, *tokens, true /*ignore empty*/); for (auto& token: *tokens) { auto pos = token.find(';'); double qvalue = 1.0; if (pos != std::string::npos) { auto qpos = token.find("q=", pos); if (qpos != std::string::npos) { folly::StringPiece qvalueStr(token.data() + qpos + 2, token.size() - (qpos + 2)); try { qvalue = folly::to<double>(&qvalueStr); } catch (const std::range_error&) { // q=<some garbage> result = false; } // we could validate that the remainder of qvalueStr was all whitespace, // for now we just discard it } else { // ; but no q= result = false; } token.reset(token.start(), pos); } // strip leading whitespace while (token.size() > 0 && isspace(token[0])) { token.reset(token.start() + 1, token.size() - 1); } if (token.size() == 0) { // empty token result = false; } else { output.emplace_back(token, qvalue); } } return result && output.size() > 0; }