From 3de766b659b7f37bd889a119f02aa0bac2df9dd5 Mon Sep 17 00:00:00 2001 From: "disttsc%bart.nl" Date: Fri, 20 Apr 2001 08:11:12 +0000 Subject: [PATCH] Bug 45143: fix 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 git-svn-id: svn://10.0.0.236/trunk@92825 18797224-902f-48f8-a5cc-f745e15eee43 --- .../html/document/src/nsHTMLContentSink.cpp | 139 +-------- mozilla/docshell/base/nsDocShell.cpp | 267 ++++++++++++------ mozilla/webshell/public/nsIRefreshURI.idl | 21 +- 3 files changed, 211 insertions(+), 216 deletions(-) diff --git a/mozilla/content/html/document/src/nsHTMLContentSink.cpp b/mozilla/content/html/document/src/nsHTMLContentSink.cpp index 40b05439244..5ad464bf19a 100644 --- a/mozilla/content/html/document/src/nsHTMLContentSink.cpp +++ b/mozilla/content/html/document/src/nsHTMLContentSink.cpp @@ -19,6 +19,7 @@ * * Contributor(s): * Pierre Phaneuf + * Peter Annema */ #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 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 - // - // 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 docShell = do_QueryInterface(mWebShell, &rv); if (NS_FAILED(rv)) return rv; @@ -4419,96 +4382,12 @@ HTMLContentSink::ProcessHeaderData(nsIAtom* aHeader,nsString& aValue,nsIHTMLCont nsCOMPtr 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: - // 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 doneIterating; token.EndReading(doneIterating); - nsReadingIterator 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 uri; - if (uriAttrib.Length() == 0) { - uri = baseURI; - } else { - rv = NS_NewURI(getter_AddRefs(uri), - uriAttrib, baseURI); + + nsCOMPtr 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 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 docShell = do_QueryInterface(mWebShell, &rv); diff --git a/mozilla/docshell/base/nsDocShell.cpp b/mozilla/docshell/base/nsDocShell.cpp index e76334fb78c..22f18521635 100644 --- a/mozilla/docshell/base/nsDocShell.cpp +++ b/mozilla/docshell/base/nsDocShell.cpp @@ -19,6 +19,7 @@ * Contributor(s): * Travis Bogard * Pierre Phaneuf + * Peter Annema */ #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 + // + // 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 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 uri; + if (tokenStart == iter) { + uri = aBaseURI; + } else { + uriAttrib = Substring(tokenStart, iter); + rv = NS_NewURI(getter_AddRefs(uri), uriAttrib, aBaseURI); + } + + if (NS_SUCCEEDED(rv)) { + nsCOMPtr 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 httpChannel(do_QueryInterface(aChannel)); - if(httpChannel) - { - nsCOMPtr referrer; - httpChannel->GetReferrer(getter_AddRefs(referrer)); + nsresult rv; + nsCOMPtr httpChannel(do_QueryInterface(aChannel, &rv)); + if (NS_SUCCEEDED(rv)) { + nsCOMPtr referrer; + rv = httpChannel->GetReferrer(getter_AddRefs(referrer)); + + if (NS_SUCCEEDED(rv)) { SetReferrerURI(referrer); + nsCOMPtr refreshAtom(dont_AddRef(NS_NewAtom("refresh"))); nsXPIDLCString refreshHeader; - nsCOMPtr refreshAtom ( dont_AddRef( NS_NewAtom("refresh") ) ); - - httpChannel -> GetResponseHeader (refreshAtom, getter_Copies (refreshHeader)); + rv = httpChannel->GetResponseHeader(refreshAtom, getter_Copies(refreshHeader)); if (refreshHeader) - { - nsCOMPtr 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 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 postData; nsCOMPtr referrerURI; - PRBool repost = PR_TRUE; - NS_ENSURE_TRUE(aEntry, NS_ERROR_FAILURE); nsCOMPtr 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 prompter; diff --git a/mozilla/webshell/public/nsIRefreshURI.idl b/mozilla/webshell/public/nsIRefreshURI.idl index a00ea621cea..c4e9cc4dda8 100644 --- a/mozilla/webshell/public/nsIRefreshURI.idl +++ b/mozilla/webshell/public/nsIRefreshURI.idl @@ -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(); };