mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-04 13:07:52 +00:00
Bug 45143: fix <meta http-equiv="refresh" content="X; url=URI"> to accept URI which contain commas. While I'm at it, merging the implementations in nsDocShell.cpp and nsHTMLContentSink.cpp. r=brendan@mozilla.org, sr=rpotts@netscape.com, a=hofmann
This commit is contained in:
parent
97e89fd687
commit
5662ed0812
@ -19,6 +19,7 @@
|
||||
*
|
||||
* Contributor(s):
|
||||
* Pierre Phaneuf <pp@ludusdesign.com>
|
||||
* Peter Annema <disttsc@bart.nl>
|
||||
*/
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsXPIDLString.h"
|
||||
@ -4298,15 +4299,14 @@ HTMLContentSink::ProcessMETATag(const nsIParserNode& aNode)
|
||||
*getter_AddRefs(nodeInfo));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsIHTMLContent* it;
|
||||
rv = NS_NewHTMLMetaElement(&it, nodeInfo);
|
||||
nsCOMPtr<nsIHTMLContent> it;
|
||||
rv = NS_NewHTMLMetaElement(getter_AddRefs(it), nodeInfo);
|
||||
if (NS_OK == rv) {
|
||||
// Add in the attributes and add the meta content object to the
|
||||
// head container.
|
||||
it->SetDocument(mDocument, PR_FALSE, PR_TRUE);
|
||||
rv = AddAttributes(aNode, it);
|
||||
if (NS_OK != rv) {
|
||||
NS_RELEASE(it);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
parent->AppendChildTo(it, PR_FALSE, PR_FALSE);
|
||||
@ -4328,7 +4328,6 @@ HTMLContentSink::ProcessMETATag(const nsIParserNode& aNode)
|
||||
}//if (result.Length() > 0)
|
||||
}//if (header.Length() > 0)
|
||||
}//if(!mInsideNoXXXTag)
|
||||
NS_RELEASE(it);
|
||||
}//if (NS_OK == rv)
|
||||
}//if (nsnull != parent)
|
||||
|
||||
@ -4375,42 +4374,6 @@ HTMLContentSink::ProcessHeaderData(nsIAtom* aHeader,nsString& aValue,nsIHTMLCont
|
||||
|
||||
// see if we have a refresh "header".
|
||||
if (aHeader == nsHTMLAtoms::refresh) {
|
||||
// Refresh headers are parsed with the following format in mind
|
||||
// <META HTTP-EQUIV=REFRESH CONTENT="5; URL=http://uri">
|
||||
// By the time we are here, the following is true:
|
||||
// header = "REFRESH"
|
||||
// result = "5; URL=http://uri" // note the URL attribute is
|
||||
// optional, if it is absent, the currently loaded url is used.
|
||||
// Also note that the second and URL seperator can be either a ';'
|
||||
// or a ','. This breaks some websites. The ',' seperator should be
|
||||
// illegal but CNN is using it.
|
||||
|
||||
//
|
||||
// We need to handle the following strings.
|
||||
// - X is a set of digits
|
||||
// - URI is either a relative or absolute URI
|
||||
// - FOO is any text
|
||||
//
|
||||
// ""
|
||||
// empty string. use the currently loaded URI
|
||||
// and refresh immediately.
|
||||
// "X"
|
||||
// Refresh the currently loaded URI in X milliseconds.
|
||||
// "X; URI"
|
||||
// Refresh using URI as the destination in X milliseconds.
|
||||
// "X; URI; Blah"
|
||||
// Refresh using URI as the destination in X milliseconds,
|
||||
// ignoring "Blah"
|
||||
// "URI"
|
||||
// Refresh immediately using URI as the destination.
|
||||
// "URI; Blah"
|
||||
// Refresh immediately using URI as the destination,
|
||||
// ignoring "Blah"
|
||||
//
|
||||
// Note that we need to remove any tokens wrapping the URI.
|
||||
// These tokens currently include spaces, double and single
|
||||
// quotes.
|
||||
|
||||
// first get our baseURI
|
||||
nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(mWebShell, &rv);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
@ -4419,96 +4382,12 @@ HTMLContentSink::ProcessHeaderData(nsIAtom* aHeader,nsString& aValue,nsIHTMLCont
|
||||
nsCOMPtr<nsIWebNavigation> webNav = do_QueryInterface(docShell);
|
||||
rv = webNav->GetCurrentURI(getter_AddRefs(baseURI));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
PRInt32 millis = -1;
|
||||
nsAutoString uriAttrib;
|
||||
|
||||
PRInt32 semiColon = aValue.FindCharInSet(";,");
|
||||
nsAutoString token;
|
||||
if (semiColon > -1)
|
||||
aValue.Left(token, semiColon);
|
||||
else
|
||||
token = aValue;
|
||||
|
||||
PRBool done = PR_FALSE;
|
||||
while (!done && !token.IsEmpty()) {
|
||||
token.CompressWhitespace();
|
||||
// Ref. bug 22886
|
||||
// Apparently CONTENT can also start with a period (.).
|
||||
// Ex: <meta http-equiv = "refresh" content=".1; url=./recommendations1.html">
|
||||
// So let's relax a little bit otherwise http://www.mozillazine.org/resources/
|
||||
// wouldn't get redirected to the correct URL.
|
||||
if (millis == -1 && (nsCRT::IsAsciiDigit(token.First()) || token.First()==PRUnichar('.'))) {
|
||||
PRBool tokenIsANumber = PR_TRUE;
|
||||
nsReadingIterator<PRUnichar> doneIterating; token.EndReading(doneIterating);
|
||||
nsReadingIterator<PRUnichar> iter; token.BeginReading(iter);
|
||||
while ( iter != doneIterating ) {
|
||||
if (!(tokenIsANumber = nsCRT::IsAsciiDigit(*iter)) && *iter!=PRUnichar('.'))
|
||||
break;
|
||||
++iter;
|
||||
}
|
||||
|
||||
if (tokenIsANumber) {
|
||||
PRInt32 err;
|
||||
millis = token.ToInteger(&err) * 1000;
|
||||
}
|
||||
else {
|
||||
done = PR_TRUE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
done = PR_TRUE;
|
||||
}
|
||||
if (done) {
|
||||
PRInt32 loc = token.FindChar('=');
|
||||
if (loc > -1)
|
||||
token.Cut(0, loc+1);
|
||||
token.Trim(" \"'");
|
||||
uriAttrib.Assign(token);
|
||||
}
|
||||
else {
|
||||
// Increment to the next token.
|
||||
if (semiColon > -1) {
|
||||
semiColon++;
|
||||
PRInt32 semiColon2 = aValue.FindCharInSet(";,", semiColon);
|
||||
if (semiColon2 == -1) semiColon2 = aValue.Length();
|
||||
aValue.Mid(token, semiColon, semiColon2 - semiColon);
|
||||
semiColon = semiColon2;
|
||||
}
|
||||
else {
|
||||
done = PR_TRUE;
|
||||
}
|
||||
}
|
||||
} // end while
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
if (uriAttrib.Length() == 0) {
|
||||
uri = baseURI;
|
||||
} else {
|
||||
rv = NS_NewURI(getter_AddRefs(uri),
|
||||
uriAttrib, baseURI);
|
||||
|
||||
nsCOMPtr<nsIRefreshURI> reefer = do_QueryInterface(mWebShell);
|
||||
if (reefer) {
|
||||
rv = reefer->RefreshURIFromHeader(baseURI, aValue);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
NS_WITH_SERVICE(nsIScriptSecurityManager,
|
||||
securityManager,
|
||||
NS_SCRIPTSECURITYMANAGER_CONTRACTID,
|
||||
&rv);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = securityManager->CheckLoadURI(baseURI,
|
||||
uri,
|
||||
nsIScriptSecurityManager::DISALLOW_FROM_MAIL);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsIRefreshURI> reefer =
|
||||
do_QueryInterface(mWebShell);
|
||||
if (reefer) {
|
||||
if (millis == -1) millis = 0;
|
||||
rv = reefer->RefreshURI(uri, millis,PR_FALSE, PR_TRUE);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}//if (reefer)
|
||||
}//if (NS_SUCCEEDED(rv)) {
|
||||
}//if (NS_SUCCEEDED(rv)) {
|
||||
}//if (NS_SUCCEEDED(rv)) {
|
||||
} // END refresh
|
||||
else if (aHeader == nsHTMLAtoms::setcookie) {
|
||||
nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(mWebShell, &rv);
|
||||
|
@ -19,6 +19,7 @@
|
||||
* Contributor(s):
|
||||
* Travis Bogard <travis@netscape.com>
|
||||
* Pierre Phaneuf <pp@ludusdesign.com>
|
||||
* Peter Annema <disttsc@bart.nl>
|
||||
*/
|
||||
|
||||
#include "nsIComponentManager.h"
|
||||
@ -3833,92 +3834,198 @@ nsDocShell::OnNewURI(nsIURI *aURI, nsIChannel *aChannel, PRUint32 aLoadType)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDocShell::RefreshURIFromHeader(nsIURI* aBaseURI, const nsAReadableString& aHeader)
|
||||
{
|
||||
// Refresh headers are parsed with the following format in mind
|
||||
// <META HTTP-EQUIV=REFRESH CONTENT="5; URL=http://uri">
|
||||
// By the time we are here, the following is true:
|
||||
// header = "REFRESH"
|
||||
// content = "5; URL=http://uri" // note the URL attribute is
|
||||
// optional, if it is absent, the currently loaded url is used.
|
||||
// Also note that the seconds and URL separator can be either
|
||||
// a ';' or a ','. The ',' separator should be illegal but CNN
|
||||
// is using it.
|
||||
//
|
||||
// We need to handle the following strings, where
|
||||
// - X is a set of digits
|
||||
// - URI is either a relative or absolute URI
|
||||
//
|
||||
// Note that URI should start with "url=" but we allow omission
|
||||
//
|
||||
// "" || ";" || ","
|
||||
// empty string. use the currently loaded URI
|
||||
// and refresh immediately.
|
||||
// "X" || "X;" || "X,"
|
||||
// Refresh the currently loaded URI in X seconds.
|
||||
// "X; URI" || "X, URI"
|
||||
// Refresh using URI as the destination in X seconds.
|
||||
// "URI" || "; URI" || ", URI"
|
||||
// Refresh immediately using URI as the destination.
|
||||
//
|
||||
// Currently, anything immediately following the URI, if
|
||||
// seperated by any char in the set "'\"\t\r\n " will be
|
||||
// ignored. So "10; url=go.html ; foo=bar" will work,
|
||||
// and so will "10; url='go.html'; foo=bar". However,
|
||||
// "10; url=go.html; foo=bar" will result in the uri
|
||||
// "go.html;" since ';' and ',' are valid uri characters.
|
||||
//
|
||||
// Note that we need to remove any tokens wrapping the URI.
|
||||
// These tokens currently include spaces, double and single
|
||||
// quotes.
|
||||
|
||||
// when done, seconds is 0 or the given number of seconds
|
||||
// uriAttrib is empty or the URI specified
|
||||
nsAutoString uriAttrib;
|
||||
PRInt32 seconds = 0;
|
||||
|
||||
nsReadingIterator<PRUnichar> iter, tokenStart, doneIterating;
|
||||
|
||||
aHeader.BeginReading(iter);
|
||||
aHeader.EndReading(doneIterating);
|
||||
|
||||
// skip leading whitespace
|
||||
while (iter != doneIterating && nsCRT::IsAsciiSpace(*iter))
|
||||
++iter;
|
||||
|
||||
tokenStart = iter;
|
||||
|
||||
// skip leading + and -
|
||||
if (iter != doneIterating && (*iter == '-' || *iter == '+'))
|
||||
++iter;
|
||||
|
||||
// parse number
|
||||
while (iter != doneIterating && (*iter >= '0' && *iter <= '9')) {
|
||||
seconds = seconds * 10 + (*iter - '0');
|
||||
++iter;
|
||||
}
|
||||
|
||||
// bug 22886, part 2: allow X to start with or contain a '.'
|
||||
if (iter != doneIterating && *iter == '.') {
|
||||
++iter;
|
||||
// throw away any digits following it
|
||||
while (iter != doneIterating && (*iter >= '0' && *iter <= '9'))
|
||||
++iter;
|
||||
}
|
||||
|
||||
if (iter != doneIterating) {
|
||||
// if this isn't whitespace, a ';' or a ',', we just parsed part of a URI
|
||||
if (!(nsCRT::IsAsciiSpace(*iter) || *iter == ';' || *iter == ',')) {
|
||||
// back to square 1
|
||||
iter = tokenStart;
|
||||
seconds = 0;
|
||||
} else {
|
||||
// if we started with a '-', number is negative
|
||||
if (*tokenStart == '-')
|
||||
seconds = -seconds;
|
||||
|
||||
// skip whitespace
|
||||
while (iter != doneIterating && nsCRT::IsAsciiSpace(*iter))
|
||||
++iter;
|
||||
|
||||
// skip ';' or ','
|
||||
if (iter != doneIterating && (*iter == ';' || *iter == ',')) {
|
||||
++iter;
|
||||
|
||||
// skip whitespace
|
||||
while (iter != doneIterating && nsCRT::IsAsciiSpace(*iter))
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// possible start of URI
|
||||
tokenStart = iter;
|
||||
|
||||
// skip "url = " to real start of URI
|
||||
if (iter != doneIterating && (*iter == 'u' || *iter == 'U')) {
|
||||
++iter;
|
||||
if (iter != doneIterating && (*iter == 'r' || *iter == 'R')) {
|
||||
++iter;
|
||||
if (iter != doneIterating && (*iter == 'l' || *iter == 'L')) {
|
||||
++iter;
|
||||
|
||||
// skip whitespace
|
||||
while (iter != doneIterating && nsCRT::IsAsciiSpace(*iter))
|
||||
++iter;
|
||||
|
||||
if (iter != doneIterating && *iter == '=') {
|
||||
++iter;
|
||||
|
||||
// skip whitespace
|
||||
while (iter != doneIterating && nsCRT::IsAsciiSpace(*iter))
|
||||
++iter;
|
||||
|
||||
// found real start of URI
|
||||
tokenStart = iter;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// skip a leading '"' (believe it or not, '\'' is a valid URI char)
|
||||
if (tokenStart != doneIterating && *tokenStart == '"')
|
||||
++tokenStart;
|
||||
|
||||
// set iter to start of URI
|
||||
iter = tokenStart;
|
||||
|
||||
// tokenStart here points to the beginning of URI
|
||||
|
||||
// skip anything which isn't whitespace or '"')
|
||||
while (iter != doneIterating && !(nsCRT::IsAsciiSpace(*iter) || *iter == '"'))
|
||||
++iter;
|
||||
|
||||
// URI is whatever's contained from tokenStart to iter.
|
||||
// note: if tokenStart == doneIterating, so is iter.
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
if (tokenStart == iter) {
|
||||
uri = aBaseURI;
|
||||
} else {
|
||||
uriAttrib = Substring(tokenStart, iter);
|
||||
rv = NS_NewURI(getter_AddRefs(uri), uriAttrib, aBaseURI);
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsIScriptSecurityManager> securityManager(do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = securityManager->CheckLoadURI(aBaseURI, uri, nsIScriptSecurityManager::DISALLOW_FROM_MAIL);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// since we can't travel back in time yet, just pretend it was meant figuratively
|
||||
if (seconds < 0)
|
||||
seconds = 0;
|
||||
|
||||
rv = RefreshURI(uri, seconds * 1000, PR_FALSE, PR_TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::SetupRefreshURI(nsIChannel * aChannel)
|
||||
{
|
||||
nsCOMPtr<nsIHTTPChannel> httpChannel(do_QueryInterface(aChannel));
|
||||
if(httpChannel)
|
||||
{
|
||||
nsCOMPtr<nsIURI> referrer;
|
||||
httpChannel->GetReferrer(getter_AddRefs(referrer));
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIHTTPChannel> httpChannel(do_QueryInterface(aChannel, &rv));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsIURI> referrer;
|
||||
rv = httpChannel->GetReferrer(getter_AddRefs(referrer));
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
SetReferrerURI(referrer);
|
||||
|
||||
nsCOMPtr<nsIAtom> refreshAtom(dont_AddRef(NS_NewAtom("refresh")));
|
||||
nsXPIDLCString refreshHeader;
|
||||
nsCOMPtr<nsIAtom> refreshAtom ( dont_AddRef( NS_NewAtom("refresh") ) );
|
||||
|
||||
httpChannel -> GetResponseHeader (refreshAtom, getter_Copies (refreshHeader));
|
||||
rv = httpChannel->GetResponseHeader(refreshAtom, getter_Copies(refreshHeader));
|
||||
|
||||
if (refreshHeader)
|
||||
{
|
||||
nsCOMPtr<nsIURI> baseURI = mCurrentURI;
|
||||
|
||||
PRInt32 millis = -1;
|
||||
nsAutoString uriAttrib;
|
||||
nsString result; result.AssignWithConversion (refreshHeader);
|
||||
|
||||
PRInt32 semiColon = result.FindCharInSet(";,");
|
||||
nsAutoString token;
|
||||
if (semiColon > -1)
|
||||
result.Left(token, semiColon);
|
||||
else
|
||||
token = result;
|
||||
|
||||
PRBool done = PR_FALSE;
|
||||
while (!done && !token.IsEmpty()) {
|
||||
token.CompressWhitespace();
|
||||
if (millis == -1 && nsCRT::IsAsciiDigit(token.First())) {
|
||||
PRInt32 i = 0;
|
||||
PRUnichar value = nsnull;
|
||||
for ( ; i < (PRInt32) token.Length (); i++)
|
||||
{
|
||||
value = token[i];
|
||||
if (!nsCRT::IsAsciiDigit(value)) {
|
||||
i = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i > -1) {
|
||||
PRInt32 err;
|
||||
millis = token.ToInteger(&err) * 1000;
|
||||
} else {
|
||||
done = PR_TRUE;
|
||||
}
|
||||
} else {
|
||||
done = PR_TRUE;
|
||||
}
|
||||
if (done) {
|
||||
PRInt32 loc = token.FindChar('=');
|
||||
if (loc > -1)
|
||||
token.Cut(0, loc+1);
|
||||
token.Trim(" \"'");
|
||||
uriAttrib = token;
|
||||
} else {
|
||||
// Increment to the next token.
|
||||
if (semiColon > -1) {
|
||||
semiColon++;
|
||||
PRInt32 semiColon2 = result.FindCharInSet(";,", semiColon);
|
||||
if (semiColon2 == -1) semiColon2 = result.Length();
|
||||
result.Mid(token, semiColon, semiColon2 - semiColon);
|
||||
semiColon = semiColon2;
|
||||
} else {
|
||||
done = PR_TRUE;
|
||||
}
|
||||
}
|
||||
} // end while
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
if (!uriAttrib.Length()) {
|
||||
uri = baseURI;
|
||||
} else {
|
||||
NS_NewURI(getter_AddRefs(uri), uriAttrib, baseURI);
|
||||
}
|
||||
|
||||
RefreshURI (uri, millis, PR_FALSE, PR_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
rv = RefreshURIFromHeader(mCurrentURI, NS_ConvertUTF8toUCS2(refreshHeader));
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsDocShell::OnLoadingSite(nsIChannel* aChannel)
|
||||
@ -4096,8 +4203,6 @@ NS_IMETHODIMP nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, PRUint32 aLoadTyp
|
||||
nsCOMPtr<nsIInputStream> postData;
|
||||
nsCOMPtr<nsIURI> referrerURI;
|
||||
|
||||
PRBool repost = PR_TRUE;
|
||||
|
||||
NS_ENSURE_TRUE(aEntry, NS_ERROR_FAILURE);
|
||||
nsCOMPtr<nsIHistoryEntry> hEntry(do_QueryInterface(aEntry));
|
||||
NS_ENSURE_TRUE(hEntry, NS_ERROR_FAILURE);
|
||||
@ -4108,6 +4213,8 @@ NS_IMETHODIMP nsDocShell::LoadHistoryEntry(nsISHEntry* aEntry, PRUint32 aLoadTyp
|
||||
NS_ERROR_FAILURE);
|
||||
|
||||
#if 0
|
||||
PRBool repost = PR_TRUE;
|
||||
|
||||
/* Ask whether to repost form post data */
|
||||
if (postData) {
|
||||
nsCOMPtr<nsIPrompt> prompter;
|
||||
|
@ -33,16 +33,25 @@ interface nsIRefreshURI : nsISupports {
|
||||
* @param repeat Do you want the uri to be repeatedly refreshed every millis milliseconds.
|
||||
* @param flag to check if this is for a META refresh
|
||||
*/
|
||||
void refreshURI(in nsIURI aURI, in long aMillis, in boolean aRepeat, in boolean aMetaRefresh);
|
||||
void refreshURI(in nsIURI aURI, in long aMillis, in boolean aRepeat, in boolean aMetaRefresh);
|
||||
|
||||
/**
|
||||
* Checks the passed in channel to see if there is a refresh header, if there is,
|
||||
* will setup a refreahURI by calling refreshURI
|
||||
*/
|
||||
void setupRefreshURI(in nsIChannel aChannel);
|
||||
* Checks the passed in channel to see if there is a refresh header, if there is,
|
||||
* will setup a refreahURI by calling refreshURI
|
||||
*/
|
||||
void setupRefreshURI(in nsIChannel aChannel);
|
||||
|
||||
/**
|
||||
* Parses the passed in header string and will call refreshURI with
|
||||
* the parsed values
|
||||
*
|
||||
* @param aBaseURI base URI to resolve refresh uri against
|
||||
* @param aHeader The meta refresh header string
|
||||
*/
|
||||
void refreshURIFromHeader(in nsIURI aBaseURI, in AString aHeader);
|
||||
|
||||
/**
|
||||
* Cancels all timer loads.
|
||||
*/
|
||||
void cancelRefreshURITimers();
|
||||
void cancelRefreshURITimers();
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user