summaryrefslogtreecommitdiff
path: root/src/AuthConfigFactory.cc
diff options
context:
space:
mode:
authorTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2009-01-30 16:12:41 +0000
committerTatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>2009-01-30 16:12:41 +0000
commite5c4b24454a37ad6eb5eae3a0685115e4078a06a (patch)
tree16138c045553f9c1df8d71a14a62101640b0bf32 /src/AuthConfigFactory.cc
parent120ea4c609b28c7fd3d907f1fa689737df92b8ef (diff)
2009-01-31 Tatsuhiro Tsujikawa <t-tujikawa@users.sourceforge.net>
Send HTTP Authorization header only if it is requested by the server(response 401). There are some exceptions. The authorization header for proxy is always sent if it is available without request by the server. If username/password is specified in the URI, it is immediately sent to the server without request by the server. AbstractAuthResolver::_defaultAuthConfig is now initialized as SharedHandle<AuthConfig>(). NetrcAuthResolver::resolveAuthConfig() returns SharedHandle<AuthConfig>() if no AuthConfig is available. * src/AbstractAuthResolver.cc * src/AbstractProxyRequestCommand.cc * src/AuthConfigFactory.cc * src/AuthConfigFactory.h * src/HttpConnection.cc * src/HttpRequest.cc * src/HttpRequest.h * src/HttpResponse.cc * src/HttpResponseCommand.cc * src/HttpSkipResponseCommand.cc * test/AuthConfigFactoryTest.cc * test/HttpRequestTest.cc * test/HttpResponseTest.cc
Diffstat (limited to 'src/AuthConfigFactory.cc')
-rw-r--r--src/AuthConfigFactory.cc115
1 files changed, 112 insertions, 3 deletions
diff --git a/src/AuthConfigFactory.cc b/src/AuthConfigFactory.cc
index 1fb61ea5..c5bf4f9f 100644
--- a/src/AuthConfigFactory.cc
+++ b/src/AuthConfigFactory.cc
@@ -33,6 +33,9 @@
*/
/* copyright --> */
#include "AuthConfigFactory.h"
+
+#include <algorithm>
+
#include "Option.h"
#include "AuthConfig.h"
#include "Netrc.h"
@@ -40,6 +43,7 @@
#include "NetrcAuthResolver.h"
#include "prefs.h"
#include "Request.h"
+#include "Util.h"
namespace aria2 {
@@ -53,10 +57,25 @@ AuthConfigFactory::AuthConfigFactory(const Option* option):
AuthConfigFactory::~AuthConfigFactory() {}
AuthConfigHandle
-AuthConfigFactory::createAuthConfig(const RequestHandle& request) const
+AuthConfigFactory::createAuthConfig(const RequestHandle& request)
{
if(request->getProtocol() == Request::PROTO_HTTP ||
request->getProtocol() == Request::PROTO_HTTPS) {
+
+ if(!request->getUsername().empty()) {
+ // TODO setting "/" as path. Should we use request->getDir() instead?
+ updateBasicCred(BasicCred(request->getUsername(), request->getPassword(),
+ request->getHost(), "/", true));
+ return createAuthConfig(request->getUsername(), request->getPassword());
+ }
+ std::deque<BasicCred>::const_iterator i =
+ findBasicCred(request->getHost(), request->getDir());
+ if(i == _basicCreds.end()) {
+ return SharedHandle<AuthConfig>();
+ } else {
+ return createAuthConfig((*i)._user, (*i)._password);
+ }
+
return createHttpAuthResolver()->resolveAuthConfig(request->getHost());
} else if(request->getProtocol() == Request::PROTO_FTP) {
if(!request->getUsername().empty()) {
@@ -65,7 +84,7 @@ AuthConfigFactory::createAuthConfig(const RequestHandle& request) const
return createFtpAuthResolver()->resolveAuthConfig(request->getHost());
}
} else {
- return SharedHandle<AuthConfig>(new AuthConfig());
+ return SharedHandle<AuthConfig>();
}
}
@@ -73,7 +92,7 @@ AuthConfigHandle
AuthConfigFactory::createAuthConfig(const std::string& user, const std::string& password) const
{
SharedHandle<AuthConfig> ac;
- if(user.length() > 0) {
+ if(!user.empty()) {
ac.reset(new AuthConfig(user, password));
}
return ac;
@@ -117,4 +136,94 @@ void AuthConfigFactory::setNetrc(const NetrcHandle& netrc)
_netrc = netrc;
}
+void AuthConfigFactory::updateBasicCred(const BasicCred& basicCred)
+{
+ std::deque<BasicCred>::iterator i =
+ std::lower_bound(_basicCreds.begin(), _basicCreds.end(), basicCred);
+
+ if(i != _basicCreds.end() && (*i) == basicCred) {
+ (*i) = basicCred;
+ } else {
+ _basicCreds.insert(i, basicCred);
+ }
+}
+
+bool AuthConfigFactory::activateBasicCred
+(const std::string& host, const std::string& path)
+{
+
+ std::deque<BasicCred>::iterator i =
+ findBasicCred(host, path);
+ if(i == _basicCreds.end()) {
+ SharedHandle<AuthConfig> authConfig =
+ createHttpAuthResolver()->resolveAuthConfig(host);
+ if(authConfig.isNull()) {
+ return false;
+ } else {
+ BasicCred bc("", "", host, path);
+ i = std::lower_bound(_basicCreds.begin(), _basicCreds.end(), bc);
+ // TODO setting "/" as path. Should we use path instead?
+ _basicCreds.insert
+ (i, BasicCred(authConfig->getUser(), authConfig->getPassword(),
+ host, "/", true));
+ return true;
+ }
+ } else {
+ (*i).activate();
+ return true;
+ }
+}
+
+AuthConfigFactory::BasicCred::BasicCred
+(const std::string& user, const std::string& password,
+ const std::string& host, const std::string& path,
+ bool activated):
+ _user(user), _password(password),
+ _host(host), _path(path), _activated(activated)
+{
+ if(!Util::endsWith(_path, "/")) {
+ _path += "/";
+ }
+}
+
+void AuthConfigFactory::BasicCred::activate()
+{
+ _activated = true;
+}
+
+bool AuthConfigFactory::BasicCred::isActivated() const
+{
+ return _activated;
+}
+
+bool AuthConfigFactory::BasicCred::operator==(const BasicCred& cred) const
+{
+ return _host == cred._host && _path == cred._path;
+}
+
+bool AuthConfigFactory::BasicCred::operator<(const BasicCred& cred) const
+{
+ int c = _host.compare(cred._host);
+ if(c == 0) {
+ return _path > cred._path;
+ } else {
+ return c < 0;
+ }
+}
+
+std::deque<AuthConfigFactory::BasicCred>::iterator
+AuthConfigFactory::findBasicCred(const std::string& host,
+ const std::string& path)
+{
+ BasicCred bc("", "", host, path);
+ std::deque<BasicCred>::iterator i =
+ std::lower_bound(_basicCreds.begin(), _basicCreds.end(), bc);
+ for(; i != _basicCreds.end() && (*i)._host == host; ++i) {
+ if(Util::startsWith(bc._path, (*i)._path)) {
+ return i;
+ }
+ }
+ return _basicCreds.end();
+}
+
} // namespace aria2