fixes bug 83471 "Redirection loops"

r=bbaetz@cs.mcgill.ca
sr=rpotts@netscape.com
This commit is contained in:
darin%netscape.com 2001-12-08 00:23:04 +00:00
Родитель f44bf906c8
Коммит 94012c9c3c
9 изменённых файлов: 104 добавлений и 27 удалений

Просмотреть файл

@ -23,6 +23,7 @@ dnsNotFound=%s could not be found. Please check the name and try again.
protocolNotFound=%s is not a registered protocol.
connectionFailure=The connection was refused when attempting to contact %s.
netTimeout=The operation timed out when attempting to contact %s.
redirectLoop=Redirection limit for this URL exceeded. Loading aborted.
repost=The page you are trying to view contains POSTDATA that has expired from cache. If you resend the data, any action the form carried out (such as a search or online purchase) will be repeated. To resend the data, click OK. Otherwise, click Cancel.
repostConfirm=The page you are trying to view contains POSTDATA. If you resend the data, any action the form carried out (such as a search or online purchase) will be repeated. To resend the data, click OK. Otherwise, click Cancel.
fileNotFound=%s does not exist or could not be accessed. Please check the file path and try again.

Просмотреть файл

@ -1218,6 +1218,26 @@ nsresult nsWebShell::EndPageLoad(nsIWebProgress *aProgress,
}
}
}
//
// Doc failed to load because the server generated too many redirects
//
else if (aStatus == NS_ERROR_REDIRECT_LOOP) {
nsCOMPtr<nsIPrompt> prompter;
nsCOMPtr<nsIStringBundle> stringBundle;
rv = GetPromptAndStringBundle(getter_AddRefs(prompter),
getter_AddRefs(stringBundle));
if (!stringBundle) {
return rv;
}
nsXPIDLString messageStr;
rv = stringBundle->GetStringFromName(NS_LITERAL_STRING("redirectLoop").get(),
getter_Copies(messageStr));
if (NS_FAILED(rv)) return rv;
prompter->Alert(nsnull, messageStr);
}
} // if we have a host
return NS_OK;

Просмотреть файл

@ -43,6 +43,7 @@ pref("network.search.url","http://cgi.netscape.com/cgi-bin/url_search.cgi?search
pref("keyword.URL", "http://keyword.netscape.com/keyword/");
pref("keyword.enabled", false);
pref("general.useragent.locale", "chrome://navigator/locale/navigator.properties");
pref("general.useragent.override", "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:0.9.5+) Gecko/20011010 Netscape6/6.1b1");
pref("general.useragent.misc", "rv:0.9.6+");
pref("general.startup.browser", true);
@ -369,6 +370,9 @@ pref("network.http.accept.default", "text/xml, application/xml, application/xhtm
pref("network.http.sendRefererHeader", 2); // 0=don't send any, 1=send only on clicks, 2=send on image requests as well
// Maximum number of consecutive redirects before aborting.
pref("network.http.redirection-limit", 10);
// Enable http compression: comment this out in case of problems with 1.1
pref("network.http.accept-encoding" ,"gzip, deflate, compress;q=0.9");

Просмотреть файл

@ -68,6 +68,9 @@
#define NS_ERROR_PORT_ACCESS_NOT_ALLOWED \
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 19)
#define NS_ERROR_REDIRECT_LOOP \
NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 31)
#undef NS_NET
#ifdef _IMPL_NS_NET
#if defined(XP_PC) && !defined(XP_OS2)

Просмотреть файл

@ -91,6 +91,13 @@ interface nsIHttpChannel : nsIChannel
* by default.
*/
attribute boolean applyConversion;
/**
* This attribute specifies the number of redirects this channel is allowed
* to make. If zero, the channel will fail to redirect and will generate
* a NS_ERROR_REDIRECT_LOOP failure status.
*/
attribute unsigned long redirectionLimit;
};
/**

Просмотреть файл

@ -62,6 +62,7 @@ nsHttpChannel::nsHttpChannel()
, mCacheAccess(0)
, mPostID(0)
, mRequestTime(0)
, mRedirectionLimit(nsHttpHandler::get()->RedirectionLimit())
, mIsPending(PR_FALSE)
, mApplyConversion(PR_TRUE)
, mFromCacheOnly(PR_FALSE)
@ -351,8 +352,18 @@ nsHttpChannel::HandleAsyncRedirect()
// in processing the redirect.
if (NS_SUCCEEDED(mStatus)) {
rv = ProcessRedirection(mResponseHead->Status());
if (NS_FAILED(rv))
if (NS_FAILED(rv)) {
// If ProcessRedirection fails, then we have to send out the
// OnStart/OnStop notifications.
LOG(("ProcessRedirection failed [rv=%x]\n", rv));
mStatus = rv;
if (mListener) {
mListener->OnStartRequest(this, mListenerContext);
mListener->OnStopRequest(this, mListenerContext, mStatus);
mListener = 0;
mListenerContext = 0;
}
}
}
// close the cache entry... blow it away if we couldn't process
@ -463,7 +474,7 @@ nsHttpChannel::ApplyContentConversions()
nsresult
nsHttpChannel::ProcessResponse()
{
nsresult rv = NS_OK;
nsresult rv;
PRUint32 httpStatus = mResponseHead->Status();
LOG(("nsHttpChannel::ProcessResponse [this=%x httpStatus=%u]\n",
@ -478,6 +489,7 @@ nsHttpChannel::ProcessResponse()
case 200:
case 203:
case 206:
// these can normally be cached
rv = ProcessNormal();
break;
case 300:
@ -485,19 +497,9 @@ nsHttpChannel::ProcessResponse()
case 302:
case 307:
// these redirects can be cached (don't store the response body)
if (mCacheEntry) {
rv = InitCacheEntry();
if (NS_SUCCEEDED(rv) && mCacheEntry) {
// XXX we must open an output stream to force the cache service to
// select a cache device for our entry -- bad cache service!!
rv = mCacheEntry->GetTransport(getter_AddRefs(mCacheTransport));
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIOutputStream> out;
rv = mCacheTransport->OpenOutputStream(0, PRUint32(-1), 0, getter_AddRefs(out));
}
}
CloseCacheEntry(rv);
}
if (mCacheEntry)
CloseCacheEntry(InitCacheEntry());
rv = ProcessRedirection(httpStatus);
if (NS_FAILED(rv)) {
LOG(("ProcessRedirection failed [rv=%x]\n", rv));
@ -508,6 +510,7 @@ nsHttpChannel::ProcessResponse()
case 305:
// these redirects cannot be cached
CloseCacheEntry(NS_ERROR_ABORT);
rv = ProcessRedirection(httpStatus);
if (NS_FAILED(rv)) {
LOG(("ProcessRedirection failed [rv=%x]\n", rv));
@ -951,6 +954,7 @@ nsHttpChannel::ReadFromCache()
// server to validate at this time, so just mark the cache entry as
// valid in order to allow others access to this cache entry.
mCacheEntry->MarkValid();
mCacheAccess = nsICache::ACCESS_READ;
}
// if this is a cached redirect, we must process the redirect asynchronously
@ -1140,7 +1144,15 @@ nsHttpChannel::ProcessRedirection(PRUint32 redirectType)
if (!location)
return NS_ERROR_FAILURE;
LOG(("redirecting to: %s\n", location));
if (mRedirectionLimit == 0) {
LOG(("redirection limit reached!\n"));
// this error code is fatal, and should be conveyed to our listener.
Cancel(NS_ERROR_REDIRECT_LOOP);
return NS_ERROR_REDIRECT_LOOP;
}
LOG(("redirecting to: %s [redirection-limit=%u]\n",
location, PRUint32(mRedirectionLimit)));
nsresult rv;
nsCOMPtr<nsIChannel> newChannel;
@ -1210,6 +1222,8 @@ nsHttpChannel::ProcessRedirection(PRUint32 redirectType)
httpChannel->SetReferrer(mReferrer, mReferrerType);
// convey the mApplyConversion flag (bug 91862)
httpChannel->SetApplyConversion(mApplyConversion);
// convey the new redirection limit
httpChannel->SetRedirectionLimit(mRedirectionLimit - 1);
}
// call out to the event sink to notify it of this redirection.
@ -1694,16 +1708,16 @@ nsHttpChannel::GetCurrentPath(char **path)
//-----------------------------------------------------------------------------
NS_IMPL_THREADSAFE_ISUPPORTS10(nsHttpChannel,
nsIRequest,
nsIChannel,
nsIRequestObserver,
nsIStreamListener,
nsIHttpChannel,
nsIInterfaceRequestor,
nsIProgressEventSink,
nsICachingChannel,
nsIUploadChannel,
nsICacheListener)
nsIRequest,
nsIChannel,
nsIRequestObserver,
nsIStreamListener,
nsIHttpChannel,
nsIInterfaceRequestor,
nsIProgressEventSink,
nsICachingChannel,
nsIUploadChannel,
nsICacheListener)
//-----------------------------------------------------------------------------
// nsHttpChannel::nsIRequest
@ -2279,6 +2293,21 @@ nsHttpChannel::SetApplyConversion(PRBool value)
return NS_OK;
}
NS_IMETHODIMP
nsHttpChannel::GetRedirectionLimit(PRUint32 *value)
{
NS_ENSURE_ARG_POINTER(value);
*value = PRUint32(mRedirectionLimit);
return NS_OK;
}
NS_IMETHODIMP
nsHttpChannel::SetRedirectionLimit(PRUint32 value)
{
mRedirectionLimit = CLAMP(value, 0, 0xff);
return NS_OK;
}
//-----------------------------------------------------------------------------
// nsHttpChannel::nsIRequestObserver
//-----------------------------------------------------------------------------

Просмотреть файл

@ -163,6 +163,9 @@ private:
nsXPIDLString mProxyUser;
nsXPIDLString mProxyPass;
// redirection specific data.
PRUint8 mRedirectionLimit;
PRPackedBool mIsPending;
PRPackedBool mApplyConversion;
PRPackedBool mFromCacheOnly;

Просмотреть файл

@ -111,6 +111,7 @@ nsHttpHandler::nsHttpHandler()
, mMaxConnectionsPerServer(8)
, mMaxPersistentConnectionsPerServer(2)
, mMaxPersistentConnectionsPerProxy(4)
, mRedirectionLimit(10)
, mLastUniqueID(NowInSeconds())
, mSessionStartTime(0)
, mActiveConnections(0)
@ -1234,11 +1235,17 @@ nsHttpHandler::PrefsChanged(nsIPrefBranch *prefs, const char *pref)
}
if (PREF_CHANGED(HTTP_PREF("sendRefererHeader"))) {
rv = prefs->GetIntPref(HTTP_PREF("sendRefererHeader"), (PRInt32 *) &val);
rv = prefs->GetIntPref(HTTP_PREF("sendRefererHeader"), &val);
if (NS_SUCCEEDED(rv))
mReferrerLevel = (PRUint8) CLAMP(val, 0, 0xff);
}
if (PREF_CHANGED(HTTP_PREF("redirection-limit"))) {
rv = prefs->GetIntPref(HTTP_PREF("redirection-limit"), &val);
if (NS_SUCCEEDED(rv))
mRedirectionLimit = (PRUint8) CLAMP(val, 0, 0xff);
}
if (PREF_CHANGED(HTTP_PREF("version"))) {
nsXPIDLCString httpVersion;
prefs->GetCharPref(HTTP_PREF("version"), getter_Copies(httpVersion));

Просмотреть файл

@ -86,6 +86,7 @@ public:
const char *UserAgent();
nsHttpVersion DefaultVersion() { return mHttpVersion; }
PRUint8 ReferrerLevel() { return mReferrerLevel; }
PRUint8 RedirectionLimit() { return mRedirectionLimit; }
PRUint16 IdleTimeout() { return mIdleTimeout; }
PRUint16 MaxRequestAttempts() { return mMaxRequestAttempts; }
nsIIDNService *IDNConverter() { return mIDNConverter; }
@ -229,6 +230,8 @@ private:
PRUint8 mMaxPersistentConnectionsPerServer;
PRUint8 mMaxPersistentConnectionsPerProxy;
PRUint8 mRedirectionLimit;
nsCString mAccept;
nsCString mAcceptLanguages;
nsCString mAcceptEncodings;