From fbe40219c99fe7f91abbfbba9138e955d9d6080e Mon Sep 17 00:00:00 2001 From: "heikki%netscape.com" Date: Tue, 13 Aug 2002 18:41:16 +0000 Subject: [PATCH] Bug 63558, we now store XML declaration in the document and can serialize it. There is fix for 158617 as well, newlines behave properly around doctype. r=bzbarsky, sr=jst. git-svn-id: svn://10.0.0.236/trunk@127185 18797224-902f-48f8-a5cc-f745e15eee43 --- .../base/public/nsIContentSerializer.h | 9 +++ .../base/src/mozSanitizingSerializer.cpp | 7 ++ .../base/src/mozSanitizingSerializer.h | 3 + .../content/base/src/nsDocumentEncoder.cpp | 12 +++- .../base/src/nsHTMLContentSerializer.cpp | 7 ++ .../base/src/nsHTMLContentSerializer.h | 3 + .../base/src/nsPlainTextSerializer.cpp | 7 ++ .../content/base/src/nsPlainTextSerializer.h | 3 + .../base/src/nsXMLContentSerializer.cpp | 34 ++++++++++ .../content/base/src/nsXMLContentSerializer.h | 3 + .../xml/document/public/nsIXMLDocument.h | 11 ++++ .../xml/document/src/nsXMLContentSink.cpp | 28 ++++++++ .../xml/document/src/nsXMLDocument.cpp | 64 ++++++++++++++++++- .../content/xml/document/src/nsXMLDocument.h | 15 ++++- .../xul/document/src/nsXULContentSink.cpp | 9 +++ .../xul/document/src/nsXULDocument.cpp | 21 ++++++ .../content/xul/document/src/nsXULDocument.h | 6 ++ mozilla/htmlparser/public/nsIExpatSink.idl | 10 +++ mozilla/htmlparser/src/nsExpatDriver.cpp | 38 ++++++++++- mozilla/htmlparser/src/nsExpatDriver.h | 2 + .../parser/htmlparser/public/nsIExpatSink.idl | 10 +++ .../parser/htmlparser/src/nsExpatDriver.cpp | 38 ++++++++++- mozilla/parser/htmlparser/src/nsExpatDriver.h | 2 + mozilla/rdf/base/src/nsRDFContentSink.cpp | 7 ++ 24 files changed, 339 insertions(+), 10 deletions(-) diff --git a/mozilla/content/base/public/nsIContentSerializer.h b/mozilla/content/base/public/nsIContentSerializer.h index 2376e917a42..da5098850b2 100644 --- a/mozilla/content/base/public/nsIContentSerializer.h +++ b/mozilla/content/base/public/nsIContentSerializer.h @@ -49,6 +49,7 @@ class nsIDOMProcessingInstruction; /* forward declaration */ class nsIDOMComment; /* forward declaration */ class nsIDOMDocumentType; /* forward declaration */ class nsIDOMElement; /* forward declaration */ +class nsIDOMDocument; /* forward declaration */ /* starting interface: nsIContentSerializer */ #define NS_ICONTENTSERIALIZER_IID_STR "61e9b9a3-d30c-429e-b0cf-ade73466df06" @@ -91,6 +92,14 @@ class nsIContentSerializer : public nsISupports { nsAString& aStr) = 0; NS_IMETHOD Flush(nsAString& aStr) = 0; + + /** + * Append any items in the beginning of the document that won't be + * serialized by other methods. XML declaration is the most likely + * thing this method can produce. + */ + NS_IMETHOD AppendDocumentStart(nsIDOMDocument *aDocument, + nsAString& aStr) = 0; }; #define NS_CONTENTSERIALIZER_CONTRACTID_PREFIX \ diff --git a/mozilla/content/base/src/mozSanitizingSerializer.cpp b/mozilla/content/base/src/mozSanitizingSerializer.cpp index 8b6b4d236ae..7ea3f40e1b7 100644 --- a/mozilla/content/base/src/mozSanitizingSerializer.cpp +++ b/mozilla/content/base/src/mozSanitizingSerializer.cpp @@ -157,6 +157,13 @@ mozSanitizingHTMLSerializer::Flush(nsAString& aStr) return NS_OK; } +NS_IMETHODIMP +mozSanitizingHTMLSerializer::AppendDocumentStart(nsIDOMDocument *aDocument, + nsAString& aStr) +{ + return NS_OK; +} + void mozSanitizingHTMLSerializer::Write(const nsAString& aString) { diff --git a/mozilla/content/base/src/mozSanitizingSerializer.h b/mozilla/content/base/src/mozSanitizingSerializer.h index b8e0320d8f1..0477bb62caf 100644 --- a/mozilla/content/base/src/mozSanitizingSerializer.h +++ b/mozilla/content/base/src/mozSanitizingSerializer.h @@ -89,6 +89,9 @@ public: NS_IMETHOD AppendElementEnd(nsIDOMElement *aElement, nsAString& aStr); NS_IMETHOD Flush(nsAString& aStr); + NS_IMETHOD AppendDocumentStart(nsIDOMDocument *aDocument, + nsAString& aStr); + // nsIContentSink NS_IMETHOD WillBuildModel(void) { return NS_OK; } NS_IMETHOD DidBuildModel(PRInt32 aQualityLevel) { return NS_OK; } diff --git a/mozilla/content/base/src/nsDocumentEncoder.cpp b/mozilla/content/base/src/nsDocumentEncoder.cpp index e45f03fdc48..55b284ddc79 100644 --- a/mozilla/content/base/src/nsDocumentEncoder.cpp +++ b/mozilla/content/base/src/nsDocumentEncoder.cpp @@ -59,6 +59,7 @@ #include "nsIDOMDocumentType.h" #include "nsIDOMNodeList.h" #include "nsIDOMRange.h" +#include "nsIDOMDocument.h" #include "nsICharsetConverterManager.h" #include "nsICharsetConverterManager2.h" #include "nsHTMLAtoms.h" @@ -159,12 +160,12 @@ protected: PRUint32 mEndDepth; PRInt32 mStartRootIndex; PRInt32 mEndRootIndex; - PRBool mHaltRangeHint; nsAutoVoidArray mCommonAncestors; nsAutoVoidArray mStartNodes; nsAutoVoidArray mStartOffsets; nsAutoVoidArray mEndNodes; nsAutoVoidArray mEndOffsets; + PRPackedBool mHaltRangeHint; PRPackedBool mIsCopying; // Set to PR_TRUE only while copying }; @@ -937,9 +938,14 @@ nsDocumentEncoder::EncodeToString(nsAString& aOutputString) mRange = nsnull; } else { - nsCOMPtr doc(do_QueryInterface(mDocument)); + nsCOMPtr domdoc(do_QueryInterface(mDocument)); + rv = mSerializer->AppendDocumentStart(domdoc, aOutputString); - rv = SerializeToStringRecursive(doc, aOutputString); + if (NS_SUCCEEDED(rv)) { + nsCOMPtr doc(do_QueryInterface(mDocument)); + + rv = SerializeToStringRecursive(doc, aOutputString); + } } NS_ENSURE_SUCCESS(rv, rv); diff --git a/mozilla/content/base/src/nsHTMLContentSerializer.cpp b/mozilla/content/base/src/nsHTMLContentSerializer.cpp index 0cc96af9b68..64e5988f718 100644 --- a/mozilla/content/base/src/nsHTMLContentSerializer.cpp +++ b/mozilla/content/base/src/nsHTMLContentSerializer.cpp @@ -206,6 +206,13 @@ nsHTMLContentSerializer::AppendText(nsIDOMText* aText, return NS_OK; } +NS_IMETHODIMP +nsHTMLContentSerializer::AppendDocumentStart(nsIDOMDocument *aDocument, + nsAString& aStr) +{ + return NS_OK; +} + PRBool nsHTMLContentSerializer::IsJavaScript(nsIAtom* aAttrNameAtom, const nsAString& aValueString) { diff --git a/mozilla/content/base/src/nsHTMLContentSerializer.h b/mozilla/content/base/src/nsHTMLContentSerializer.h index 81bf8db8a82..125dd760f79 100644 --- a/mozilla/content/base/src/nsHTMLContentSerializer.h +++ b/mozilla/content/base/src/nsHTMLContentSerializer.h @@ -64,6 +64,9 @@ class nsHTMLContentSerializer : public nsXMLContentSerializer { NS_IMETHOD AppendElementEnd(nsIDOMElement *aElement, nsAString& aStr); + + NS_IMETHOD AppendDocumentStart(nsIDOMDocument *aDocument, + nsAString& aStr); protected: PRBool HasDirtyAttr(nsIContent* aContent); PRBool LineBreakBeforeOpen(nsIAtom* aName, PRBool aHasDirtyAttr); diff --git a/mozilla/content/base/src/nsPlainTextSerializer.cpp b/mozilla/content/base/src/nsPlainTextSerializer.cpp index 7e775c56003..dcc2f242bf1 100644 --- a/mozilla/content/base/src/nsPlainTextSerializer.cpp +++ b/mozilla/content/base/src/nsPlainTextSerializer.cpp @@ -401,6 +401,13 @@ nsPlainTextSerializer::Flush(nsAString& aStr) return NS_OK; } +NS_IMETHODIMP +nsPlainTextSerializer::AppendDocumentStart(nsIDOMDocument *aDocument, + nsAString& aStr) +{ + return NS_OK; +} + NS_IMETHODIMP nsPlainTextSerializer::OpenContainer(const nsIParserNode& aNode) { diff --git a/mozilla/content/base/src/nsPlainTextSerializer.h b/mozilla/content/base/src/nsPlainTextSerializer.h index 9a89c456afd..98f3cb072b9 100644 --- a/mozilla/content/base/src/nsPlainTextSerializer.h +++ b/mozilla/content/base/src/nsPlainTextSerializer.h @@ -86,6 +86,9 @@ public: nsAString& aStr); NS_IMETHOD Flush(nsAString& aStr); + NS_IMETHOD AppendDocumentStart(nsIDOMDocument *aDocument, + nsAString& aStr); + // nsIContentSink NS_IMETHOD WillBuildModel(void) { return NS_OK; } NS_IMETHOD DidBuildModel(PRInt32 aQualityLevel) { return NS_OK; } diff --git a/mozilla/content/base/src/nsXMLContentSerializer.cpp b/mozilla/content/base/src/nsXMLContentSerializer.cpp index e4fd64290a6..91c69a7b145 100644 --- a/mozilla/content/base/src/nsXMLContentSerializer.cpp +++ b/mozilla/content/base/src/nsXMLContentSerializer.cpp @@ -43,6 +43,7 @@ #include "nsIDOMCDATASection.h" #include "nsIDOMProcessingInstruction.h" #include "nsIDOMComment.h" +#include "nsIDOMDocument.h" #include "nsIDOMDocumentType.h" #include "nsIDOMElement.h" #include "nsIContent.h" @@ -54,6 +55,7 @@ #include "prprf.h" #include "nsUnicharUtils.h" #include "nsCRT.h" +#include "nsIXMLDocument.h" typedef struct { nsString mPrefix; @@ -754,3 +756,35 @@ nsXMLContentSerializer::IsShorthandAttr(const nsIAtom* aAttrName, return PR_FALSE; } + +NS_IMETHODIMP +nsXMLContentSerializer::AppendDocumentStart(nsIDOMDocument *aDocument, + nsAString& aStr) +{ + NS_ENSURE_ARG_POINTER(aDocument); + + nsCOMPtr xml(do_QueryInterface(aDocument)); + NS_ENSURE_TRUE(xml, NS_ERROR_UNEXPECTED); + + nsAutoString version, encoding, standalone; + xml->GetXMLDeclaration(version, encoding, standalone); + + if (version.IsEmpty()) + return NS_OK; // A declaration must have version, or there is no decl + + NS_NAMED_LITERAL_STRING(endQuote, "\""); + + aStr += NS_LITERAL_STRING(""); + + return NS_OK; +} diff --git a/mozilla/content/base/src/nsXMLContentSerializer.h b/mozilla/content/base/src/nsXMLContentSerializer.h index 5f1c37dab74..54727b3e054 100644 --- a/mozilla/content/base/src/nsXMLContentSerializer.h +++ b/mozilla/content/base/src/nsXMLContentSerializer.h @@ -83,6 +83,9 @@ class nsXMLContentSerializer : public nsIContentSerializer { NS_IMETHOD Flush(nsAString& aStr) { return NS_OK; } + NS_IMETHOD AppendDocumentStart(nsIDOMDocument *aDocument, + nsAString& aStr); + protected: virtual void AppendToString(const PRUnichar* aStr, PRInt32 aLength, diff --git a/mozilla/content/xml/document/public/nsIXMLDocument.h b/mozilla/content/xml/document/public/nsIXMLDocument.h index 6c302a01493..3a04c953b68 100644 --- a/mozilla/content/xml/document/public/nsIXMLDocument.h +++ b/mozilla/content/xml/document/public/nsIXMLDocument.h @@ -57,6 +57,17 @@ public: NS_DEFINE_STATIC_IID_ACCESSOR(NS_IXMLDOCUMENT_IID) NS_IMETHOD SetDefaultStylesheets(nsIURI* aUrl)=0; + + /** + * Set and get XML declaration. Notice that if version is empty, + * there can be no XML declaration (it is a required part). + */ + NS_IMETHOD SetXMLDeclaration(const nsAString& aVersion, + const nsAString& aEncoding, + const nsAString& Standalone)=0; + NS_IMETHOD GetXMLDeclaration(nsAString& aVersion, + nsAString& aEncoding, + nsAString& Standalone)=0; }; #endif // nsIXMLDocument_h___ diff --git a/mozilla/content/xml/document/src/nsXMLContentSink.cpp b/mozilla/content/xml/document/src/nsXMLContentSink.cpp index 3db307821b4..f2234ff19f7 100644 --- a/mozilla/content/xml/document/src/nsXMLContentSink.cpp +++ b/mozilla/content/xml/document/src/nsXMLContentSink.cpp @@ -1832,6 +1832,8 @@ nsXMLContentSink::HandleDoctypeDecl(const nsAString & aSubset, const nsAString & aPublicId, nsISupports* aCatalogData) { + FlushText(); + nsresult rv = NS_OK; nsCOMPtr doc(do_QueryInterface(mDocument)); @@ -1949,6 +1951,32 @@ nsXMLContentSink::HandleProcessingInstruction(const PRUnichar *aTarget, return result; } +NS_IMETHODIMP +nsXMLContentSink::HandleXMLDeclaration(const PRUnichar *aData, + PRUint32 aLength) +{ + NS_ENSURE_ARG_POINTER(aData); + // strlen("") == 19, shortest decl + NS_ENSURE_TRUE(aLength >= 19, NS_ERROR_INVALID_ARG); + + nsCOMPtr xml(do_QueryInterface(mDocument)); + NS_WARN_IF_FALSE(xml, "why is XML sink building non-XML document?"); + if (!xml) + return NS_OK; + + // + const nsAString& data = Substring(aData + 6, aData + aLength - 2); // strip out "" + + nsAutoString version, encoding, standalone; + + // XXX If this is too slow we need to parse this here + nsParserUtils::GetQuotedAttributeValue(data, NS_LITERAL_STRING("version"), version); + nsParserUtils::GetQuotedAttributeValue(data, NS_LITERAL_STRING("encoding"), encoding); + nsParserUtils::GetQuotedAttributeValue(data, NS_LITERAL_STRING("standalone"), standalone); + + return xml->SetXMLDeclaration(version, encoding, standalone); +} + NS_IMETHODIMP nsXMLContentSink::ReportError(const PRUnichar* aErrorText, const PRUnichar* aSourceText) diff --git a/mozilla/content/xml/document/src/nsXMLDocument.cpp b/mozilla/content/xml/document/src/nsXMLDocument.cpp index 39813b313b9..838b23db6cd 100644 --- a/mozilla/content/xml/document/src/nsXMLDocument.cpp +++ b/mozilla/content/xml/document/src/nsXMLDocument.cpp @@ -221,7 +221,7 @@ NS_NewXMLDocument(nsIDocument** aInstancePtrResult) nsXMLDocument::nsXMLDocument() : mAttrStyleSheet(nsnull), mInlineStyleSheet(nsnull), mCountCatalogSheets(0), mParser(nsnull), - mCrossSiteAccessEnabled(PR_FALSE) + mCrossSiteAccessEnabled(PR_FALSE), mXMLDeclarationBits(0) { } @@ -422,9 +422,12 @@ nsXMLDocument::Load(const nsAString& aUrl) // Find out if UniversalBrowserRead privileges are enabled - we will need this // in case of a redirect - rv = secMan->IsCapabilityEnabled("UniversalBrowserRead", &mCrossSiteAccessEnabled); + PRBool crossSiteAccessEnabled; + rv = secMan->IsCapabilityEnabled("UniversalBrowserRead", &crossSiteAccessEnabled); if (NS_FAILED(rv)) return rv; + mCrossSiteAccessEnabled = crossSiteAccessEnabled; + // Create a channel rv = NS_NewChannel(getter_AddRefs(channel), uri, nsnull, nsnull, this); if (NS_FAILED(rv)) return rv; @@ -1094,6 +1097,63 @@ nsXMLDocument::SetDefaultStylesheets(nsIURI* aUrl) return result; } +NS_IMETHODIMP +nsXMLDocument::SetXMLDeclaration(const nsAString& aVersion, + const nsAString& aEncoding, + const nsAString& aStandalone) +{ + if (aVersion.IsEmpty()) { + mXMLDeclarationBits = 0; + return NS_OK; + } + + mXMLDeclarationBits = XML_DECLARATION_BITS_DECLARATION_EXISTS; + + if (!aEncoding.IsEmpty()) { + mXMLDeclarationBits |= XML_DECLARATION_BITS_ENCODING_EXISTS; + } + + if (aStandalone.Equals(NS_LITERAL_STRING("yes"))) { + mXMLDeclarationBits |= XML_DECLARATION_BITS_STANDALONE_EXISTS | + XML_DECLARATION_BITS_STANDALONE_YES; + } else if (aStandalone.Equals(NS_LITERAL_STRING("no"))) { + mXMLDeclarationBits |= XML_DECLARATION_BITS_STANDALONE_EXISTS; + } + + return NS_OK; +} + +NS_IMETHODIMP +nsXMLDocument::GetXMLDeclaration(nsAString& aVersion, + nsAString& aEncoding, + nsAString& aStandalone) +{ + aVersion.Truncate(); + aEncoding.Truncate(); + aStandalone.Truncate(); + + if (!(mXMLDeclarationBits & XML_DECLARATION_BITS_DECLARATION_EXISTS)) { + return NS_OK; + } + + aVersion.Assign(NS_LITERAL_STRING("1.0")); // always until we start supporting 1.1 etc. + + if (mXMLDeclarationBits & XML_DECLARATION_BITS_ENCODING_EXISTS) { + GetDocumentCharacterSet(aEncoding); // This is what we have stored, not necessarily what was written in the original + } + + if (mXMLDeclarationBits & XML_DECLARATION_BITS_STANDALONE_EXISTS) { + if (mXMLDeclarationBits & XML_DECLARATION_BITS_STANDALONE_YES) { + aStandalone.Assign(NS_LITERAL_STRING("yes")); + } else { + aStandalone.Assign(NS_LITERAL_STRING("no")); + } + } + + return NS_OK; +} + + NS_IMETHODIMP nsXMLDocument::SetBaseTarget(const nsAString &aBaseTarget) { diff --git a/mozilla/content/xml/document/src/nsXMLDocument.h b/mozilla/content/xml/document/src/nsXMLDocument.h index d8415cd1d53..d571eb3b440 100644 --- a/mozilla/content/xml/document/src/nsXMLDocument.h +++ b/mozilla/content/xml/document/src/nsXMLDocument.h @@ -53,6 +53,11 @@ class nsIDOMNode; class nsICSSLoader; class nsIURI; +#define XML_DECLARATION_BITS_DECLARATION_EXISTS 1 +#define XML_DECLARATION_BITS_ENCODING_EXISTS 2 +#define XML_DECLARATION_BITS_STANDALONE_EXISTS 4 +#define XML_DECLARATION_BITS_STANDALONE_YES 8 + class nsXMLDocument : public nsMarkupDocument, public nsIXMLDocument, public nsIHTMLContentContainer, @@ -107,6 +112,12 @@ public: // nsIXMLDocument interface NS_IMETHOD SetDefaultStylesheets(nsIURI* aUrl); + NS_IMETHOD SetXMLDeclaration(const nsAString& aVersion, + const nsAString& aEncoding, + const nsAString& Standalone); + NS_IMETHOD GetXMLDeclaration(nsAString& aVersion, + nsAString& aEncoding, + nsAString& Standalone); // nsIHTMLContentContainer NS_IMETHOD GetAttributeStyleSheet(nsIHTMLStyleSheet** aResult); @@ -142,7 +153,9 @@ protected: nsIParser *mParser; nsCOMPtr mScriptContext; - PRBool mCrossSiteAccessEnabled; + PRPackedBool mCrossSiteAccessEnabled; + + PRUint8 mXMLDeclarationBits; }; diff --git a/mozilla/content/xul/document/src/nsXULContentSink.cpp b/mozilla/content/xul/document/src/nsXULContentSink.cpp index 7991012d31d..688c9ab5262 100644 --- a/mozilla/content/xul/document/src/nsXULContentSink.cpp +++ b/mozilla/content/xul/document/src/nsXULContentSink.cpp @@ -1106,6 +1106,15 @@ XULContentSinkImpl::HandleProcessingInstruction(const PRUnichar *aTarget, return NS_OK; } + +NS_IMETHODIMP +XULContentSinkImpl::HandleXMLDeclaration(const PRUnichar *aData, + const PRUint32 aLength) +{ + return NS_OK; +} + + NS_IMETHODIMP XULContentSinkImpl::ReportError(const PRUnichar* aErrorText, const PRUnichar* aSourceText) diff --git a/mozilla/content/xul/document/src/nsXULDocument.cpp b/mozilla/content/xul/document/src/nsXULDocument.cpp index a4a89f2b176..1015f7a09be 100644 --- a/mozilla/content/xul/document/src/nsXULDocument.cpp +++ b/mozilla/content/xul/document/src/nsXULDocument.cpp @@ -2670,6 +2670,27 @@ nsXULDocument::SetTitle(const PRUnichar *aTitle) return SetTitle(nsDependentString(aTitle)); } +NS_IMETHODIMP +nsXULDocument::SetXMLDeclaration(const nsAString& aVersion, + const nsAString& aEncoding, + const nsAString& aStandalone) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsXULDocument::GetXMLDeclaration(nsAString& aVersion, + nsAString& aEncoding, + nsAString& aStandalone) +{ + aVersion.Truncate(); + aEncoding.Truncate(); + aStandalone.Truncate(); + return NS_OK; +} + + + //---------------------------------------------------------------------- // // nsIXULDocument interface diff --git a/mozilla/content/xul/document/src/nsXULDocument.h b/mozilla/content/xul/document/src/nsXULDocument.h index a2a951fb3a3..f5fc78c8561 100644 --- a/mozilla/content/xul/document/src/nsXULDocument.h +++ b/mozilla/content/xul/document/src/nsXULDocument.h @@ -351,6 +351,12 @@ public: // nsIXMLDocument interface NS_IMETHOD SetDefaultStylesheets(nsIURI* aUrl); NS_IMETHOD SetTitle(const PRUnichar *aTitle); + NS_IMETHOD SetXMLDeclaration(const nsAString& aVersion, + const nsAString& aEncoding, + const nsAString& Standalone); + NS_IMETHOD GetXMLDeclaration(nsAString& aVersion, + nsAString& aEncoding, + nsAString& Standalone); // nsIXULDocument interface NS_IMETHOD AddElementForID(const nsAString& aID, nsIContent* aElement); diff --git a/mozilla/htmlparser/public/nsIExpatSink.idl b/mozilla/htmlparser/public/nsIExpatSink.idl index 5ccdfd035d1..6051ad1f55b 100644 --- a/mozilla/htmlparser/public/nsIExpatSink.idl +++ b/mozilla/htmlparser/public/nsIExpatSink.idl @@ -66,6 +66,16 @@ interface nsIExpatSink : nsISupports void HandleProcessingInstruction(in wstring aTarget, in wstring aData); + /** + * Handle the XML Declaration. + * + * @param aData The string. + * @param aLength The length of the declaration from + * opening '<' to closing '>'. + **/ + void HandleXMLDeclaration(in wstring aData, + in unsigned long aLength); + void ReportError(in wstring aErrorText, in wstring aSourceText); }; diff --git a/mozilla/htmlparser/src/nsExpatDriver.cpp b/mozilla/htmlparser/src/nsExpatDriver.cpp index f05bbd6c44c..0e8f505ab62 100644 --- a/mozilla/htmlparser/src/nsExpatDriver.cpp +++ b/mozilla/htmlparser/src/nsExpatDriver.cpp @@ -300,8 +300,9 @@ NS_NewExpatDriver(nsIDTD** aResult) { nsExpatDriver::nsExpatDriver() :mExpatParser(0), - mInCData(0), - mInDoctype(0), + mInCData(PR_FALSE), + mInDoctype(PR_FALSE), + mHandledXMLDeclaration(PR_FALSE), mBytePosition(0), mInternalState(NS_OK), mBytesParsed(0), @@ -399,6 +400,30 @@ nsExpatDriver::HandleProcessingInstruction(const PRUnichar *aTarget, return NS_OK; } +nsresult +nsExpatDriver::HandleXMLDeclaration(const PRUnichar *aValue, + const PRUint32 aLength) +{ + mHandledXMLDeclaration = PR_TRUE; + + // + // 0123456789012345678 + PRUint32 i = 17; // ?> can start at position 17 at the earliest + for (; i < aLength; i++) { + if (aValue[i] == '?') + break; + } + + // +1 because index starts from 0 + // +1 because '>' follows '?' + i += 2; + + if (i > aLength) + return NS_OK; // Bad declaration + + return mSink->HandleXMLDeclaration(aValue, i); +} + nsresult nsExpatDriver::HandleDefault(const PRUnichar *aValue, const PRUint32 aLength) @@ -409,6 +434,15 @@ nsExpatDriver::HandleDefault(const PRUnichar *aValue, mDoctypeText.Append(aValue, aLength); } else if (mSink) { + if (!mHandledXMLDeclaration && !mBytesParsed) { + static const PRUnichar xmlDecl[] = {'<', '?', 'x', 'm', 'l', ' ', '\0'}; + // strlen("") == 19, shortest decl + if ((aLength >= 19) && + (nsCRT::strncmp(aValue, xmlDecl, 6) == 0)) { + HandleXMLDeclaration(aValue, aLength); + } + } + static const PRUnichar newline[] = {'\n','\0'}; for (PRUint32 i = 0; i < aLength && NS_SUCCEEDED(mInternalState); i++) { if (aValue[i] == '\n' || aValue[i] == '\r') { diff --git a/mozilla/htmlparser/src/nsExpatDriver.h b/mozilla/htmlparser/src/nsExpatDriver.h index 749cf27561c..38a70791b45 100644 --- a/mozilla/htmlparser/src/nsExpatDriver.h +++ b/mozilla/htmlparser/src/nsExpatDriver.h @@ -68,6 +68,7 @@ public: nsresult HandleCharacterData(const PRUnichar *aCData, const PRUint32 aLength); nsresult HandleComment(const PRUnichar *aName); nsresult HandleProcessingInstruction(const PRUnichar *aTarget, const PRUnichar *aData); + nsresult HandleXMLDeclaration(const PRUnichar *aData, const PRUint32 aLength); nsresult HandleDefault(const PRUnichar *aData, const PRUint32 aLength); nsresult HandleStartCdataSection(); nsresult HandleEndCdataSection(); @@ -93,6 +94,7 @@ protected: nsString mDoctypeText; PRPackedBool mInCData; PRPackedBool mInDoctype; + PRPackedBool mHandledXMLDeclaration; PRInt32 mBytePosition; nsresult mInternalState; PRUint32 mBytesParsed; diff --git a/mozilla/parser/htmlparser/public/nsIExpatSink.idl b/mozilla/parser/htmlparser/public/nsIExpatSink.idl index 5ccdfd035d1..6051ad1f55b 100644 --- a/mozilla/parser/htmlparser/public/nsIExpatSink.idl +++ b/mozilla/parser/htmlparser/public/nsIExpatSink.idl @@ -66,6 +66,16 @@ interface nsIExpatSink : nsISupports void HandleProcessingInstruction(in wstring aTarget, in wstring aData); + /** + * Handle the XML Declaration. + * + * @param aData The string. + * @param aLength The length of the declaration from + * opening '<' to closing '>'. + **/ + void HandleXMLDeclaration(in wstring aData, + in unsigned long aLength); + void ReportError(in wstring aErrorText, in wstring aSourceText); }; diff --git a/mozilla/parser/htmlparser/src/nsExpatDriver.cpp b/mozilla/parser/htmlparser/src/nsExpatDriver.cpp index f05bbd6c44c..0e8f505ab62 100644 --- a/mozilla/parser/htmlparser/src/nsExpatDriver.cpp +++ b/mozilla/parser/htmlparser/src/nsExpatDriver.cpp @@ -300,8 +300,9 @@ NS_NewExpatDriver(nsIDTD** aResult) { nsExpatDriver::nsExpatDriver() :mExpatParser(0), - mInCData(0), - mInDoctype(0), + mInCData(PR_FALSE), + mInDoctype(PR_FALSE), + mHandledXMLDeclaration(PR_FALSE), mBytePosition(0), mInternalState(NS_OK), mBytesParsed(0), @@ -399,6 +400,30 @@ nsExpatDriver::HandleProcessingInstruction(const PRUnichar *aTarget, return NS_OK; } +nsresult +nsExpatDriver::HandleXMLDeclaration(const PRUnichar *aValue, + const PRUint32 aLength) +{ + mHandledXMLDeclaration = PR_TRUE; + + // + // 0123456789012345678 + PRUint32 i = 17; // ?> can start at position 17 at the earliest + for (; i < aLength; i++) { + if (aValue[i] == '?') + break; + } + + // +1 because index starts from 0 + // +1 because '>' follows '?' + i += 2; + + if (i > aLength) + return NS_OK; // Bad declaration + + return mSink->HandleXMLDeclaration(aValue, i); +} + nsresult nsExpatDriver::HandleDefault(const PRUnichar *aValue, const PRUint32 aLength) @@ -409,6 +434,15 @@ nsExpatDriver::HandleDefault(const PRUnichar *aValue, mDoctypeText.Append(aValue, aLength); } else if (mSink) { + if (!mHandledXMLDeclaration && !mBytesParsed) { + static const PRUnichar xmlDecl[] = {'<', '?', 'x', 'm', 'l', ' ', '\0'}; + // strlen("") == 19, shortest decl + if ((aLength >= 19) && + (nsCRT::strncmp(aValue, xmlDecl, 6) == 0)) { + HandleXMLDeclaration(aValue, aLength); + } + } + static const PRUnichar newline[] = {'\n','\0'}; for (PRUint32 i = 0; i < aLength && NS_SUCCEEDED(mInternalState); i++) { if (aValue[i] == '\n' || aValue[i] == '\r') { diff --git a/mozilla/parser/htmlparser/src/nsExpatDriver.h b/mozilla/parser/htmlparser/src/nsExpatDriver.h index 749cf27561c..38a70791b45 100644 --- a/mozilla/parser/htmlparser/src/nsExpatDriver.h +++ b/mozilla/parser/htmlparser/src/nsExpatDriver.h @@ -68,6 +68,7 @@ public: nsresult HandleCharacterData(const PRUnichar *aCData, const PRUint32 aLength); nsresult HandleComment(const PRUnichar *aName); nsresult HandleProcessingInstruction(const PRUnichar *aTarget, const PRUnichar *aData); + nsresult HandleXMLDeclaration(const PRUnichar *aData, const PRUint32 aLength); nsresult HandleDefault(const PRUnichar *aData, const PRUint32 aLength); nsresult HandleStartCdataSection(); nsresult HandleEndCdataSection(); @@ -93,6 +94,7 @@ protected: nsString mDoctypeText; PRPackedBool mInCData; PRPackedBool mInDoctype; + PRPackedBool mHandledXMLDeclaration; PRInt32 mBytePosition; nsresult mInternalState; PRUint32 mBytesParsed; diff --git a/mozilla/rdf/base/src/nsRDFContentSink.cpp b/mozilla/rdf/base/src/nsRDFContentSink.cpp index 5a160129927..1974e648398 100644 --- a/mozilla/rdf/base/src/nsRDFContentSink.cpp +++ b/mozilla/rdf/base/src/nsRDFContentSink.cpp @@ -625,6 +625,13 @@ RDFContentSinkImpl::HandleProcessingInstruction(const PRUnichar *aTarget, return NS_OK; } +NS_IMETHODIMP +RDFContentSinkImpl::HandleXMLDeclaration(const PRUnichar *aData, + PRUint32 aLength) +{ + return NS_OK; +} + NS_IMETHODIMP RDFContentSinkImpl::ReportError(const PRUnichar* aErrorText, const PRUnichar* aSourceText)