/* */ #include "Request.h" #include #include #include "util.h" #include "fmt.h" #include "A2STR.h" #include "uri.h" #include "PeerStat.h" namespace aria2 { const std::string Request::METHOD_GET = "GET"; const std::string Request::METHOD_HEAD = "HEAD"; const std::string Request::PROTO_HTTP("http"); const std::string Request::PROTO_HTTPS("https"); const std::string Request::PROTO_FTP("ftp"); Request::Request(): port_(0), tryCount_(0), redirectCount_(0), supportsPersistentConnection_(true), keepAliveHint_(false), pipeliningHint_(false), maxPipelinedRequest_(1), method_(METHOD_GET), hasPassword_(false), ipv6LiteralAddress_(false), removalRequested_(false), connectedPort_(0) {} Request::~Request() {} namespace { std::string removeFragment(const std::string& uri) { std::string::size_type sharpIndex = uri.find("#"); if(sharpIndex == std::string::npos) { return uri; } else { return uri.substr(0, sharpIndex); } } } // namespace namespace { std::string percentEncode(const std::string& src) { std::string result = src; if(src.empty()) { return result; } result += " "; for(int index = src.size()-1; index >= 0; --index) { const unsigned char c = result[index]; // '/' is not percent encoded because src is expected to be a path. if(!util::inRFC3986ReservedChars(c) && !util::inRFC3986UnreservedChars(c)) { if(c == '%') { if(!util::isHexDigit(result[index+1]) || !util::isHexDigit(result[index+2])) { result.replace(index, 1, "%25"); } } else { result.replace(index, 1, fmt("%%%02X", c)); } } } result.erase(result.size()-2); return result; } } // namespace bool Request::setUri(const std::string& uri) { supportsPersistentConnection_ = true; uri_ = uri; return parseUri(uri_); } bool Request::resetUri() { previousUri_ = referer_; supportsPersistentConnection_ = true; setConnectedAddrInfo(A2STR::NIL, A2STR::NIL, 0); return parseUri(uri_); } void Request::setReferer(const std::string& uri) { referer_ = previousUri_ = percentEncode(removeFragment(uri)); } bool Request::redirectUri(const std::string& uri) { supportsPersistentConnection_ = true; ++redirectCount_; std::string redirectedUri; if(uri.find("://") == std::string::npos) { // rfc2616 requires absolute URI should be provided by Location header // field, but some servers don't obey this rule. if(util::startsWith(uri, "/")) { // abosulute path redirectedUri = strconcat(protocol_, "://", host_, uri); } else { // relative path redirectedUri = strconcat(protocol_, "://", host_, dir_, "/", uri); } } else { redirectedUri = uri; } return parseUri(redirectedUri); } bool Request::parseUri(const std::string& srcUri) { currentUri_ = percentEncode(removeFragment(srcUri)); uri::UriStruct us; if(uri::parse(us, currentUri_)) { protocol_.swap(us.protocol); host_.swap(us.host); port_ = us.port; dir_.swap(us.dir); file_.swap(us.file); query_.swap(us.query); username_.swap(us.username); password_.swap(us.password); hasPassword_ = us.hasPassword; ipv6LiteralAddress_ = us.ipv6LiteralAddress; return true; } else { return false; } } void Request::resetRedirectCount() { redirectCount_ = 0; } void Request::setMaxPipelinedRequest(unsigned int num) { maxPipelinedRequest_ = num; } const SharedHandle& Request::initPeerStat() { // Use host and protocol in original URI, because URI selector // selects URI based on original URI, not redirected one. uri::UriStruct us; bool v = uri::parse(us, uri_); assert(v); peerStat_.reset(new PeerStat(0, us.host, us.protocol)); return peerStat_; } std::string Request::getURIHost() const { if(isIPv6LiteralAddress()) { return strconcat("[", getHost(), "]"); } else { return getHost(); } } void Request::setMethod(const std::string& method) { method_ = method; } void Request::setConnectedAddrInfo (const std::string& hostname, const std::string& addr, uint16_t port) { connectedHostname_ = hostname; connectedAddr_ = addr; connectedPort_ = port; } } // namespace aria2