[haiku-commits] haiku: hrev46298 - src/kits/network/libnetapi headers/os/net

  • From: pulkomandy@xxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Mon, 28 Oct 2013 17:30:23 +0100 (CET)

hrev46298 adds 2 changesets to branch 'master'
old head: c157484a81328535c34fb21893308f2311d9ec91
new head: 9ce2f7e3863c7c69284eaad6466c6b0247f0037b
overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=9ce2f7e+%5Ec157484

----------------------------------------------------------------------------

b7617dd: Network Cookie Jar: implement assignment operator.
  
  This change is needed for implementing cookie persistence in Web+ using
  the network kit backend.
  
  The current implementation requires the user to unarchive the cookie
  jar, then hand it over to the BUrlContext which will copy it to its own
  field. This makes the code simpler, but maybe doing a complete copy
  (with all the cookies) is an heavy operation and could be avoided.

9ce2f7e: Improve HTTP authentication support.
  
  The authentication state is stored (in a hash map, using the domain+path
  as a key) in the UrlContext class. It can then be reused for multiple
  requests to the same place. We also lookup stored authentications for
  parent directories and stop at the first we find.
  
  Authentication state is not stored on disk (unlike cookies), and there
  can only be one for each domain+path.

                             [ Adrien Destugues <pulkomandy@xxxxxxxxxxxxx> ]

----------------------------------------------------------------------------

6 files changed, 139 insertions(+), 21 deletions(-)
headers/os/net/HttpRequest.h                    |  2 -
headers/os/net/NetworkCookieJar.h               |  3 +
headers/os/net/UrlContext.h                     | 14 +++++
src/kits/network/libnetapi/HttpRequest.cpp      | 54 ++++++++++++------
src/kits/network/libnetapi/NetworkCookieJar.cpp | 26 +++++++++
src/kits/network/libnetapi/UrlContext.cpp       | 61 ++++++++++++++++++++-

############################################################################

Commit:      b7617ddd68d4b2b95d8394edad08f2954e859bf5
URL:         http://cgit.haiku-os.org/haiku/commit/?id=b7617dd
Author:      Adrien Destugues <pulkomandy@xxxxxxxxxxxxx>
Date:        Fri Oct 25 15:14:33 2013 UTC

Network Cookie Jar: implement assignment operator.

This change is needed for implementing cookie persistence in Web+ using
the network kit backend.

The current implementation requires the user to unarchive the cookie
jar, then hand it over to the BUrlContext which will copy it to its own
field. This makes the code simpler, but maybe doing a complete copy
(with all the cookies) is an heavy operation and could be avoided.

----------------------------------------------------------------------------

diff --git a/headers/os/net/NetworkCookieJar.h 
b/headers/os/net/NetworkCookieJar.h
index 0bf070f..58364a6 100644
--- a/headers/os/net/NetworkCookieJar.h
+++ b/headers/os/net/NetworkCookieJar.h
@@ -58,10 +58,13 @@ public:
        virtual status_t                        Unflatten(type_code code,
                                                                        const 
void* buffer, ssize_t size);
 
+                       BNetworkCookieJar&      operator=(const 
BNetworkCookieJar& other);
+
        // Iterators
                        Iterator                        GetIterator() const;
                        UrlIterator                     GetUrlIterator(const 
BUrl& url) const;
 
+
 private:
                        void                            _DoFlatten() const;
 
diff --git a/src/kits/network/libnetapi/NetworkCookieJar.cpp 
b/src/kits/network/libnetapi/NetworkCookieJar.cpp
index 03c894c..ee0c4de 100644
--- a/src/kits/network/libnetapi/NetworkCookieJar.cpp
+++ b/src/kits/network/libnetapi/NetworkCookieJar.cpp
@@ -71,6 +71,8 @@ BNetworkCookieJar::~BNetworkCookieJar()
 {
        for (Iterator it = GetIterator(); it.Next() != NULL;)
                delete it.Remove();
+
+       delete fCookieHashMap;
 }
 
 
@@ -356,6 +358,30 @@ BNetworkCookieJar::Unflatten(type_code, const void* 
buffer, ssize_t size)
 }
 
 
+BNetworkCookieJar&
+BNetworkCookieJar::operator=(const BNetworkCookieJar& other)
+{
+       if(&other == this)
+               return *this;
+
+       BArchivable::operator=(other);
+       BFlattenable::operator=(other);
+
+       fFlattened = other.fFlattened;
+
+       delete fCookieHashMap;
+       fCookieHashMap = new PrivateHashMap();
+
+       for (Iterator it = other.GetIterator(); it.HasNext();)
+       {
+               BNetworkCookie* cookie = it.Next();
+               AddCookie(*cookie); // Pass by reference so the cookie is 
copied.
+       }
+
+       return *this;
+}
+
+
 // #pragma mark Iterators
 
 

############################################################################

Revision:    hrev46298
Commit:      9ce2f7e3863c7c69284eaad6466c6b0247f0037b
URL:         http://cgit.haiku-os.org/haiku/commit/?id=9ce2f7e
Author:      Adrien Destugues <pulkomandy@xxxxxxxxxxxxx>
Date:        Mon Oct 28 16:09:18 2013 UTC

Improve HTTP authentication support.

The authentication state is stored (in a hash map, using the domain+path
as a key) in the UrlContext class. It can then be reused for multiple
requests to the same place. We also lookup stored authentications for
parent directories and stop at the first we find.

Authentication state is not stored on disk (unlike cookies), and there
can only be one for each domain+path.

----------------------------------------------------------------------------

diff --git a/headers/os/net/HttpRequest.h b/headers/os/net/HttpRequest.h
index 2c4248c..d18222a 100644
--- a/headers/os/net/HttpRequest.h
+++ b/headers/os/net/HttpRequest.h
@@ -9,7 +9,6 @@
 #include <deque>
 
 
-#include <HttpAuthentication.h>
 #include <HttpForm.h>
 #include <HttpHeaders.h>
 #include <HttpResult.h>
@@ -93,7 +92,6 @@ private:
                        BNetBuffer                      fInputBuffer;
 
                        BHttpHeaders            fHeaders;
-                       BHttpAuthentication     fAuthentication;
 
        // Request status
 
diff --git a/headers/os/net/UrlContext.h b/headers/os/net/UrlContext.h
index 414a371..6a4541f 100644
--- a/headers/os/net/UrlContext.h
+++ b/headers/os/net/UrlContext.h
@@ -6,22 +6,36 @@
 #define _B_URL_CONTEXT_H_
 
 
+#include <HttpAuthentication.h>
 #include <NetworkCookieJar.h>
 
 
+namespace BPrivate {
+       template <class key, class value> class HashMap;
+       class HashString;
+}
+
+
 class BUrlContext {
 public:
                                                                BUrlContext();
+                                                               ~BUrlContext();
 
        // Context modifiers
                        void                            SetCookieJar(
                                                                        const 
BNetworkCookieJar& cookieJar);
+                       void                            AddAuthentication(const 
BUrl& url,
+                                                                       
BHttpAuthentication* const authentication);
                                                                                
        
        // Context accessors
                        BNetworkCookieJar&      GetCookieJar();
+                       BHttpAuthentication& GetAuthentication(const BUrl& url);
 
 private:
                        BNetworkCookieJar       fCookieJar;
+                       typedef BPrivate::HashMap<BPrivate::HashString,
+                               BHttpAuthentication*> BHttpAuthenticationMap;
+                       BHttpAuthenticationMap* fAuthenticationMap;
 };
 
 #endif // _B_URL_CONTEXT_H_
diff --git a/src/kits/network/libnetapi/HttpRequest.cpp 
b/src/kits/network/libnetapi/HttpRequest.cpp
index 7b19990..6330a30 100644
--- a/src/kits/network/libnetapi/HttpRequest.cpp
+++ b/src/kits/network/libnetapi/HttpRequest.cpp
@@ -344,22 +344,35 @@ BHttpRequest::_ProtocolLoop()
                                break;
 
                        case B_HTTP_STATUS_CLASS_CLIENT_ERROR:
-                               switch (fResult.StatusCode()) {
-                                       case B_HTTP_STATUS_UNAUTHORIZED:
-                                               if (fAuthentication.Method() != 
B_HTTP_AUTHENTICATION_NONE) {
-                                                       newRequest = false;
-                                                       break;
-                                               }
+                               if(fResult.StatusCode() == 
B_HTTP_STATUS_UNAUTHORIZED) {
+                                       BHttpAuthentication* authentication
+                                               = 
&fContext->GetAuthentication(fUrl);
+                                       status_t status = B_OK;
+
+                                       if (authentication->Method() == 
B_HTTP_AUTHENTICATION_NONE)
+                                       {
+                                               // There is no authentication 
context for this
+                                               // url yet, so let's create one.
+                                               authentication = new 
BHttpAuthentication();
+                                               status = 
authentication->Initialize(
+                                                       
fHeaders["WWW-Authenticate"]);
+                                               
fContext->AddAuthentication(fUrl, authentication);
+                                       }
 
-                                               newRequest = false;
-                                               if (fOptUsername.Length() > 0
-                                                       && 
fAuthentication.Initialize(fHeaders["WWW-Authenticate"])
-                                                               == B_OK) {
-                                                       
fAuthentication.SetUserName(fOptUsername);
-                                                       
fAuthentication.SetPassword(fOptPassword);
-                                                       newRequest = true;
-                                               }
-                                               break;
+                                       newRequest = false;
+                                       if (fOptUsername.Length() > 0 && status 
== B_OK) {
+                                               // If we received an username 
and password, add them
+                                               // to the request. This will 
either change the
+                                               // credentials for an existing 
request, or set them
+                                               // for a new one we created 
just above.
+                                               //
+                                               // If this request handles HTTP 
redirections, it will
+                                               // also automatically retry 
connecting and send the
+                                               // login information.
+                                               
authentication->SetUserName(fOptUsername);
+                                               
authentication->SetPassword(fOptPassword);
+                                               newRequest = true;
+                                       }
                                }
                                break;
 
@@ -811,11 +824,16 @@ BHttpRequest::_AddHeaders()
                fOutputHeaders.AddHeader("Referer", fOptReferer.String());
 
        // Authentication
-       if (fAuthentication.Method() != B_HTTP_AUTHENTICATION_NONE) {
-               BString request(fRequestMethod);
+       BHttpAuthentication& authentication = fContext->GetAuthentication(fUrl);
+       if (authentication.Method() != B_HTTP_AUTHENTICATION_NONE) {
+               if (fOptUsername.Length() > 0) {
+                       authentication.SetUserName(fOptUsername);
+                       authentication.SetPassword(fOptPassword);
+               }
 
+               BString request(fRequestMethod);
                fOutputHeaders.AddHeader("Authorization",
-                       fAuthentication.Authorization(fUrl, request));
+                       authentication.Authorization(fUrl, request));
        }
 
        // Required headers for POST data
diff --git a/src/kits/network/libnetapi/UrlContext.cpp 
b/src/kits/network/libnetapi/UrlContext.cpp
index a869304..429eb59 100644
--- a/src/kits/network/libnetapi/UrlContext.cpp
+++ b/src/kits/network/libnetapi/UrlContext.cpp
@@ -9,11 +9,35 @@
 
 #include <UrlContext.h>
 
+#include <stdio.h>
+
+#include <HashMap.h>
+#include <HashString.h>
+
 
 BUrlContext::BUrlContext()
        : 
-       fCookieJar()
+       fCookieJar(),
+       fAuthenticationMap(NULL)
 {
+       fAuthenticationMap = new(std::nothrow) BHttpAuthenticationMap();
+       if(!fAuthenticationMap)
+               return;
+       // This is the default authentication, used when nothing else is found.
+       // The empty string used as a key will match all the domain strings, 
once
+       // we have removed all components.
+       fAuthenticationMap->Put(HashString("", 0), new BHttpAuthentication());
+}
+
+
+BUrlContext::~BUrlContext()
+{
+       BHttpAuthenticationMap::Iterator iterator =
+               fAuthenticationMap->GetIterator();
+       while(iterator.HasNext())
+               delete iterator.Remove().value;
+
+       delete fAuthenticationMap;
 }
 
 
@@ -27,6 +51,21 @@ BUrlContext::SetCookieJar(const BNetworkCookieJar& cookieJar)
 }
 
 
+void
+BUrlContext::AddAuthentication(const BUrl& url,
+       BHttpAuthentication* const authentication)
+{
+       BString domain = url.Host();
+       domain += url.Path();
+       BPrivate::HashString hostHash(domain.String(), domain.Length());
+
+       delete fAuthenticationMap->Get(hostHash);
+               // Make sure we don't leak memory by overriding a previous
+               // authentication for the same domain.
+       fAuthenticationMap->Put(hostHash, authentication);
+}
+
+
 // #pragma mark Context accessors
 
 
@@ -35,3 +74,23 @@ BUrlContext::GetCookieJar()
 {
        return fCookieJar;
 }
+
+
+BHttpAuthentication&
+BUrlContext::GetAuthentication(const BUrl& url)
+{
+       BString domain = url.Host();
+       domain += url.Path();
+
+       BHttpAuthentication* authentication = NULL;
+
+       do {
+               authentication = fAuthenticationMap->Get( 
HashString(domain.String(),
+                       domain.Length()));
+
+               domain.Truncate(domain.FindLast('/'));
+
+       } while(authentication == NULL);
+
+       return *authentication;
+}


Other related posts:

  • » [haiku-commits] haiku: hrev46298 - src/kits/network/libnetapi headers/os/net - pulkomandy