diff --git a/ChangeLog b/ChangeLog index e737d062..4a1ec76c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,58 @@ +2007-03-19 Tatsuhiro Tsujikawa + + To integrate Netrc into exsiting classes: + * src/Request.h + (_userDefinedAuthConfig): New variable. + (findNetrcAuthenticator): New function. + (segment): Removed. + (setUserDefinedAuthConfig): New function. + (resolveHttpAuthConfigItem): New function. + (resolveFtpAuthConfigItem): New function. + (resolveHttpProxyAuthConfigItem): New function. + * src/HttpRequest.h + (authConfig): Removed. + (proxyAuthConfig): Removed. + (setAuthConfig): Removed. + (setProxyAuthConfig): Removed. + * src/UrlRequest.h + (getHeadResult): Added a parameter: authConfigHandle + * src/common.h + (SingletonHolder.h): New include. + * src/main.cc + (Netrc.h): New include. + (main): Removed initial values of PREF_FTP_USER, PREF_FTP_PASSWD. + Added initial value of PREF_NETRC_PATH. + Added the initialization of netrc. + * src/AuthConfig.h: New class. + * src/prefs.h + (PREF_NETRC_PATH): New definition. + * src/HttpAuthConfig.h: Removed. + * src/Netrc.cc + (getRequiredNextToken): New function. + (skipMacdef): New function. + (parse): Rewritten. + * src/Netrc.h + (getRequiredNextToken): New function. + (skipMacdef): New function. + * src/Util.h, src/Util.cc + (getHomeDir): New function. + * src/TrackerWatcherComand.cc + (createRequestCommand): Use AuthConfig. + * src/FtpConnection.cc + (sendUser): Use Request::resolveFtpAuthConfigItem(). + (sendPass): Use Request::resolveFtpAuthConfigItem(). + * src/Request.cc + (findNetrcAuthenticator): New function. + (resolveHttpAuthConfigItem): New function. + (resolveFtpAuthConfigItem): New function. + (resolveHttpProxyAuthConfigItem): New function. + * src/UrlRequestInfo.cc: Use AuthConfig. + * src/HttpRequest.cc + (createRequest): Use authConfig. + (getProxyAuthString): Use authConfig. + (configure): Removed PREF_HTTP_USER, PREF_HTTP_PASSWD, + PREF_HTTP_PROXY_USER, PREF_HTTP_PROXY_PASSWD. + 2007-03-16 Tatsuhiro Tsujikawa To reduce overhead to find commands whose socket is either @@ -14,8 +69,6 @@ (waitData): Call Command::setStatusActive() when command's socket is readable or writable. - - 2007-03-15 Tatsuhiro Tsujikawa To handle Segment as SegmentHandle: diff --git a/TODO b/TODO index 2db8af0a..2be6e641 100644 --- a/TODO +++ b/TODO @@ -25,3 +25,5 @@ * Add an ability of seeding * Continue file allocation with existing file * Rewrite HttpConnection::receiveResponse() using {i,o}stringstream +* -c command line option to continue the download of existing file assuming +that it was downloaded from the beginning. \ No newline at end of file diff --git a/src/AuthConfig.h b/src/AuthConfig.h new file mode 100644 index 00000000..580c4853 --- /dev/null +++ b/src/AuthConfig.h @@ -0,0 +1,106 @@ +/* */ +#ifndef _D_AUTH_CONFIG_H_ +#define _D_AUTH_CONFIG_H_ + +#include "common.h" +#include "AuthConfigItem.h" +#include "prefs.h" +#include "Option.h" + +class AuthConfig { +private: + AuthConfigItemHandle httpAuthConfigItem; + AuthConfigItemHandle ftpAuthConfigItem; + AuthConfigItemHandle httpProxyAuthConfigItem; + + AuthConfigItemHandle createAuthConfigItem(const string& user, const string& password) + { + if(user.length() > 0) { + return new AuthConfigItem(user, password); + } else { + return 0; + } + } +public: + + AuthConfig():httpAuthConfigItem(0), + ftpAuthConfigItem(0), + httpProxyAuthConfigItem(0) {} + + AuthConfigItemHandle getHttpAuthConfigItem() const + { + return httpAuthConfigItem; + } + + void setHttpAuthConfigItem(const string& user, const string& password) + { + httpAuthConfigItem = createAuthConfigItem(user, password); + } + + AuthConfigItemHandle getFtpAuthConfigItem() const + { + return ftpAuthConfigItem; + } + + void setFtpAuthConfigItem(const string& user, const string& password) + { + ftpAuthConfigItem = createAuthConfigItem(user, password); + } + + AuthConfigItemHandle getHttpProxyAuthConfigItem() const + { + return httpProxyAuthConfigItem; + } + + void setHttpProxyAuthConfigItem(const string& user, const string& password) + { + httpProxyAuthConfigItem = createAuthConfigItem(user, password); + } + + void configure(const Option* op) + { + setHttpAuthConfigItem(op->get(PREF_HTTP_USER), + op->get(PREF_HTTP_PASSWD)); + setFtpAuthConfigItem(op->get(PREF_FTP_USER), + op->get(PREF_FTP_PASSWD)); + setHttpProxyAuthConfigItem(op->get(PREF_HTTP_PROXY_USER), + op->get(PREF_HTTP_PROXY_PASSWD)); + } +}; + +typedef SharedHandle AuthConfigHandle; + +#endif // _D_AUTH_CONFIG_H_ diff --git a/src/AuthConfigItem.h b/src/AuthConfigItem.h new file mode 100644 index 00000000..68904251 --- /dev/null +++ b/src/AuthConfigItem.h @@ -0,0 +1,68 @@ +/* */ +#ifndef _D_AUTH_CONFIG_ITEM_H_ +#define _D_AUTH_CONFIG_ITEM_H_ + +#include "common.h" + +class AuthConfigItem { +private: + string _authScheme; + string _user; + string _password; +public: + + AuthConfigItem(const string& user, const string& password): + _user(user), _password(password) {} + + string getAuthText() const + { + return _user+":"+_password; + } + + const string& getUser() const + { + return _user; + } + + const string& getPassword() const + { + return _password; + } +}; + +typedef SharedHandle AuthConfigItemHandle; + +#endif // _D_AUTH_CONFIG_ITEM_H_ diff --git a/src/FtpConnection.cc b/src/FtpConnection.cc index 48bd416a..edb58109 100644 --- a/src/FtpConnection.cc +++ b/src/FtpConnection.cc @@ -49,13 +49,13 @@ FtpConnection::FtpConnection(int cuid, const SocketHandle& socket, FtpConnection::~FtpConnection() {} void FtpConnection::sendUser() const { - string request = "USER "+option->get(PREF_FTP_USER)+"\r\n"; + string request = "USER "+req->resolveFtpAuthConfigItem()->getUser()+"\r\n"; logger->info(MSG_SENDING_REQUEST, cuid, request.c_str()); socket->writeData(request); } void FtpConnection::sendPass() const { - string request = "PASS "+option->get(PREF_FTP_PASSWD)+"\r\n"; + string request = "PASS "+req->resolveFtpAuthConfigItem()->getPassword()+"\r\n"; logger->info(MSG_SENDING_REQUEST, cuid, "PASS ********"); socket->writeData(request); } diff --git a/src/HttpRequest.cc b/src/HttpRequest.cc index b746f612..19cfdbe1 100644 --- a/src/HttpRequest.cc +++ b/src/HttpRequest.cc @@ -107,7 +107,7 @@ string HttpRequest::createRequest() const } if(authEnabled) { requestLine += "Authorization: Basic "+ - Base64::encode(authConfig->getAuthText())+"\r\n"; + Base64::encode(request->resolveHttpAuthConfigItem()->getAuthText())+"\r\n"; } if(getPreviousURI().size()) { requestLine += "Referer: "+getPreviousURI()+"\r\n"; @@ -145,7 +145,7 @@ string HttpRequest::createProxyRequest() const string HttpRequest::getProxyAuthString() const { return "Proxy-Authorization: Basic "+ - Base64::encode(proxyAuthConfig->getAuthText())+"\r\n"; + Base64::encode(request->resolveHttpProxyAuthConfigItem()->getAuthText())+"\r\n"; } void HttpRequest::configure(const Option* option) @@ -155,8 +155,4 @@ void HttpRequest::configure(const Option* option) option->get(PREF_HTTP_PROXY_ENABLED) == V_TRUE && option->get(PREF_HTTP_PROXY_METHOD) == V_GET; proxyAuthEnabled = option->get(PREF_HTTP_PROXY_AUTH_ENABLED) == V_TRUE; - authConfig = new HttpAuthConfig(option->get(PREF_HTTP_USER), - option->get(PREF_HTTP_PASSWD)); - proxyAuthConfig = new HttpAuthConfig(option->get(PREF_HTTP_PROXY_USER), - option->get(PREF_HTTP_PROXY_PASSWD)); } diff --git a/src/HttpRequest.h b/src/HttpRequest.h index d6f4ca4f..8cfe45d9 100644 --- a/src/HttpRequest.h +++ b/src/HttpRequest.h @@ -39,7 +39,6 @@ #include "Segment.h" #include "Range.h" #include "Request.h" -#include "HttpAuthConfig.h" #include "Option.h" #include @@ -54,14 +53,10 @@ private: bool authEnabled; - HttpAuthConfigHandle authConfig; - bool proxyEnabled; bool proxyAuthEnabled; - HttpAuthConfigHandle proxyAuthConfig; - string userAgent; string getHostText(const string& host, in_port_t port) const; @@ -73,10 +68,8 @@ public: segment(0), entityLength(0), authEnabled(false), - authConfig(0), proxyEnabled(false), proxyAuthEnabled(false), - proxyAuthConfig(0), userAgent(USER_AGENT) {} @@ -221,16 +214,6 @@ public: this->authEnabled = authEnabled; } - void setAuthConfig(const HttpAuthConfigHandle& authConfig) - { - this->authConfig = authConfig; - } - - void setProxyAuthConfig(const HttpAuthConfigHandle& proxyAuthConfig) - { - this->proxyAuthConfig = proxyAuthConfig; - } - void setUserAgent(const string& userAgent) { this->userAgent = userAgent; diff --git a/src/Netrc.cc b/src/Netrc.cc index a30e8485..4538f526 100644 --- a/src/Netrc.cc +++ b/src/Netrc.cc @@ -37,6 +37,27 @@ #include "RecoverableException.h" #include +string Netrc::getRequiredNextToken(ifstream& f) const +{ + string token; + if(f >> token) { + return token; + } else { + throw new RecoverableException("Netrc:parse error. EOF reached where a token expected."); + } +} + +void Netrc::skipMacdef(ifstream& f) const +{ + string line; + getline(f, line); + while(getline(f, line)) { + if(line == "\r" || line == "") { + break; + } + } +} + void Netrc::parse(const string& path) { authenticators.clear(); @@ -46,32 +67,29 @@ void Netrc::parse(const string& path) throw new RecoverableException("File not found: %s", path.c_str()); } - int32_t lineNum = 0; - string line; AuthenticatorHandle authenticator = 0; - while(getline(f, line)) { - ++lineNum; - if(Util::trim(line).empty()) { - continue; - } - pair nameValuePair = Util::split(line, "\r\n\t "); - if(nameValuePair.first == "machine") { + string token; + while(f >> token) { + if(token == "machine") { storeAuthenticator(authenticator); authenticator = new Authenticator(); - authenticator->setMachine(nameValuePair.second); - } else if(nameValuePair.first == "default") { + authenticator->setMachine(getRequiredNextToken(f)); + } else if(token == "default") { storeAuthenticator(authenticator); authenticator = new DefaultAuthenticator(); } else { if(authenticator.isNull()) { - throw new RecoverableException("Malformed netrc file: line %d", lineNum); + throw new RecoverableException("Netrc:parse error. %s encounterd where 'machine' or 'default' expected."); } - if(nameValuePair.first == "login") { - authenticator->setLogin(nameValuePair.second); - } else if(nameValuePair.first == "password") { - authenticator->setPassword(nameValuePair.second); - } else if(nameValuePair.first == "account") { - authenticator->setAccount(nameValuePair.second); + if(token == "login") { + authenticator->setLogin(getRequiredNextToken(f)); + } else if(token == "password") { + authenticator->setPassword(getRequiredNextToken(f)); + } else if(token == "account") { + authenticator->setAccount(getRequiredNextToken(f)); + } else if(token == "macdef") { + getRequiredNextToken(f); + skipMacdef(f); } } } diff --git a/src/Netrc.h b/src/Netrc.h index b36599eb..07f7c738 100644 --- a/src/Netrc.h +++ b/src/Netrc.h @@ -127,6 +127,10 @@ private: Authenticators authenticators; void storeAuthenticator(const AuthenticatorHandle& authenticator); + + string getRequiredNextToken(ifstream& f) const; + + void skipMacdef(ifstream& f) const; public: Netrc() {} diff --git a/src/Request.cc b/src/Request.cc index 62248826..8ff53a88 100644 --- a/src/Request.cc +++ b/src/Request.cc @@ -35,12 +35,16 @@ #include "Request.h" #include "Util.h" #include "FeatureConfig.h" +#include "Netrc.h" const string Request::METHOD_GET = "get"; const string Request::METHOD_HEAD = "head"; -Request::Request():port(0), tryCount(0), keepAlive(true), method(METHOD_GET), isTorrent(false) { +Request::Request():port(0), tryCount(0), keepAlive(true), method(METHOD_GET), + _userDefinedAuthConfig(0), + isTorrent(false) +{ cookieBox = new CookieBox(); } @@ -55,7 +59,6 @@ bool Request::setUrl(const string& url) { bool Request::resetUrl() { previousUrl = referer; - segment = Segment(); return setUrl(url); } @@ -130,3 +133,52 @@ bool Request::parseUrl(const string& url) { file += query; return true; } + +AuthConfigItemHandle Request::findNetrcAuthenticator() const +{ + if(!NetrcSingletonHolder::instance().isNull()) { + AuthenticatorHandle auth = NetrcSingletonHolder::instance()->findAuthenticator(getHost()); + if(auth.isNull()) { + return 0; + } else { + return new AuthConfigItem(auth->getLogin(), auth->getPassword()); + } + } else { + return 0; + } +} + +AuthConfigItemHandle Request::resolveHttpAuthConfigItem() const +{ + if(!_userDefinedAuthConfig.isNull() && + !_userDefinedAuthConfig->getHttpAuthConfigItem().isNull()) { + return _userDefinedAuthConfig->getHttpAuthConfigItem(); + } else { + return findNetrcAuthenticator(); + } +} + +AuthConfigItemHandle Request::resolveFtpAuthConfigItem() const +{ + if(!_userDefinedAuthConfig.isNull() && + !_userDefinedAuthConfig->getFtpAuthConfigItem().isNull()) { + return _userDefinedAuthConfig->getFtpAuthConfigItem(); + } else { + AuthConfigItemHandle authConfig = findNetrcAuthenticator(); + if(authConfig.isNull()) { + return new AuthConfigItem("anonymous", "ARIA2USER@"); + } else { + return authConfig; + } + } +} + +AuthConfigItemHandle Request::resolveHttpProxyAuthConfigItem() const +{ + if(!_userDefinedAuthConfig.isNull() && + !_userDefinedAuthConfig->getHttpProxyAuthConfigItem().isNull()) { + return _userDefinedAuthConfig->getHttpProxyAuthConfigItem(); + } else { + return findNetrcAuthenticator(); + } +} diff --git a/src/Request.h b/src/Request.h index 04f8aad7..f7b9c9ec 100644 --- a/src/Request.h +++ b/src/Request.h @@ -34,14 +34,9 @@ /* copyright --> */ #ifndef _D_REQUEST_H_ #define _D_REQUEST_H_ -#include -#include -#include "CookieBox.h" -#include "Segment.h" #include "common.h" -#include "SharedHandle.h" - -using namespace std; +#include "CookieBox.h" +#include "AuthConfig.h" #define SAFE_CHARS "abcdefghijklmnopqrstuvwxyz"\ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"\ @@ -75,9 +70,14 @@ private: int trackerEvent; bool keepAlive; string method; + + AuthConfigHandle _userDefinedAuthConfig; + bool parseUrl(const string& url); + + AuthConfigItemHandle findNetrcAuthenticator() const; + public: - Segment segment; CookieBox* cookieBox; bool isTorrent; public: @@ -116,6 +116,17 @@ public: this->method = method; } + void setUserDefinedAuthConfig(const AuthConfigHandle& authConfig) + { + _userDefinedAuthConfig = authConfig; + } + + AuthConfigItemHandle resolveHttpAuthConfigItem() const; + + AuthConfigItemHandle resolveFtpAuthConfigItem() const; + + AuthConfigItemHandle resolveHttpProxyAuthConfigItem() const; + const string& getMethod() const { return method; } diff --git a/src/HttpAuthConfig.h b/src/SingletonHolder.h similarity index 78% rename from src/HttpAuthConfig.h rename to src/SingletonHolder.h index 4367a78e..d6d2eebf 100644 --- a/src/HttpAuthConfig.h +++ b/src/SingletonHolder.h @@ -32,27 +32,30 @@ * files in the program, then also delete it here. */ /* copyright --> */ -#ifndef _D_HTTP_AUTH_CONFIG_H_ -#define _D_HTTP_AUTH_CONFIG_H_ +#ifndef _D_SINGLETON_HOLDER_H_ +#define _D_SINGLETON_HOLDER_H_ -#include "common.h" - -class HttpAuthConfig { +template +class SingletonHolder { private: - string authScheme; - string authUser; - string authPassword; + static T _instance; + + SingletonHolder() {} public: + ~SingletonHolder() {} - HttpAuthConfig(const string& authUser, const string& authPassword): - authUser(authUser), authPassword(authPassword) {} - - string getAuthText() const + static T& instance() { - return authUser+":"+authPassword; + return _instance; + } + + static void instance(T& instance) + { + _instance = instance; } }; -typedef SharedHandle HttpAuthConfigHandle; +template +T SingletonHolder::_instance = 0; -#endif // _D_HTTP_AUTH_CONFIG_H_ +#endif // _D_SINGLETON_HOLDER_H_ diff --git a/src/TrackerWatcherCommand.cc b/src/TrackerWatcherCommand.cc index 8d98e682..2afb6dc2 100644 --- a/src/TrackerWatcherCommand.cc +++ b/src/TrackerWatcherCommand.cc @@ -81,8 +81,11 @@ Command* TrackerWatcherCommand::createCommand() { } Command* TrackerWatcherCommand::createRequestCommand(const string& url) { + AuthConfigHandle authConfig = new AuthConfig(); + authConfig->configure(e->option); RequestHandle req; req->setUrl(url); + req->setUserDefinedAuthConfig(authConfig); req->isTorrent = true; Command* command = InitiateConnectionCommandFactory::createInitiateConnectionCommand(btRuntime->getNewCuid(), req, e); diff --git a/src/UrlRequestInfo.cc b/src/UrlRequestInfo.cc index d33924fb..38778c36 100644 --- a/src/UrlRequestInfo.cc +++ b/src/UrlRequestInfo.cc @@ -88,15 +88,18 @@ private: Requests* requestsPtr; string referer; int split; + AuthConfigHandle _userDefinedAuthConfig; string method; public: CreateRequest(Requests* requestsPtr, const string& referer, int split, + const AuthConfigHandle& userDefinedAuthConfig, const string& method = Request::METHOD_GET) :requestsPtr(requestsPtr), referer(referer), split(split), + _userDefinedAuthConfig(userDefinedAuthConfig), method(method) {} void operator()(const string& url) { @@ -104,6 +107,7 @@ public: RequestHandle req; req->setReferer(referer); req->setMethod(method); + req->setUserDefinedAuthConfig(_userDefinedAuthConfig); if(req->setUrl(url)) { requestsPtr->push_back(req); } else { @@ -120,12 +124,13 @@ void UrlRequestInfo::printUrls(const Strings& urls) const { } } -HeadResultHandle UrlRequestInfo::getHeadResult() { +HeadResultHandle UrlRequestInfo::getHeadResult(const AuthConfigHandle& authConfig) { Requests requests; for_each(urls.begin(), urls.end(), CreateRequest(&requests, op->get(PREF_REFERER), 1, + authConfig, Request::METHOD_HEAD)); if(requests.size() == 0) { return 0; @@ -153,12 +158,17 @@ RequestInfos UrlRequestInfo::execute() { Requests requests; Requests reserved; printUrls(urls); - HeadResultHandle hr = getHeadResult(); + AuthConfigHandle authConfig = new AuthConfig(); + authConfig->configure(op); + + HeadResultHandle hr = getHeadResult(authConfig); + for_each(urls.begin(), urls.end(), CreateRequest(&requests, op->get(PREF_REFERER), - op->getAsInt(PREF_SPLIT))); + op->getAsInt(PREF_SPLIT), + authConfig)); logger->info("Head result: filename=%s, total length=%s", hr->filename.c_str(), Util::ullitos(hr->totalLength, true).c_str()); diff --git a/src/UrlRequestInfo.h b/src/UrlRequestInfo.h index 94e1680b..e349f19b 100644 --- a/src/UrlRequestInfo.h +++ b/src/UrlRequestInfo.h @@ -64,7 +64,7 @@ private: Requests& reserved, int maxConnections) const; void printUrls(const Strings& urls) const; - HeadResultHandle getHeadResult(); + HeadResultHandle getHeadResult(const AuthConfigHandle& authConfig); public: UrlRequestInfo(const Strings& urls, int maxConnections, Option* op): RequestInfo(op), diff --git a/src/Util.cc b/src/Util.cc index 89d241fd..2c096f3e 100644 --- a/src/Util.cc +++ b/src/Util.cc @@ -664,3 +664,12 @@ void Util::indexRange(int32_t& startIndex, int32_t& endIndex, endIndex = _endIndex; } +string Util::getHomeDir() +{ + const char* p = getenv("HOME"); + if(p) { + return p; + } else { + return ""; + } +} diff --git a/src/Util.h b/src/Util.h index fd1f1cd1..6127b41e 100644 --- a/src/Util.h +++ b/src/Util.h @@ -144,6 +144,8 @@ public: static void indexRange(int32_t& startIndex, int32_t& endIndex, int64_t offset, int32_t srcLength, int32_t destLength); + + static string getHomeDir(); }; #endif // _D_UTIL_H_ diff --git a/src/common.h b/src/common.h index 91049cb5..fd0e9c70 100644 --- a/src/common.h +++ b/src/common.h @@ -70,6 +70,7 @@ public: }; #include "SharedHandle.h" +#include "SingletonHolder.h" typedef deque Strings; typedef deque Integers; diff --git a/src/main.cc b/src/main.cc index b6533ed5..97d4fda5 100644 --- a/src/main.cc +++ b/src/main.cc @@ -48,6 +48,7 @@ #include "BitfieldManFactory.h" #include "SimpleRandomizer.h" #include "ConsoleFileAllocationMonitor.h" +#include "Netrc.h" #include #include #include @@ -342,8 +343,6 @@ int main(int argc, char* argv[]) { op->put(PREF_MAX_TRIES, "5"); op->put(PREF_HTTP_AUTH_SCHEME, V_BASIC); op->put(PREF_HTTP_PROXY_METHOD, V_TUNNEL); - op->put(PREF_FTP_USER, "anonymous"); - op->put(PREF_FTP_PASSWD, "ARIA2USER@"); op->put(PREF_FTP_TYPE, V_BINARY); op->put(PREF_FTP_VIA_HTTP_PROXY, V_TUNNEL); op->put(PREF_AUTO_SAVE_INTERVAL, "60"); @@ -357,6 +356,7 @@ int main(int argc, char* argv[]) { op->put(PREF_ALLOW_OVERWRITE, V_FALSE); op->put(PREF_REALTIME_CHUNK_CHECKSUM, V_TRUE); op->put(PREF_CHECK_INTEGRITY, V_FALSE); + op->put(PREF_NETRC_PATH, Util::getHomeDir()+"/.netrc"); while(1) { int optIndex = 0; int lopt; @@ -773,6 +773,10 @@ int main(int argc, char* argv[]) { logger->info("%s %s", PACKAGE, PACKAGE_VERSION); logger->info("Logging started."); + NetrcHandle netrc = new Netrc(); + netrc->parse(op->get(PREF_NETRC_PATH)); + NetrcSingletonHolder::instance(netrc); + Util::setGlobalSignalHandler(SIGPIPE, SIG_IGN, 0); RequestInfo* firstReqInfo = 0; diff --git a/src/prefs.h b/src/prefs.h index 95e8c312..4846f80b 100644 --- a/src/prefs.h +++ b/src/prefs.h @@ -90,6 +90,8 @@ #define PREF_REALTIME_CHUNK_CHECKSUM "realtime_chunk_checksum" // value: true | false #define PREF_CHECK_INTEGRITY "check_integrity" +// value: string that your file system recognizes as a file name. +#define PREF_NETRC_PATH "netrc_path" /** * FTP related preferences diff --git a/test/AuthConfigTest.cc b/test/AuthConfigTest.cc new file mode 100644 index 00000000..c80ba7fe --- /dev/null +++ b/test/AuthConfigTest.cc @@ -0,0 +1,43 @@ +#include "AuthConfig.h" +#include "Option.h" +#include "prefs.h" +#include + +class AuthConfigTest:public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE(AuthConfigTest); + CPPUNIT_TEST(testGet); + CPPUNIT_TEST_SUITE_END(); + +public: + void testGet(); +}; + + +CPPUNIT_TEST_SUITE_REGISTRATION( AuthConfigTest ); + +void AuthConfigTest::testGet() +{ + Option option; + option.put(PREF_HTTP_USER, "httpUser"); + option.put(PREF_HTTP_PASSWD, "httpPassword"); + option.put(PREF_FTP_USER, "ftpUser"); + option.put(PREF_FTP_PASSWD, "ftpPassword"); + option.put(PREF_HTTP_PROXY_USER, "httpProxyUser"); + option.put(PREF_HTTP_PROXY_PASSWD, "httpProxyPassword"); + + AuthConfig authConfig; + authConfig.configure(&option); + + AuthConfigItemHandle httpAuth = authConfig.getHttpAuthConfigItem(); + CPPUNIT_ASSERT_EQUAL(string("httpUser"), httpAuth->getUser()); + CPPUNIT_ASSERT_EQUAL(string("httpPassword"), httpAuth->getPassword()); + + AuthConfigItemHandle ftpAuth = authConfig.getFtpAuthConfigItem(); + CPPUNIT_ASSERT_EQUAL(string("ftpUser"), ftpAuth->getUser()); + CPPUNIT_ASSERT_EQUAL(string("ftpPassword"), ftpAuth->getPassword()); + + AuthConfigItemHandle httpProxyAuth = authConfig.getHttpProxyAuthConfigItem(); + CPPUNIT_ASSERT_EQUAL(string("httpProxyUser"), httpProxyAuth->getUser()); + CPPUNIT_ASSERT_EQUAL(string("httpProxyPassword"), httpProxyAuth->getPassword()); +} diff --git a/test/HttpRequestTest.cc b/test/HttpRequestTest.cc index a777a0ea..671d1628 100644 --- a/test/HttpRequestTest.cc +++ b/test/HttpRequestTest.cc @@ -81,6 +81,9 @@ void HttpRequestTest::testCreateRequest() { RequestHandle request = new Request(); request->setUrl("http://localhost:8080/archives/aria2-1.0.0.tar.bz2"); + AuthConfigHandle authConfig = new AuthConfig(); + request->setUserDefinedAuthConfig(authConfig); + SegmentHandle segment = new Segment(); HttpRequest httpRequest; @@ -168,6 +171,7 @@ void HttpRequestTest::testCreateRequest() option->put(PREF_HTTP_PROXY_USER, "aria2proxyuser"); option->put(PREF_HTTP_PROXY_PASSWD, "aria2proxypasswd"); + authConfig->configure(option.get()); httpRequest.configure(option.get()); expectedText = "GET /archives/aria2-1.0.0.tar.bz2 HTTP/1.1\r\n" @@ -278,6 +282,8 @@ void HttpRequestTest::testCreateRequest_ftp() { RequestHandle request = new Request(); request->setUrl("ftp://localhost:8080/archives/aria2-1.0.0.tar.bz2"); + AuthConfigHandle authConfig = new AuthConfig(); + request->setUserDefinedAuthConfig(authConfig); SegmentHandle segment = new Segment(); HttpRequest httpRequest; @@ -296,6 +302,7 @@ void HttpRequestTest::testCreateRequest_ftp() option->put(PREF_HTTP_PROXY_PASSWD, "aria2proxypasswd"); httpRequest.configure(option.get()); + authConfig->configure(option.get()); string expectedText = "GET ftp://localhost:8080/archives/aria2-1.0.0.tar.bz2 HTTP/1.1\r\n" "User-Agent: aria2\r\n" diff --git a/test/Makefile.am b/test/Makefile.am index 9317de6e..d13dcf15 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,10 +1,12 @@ TESTS = aria2c check_PROGRAMS = $(TESTS) aria2c_SOURCES = AllTest.cc\ - HttpHeaderTest.cc\ - HttpRequestTest.cc\ - HttpResponseTest.cc\ NetrcTest.cc\ + HttpRequestTest.cc\ + AuthConfigTest.cc\ + SingletonHolderTest.cc\ + HttpHeaderTest.cc\ + HttpResponseTest.cc\ BitfieldManTest.cc\ SharedHandleTest.cc\ RequestTest.cc\ diff --git a/test/Makefile.in b/test/Makefile.in index 1e38ccca..e86bd085 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -57,9 +57,10 @@ mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = am__EXEEXT_1 = aria2c$(EXEEXT) -am_aria2c_OBJECTS = AllTest.$(OBJEXT) HttpHeaderTest.$(OBJEXT) \ - HttpRequestTest.$(OBJEXT) HttpResponseTest.$(OBJEXT) \ - NetrcTest.$(OBJEXT) BitfieldManTest.$(OBJEXT) \ +am_aria2c_OBJECTS = AllTest.$(OBJEXT) NetrcTest.$(OBJEXT) \ + HttpRequestTest.$(OBJEXT) AuthConfigTest.$(OBJEXT) \ + SingletonHolderTest.$(OBJEXT) HttpHeaderTest.$(OBJEXT) \ + HttpResponseTest.$(OBJEXT) BitfieldManTest.$(OBJEXT) \ SharedHandleTest.$(OBJEXT) RequestTest.$(OBJEXT) \ ChunkedEncodingTest.$(OBJEXT) FileTest.$(OBJEXT) \ OptionTest.$(OBJEXT) Base64Test.$(OBJEXT) UtilTest.$(OBJEXT) \ @@ -258,10 +259,12 @@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ TESTS = aria2c aria2c_SOURCES = AllTest.cc\ - HttpHeaderTest.cc\ - HttpRequestTest.cc\ - HttpResponseTest.cc\ NetrcTest.cc\ + HttpRequestTest.cc\ + AuthConfigTest.cc\ + SingletonHolderTest.cc\ + HttpHeaderTest.cc\ + HttpResponseTest.cc\ BitfieldManTest.cc\ SharedHandleTest.cc\ RequestTest.cc\ @@ -386,6 +389,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AllTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AnnounceListTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AuthConfigTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Base64Test.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BitfieldManTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BtAllowedFastMessageTest.Po@am__quote@ @@ -439,6 +443,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ShaVisitorTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ShareRatioSeedCriteriaTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SharedHandleTest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SingletonHolderTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SpeedCalcTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TimeSeedCriteriaTest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/TrackerWatcherCommandTest.Po@am__quote@ diff --git a/test/NetrcTest.cc b/test/NetrcTest.cc index a02b7117..caa6dff7 100644 --- a/test/NetrcTest.cc +++ b/test/NetrcTest.cc @@ -7,10 +7,11 @@ using namespace std; class NetrcTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(NetrcTest); - CPPUNIT_TEST(testFindAuthenticatable); + CPPUNIT_TEST(testFindAuthenticator); CPPUNIT_TEST(testParse); CPPUNIT_TEST(testParse_fileNotFound); CPPUNIT_TEST(testParse_emptyfile); + CPPUNIT_TEST(testParse_malformedNetrc); CPPUNIT_TEST_SUITE_END(); private: @@ -18,29 +19,30 @@ public: void setUp() { } - void testFindAuthenticatable(); + void testFindAuthenticator(); void testParse(); void testParse_fileNotFound(); void testParse_emptyfile(); + void testParse_malformedNetrc(); }; CPPUNIT_TEST_SUITE_REGISTRATION( NetrcTest ); -void NetrcTest::testFindAuthenticatable() +void NetrcTest::testFindAuthenticator() { Netrc netrc; - netrc.addAuthenticatable(new Authenticator("host1", "tujikawa", "tujikawapasswd", "tujikawaaccount")); - netrc.addAuthenticatable(new Authenticator("host2", "aria2", "aria2password", "aria2account")); - netrc.addAuthenticatable(new DefaultAuthenticator("default", "defaultpassword", "defaultaccount")); + netrc.addAuthenticator(new Authenticator("host1", "tujikawa", "tujikawapasswd", "tujikawaaccount")); + netrc.addAuthenticator(new Authenticator("host2", "aria2", "aria2password", "aria2account")); + netrc.addAuthenticator(new DefaultAuthenticator("default", "defaultpassword", "defaultaccount")); - AuthenticatorHandle aria2auth = netrc.findAuthenticatable("host2"); + AuthenticatorHandle aria2auth = netrc.findAuthenticator("host2"); CPPUNIT_ASSERT(!aria2auth.isNull()); CPPUNIT_ASSERT_EQUAL(string("aria2"), aria2auth->getLogin()); CPPUNIT_ASSERT_EQUAL(string("aria2password"), aria2auth->getPassword()); CPPUNIT_ASSERT_EQUAL(string("aria2account"), aria2auth->getAccount()); - AuthenticatorHandle defaultauth = netrc.findAuthenticatable("host3"); + AuthenticatorHandle defaultauth = netrc.findAuthenticator("host3"); CPPUNIT_ASSERT(!defaultauth.isNull()); CPPUNIT_ASSERT_EQUAL(string("default"), defaultauth->getLogin()); CPPUNIT_ASSERT_EQUAL(string("defaultpassword"), defaultauth->getPassword()); @@ -51,7 +53,7 @@ void NetrcTest::testParse() { Netrc netrc; netrc.parse("sample.netrc"); - Authenticatables::const_iterator itr = netrc.getAuthenticatables().begin(); + Authenticators::const_iterator itr = netrc.getAuthenticators().begin(); AuthenticatorHandle tujikawaauth = *itr; CPPUNIT_ASSERT(!tujikawaauth.isNull()); @@ -91,5 +93,17 @@ void NetrcTest::testParse_emptyfile() Netrc netrc; netrc.parse("emptyfile"); - CPPUNIT_ASSERT_EQUAL((size_t)0, netrc.getAuthenticatables().size()); + CPPUNIT_ASSERT_EQUAL((size_t)0, netrc.getAuthenticators().size()); +} + +void NetrcTest::testParse_malformedNetrc() +{ + Netrc netrc; + try { + netrc.parse("malformed.netrc"); + CPPUNIT_FAIL("exception must be threw."); + } catch(Exception* e) { + cerr << e->getMsg() << endl; + delete e; + } } diff --git a/test/RequestTest.cc b/test/RequestTest.cc index e5a1311b..d76f2c55 100644 --- a/test/RequestTest.cc +++ b/test/RequestTest.cc @@ -1,5 +1,5 @@ #include "Request.h" - +#include "Netrc.h" #include class RequestTest:public CppUnit::TestFixture { @@ -25,6 +25,12 @@ class RequestTest:public CppUnit::TestFixture { CPPUNIT_TEST(testSafeChar); CPPUNIT_TEST(testInnerLink); CPPUNIT_TEST(testMetalink); + CPPUNIT_TEST(testResolveHttpAuthConfigItem); + CPPUNIT_TEST(testResolveHttpAuthConfigItem_noCandidate); + CPPUNIT_TEST(testResolveHttpProxyAuthConfigItem); + CPPUNIT_TEST(testResolveHttpProxyAuthConfigItem_noCandidate); + CPPUNIT_TEST(testResolveFtpAuthConfigItem); + CPPUNIT_TEST(testResolveFtpAuthConfigItem_noCandidate); CPPUNIT_TEST_SUITE_END(); public: @@ -48,6 +54,12 @@ public: void testSafeChar(); void testInnerLink(); void testMetalink(); + void testResolveHttpAuthConfigItem(); + void testResolveHttpAuthConfigItem_noCandidate(); + void testResolveHttpProxyAuthConfigItem(); + void testResolveHttpProxyAuthConfigItem_noCandidate(); + void testResolveFtpAuthConfigItem(); + void testResolveFtpAuthConfigItem_noCandidate(); }; @@ -293,3 +305,118 @@ void RequestTest::testMetalink() { bool v2 = req.setUrl("http://aria.rednoah.com/download/aria.tar.bz2#!metalink3!"); CPPUNIT_ASSERT(!v2); } + +void RequestTest::testResolveHttpAuthConfigItem() +{ + Request req; + req.setUrl("http://localhost/download/aria2-1.0.0.tar.bz2"); + // with no authConfig + CPPUNIT_ASSERT(req.resolveHttpAuthConfigItem().isNull()); + + // with Netrc + NetrcHandle netrc = new Netrc(); + netrc->addAuthenticator(new DefaultAuthenticator("default", "defaultpassword", "defaultaccount")); + NetrcSingletonHolder::instance(netrc); + CPPUNIT_ASSERT(!req.resolveHttpAuthConfigItem().isNull()); + AuthConfigItemHandle authConfig1 = req.resolveHttpAuthConfigItem(); + CPPUNIT_ASSERT_EQUAL(string("default"), authConfig1->getUser()); + CPPUNIT_ASSERT_EQUAL(string("defaultpassword"), authConfig1->getPassword()); + + // with Netrc + user defined + AuthConfigHandle authConfig = new AuthConfig(); + authConfig->setHttpAuthConfigItem("userDefinedUser", "userDefinedPassword"); + req.setUserDefinedAuthConfig(authConfig); + CPPUNIT_ASSERT(!req.resolveHttpAuthConfigItem().isNull()); + AuthConfigItemHandle authConfig2 = req.resolveHttpAuthConfigItem(); + CPPUNIT_ASSERT_EQUAL(string("userDefinedUser"), authConfig2->getUser()); + CPPUNIT_ASSERT_EQUAL(string("userDefinedPassword"), authConfig2->getPassword()); +} + +void RequestTest::testResolveHttpAuthConfigItem_noCandidate() +{ + Request req; + req.setUrl("http://localhost/download/aria2-1.0.0.tar.bz2"); + + NetrcHandle netrc = new Netrc(); + netrc->addAuthenticator(new Authenticator("localhost2", "default", "defaultpassword", "defaultaccount")); + NetrcSingletonHolder::instance(netrc); + CPPUNIT_ASSERT(req.resolveHttpAuthConfigItem().isNull()); +} + +void RequestTest::testResolveHttpProxyAuthConfigItem() +{ + Request req; + req.setUrl("http://localhost/download/aria2-1.0.0.tar.bz2"); + // with no authConfig + CPPUNIT_ASSERT(req.resolveHttpProxyAuthConfigItem().isNull()); + + // with Netrc + NetrcHandle netrc = new Netrc(); + netrc->addAuthenticator(new DefaultAuthenticator("default", "defaultpassword", "defaultaccount")); + NetrcSingletonHolder::instance(netrc); + CPPUNIT_ASSERT(!req.resolveHttpProxyAuthConfigItem().isNull()); + AuthConfigItemHandle authConfig1 = req.resolveHttpProxyAuthConfigItem(); + CPPUNIT_ASSERT_EQUAL(string("default"), authConfig1->getUser()); + CPPUNIT_ASSERT_EQUAL(string("defaultpassword"), authConfig1->getPassword()); + + // with Netrc + user defined + AuthConfigHandle authConfig = new AuthConfig(); + authConfig->setHttpProxyAuthConfigItem("userDefinedUser", "userDefinedPassword"); + req.setUserDefinedAuthConfig(authConfig); + CPPUNIT_ASSERT(!req.resolveHttpProxyAuthConfigItem().isNull()); + AuthConfigItemHandle authConfig2 = req.resolveHttpProxyAuthConfigItem(); + CPPUNIT_ASSERT_EQUAL(string("userDefinedUser"), authConfig2->getUser()); + CPPUNIT_ASSERT_EQUAL(string("userDefinedPassword"), authConfig2->getPassword()); +} + +void RequestTest::testResolveHttpProxyAuthConfigItem_noCandidate() +{ + Request req; + req.setUrl("http://localhost/download/aria2-1.0.0.tar.bz2"); + + NetrcHandle netrc = new Netrc(); + netrc->addAuthenticator(new Authenticator("localhost2", "default", "defaultpassword", "defaultaccount")); + NetrcSingletonHolder::instance(netrc); + CPPUNIT_ASSERT(req.resolveHttpProxyAuthConfigItem().isNull()); +} + +void RequestTest::testResolveFtpAuthConfigItem() +{ + Request req; + req.setUrl("http://localhost/download/aria2-1.0.0.tar.bz2"); + // with no authConfig + CPPUNIT_ASSERT(!req.resolveFtpAuthConfigItem().isNull()); + CPPUNIT_ASSERT_EQUAL(string("anonymous"), req.resolveFtpAuthConfigItem()->getUser()); + CPPUNIT_ASSERT_EQUAL(string("ARIA2USER@"), req.resolveFtpAuthConfigItem()->getPassword()); + + // with Netrc + NetrcHandle netrc = new Netrc(); + netrc->addAuthenticator(new DefaultAuthenticator("default", "defaultpassword", "defaultaccount")); + NetrcSingletonHolder::instance(netrc); + CPPUNIT_ASSERT(!req.resolveFtpAuthConfigItem().isNull()); + AuthConfigItemHandle authConfig1 = req.resolveFtpAuthConfigItem(); + CPPUNIT_ASSERT_EQUAL(string("default"), authConfig1->getUser()); + CPPUNIT_ASSERT_EQUAL(string("defaultpassword"), authConfig1->getPassword()); + + // with Netrc + user defined + AuthConfigHandle authConfig = new AuthConfig(); + authConfig->setFtpAuthConfigItem("userDefinedUser", "userDefinedPassword"); + req.setUserDefinedAuthConfig(authConfig); + CPPUNIT_ASSERT(!req.resolveFtpAuthConfigItem().isNull()); + AuthConfigItemHandle authConfig2 = req.resolveFtpAuthConfigItem(); + CPPUNIT_ASSERT_EQUAL(string("userDefinedUser"), authConfig2->getUser()); + CPPUNIT_ASSERT_EQUAL(string("userDefinedPassword"), authConfig2->getPassword()); +} + +void RequestTest::testResolveFtpAuthConfigItem_noCandidate() +{ + Request req; + req.setUrl("http://localhost/download/aria2-1.0.0.tar.bz2"); + + NetrcHandle netrc = new Netrc(); + netrc->addAuthenticator(new Authenticator("localhost2", "default", "defaultpassword", "defaultaccount")); + NetrcSingletonHolder::instance(netrc); + CPPUNIT_ASSERT(!req.resolveFtpAuthConfigItem().isNull()); + CPPUNIT_ASSERT_EQUAL(string("anonymous"), req.resolveFtpAuthConfigItem()->getUser()); + CPPUNIT_ASSERT_EQUAL(string("ARIA2USER@"), req.resolveFtpAuthConfigItem()->getPassword()); +} diff --git a/test/SingletonHolderTest.cc b/test/SingletonHolderTest.cc new file mode 100644 index 00000000..71f99dfa --- /dev/null +++ b/test/SingletonHolderTest.cc @@ -0,0 +1,57 @@ +#include "SingletonHolder.h" +#include "SharedHandle.h" +#include + +using namespace std; + +class SingletonHolderTest : public CppUnit::TestFixture { + + CPPUNIT_TEST_SUITE(SingletonHolderTest); + CPPUNIT_TEST(testInstance); + CPPUNIT_TEST_SUITE_END(); +private: + +public: + void setUp() { + } + + void testInstance(); +}; + + +CPPUNIT_TEST_SUITE_REGISTRATION( SingletonHolderTest ); + +class M { +private: + string _greeting; +public: + M(const string& greeting):_greeting(greeting) {} + + const string& greeting() const { return _greeting; } + + void greeting(const string& greeting) { + _greeting = greeting; + } +}; + +typedef SharedHandle MHandle; +typedef SharedHandle IntHandle; + +void SingletonHolderTest::testInstance() +{ + MHandle m = new M("Hello world."); + SingletonHolder::instance(m); + + cerr << SingletonHolder::instance()->greeting() << endl; + + SingletonHolder::instance()->greeting("Yes, it worked!"); + + cerr << SingletonHolder::instance()->greeting() << endl; + + IntHandle i = new int(100); + SingletonHolder::instance(i); + cerr << SingletonHolder::instance() << endl; + + cerr << SingletonHolder::instance()->greeting() << endl; + +} diff --git a/test/malformed.netrc b/test/malformed.netrc new file mode 100644 index 00000000..2d27e03e --- /dev/null +++ b/test/malformed.netrc @@ -0,0 +1,4 @@ +machine host2 +login aria2 +password aria2password +account diff --git a/test/sample.netrc b/test/sample.netrc index 84328d91..4df1a244 100644 --- a/test/sample.netrc +++ b/test/sample.netrc @@ -2,13 +2,12 @@ machine host1 login tujikawa password tujikawapassword account tujikawaaccount +macdef init +cd /home/aria2 machine machine host2 login aria2 password aria2password account aria2account -default -login anonymous -password ARIA2@USER -account ARIA2@ACCT \ No newline at end of file +default login anonymous password ARIA2@USER account ARIA2@ACCT \ No newline at end of file