/* */ #include "HttpHeader.h" #include #include "Range.h" #include "Util.h" #include "A2STR.h" namespace aria2 { const std::string HttpHeader::LOCATION("Location"); const std::string HttpHeader::TRANSFER_ENCODING("Transfer-Encoding"); const std::string HttpHeader::CONTENT_ENCODING("Content-Encoding"); const std::string HttpHeader::CONTENT_DISPOSITION("Content-Disposition"); const std::string HttpHeader::SET_COOKIE("Set-Cookie"); const std::string HttpHeader::CHUNKED("chunked"); const std::string HttpHeader::GZIP("gzip"); const std::string HttpHeader::DEFLATE("deflate"); const std::string HttpHeader::CONTENT_TYPE("Content-Type"); const std::string HttpHeader::RETRY_AFTER("Retry-After"); const std::string HttpHeader::CONNECTION("Connection"); const std::string HttpHeader::CLOSE("close"); const std::string HttpHeader::CONTENT_LENGTH("Content-Length"); const std::string HttpHeader::CONTENT_RANGE("Content-Range"); const std::string HttpHeader::LAST_MODIFIED("Last-Modified"); const std::string HttpHeader::HTTP_1_1("HTTP/1.1"); const std::string HttpHeader::S200("200"); const std::string HttpHeader::S300("300"); const std::string HttpHeader::S400("400"); const std::string HttpHeader::S401("401"); const std::string HttpHeader::S404("404"); void HttpHeader::put(const std::string& name, const std::string& value) { std::multimap::value_type vt(util::toLower(name), value); table.insert(vt); } bool HttpHeader::defined(const std::string& name) const { return table.count(util::toLower(name)) >= 1; } const std::string& HttpHeader::getFirst(const std::string& name) const { std::multimap::const_iterator itr = table.find(util::toLower(name)); if(itr == table.end()) { return A2STR::NIL; } else { return (*itr).second; } } std::deque HttpHeader::get(const std::string& name) const { std::deque v; std::string n(util::toLower(name)); std::multimap::const_iterator first = table.lower_bound(n); std::multimap::const_iterator last = table.upper_bound(n); while(first != last) { v.push_back((*first).second); ++first; } return v; } unsigned int HttpHeader::getFirstAsUInt(const std::string& name) const { return getFirstAsULLInt(name); } uint64_t HttpHeader::getFirstAsULLInt(const std::string& name) const { const std::string& value = getFirst(name); if(value.empty()) { return 0; } else { return util::parseULLInt(value); } } RangeHandle HttpHeader::getRange() const { const std::string& rangeStr = getFirst(CONTENT_RANGE); if(rangeStr.empty()) { const std::string& contentLengthStr = getFirst(CONTENT_LENGTH); if(contentLengthStr.empty()) { return SharedHandle(new Range()); } else { uint64_t contentLength = util::parseULLInt(contentLengthStr); if(contentLength == 0) { return SharedHandle(new Range()); } else { return SharedHandle(new Range(0, contentLength-1, contentLength)); } } } std::string byteRangeSpec; { // we expect that rangeStr looks like 'bytes 100-199/100' // but some server returns '100-199/100', omitting bytes-unit sepcifier // 'bytes'. std::pair splist; util::split(splist, rangeStr, ' '); if(splist.second.empty()) { // we assume bytes-unit specifier omitted. byteRangeSpec = splist.first; } else { byteRangeSpec = splist.second; } } std::pair byteRangeSpecPair; util::split(byteRangeSpecPair, byteRangeSpec, '/'); std::pair byteRangeRespSpecPair; util::split(byteRangeRespSpecPair, byteRangeSpecPair.first, '-'); off_t startByte = util::parseLLInt(byteRangeRespSpecPair.first); off_t endByte = util::parseLLInt(byteRangeRespSpecPair.second); uint64_t entityLength = util::parseULLInt(byteRangeSpecPair.second); return SharedHandle(new Range(startByte, endByte, entityLength)); } void HttpHeader::setResponseStatus(const std::string& responseStatus) { _responseStatus = responseStatus; } void HttpHeader::setVersion(const std::string& version) { _version = version; } void HttpHeader::setMethod(const std::string& method) { _method = method; } void HttpHeader::setRequestPath(const std::string& requestPath) { _requestPath = requestPath; } void HttpHeader::fill(std::istream& in) { std::string line; while(std::getline(in, line)) { line = util::trim(line); if(line.empty()) { continue; } std::pair hp; util::split(hp, line, ':'); put(hp.first, hp.second); } } void HttpHeader::clearField() { table.clear(); } } // namespace aria2