| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325 | 
							- /* <!-- copyright */
 
- /*
 
-  * aria2 - The high speed download utility
 
-  *
 
-  * Copyright (C) 2006 Tatsuhiro Tsujikawa
 
-  *
 
-  * This program is free software; you can redistribute it and/or modify
 
-  * it under the terms of the GNU General Public License as published by
 
-  * the Free Software Foundation; either version 2 of the License, or
 
-  * (at your option) any later version.
 
-  *
 
-  * This program is distributed in the hope that it will be useful,
 
-  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
-  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
-  * GNU General Public License for more details.
 
-  *
 
-  * You should have received a copy of the GNU General Public License
 
-  * along with this program; if not, write to the Free Software
 
-  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
-  *
 
-  * In addition, as a special exception, the copyright holders give
 
-  * permission to link the code of portions of this program with the
 
-  * OpenSSL library under certain conditions as described in each
 
-  * individual source file, and distribute linked combinations
 
-  * including the two.
 
-  * You must obey the GNU General Public License in all respects
 
-  * for all of the code used other than OpenSSL.  If you modify
 
-  * file(s) with this exception, you may extend this exception to your
 
-  * version of the file(s), but you are not obligated to do so.  If you
 
-  * do not wish to do so, delete this exception statement from your
 
-  * version.  If you delete this exception statement from all source
 
-  * files in the program, then also delete it here.
 
-  */
 
- /* copyright --> */
 
- #include "Request.h"
 
- #include <utility>
 
- #include "util.h"
 
- #include "FeatureConfig.h"
 
- #include "StringFormat.h"
 
- #include "A2STR.h"
 
- #include "a2functional.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)
 
- {}
 
- static 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);
 
-   }
 
- }
 
- static bool isHexNumber(const char c)
 
- {
 
-   return ('0' <= c && c <= '9') || ('A' <= c && c <= 'F') ||
 
-     ('a' <= c && c <= 'f');
 
- }
 
- static 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(!isHexNumber(result[index+1]) || !isHexNumber(result[index+2])) {
 
-           result.replace(index, 1, "%25");
 
-         }
 
-       } else {
 
-         result.replace(index, 1, StringFormat("%%%02X", c).str());
 
-       }
 
-     }
 
-   }
 
-   result.erase(result.size()-2);
 
-   return result;
 
- }
 
- bool Request::setUri(const std::string& uri) {
 
-   supportsPersistentConnection_ = true;
 
-   uri_ = uri;
 
-   return parseUri(uri_);
 
- }
 
- bool Request::resetUri() {
 
-   previousUri_ = referer_;
 
-   supportsPersistentConnection_ = true;
 
-   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) {
 
-   const std::string uri = percentEncode(removeFragment(srcUri));
 
-   currentUri_ = uri;
 
-   host_ = A2STR::NIL;
 
-   port_ = 0;
 
-   dir_ = A2STR::NIL;
 
-   file_ = A2STR::NIL;
 
-   query_ = A2STR::NIL;
 
-   username_ = A2STR::NIL;
 
-   password_ = A2STR::NIL;
 
-   hasPassword_ = false;
 
-   ipv6LiteralAddress_ = false;
 
-   // http://user:password@aria2.sourceforge.net:80/dir/file?query
 
-   //        |            ||                    || |   |    |
 
-   //        |            ||             hostLast| |   |    |
 
-   //        |            ||              portFirst|   |    |
 
-   //    authorityFirst   ||             authorityLast |    |
 
-   //                     ||                       |   |    |
 
-   //                   userInfoLast               |   |    |
 
-   //                      |                       |   |    |
 
-   //                     hostPortFirst            |   |    |
 
-   //                                              |   |    |
 
-   //                                       dirFirst dirLast|
 
-   //                                                       |
 
-   //                                                queryFirst
 
-   // find query part
 
-   std::string::const_iterator queryFirst = uri.begin();
 
-   for(; queryFirst != uri.end(); ++queryFirst) {
 
-     if(*queryFirst == '?') break;
 
-   }
 
-   query_ = std::string(queryFirst, uri.end());
 
-   // find protocol
 
-   std::string::size_type protocolOffset = uri.find("://");
 
-   if(protocolOffset == std::string::npos) return false;
 
-   protocol_ = std::string(uri.begin(), uri.begin()+protocolOffset);
 
-   uint16_t defPort;
 
-   if((defPort = FeatureConfig::getInstance()->getDefaultPort(protocol_)) == 0) {
 
-     return false;
 
-   }
 
-   // find authority
 
-   std::string::const_iterator authorityFirst = uri.begin()+protocolOffset+3;
 
-   std::string::const_iterator authorityLast = authorityFirst;
 
-   for(; authorityLast != queryFirst; ++authorityLast) {
 
-     if(*authorityLast == '/') break;
 
-   }
 
-   if(authorityFirst == authorityLast) {
 
-     // No authority found
 
-     return false;
 
-   }
 
-   // find userinfo(username and password) in authority if they exist
 
-   std::string::const_iterator userInfoLast = authorityLast;
 
-   std::string::const_iterator hostPortFirst = authorityFirst;
 
-   for(; userInfoLast != authorityFirst-1; --userInfoLast) {
 
-     if(*userInfoLast == '@') {
 
-       hostPortFirst = userInfoLast;
 
-       ++hostPortFirst;
 
-       std::string::const_iterator userLast = authorityFirst;
 
-       for(; userLast != userInfoLast; ++userLast) {
 
-         if(*userLast == ':') {
 
-           password_ = util::percentDecode(std::string(userLast+1,userInfoLast));
 
-           hasPassword_ = true;
 
-           break;
 
-         }
 
-       }
 
-       username_ = util::percentDecode(std::string(authorityFirst, userLast));
 
-       break;
 
-     }
 
-   }
 
-   std::string::const_iterator hostLast = hostPortFirst;
 
-   std::string::const_iterator portFirst = authorityLast;
 
-   if(*hostPortFirst == '[') {
 
-     // Detected IPv6 literal address in square brackets
 
-     for(; hostLast != authorityLast; ++hostLast) {
 
-       if(*hostLast == ']') {
 
-         ++hostLast;
 
-         if(hostLast == authorityLast) {
 
-           ipv6LiteralAddress_ = true;
 
-         } else {
 
-           if(*hostLast == ':') {
 
-             portFirst = hostLast;
 
-             ++portFirst;
 
-             ipv6LiteralAddress_ = true;
 
-           }
 
-         }
 
-         break;
 
-       }
 
-     }
 
-     if(!ipv6LiteralAddress_) {
 
-       return false;
 
-     }
 
-   } else {
 
-     for(; hostLast != authorityLast; ++hostLast) {
 
-       if(*hostLast == ':') {
 
-         portFirst = hostLast;
 
-         ++portFirst;
 
-         break;
 
-       }
 
-     }
 
-   }
 
-   if(hostPortFirst == hostLast) {
 
-     // No host
 
-     return false;
 
-   }
 
-   if(portFirst == authorityLast) {
 
-     // If port is not specified, then we set it to default port of
 
-     // its protocol..
 
-     port_ = defPort;
 
-   } else {
 
-     uint32_t tempPort;
 
-     if(util::parseUIntNoThrow(tempPort, std::string(portFirst, authorityLast))){
 
-       if(65535 < tempPort) {
 
-         return false;
 
-       }
 
-       port_ = tempPort;      
 
-     } else {
 
-       return false;
 
-     }
 
-   }
 
-   if(ipv6LiteralAddress_) {
 
-     host_ = std::string(hostPortFirst+1, hostLast-1);
 
-   } else {
 
-     host_ = std::string(hostPortFirst, hostLast);
 
-   }
 
-   // find directory and file part
 
-   std::string::const_iterator dirLast = authorityLast;
 
-   for(std::string::const_iterator i = authorityLast;
 
-       i != queryFirst; ++i) {
 
-     if(*i == '/') {
 
-       dirLast = i;
 
-     }
 
-   }
 
-   if(dirLast != queryFirst) {
 
-     file_ = std::string(dirLast+1, queryFirst);
 
-   }
 
-   // Erase duplicated slashes.
 
-   std::string::const_iterator dirFirst = authorityLast;
 
-   for(; dirFirst != dirLast; ++dirFirst) {
 
-     if(*dirFirst != '/') {
 
-       --dirFirst;
 
-       break;
 
-     }
 
-   }
 
-   for(; dirLast != dirFirst; --dirLast) {
 
-     if(*dirLast != '/') {
 
-       ++dirLast;
 
-       break;
 
-     }
 
-   }
 
-   if(dirFirst == dirLast) {
 
-     dir_ = A2STR::SLASH_C;
 
-   } else {
 
-     dir_ = std::string(dirFirst, dirLast);
 
-   }
 
-   return true;
 
- }
 
- void Request::resetRedirectCount()
 
- {
 
-   redirectCount_ = 0;
 
- }
 
-   
 
- void Request::setMaxPipelinedRequest(unsigned int num)
 
- {
 
-   maxPipelinedRequest_ = num;
 
- }
 
- const SharedHandle<PeerStat>& Request::initPeerStat()
 
- {
 
-   // Use host and protocol in original URI, because URI selector
 
-   // selects URI based on original URI, not redirected one.
 
-   Request origReq;
 
-   origReq.setUri(uri_);
 
-   peerStat_.reset(new PeerStat(0, origReq.getHost(), origReq.getProtocol()));
 
-   return peerStat_;
 
- }
 
- } // namespace aria2
 
 
  |