From 660a5e7f371005a29ae4281d4ff7e09aefda48bb Mon Sep 17 00:00:00 2001 From: "gagan%netscape.com" Date: Fri, 11 Feb 2000 00:47:50 +0000 Subject: [PATCH] Fixed bug 27024. Changed nsIHTTPChannel.idl to have proxy host/port accessors and modifiers. Channels may now override the proxy setting from the HTTP handler. r=valeski Fixed bug 24329. Made mProxyAuthList in nsAuthEngine to keep the list of proxy authentications. Logout now clears both proxy and basic auths. r=rjc Fixed bug 26149. Authenticate now aborts only if the user doesn't click cancel on the PromptUserPass dialog. Removed the unnecessary nsIChannel* parameter on Authenticate. r=rjc Fixed bug 24304. We now register a callback for proxy preferences. r=rjc Fixed bug 17158. We now honor "network.proxy.no_proxies_on" preference to diable proxy activity on specified host or domain. We still need a fix for 27141 to read and write this pref correctly. r=rjc Fixed bug 16442. Referer is only added if its an http URI. r=rjc git-svn-id: svn://10.0.0.236/trunk@60340 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/netwerk/base/public/MANIFEST | 1 + mozilla/netwerk/base/public/Makefile.in | 1 + mozilla/netwerk/base/public/makefile.win | 1 + .../protocol/http/public/nsIHTTPChannel.idl | 5 + .../protocol/http/src/nsAuthEngine.cpp | 94 +++++- .../netwerk/protocol/http/src/nsAuthEngine.h | 41 ++- .../protocol/http/src/nsHTTPChannel.cpp | 185 +++++++++--- .../netwerk/protocol/http/src/nsHTTPChannel.h | 7 +- .../protocol/http/src/nsHTTPHandler.cpp | 281 ++++++++++++++---- .../netwerk/protocol/http/src/nsHTTPHandler.h | 27 +- .../protocol/http/src/nsHTTPRequest.cpp | 31 -- .../http/src/nsHTTPResponseListener.cpp | 1 - 12 files changed, 507 insertions(+), 168 deletions(-) diff --git a/mozilla/netwerk/base/public/MANIFEST b/mozilla/netwerk/base/public/MANIFEST index a38089fcee4..73716e1f718 100644 --- a/mozilla/netwerk/base/public/MANIFEST +++ b/mozilla/netwerk/base/public/MANIFEST @@ -4,3 +4,4 @@ netCore.h nsNetUtil.h +nsUnixColorPrintf.h diff --git a/mozilla/netwerk/base/public/Makefile.in b/mozilla/netwerk/base/public/Makefile.in index 9cca0383e04..9ade734a9f4 100644 --- a/mozilla/netwerk/base/public/Makefile.in +++ b/mozilla/netwerk/base/public/Makefile.in @@ -59,6 +59,7 @@ XPIDLSRCS = \ EXPORTS = \ netCore.h \ nsNetUtil.h \ + nsUnixColorPrintf.h \ $(NULL) include $(topsrcdir)/config/rules.mk diff --git a/mozilla/netwerk/base/public/makefile.win b/mozilla/netwerk/base/public/makefile.win index a5267ee772e..a6b29598f5b 100644 --- a/mozilla/netwerk/base/public/makefile.win +++ b/mozilla/netwerk/base/public/makefile.win @@ -27,6 +27,7 @@ include <$(DEPTH)/config/config.mak> EXPORTS = \ netCore.h \ nsNetUtil.h \ + nsUnixColorPrintf.h \ $(NULL) XPIDLSRCS = \ diff --git a/mozilla/netwerk/protocol/http/public/nsIHTTPChannel.idl b/mozilla/netwerk/protocol/http/public/nsIHTTPChannel.idl index 3ad94f5585a..6ec4f1a620e 100644 --- a/mozilla/netwerk/protocol/http/public/nsIHTTPChannel.idl +++ b/mozilla/netwerk/protocol/http/public/nsIHTTPChannel.idl @@ -55,6 +55,11 @@ interface nsIHTTPChannel : nsIChannel */ attribute nsIInputStream PostDataStream; + /* Since multiple inheritence is not supported in idl */ + attribute string ProxyHost; + attribute long ProxyPort; + attribute PRBool UsingProxy; + /* Response funtions. A call to any of these implicitly calls Load() on this protocol instance. diff --git a/mozilla/netwerk/protocol/http/src/nsAuthEngine.cpp b/mozilla/netwerk/protocol/http/src/nsAuthEngine.cpp index 0ce318efd38..28fef0147ce 100644 --- a/mozilla/netwerk/protocol/http/src/nsAuthEngine.cpp +++ b/mozilla/netwerk/protocol/http/src/nsAuthEngine.cpp @@ -26,22 +26,33 @@ #include "nsCRT.h" #include "plstr.h" #include "nsXPIDLString.h" +#include "nsString.h" +#include "nsIIOService.h" +#include "nsUnixColorPrintf.h" +#include "nsIServiceManager.h" + +static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); nsAuthEngine::nsAuthEngine() { if (NS_FAILED(NS_NewISupportsArray(getter_AddRefs(mAuthList)))) NS_ERROR("unable to create new auth list"); + if (NS_FAILED(NS_NewISupportsArray(getter_AddRefs(mProxyAuthList)))) + NS_ERROR("unable to create new auth list"); } nsAuthEngine::~nsAuthEngine() { mAuthList->Clear(); + mProxyAuthList->Clear(); } nsresult nsAuthEngine::Logout() { - return mAuthList->Clear(); + return NS_SUCCEEDED(mAuthList->Clear()) && + NS_SUCCEEDED(mProxyAuthList->Clear()) ? + NS_OK : NS_ERROR_FAILURE; } nsresult @@ -52,7 +63,6 @@ nsAuthEngine::GetAuthString(nsIURI* i_URI, char** o_AuthString) return NS_ERROR_NULL_POINTER; *o_AuthString = nsnull; NS_ASSERTION(mAuthList, "No auth list!"); - // or should we try and make this if (!mAuthList) return NS_ERROR_FAILURE; nsXPIDLCString host; @@ -82,8 +92,7 @@ nsAuthEngine::GetAuthString(nsIURI* i_URI, char** o_AuthString) if (auth->uri.get() == i_URI) { *o_AuthString = nsCRT::strdup(auth->encodedString); - if (!*o_AuthString) return NS_ERROR_OUT_OF_MEMORY; - return NS_OK; + return (!*o_AuthString) ? NS_ERROR_OUT_OF_MEMORY : NS_OK; } /* @@ -124,26 +133,93 @@ nsAuthEngine::GetAuthString(nsIURI* i_URI, char** o_AuthString) PL_strlen(authDir)))) { *o_AuthString = nsCRT::strdup(auth->encodedString); - if (!*o_AuthString) return NS_ERROR_OUT_OF_MEMORY; - return NS_OK; + return (!*o_AuthString) ? NS_ERROR_OUT_OF_MEMORY : NS_OK; } } return rv; } nsresult -nsAuthEngine::SetAuthString(nsIURI* i_URI, const char* i_AuthString) +nsAuthEngine::SetAuth(nsIURI* i_URI, + const char* i_AuthString, + PRBool bProxyAuth) { if (!i_URI || !i_AuthString) return NS_ERROR_NULL_POINTER; - NS_ASSERTION(mAuthList, "No authentication list"); + NS_ASSERTION(bProxyAuth ? mProxyAuthList : mAuthList, + "No authentication list"); + if ((bProxyAuth && !mProxyAuthList) || (!bProxyAuth && !mAuthList)) + return NS_ERROR_FAILURE; // TODO Extract user/pass info if available nsAuth* auth = new nsAuth(i_URI, i_AuthString); if (!auth) return NS_ERROR_OUT_OF_MEMORY; - nsresult rv = mAuthList->AppendElement(auth) ? NS_OK : NS_ERROR_FAILURE; + // We have to replace elements with earliar matching...TODO + return + bProxyAuth ? + (mProxyAuthList->AppendElement(auth) ? NS_OK : NS_ERROR_FAILURE): + (mAuthList->AppendElement(auth) ? NS_OK : NS_ERROR_FAILURE); +} + + +nsresult +nsAuthEngine::GetProxyAuthString(const char* i_Host, + PRInt32 i_Port, + char* *o_AuthString) +{ + nsresult rv = NS_OK; + if (!o_AuthString) + return NS_ERROR_NULL_POINTER; + *o_AuthString = nsnull; + NS_ASSERTION(mProxyAuthList, "No proxy auth list!"); + if (!mProxyAuthList) + return NS_ERROR_FAILURE; + + PRUint32 count=0; + (void)mProxyAuthList->Count(&count); + if (count <=0) + return NS_OK; // not found... + + nsXPIDLCString authHost; + PRInt32 authPort; + for (PRInt32 i = count-1; i>=0; --i) + { + nsAuth* auth = (nsAuth*)mProxyAuthList->ElementAt(i); + (void) auth->uri->GetHost(getter_Copies(authHost)); + (void)auth->uri->GetPort(&authPort); + if ((0 == PL_strncasecmp(authHost, i_Host, + PL_strlen(authHost))) && + (i_Port == authPort)) + { + *o_AuthString = nsCRT::strdup(auth->encodedString); + return (!*o_AuthString) ? NS_ERROR_OUT_OF_MEMORY : NS_OK; + } + } return rv; } + + +nsresult +nsAuthEngine::SetProxyAuthString(const char* host, + PRInt32 port, + const char* i_AuthString) +{ + nsresult rv; + nsCAutoString spec("http://"); + nsCOMPtr uri; + + spec.Append(host); + spec.Append(':'); + spec.Append(port); + + NS_WITH_SERVICE(nsIIOService, serv, kIOServiceCID, &rv); + if (NS_FAILED(rv)) return rv; + + rv = serv->NewURI(spec.GetBuffer(), nsnull, getter_AddRefs(uri)); + if (NS_FAILED(rv)) return rv; + + return SetAuth(uri, i_AuthString, PR_TRUE); +} diff --git a/mozilla/netwerk/protocol/http/src/nsAuthEngine.h b/mozilla/netwerk/protocol/http/src/nsAuthEngine.h index 82814d54789..fad2420baa9 100644 --- a/mozilla/netwerk/protocol/http/src/nsAuthEngine.h +++ b/mozilla/netwerk/protocol/http/src/nsAuthEngine.h @@ -31,6 +31,9 @@ class nsIURI; The nsAuthEngine class is the central class for handling authentication lists, checks etc. + There should be a class nsProxyAuthEngine that shares all this... + I will move it that way... someday... + -Gagan Saksena 11/12/99 */ class nsAuthEngine @@ -40,26 +43,44 @@ public: nsAuthEngine(void); virtual ~nsAuthEngine(); - /* - enum authType { Basic, Digest } - */ - - // Set an auth string - NS_IMETHOD SetAuthString(nsIURI* i_URI, - const char* i_AuthString /*, int* type */); // Get an auth string - NS_IMETHOD GetAuthString(nsIURI* i_URI, - char** o_AuthString /*, int* type */); + NS_IMETHOD GetAuthString(nsIURI* i_URI, char** o_AuthString); + + // Set an auth string + NS_IMETHOD SetAuthString(nsIURI* i_URI, const char* i_AuthString); + + // Get a proxy auth string with host/port + NS_IMETHOD GetProxyAuthString(const char* host, + PRInt32 port, + char** o_AuthString); + + // Set a proxy auth string + NS_IMETHOD SetProxyAuthString(const char* host, + PRInt32 port, + const char* i_AuthString); + /* - Expire all existing auth list entries. + Expire all existing auth list entries including proxy auths. */ NS_IMETHOD Logout(void); protected: + NS_IMETHOD SetAuth(nsIURI* i_URI, + const char* i_AuthString, + PRBool bProxyAuth = PR_FALSE); + nsCOMPtr mAuthList; + // this needs to be a list becuz pac can produce more ... + nsCOMPtr mProxyAuthList; }; +inline nsresult +nsAuthEngine::SetAuthString(nsIURI* i_URI, const char* i_AuthString) +{ + return SetAuth(i_URI, i_AuthString); +} + #endif /* _nsAuthEngine_h_ */ diff --git a/mozilla/netwerk/protocol/http/src/nsHTTPChannel.cpp b/mozilla/netwerk/protocol/http/src/nsHTTPChannel.cpp index 1fce581fdc9..54fd9a0f814 100644 --- a/mozilla/netwerk/protocol/http/src/nsHTTPChannel.cpp +++ b/mozilla/netwerk/protocol/http/src/nsHTTPChannel.cpp @@ -50,6 +50,7 @@ #include "nsINetDataCacheManager.h" #include "nsINetDataCache.h" #include "nsIScriptSecurityManager.h" +#include "nsIProxy.h" #include "nsMimeTypes.h" #ifdef DEBUG_gagan @@ -105,6 +106,8 @@ nsHTTPChannel::nsHTTPChannel(nsIURI* i_URL, mFiredOpenOnStartRequest(PR_FALSE), mAuthTriedWithPrehost(PR_FALSE), mUsingProxy(PR_FALSE), + mProxy(0), + mProxyPort(-1), mBufferSegmentSize(bufferSegmentSize), mBufferMaxSize(bufferMaxSize) { @@ -130,6 +133,7 @@ nsHTTPChannel::~nsHTTPChannel() mEventSink = null_nsCOMPtr(); mResponseContext = null_nsCOMPtr(); mLoadGroup = null_nsCOMPtr(); + CRTFREEIF(mProxy); } NS_IMPL_ISUPPORTS4(nsHTTPChannel, nsIHTTPChannel, nsIChannel, nsIInterfaceRequestor, nsIProgressEventSink); @@ -614,7 +618,8 @@ nsHTTPChannel::OnStatus(nsIChannel *aChannel, nsresult rv = NS_OK; if (mCallbacks) { nsCOMPtr progressProxy; - rv = mCallbacks->GetInterface(NS_GET_IID(nsIProgressEventSink), getter_AddRefs(progressProxy)); + rv = mCallbacks->GetInterface(NS_GET_IID(nsIProgressEventSink), + getter_AddRefs(progressProxy)); if (NS_FAILED(rv)) return rv; rv = progressProxy->OnStatus(this, aContext, aMsg); } @@ -1250,7 +1255,7 @@ nsresult nsHTTPChannel::Redirect(const char *aNewLocation, newURLSpec = nsnull; log_rv = newURI->GetSpec(&newURLSpec); if (NS_FAILED(log_rv)) - newURLSpec = nsCRT::strdup("?"); + newURLSpec = nsCRT::strdup("?"); PR_LOG(gHTTPLog, PR_LOG_ALWAYS, ("ProcessRedirect [this=%x].\tRedirecting to: %s.\n", this, newURLSpec)); @@ -1435,16 +1440,13 @@ nsresult nsHTTPChannel::OnHeadersAvailable() nsresult -nsHTTPChannel::Authenticate(const char *iChallenge, - nsIChannel **oChannel, PRBool iProxyAuth) +nsHTTPChannel::Authenticate(const char *iChallenge, PRBool iProxyAuth) { nsresult rv = NS_ERROR_FAILURE; - nsCOMPtr channel; - if (!oChannel || !iChallenge) + nsIChannel* channel; + if (!iChallenge) return NS_ERROR_NULL_POINTER; - *oChannel = nsnull; // Initialize... - // Determine the new username password combination to use char* newUserPass = nsnull; if (!mAuthTriedWithPrehost && !iProxyAuth) // Proxy auth's never in prehost @@ -1526,11 +1528,9 @@ nsHTTPChannel::Authenticate(const char *iChallenge, } CRTFREEIF(newUserPass); newUserPass = temp.ToNewCString(); -#ifdef DEBUG_gagan - PRINTF_BLUE; - printf("UserPassword- %s",newUserPass); -#endif } + else + return rv; } // Construct the auth string request header based on info provided. @@ -1557,8 +1557,10 @@ nsHTTPChannel::Authenticate(const char *iChallenge, mCallbacks, mLoadAttributes, mOriginalURI, mBufferSegmentSize, mBufferMaxSize, - getter_AddRefs(channel)); + &channel);// delibrately... if (NS_FAILED(rv)) return rv; + if (!channel) + return NS_ERROR_OUT_OF_MEMORY; nsCOMPtr httpChannel = do_QueryInterface(channel); NS_ASSERTION(httpChannel, "Something terrible happened..!"); @@ -1575,16 +1577,13 @@ nsHTTPChannel::Authenticate(const char *iChallenge, // Fire the new request... rv = channel->AsyncRead(0, -1, mResponseContext, mResponseDataListener); - *oChannel = channel; - NS_ADDREF(*oChannel); - return rv; -} -nsresult -nsHTTPChannel::SetUsingProxy(PRBool i_UsingProxy) -{ - mUsingProxy = i_UsingProxy; - return NS_OK; + // Abort the current response... This will disconnect the consumer from + // the response listener... Thus allowing the entity that follows to + // be discarded without notifying the consumer... + Abort(); + + return rv; } nsresult @@ -1622,9 +1621,7 @@ nsHTTPChannel::FinishedResponseHeaders(void) // If a redirect (ie. 30x) occurs, the mResponseDataListener is // released and a new request is issued... // - rv = ProcessStatusCode(); - - return rv; + return ProcessStatusCode(); } nsresult @@ -1636,18 +1633,32 @@ nsHTTPChannel::ProcessStatusCode(void) statusCode = 0; mResponse->GetStatus(&statusCode); - if ( statusCode != 401 && mAuthTriedWithPrehost) { - // We know this auth challenge response was successful. Cache any - // authentication so that future accesses can make use of it, - // particularly other URLs loaded from the body of this response. - nsAuthEngine* pEngine; - NS_ASSERTION(mHandler, "HTTP handler went away"); - if (NS_SUCCEEDED(mHandler->GetAuthEngine(&pEngine))) { - nsXPIDLCString authString; - rv = GetRequestHeader(nsHTTPAtoms::Authorization, getter_Copies(authString)); - if (NS_FAILED(rv)) return rv; - - pEngine->SetAuthString(mURI, authString); + NS_ASSERTION(mHandler, "HTTP handler went away"); + nsAuthEngine* pEngine; + // We know this auth challenge response was successful. Cache any + // authentication so that future accesses can make use of it, + // particularly other URLs loaded from the body of this response. + if (NS_SUCCEEDED(mHandler->GetAuthEngine(&pEngine))) + { + nsXPIDLCString authString; + if (statusCode != 407) + { + if (mUsingProxy) + { + rv = GetRequestHeader(nsHTTPAtoms::Proxy_Authorization, + getter_Copies(authString)); + if (NS_FAILED(rv)) return rv; + + pEngine->SetProxyAuthString( + mProxy, mProxyPort, authString); + } + + if (statusCode != 401 && mAuthTriedWithPrehost) + { + rv = GetRequestHeader(nsHTTPAtoms::Authorization, + getter_Copies(authString)); + pEngine->SetAuthString(mURI, authString); + } } } @@ -1835,16 +1846,98 @@ nsHTTPChannel::ProcessAuthentication(PRInt32 aStatusCode) if (NS_FAILED(rv) || !challenge || !*challenge) return rv; - nsCOMPtr channel; - if (NS_FAILED(rv = Authenticate(challenge, - getter_AddRefs(channel), - (407 == aStatusCode)))) - return rv; + return Authenticate(challenge, (407 == aStatusCode)); +} - // Abort the current response... This will disconnect the consumer from - // the response listener... Thus allowing the entity that follows to - // be discarded without notifying the consumer... - Abort(); +// nsIProxy methods- but not. since we cant multi in idl. +NS_IMETHODIMP +nsHTTPChannel::GetProxyHost(char* *o_ProxyHost) +{ + if (!o_ProxyHost) + return NS_ERROR_NULL_POINTER; + if (mProxy) + { + *o_ProxyHost = nsCRT::strdup(mProxy); + return (*o_ProxyHost == nsnull) ? NS_ERROR_OUT_OF_MEMORY : NS_OK; + } + else + { + *o_ProxyHost = nsnull; + return NS_OK; + } +} +NS_IMETHODIMP +nsHTTPChannel::SetProxyHost(const char* i_ProxyHost) +{ + CRTFREEIF(mProxy); + if (i_ProxyHost) + { + mProxy = nsCRT::strdup(i_ProxyHost); + return (mProxy == nsnull) ? NS_ERROR_OUT_OF_MEMORY : NS_OK; + } + return NS_OK; +} + +NS_IMETHODIMP +nsHTTPChannel::GetProxyPort(PRInt32 *aPort) +{ + *aPort = mProxyPort; + return NS_OK; +} + +NS_IMETHODIMP +nsHTTPChannel::SetProxyPort(PRInt32 i_ProxyPort) +{ + mProxyPort = i_ProxyPort; + return NS_OK; +} + +NS_IMETHODIMP +nsHTTPChannel::SetUsingProxy(PRBool i_UsingProxy) +{ + mUsingProxy = i_UsingProxy; + nsresult rv = NS_OK; + // Check for proxy associated header if needed- + if (mUsingProxy) + { + nsAuthEngine* pAuthEngine = nsnull; + NS_ASSERTION(mHandler, "Handler went away!"); + if (!mHandler) return rv; + rv = mHandler->GetAuthEngine(&pAuthEngine); + if (NS_SUCCEEDED(rv) && pAuthEngine) + { + nsXPIDLCString authStr; + nsXPIDLCString proxyHost; + PRInt32 proxyPort; + // When we switch on proxy auto config this will change... + mHandler->GetProxyHost(getter_Copies(proxyHost)); + mHandler->GetProxyPort(&proxyPort); + + if (NS_SUCCEEDED(pAuthEngine->GetProxyAuthString(proxyHost, + proxyPort, + getter_Copies(authStr)))) + { + if (authStr && *authStr) + mRequest->SetHeader(nsHTTPAtoms::Proxy_Authorization, + authStr); + } + // check for auth as well... + if (NS_SUCCEEDED(pAuthEngine->GetAuthString(mURI, + getter_Copies(authStr)))) + { + if (authStr && *authStr) + mRequest->SetHeader(nsHTTPAtoms::Authorization, + authStr); + } + } + } return rv; } + +NS_IMETHODIMP +nsHTTPChannel::GetUsingProxy(PRBool* o_UsingProxy) +{ + *o_UsingProxy = mUsingProxy; + return NS_OK; +} diff --git a/mozilla/netwerk/protocol/http/src/nsHTTPChannel.h b/mozilla/netwerk/protocol/http/src/nsHTTPChannel.h index b137fe8fc24..201e8443fe8 100644 --- a/mozilla/netwerk/protocol/http/src/nsHTTPChannel.h +++ b/mozilla/netwerk/protocol/http/src/nsHTTPChannel.h @@ -81,7 +81,6 @@ public: // nsHTTPChannel methods: nsresult Authenticate(const char *iChallenge, - nsIChannel **oChannel, PRBool bProxyAuth = PR_FALSE); nsresult Init(nsILoadGroup *aGroup); nsresult Open(); @@ -100,9 +99,6 @@ public: nsresult OnHeadersAvailable(); - // Set if this channel is using proxy to connect - nsresult SetUsingProxy(PRBool i_UsingProxy); - nsresult FinishedResponseHeaders(); nsresult Abort(); @@ -163,7 +159,10 @@ protected: And so we need to throw a dialog box! */ PRBool mAuthTriedWithPrehost; + PRBool mUsingProxy; + char* mProxy; + PRInt32 mProxyPort; PRUint32 mBufferSegmentSize; PRUint32 mBufferMaxSize; diff --git a/mozilla/netwerk/protocol/http/src/nsHTTPHandler.cpp b/mozilla/netwerk/protocol/http/src/nsHTTPHandler.cpp index 9838b704c94..3bc60d2a023 100644 --- a/mozilla/netwerk/protocol/http/src/nsHTTPHandler.cpp +++ b/mozilla/netwerk/protocol/http/src/nsHTTPHandler.cpp @@ -70,11 +70,13 @@ // the file nspr.log // PRLogModuleInfo* gHTTPLog = nsnull; - #endif /* PR_LOGGING */ #define MAX_NUMBER_OF_OPEN_TRANSPORTS 8 +static PRInt32 PR_CALLBACK ProxyPrefsCallback(const char* pref, void* instance); +static const char PROXY_PREFS[] = "network.proxy"; + static NS_DEFINE_CID(kStandardUrlCID, NS_STANDARDURL_CID); static NS_DEFINE_CID(kAuthUrlParserCID, NS_AUTHORITYURLPARSER_CID); static NS_DEFINE_CID(kSocketTransportServiceCID, NS_SOCKETTRANSPORTSERVICE_CID); @@ -114,6 +116,7 @@ static nsresult CategoryCreateService( const char *category ) { nsresult rv = NS_OK; + int nFailed = 0; nsCOMPtr categoryManager = do_GetService("mozilla.categorymanager.1", &rv); if (!categoryManager) return rv; @@ -265,14 +268,27 @@ nsHTTPHandler::NewChannel(const char* verb, nsIURI* i_URL, rv = pChannel->SetNotificationCallbacks(notificationCallbacks); if (NS_FAILED(rv)) goto done; + PRBool useProxy = mUseProxy && CanUseProxy(i_URL); + if (useProxy) + { + rv = pChannel->SetProxyHost(mProxy); + if (NS_FAILED(rv)) goto done; + rv = pChannel->SetProxyPort(mProxyPort); + if (NS_FAILED(rv)) goto done; + } + rv = pChannel->SetUsingProxy(useProxy); + if (originalURI) { // Referer - misspelled, but per the HTTP spec nsCOMPtr key = NS_NewAtom("referer"); nsXPIDLCString spec; originalURI->GetSpec(getter_Copies(spec)); - if (spec) + if (spec && (0 == PL_strncasecmp((const char*)spec, + "http",4))) + { pChannel->SetRequestHeader(key, spec); + } } rv = pChannel->QueryInterface(NS_GET_IID(nsIChannel), (void**)o_Instance); @@ -552,7 +568,8 @@ nsHTTPHandler::SetProxyPort(PRInt32 i_ProxyPort) nsHTTPHandler::nsHTTPHandler(): mAcceptLanguages(nsnull), mDoKeepAlive(PR_FALSE), - mProxy(nsnull), + mNoProxyFor(0), + mProxy(0), mUseProxy(PR_FALSE) { NS_INIT_REFCNT(); @@ -563,8 +580,13 @@ nsHTTPHandler::Init() { nsresult rv = NS_OK; - NS_WITH_SERVICE(nsIPref, prefs, kPrefServiceCID, &rv); - if (NS_FAILED(rv)) return rv; + mPrefs = do_GetService(kPrefServiceCID, &rv); + if (!mPrefs) + return NS_ERROR_OUT_OF_MEMORY; + + mPrefs->RegisterCallback(PROXY_PREFS, + ProxyPrefsCallback, (void*)this); + PrefsChanged(); // initialize the version and app components mAppName = "Mozilla"; @@ -572,14 +594,14 @@ nsHTTPHandler::Init() mAppSecurity = "N"; nsXPIDLCString locale; - rv = prefs->CopyCharPref("general.useragent.locale", + rv = mPrefs->CopyCharPref("general.useragent.locale", getter_Copies(locale)); if (NS_SUCCEEDED(rv)) { mAppLanguage = locale; } nsXPIDLCString milestone; - rv = prefs->CopyCharPref("general.milestone", + rv = mPrefs->CopyCharPref("general.milestone", getter_Copies(milestone)); if (NS_SUCCEEDED(rv)) { mAppVersion += milestone; @@ -662,49 +684,7 @@ nsHTTPHandler::Init() rv = NS_NewISupportsArray(getter_AddRefs(mIdleTransports)); if (NS_FAILED(rv)) return rv; -#if 1 // only for keep alive - // This stuff only till Keep-Alive is not switched on by default - PRInt32 keepalive = -1; - rv = prefs->GetIntPref("network.http.keep-alive", &keepalive); - mDoKeepAlive = (keepalive == 1); -#ifdef DEBUG_gagan - printf("Keep-alive switched "); - printf(mDoKeepAlive ? STARTYELLOW "on\n" ENDCOLOR : - STARTRED "off\n" ENDCOLOR); -#endif //DEBUG_gagan -#endif // remove till here - nsXPIDLCString proxyServer; - nsXPIDLCString acceptLanguages; - PRInt32 proxyPort = -1; - PRInt32 type = -1; - rv = prefs->GetIntPref("network.proxy.type", &type); - //WARN for type==2 - mUseProxy = (type == 1); //type == 2 is autoconfig stuff. - if (NS_FAILED(rv)) return rv; - - rv = prefs->CopyCharPref("network.proxy.http", - getter_Copies(proxyServer)); - if (NS_FAILED(rv)) return rv; - - rv = prefs->GetIntPref("network.proxy.http_port",&proxyPort); - if (NS_FAILED(rv)) return rv; - - if (NS_SUCCEEDED(rv) && (proxyPort>0)) // currently a bug in IntPref - { - rv = SetProxyHost(proxyServer); - if (NS_FAILED(rv)) return rv; - - rv = SetProxyPort(proxyPort); - if (NS_FAILED(rv)) return rv; - } - rv = prefs->CopyCharPref("intl.accept_languages", - getter_Copies(acceptLanguages)); - if (NS_FAILED(rv)) return rv; - - rv = SetAcceptLanguages(acceptLanguages); - if (NS_FAILED(rv)) return rv; - // Startup the http category // Bring alive the objects in the http-protocol-startup category CategoryCreateService(NS_HTTP_STARTUP_CATEGORY); @@ -726,9 +706,13 @@ nsHTTPHandler::~nsHTTPHandler() // Release the Atoms used by the HTTP protocol... nsHTTPAtoms::ReleaseAtoms(); - CRTFREEIF(mAcceptLanguages); - CRTFREEIF(mProxy); + if (mPrefs) + mPrefs->UnregisterCallback(PROXY_PREFS, + ProxyPrefsCallback, (void*)this); + CRTFREEIF(mAcceptLanguages); + CRTFREEIF(mNoProxyFor); + CRTFREEIF(mProxy); } nsresult nsHTTPHandler::RequestTransport(nsIURI* i_Uri, @@ -825,24 +809,50 @@ nsresult nsHTTPHandler::RequestTransport(nsIURI* i_Uri, // if we didn't find any from the keep-alive idlelist if (*o_pTrans == nsnull) { - // Create a new one... - if (!mProxy || !mUseProxy) + // Ask the channel for proxy info... since that overrides + PRBool usingProxy; + + i_Channel->GetUsingProxy(&usingProxy); + if (usingProxy) { - rv = CreateTransport(host, port, host, - bufferSegmentSize, bufferMaxSize, &trans); + nsXPIDLCString proxy; + PRInt32 proxyPort = -1; + + rv = i_Channel->GetProxyHost(getter_Copies(proxy)); + if (NS_FAILED(rv)) return rv; + + rv = i_Channel->GetProxyPort(&proxyPort); + if (NS_FAILED(rv)) return rv; + + rv = CreateTransport(proxy, proxyPort, host, + bufferSegmentSize, bufferMaxSize, &trans); } else { - rv = CreateTransport(mProxy, mProxyPort, host, - bufferSegmentSize, bufferMaxSize, &trans); + // Create a new one... + if (!mProxy || !mUseProxy || !CanUseProxy(i_Uri)) + { + rv = CreateTransport(host, port, host, + bufferSegmentSize, bufferMaxSize, &trans); + // Update the proxy information on the channel + i_Channel->SetProxyHost(mProxy); + i_Channel->SetProxyPort(mProxyPort); + i_Channel->SetUsingProxy(PR_TRUE); + } + else + { + rv = CreateTransport(mProxy, mProxyPort, host, + bufferSegmentSize, bufferMaxSize, &trans); + i_Channel->SetUsingProxy(PR_FALSE); + } } if (NS_FAILED(rv)) return rv; } - i_Channel->SetUsingProxy(mUseProxy); // Put it in the table... // XXX this method incorrectly returns a bool - rv = mTransportList->AppendElement(trans) ? NS_OK : NS_ERROR_FAILURE; + rv = mTransportList->AppendElement(trans) ? + NS_OK : NS_ERROR_FAILURE; if (NS_FAILED(rv)) return rv; *o_pTrans = trans; @@ -1015,3 +1025,156 @@ nsHTTPHandler::BuildUserAgent() { return NS_OK; } +void +nsHTTPHandler::PrefsChanged(const char* pref) +{ + PRBool bChangedAll = (pref) ? PR_FALSE : PR_TRUE; + NS_ASSERTION(mPrefs, "No preference service available!"); + if (!mPrefs) + return; + + nsresult rv = NS_OK; + +#if 1 // only for keep alive TODO + // This stuff only till Keep-Alive is not switched on by default + PRInt32 keepalive = -1; + rv = mPrefs->GetIntPref("network.http.keep-alive", &keepalive); + mDoKeepAlive = (keepalive == 1); +#endif // remove till here + + if (bChangedAll || !PL_strcmp(pref, "network.proxy.type")) + { + PRInt32 type = -1; + rv = mPrefs->GetIntPref("network.proxy.type",&type); + if (NS_SUCCEEDED(rv)) + mUseProxy = (type == 1); // type == 2 is autoconfig stuff + } + + if (bChangedAll || !PL_strcmp(pref, "network.proxy.http")) + { + nsXPIDLCString proxyServer; + rv = mPrefs->CopyCharPref("network.proxy.http", + getter_Copies(proxyServer)); + if (NS_SUCCEEDED(rv)) + SetProxyHost(proxyServer); + } + + if (bChangedAll || !PL_strcmp(pref, "network.proxy.http_port")) + { + PRInt32 proxyPort = -1; + rv = mPrefs->GetIntPref("network.proxy.http_port",&proxyPort); + if (NS_SUCCEEDED(rv) && proxyPort>0) + SetProxyPort(proxyPort); + } + + if (bChangedAll || !PL_strcmp(pref, "network.proxy.no_proxies_on")) + { + nsXPIDLCString noProxy; + rv = mPrefs->CopyCharPref("network.proxy.no_proxies_on", + getter_Copies(noProxy)); + if (NS_SUCCEEDED(rv)) + SetDontUseProxyFor(noProxy); + } + + // Things read only during initialization... + if (bChangedAll) // intl.accept_languages + { + nsXPIDLCString acceptLanguages; + rv = mPrefs->CopyCharPref("intl.accept_languages", + getter_Copies(acceptLanguages)); + if (NS_SUCCEEDED(rv)) + SetAcceptLanguages(acceptLanguages); + } +} + +PRInt32 PR_CALLBACK ProxyPrefsCallback(const char* pref, void* instance) +{ + nsHTTPHandler* pHandler = (nsHTTPHandler*) instance; + NS_ASSERTION(nsnull != pHandler, "bad instance data"); + if (nsnull != pHandler) + pHandler->PrefsChanged(pref); + return 0; +} + +nsresult +nsHTTPHandler::SetDontUseProxyFor(const char* i_hostlist) +{ + CRTFREEIF(mNoProxyFor); + if (i_hostlist) + { + mNoProxyFor = nsCRT::strdup(i_hostlist); + return (mNoProxyFor == nsnull) ? NS_ERROR_OUT_OF_MEMORY : NS_OK; + } + return NS_OK; +} + +PRBool +nsHTTPHandler::CanUseProxy(nsIURI* i_Uri) +{ + + NS_ASSERTION(mProxy, + "This shouldn't even get called if mProxy is null"); + + PRBool rv = PR_TRUE; + if (!mNoProxyFor || !*mNoProxyFor) + return rv; + + PRInt32 port; + char* host; + + rv = i_Uri->GetHost(&host); + if (NS_FAILED(rv)) return rv; + + rv = i_Uri->GetPort(&port); + if (NS_FAILED(rv)) + { + nsCRT::free(host); + return rv; + } + + if (!host) + return rv; + + // mNoProxyFor is of type "foo bar:8080, baz.com ..." + char* brk = PL_strpbrk(mNoProxyFor, " ,:"); + char* noProxy = mNoProxyFor; + PRInt32 noProxyPort = -1; + int hostLen = PL_strlen(host); + char* end = (char*)host+hostLen; + char* nextbrk = end; + int matchLen = 0; + do + { + if (brk) + { + if (*brk == ':') + { + noProxyPort = atoi(brk+1); + nextbrk = PL_strpbrk(brk+1, " ,"); + if (!nextbrk) + nextbrk = end; + } + matchLen = brk-noProxy; + } + else + matchLen = end-noProxy; + + if (matchLen <= hostLen) // match is smaller than host + { + if (((noProxyPort == -1) || (noProxyPort == port)) && + (0 == PL_strncasecmp(host+hostLen-matchLen, + noProxy, matchLen))) + { + nsCRT::free(host); + return PR_FALSE; + } + } + + noProxy = nextbrk; + brk = PL_strpbrk(noProxy, " ,:"); + } + while (brk); + + CRTFREEIF(host); + return rv; +} diff --git a/mozilla/netwerk/protocol/http/src/nsHTTPHandler.h b/mozilla/netwerk/protocol/http/src/nsHTTPHandler.h index 395901c7db0..30698246fff 100644 --- a/mozilla/netwerk/protocol/http/src/nsHTTPHandler.h +++ b/mozilla/netwerk/protocol/http/src/nsHTTPHandler.h @@ -45,7 +45,7 @@ #include "nsISupportsArray.h" #include "nsCRT.h" #include "nsAuthEngine.h" -#include "nsIProxy.h" +#include "nsIPref.h" #include "prtime.h" #include "nsString.h" @@ -89,25 +89,36 @@ public: virtual nsresult ReleaseTransport(nsIChannel* i_pTrans); virtual nsresult CancelPendingChannel(nsHTTPChannel* aChannel); PRTime GetSessionStartTime() { return mSessionStartTime; } + + void PrefsChanged(const char* pref = 0); + nsresult FollowRedirects(PRBool bFollow=PR_TRUE); + + nsresult SetDontUseProxyFor(const char* i_hostlist); + protected: virtual ~nsHTTPHandler(); + // Determine if this host/port can connect thru proxy + PRBool CanUseProxy(nsIURI* i_Uri); + // This is the array of connections that the handler thread // maintains to verify unique requests. nsCOMPtr mConnections; nsCOMPtr mPendingChannelList; - nsAuthEngine mAuthEngine; nsCOMPtr mTransportList; // Transports that are idle (ready to be used again) nsCOMPtr mIdleTransports; - char* mAcceptLanguages; - PRBool mDoKeepAlive; - char* mProxy; - PRInt32 mProxyPort; - PRTime mSessionStartTime; - PRBool mUseProxy; + char* mAcceptLanguages; + nsAuthEngine mAuthEngine; + PRBool mDoKeepAlive; + char* mNoProxyFor; + nsCOMPtr mPrefs; + char* mProxy; + PRInt32 mProxyPort; + PRTime mSessionStartTime; + PRBool mUseProxy; nsresult BuildUserAgent(); nsCAutoString mAppName; diff --git a/mozilla/netwerk/protocol/http/src/nsHTTPRequest.cpp b/mozilla/netwerk/protocol/http/src/nsHTTPRequest.cpp index da3d2afa03b..e68f0d4386b 100644 --- a/mozilla/netwerk/protocol/http/src/nsHTTPRequest.cpp +++ b/mozilla/netwerk/protocol/http/src/nsHTTPRequest.cpp @@ -237,37 +237,6 @@ nsresult nsHTTPRequest::WriteRequest(nsIChannel *aTransport, PRBool aIsProxied) mTransport = aTransport; mUsingProxy = aIsProxied; -#if 0 // Make proxy auth persistent later - if (mUsingProxy) - { - // Additional headers for proxy usage - // When Keep-Alive gets ready TODO - //SetHeader(nsHTTPAtoms::Proxy-Connection, "Keep-Alive"); - - // Add proxy auth stuff- - // Check to see if an authentication header is required - nsAuthEngine* pAuthEngine = nsnull; - - NS_WITH_SERVICE(nsIHTTPProtocolHandler, httpHandler, kHTTPHandlerCID, &rv); - if (NS_SUCCEEDED(rv)) - { - rv = httpHandler->GetAuthEngine(&pAuthEngine); - if (NS_SUCCEEDED(rv) && pAuthEngine) - { - // Qvq lbh xabj gung t?? Ebg13f n yvar va IVZ? Jbj. - nsXPIDLCString authStr; - //PRUint32 authType = 0; - if (NS_SUCCEEDED(pAuthEngine->GetAuthString(nsnull, - getter_Copies(authStr)))) - //&authType)) && (authType == 1)) - { - if (authStr && *authStr) - SetHeader(nsHTTPAtoms::Proxy_Authorization, authStr); - } - } - } - } -#endif // 0 PRUint32 loadAttributes; mConnection->GetLoadAttributes(&loadAttributes); diff --git a/mozilla/netwerk/protocol/http/src/nsHTTPResponseListener.cpp b/mozilla/netwerk/protocol/http/src/nsHTTPResponseListener.cpp index 3fce42aa442..81acfca40c6 100644 --- a/mozilla/netwerk/protocol/http/src/nsHTTPResponseListener.cpp +++ b/mozilla/netwerk/protocol/http/src/nsHTTPResponseListener.cpp @@ -21,7 +21,6 @@ */ #include "nspr.h" -#include "nsAuthEngine.h" #include "nsHTTPRequest.h" #include "nsIStreamListener.h" #include "nsHTTPResponseListener.h"