diff --git a/build/mac/build_scripts/MozillaBuildList.pm b/build/mac/build_scripts/MozillaBuildList.pm
index 15b796c59e3..44866d05ecc 100644
--- a/build/mac/build_scripts/MozillaBuildList.pm
+++ b/build/mac/build_scripts/MozillaBuildList.pm
@@ -353,6 +353,7 @@ sub ProcessJarManifests()
CreateJarFromManifest(":mozilla:extensions:irc:jar.mn", $chrome_dir, \%jars);
CreateJarFromManifest(":mozilla:extensions:wallet:jar.mn", $chrome_dir, \%jars);
CreateJarFromManifest(":mozilla:intl:uconv:src:jar.mn", $chrome_dir, \%jars);
+ CreateJarFromManifest(":mozilla:htmlparser:src:jar.mn", $chrome_dir, \%jars);
CreateJarFromManifest(":mozilla:layout:html:forms:src:jar.mn", $chrome_dir, \%jars);
CreateJarFromManifest(":mozilla:layout:html:base:src:jar.mn", $chrome_dir, \%jars);
CreateJarFromManifest(":mozilla:mailnews:jar.mn", $chrome_dir, \%jars);
diff --git a/htmlparser/macbuild/htmlparser.mcp b/htmlparser/macbuild/htmlparser.mcp
index 80d03e559f4..3adc6cdeac3 100644
Binary files a/htmlparser/macbuild/htmlparser.mcp and b/htmlparser/macbuild/htmlparser.mcp differ
diff --git a/htmlparser/src/MANIFEST_PROPERTIES b/htmlparser/src/MANIFEST_PROPERTIES
new file mode 100644
index 00000000000..515cf9a5d7d
--- /dev/null
+++ b/htmlparser/src/MANIFEST_PROPERTIES
@@ -0,0 +1 @@
+xmlparse.properties
diff --git a/htmlparser/src/Makefile.in b/htmlparser/src/Makefile.in
index 19a8d36a68e..fbbdf6f9189 100644
--- a/htmlparser/src/Makefile.in
+++ b/htmlparser/src/Makefile.in
@@ -61,6 +61,7 @@ CPPSRCS = \
nsToken.cpp \
nsWellFormedDTD.cpp \
nsViewSourceHTML.cpp\
+ nsParserMsgUtils.cpp\
$(NULL)
ifndef MOZ_DISABLE_DTD_DEBUG
diff --git a/htmlparser/src/jar.mn b/htmlparser/src/jar.mn
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/htmlparser/src/makefile.win b/htmlparser/src/makefile.win
index 305fa030457..dc710fcf4cf 100644
--- a/htmlparser/src/makefile.win
+++ b/htmlparser/src/makefile.win
@@ -48,6 +48,7 @@ CPPSRCS = \
nsWellFormedDTD.cpp \
nsViewSourceHTML.cpp\
nsParserModule.cpp \
+ nsParserMsgUtils.cpp \
!if !defined(MOZ_DISABLE_DTD_DEBUG)
nsLoggingSink.cpp \
nsHTMLNullSink.cpp \
@@ -72,6 +73,7 @@ CPP_OBJS = \
.\$(OBJDIR)\nsWellFormedDTD.obj \
.\$(OBJDIR)\nsViewSourceHTML.obj\
.\$(OBJDIR)\nsParserModule.obj \
+ .\$(OBJDIR)\nsParserMsgUtils.obj \
!if !defined(MOZ_DISABLE_DTD_DEBUG)
.\$(OBJDIR)\nsLoggingSink.obj \
.\$(OBJDIR)\nsHTMLNullSink.obj \
diff --git a/htmlparser/src/nsExpatTokenizer.cpp b/htmlparser/src/nsExpatTokenizer.cpp
index 66154226fe6..ab926f5094e 100644
--- a/htmlparser/src/nsExpatTokenizer.cpp
+++ b/htmlparser/src/nsExpatTokenizer.cpp
@@ -42,6 +42,9 @@
#include "nsSpecialSystemDirectory.h"
#include "nsIURL.h"
+#include "nsParserMsgUtils.h"
+#include "nsTextFormatter.h"
+
typedef struct _XMLParserState {
XML_Parser parser;
nsScanner* scanner;
@@ -278,21 +281,24 @@ void nsExpatTokenizer::GetLine(const char* aSourceBuffer, PRUint32 aLength,
}
}
-
static nsresult
CreateErrorText(const nsParserError* aError, nsString& aErrorString)
{
- aErrorString.AssignWithConversion("XML Parsing Error: ");
+ aErrorString.Truncate();
if (aError) {
- aErrorString.Append(aError->description);
- aErrorString.AppendWithConversion("\nLocation: ");
- aErrorString.Append(aError->sourceURL);
- aErrorString.AppendWithConversion("\nLine Number ");
- aErrorString.AppendInt(aError->lineNumber, 10);
- aErrorString.AppendWithConversion(", Column ");
- aErrorString.AppendInt(aError->colNumber, 10);
- aErrorString.AppendWithConversion(":");
+ nsAutoString msg;
+ nsresult rv = nsParserMsgUtils::GetLocalizedStringByName(XMLPARSER_PROPERTIES,"XMLParsingError",msg);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // XML Parsing Error: %1$S\nLocation: %2$S\nLine Number %3$d, Column %4$d:
+ PRUnichar *message = nsTextFormatter::smprintf(msg.get(),aError->description.get(),aError->sourceURL.get(),aError->lineNumber,aError->colNumber);
+ if (!message) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ aErrorString.Assign(message);
+ nsTextFormatter::smprintf_free(message);
}
return NS_OK;
@@ -379,89 +385,109 @@ nsExpatTokenizer::PushXMLErrorTokens(const char *aBuffer, PRUint32 aLength, PRBo
{
CErrorToken* errorToken= (CErrorToken *) mState->tokenAllocator->CreateTokenOfType(eToken_error, eHTMLTag_unknown);
nsParserError *error = new nsParserError;
- nsresult rv = NS_OK;
-
- if (error && errorToken) {
- /* Fill in the values of the error token */
- error->code = XML_GetErrorCode(mExpatParser);
- error->lineNumber = XML_GetCurrentLineNumber(mExpatParser);
- // Adjust the column number so that it is one based rather than zero based.
- error->colNumber = XML_GetCurrentColumnNumber(mExpatParser) + 1;
- error->description.AssignWithConversion(XML_ErrorString(error->code));
- if (error->code==XML_ERROR_TAG_MISMATCH){
- /*
- * Certain things can be assumed about the token stream because of
- * the way expat behaves. eg:
- *
- * - data:text/xml, is NOT WELL-FORMED
- * - data:text/xml, is a TAG_MISMATCH.
- *
- * We can assume that there is at least one extra open tag (the one we
- * want), so balance is initially set to one.
- *
- * Then loop through the tokens:
- * - Each time we see eToken_end () increment balance, because
- * that means there is another pair of tags we don't care about.
- * - Each time we see eToken_start () decrement balance because it
- * matches a close tag (perhaps the MISMATCHed tag in which case
- * balance should hit 0).
- * - If balance ever hits zero, exit the loop. Because of the way
- * balance is adjusted, if balance is zero expected *must* be a start
- * tag.
- *
- * We must check expected in the condition in case expat or nsDeque go
- * crazy and give us 0 (null) before balance reaches 0.
- */
- nsDequeIterator current = mState->tokenDeque->End();
- CToken *expected = NS_STATIC_CAST(CToken*,--current);
- PRUint32 balance = 1;
-
- while (expected) {
- switch (expected->GetTokenType()) {
- case eToken_start:
- --balance;
- break;
- case eToken_end:
- ++balance;
- break;
- default:
- break; // we don't care about newlines or other tokens
- }
-
- if (!balance) {
- // if balance is zero, this must be a start tag
- CStartToken *startToken=NS_STATIC_CAST(CStartToken*,expected);
- error->description.Append(NS_LITERAL_STRING(". Expected: "));
- error->description.Append(startToken->GetStringValue());
- error->description.Append(NS_LITERAL_STRING(">"));
- break;
- }
-
- expected = NS_STATIC_CAST(CToken*,--current);
- }
- }
- error->sourceURL.Assign((PRUnichar*)XML_GetBase(mExpatParser));
- if (!aIsFinal) {
- PRInt32 byteIndexRelativeToFile = 0;
- byteIndexRelativeToFile = XML_GetCurrentByteIndex(mExpatParser);
- GetLine(aBuffer, aLength, (byteIndexRelativeToFile - mBytesParsed), error->sourceLine);
- }
- else {
- error->sourceLine.Append(mLastLine);
- }
-
- errorToken->SetError(error);
-
-
- /* Add the error token */
- CToken* newToken = (CToken*) errorToken;
- AddToken(newToken, NS_OK, mState->tokenDeque, mState->tokenAllocator);
-
- /* Add the error message tokens */
- AddErrorMessageTokens(error);
+ if (!error || !errorToken) {
+ delete error;
+ IF_FREE(errorToken,mState->tokenAllocator);
+ return NS_ERROR_OUT_OF_MEMORY;
}
- return rv;
+ /* Fill in the values of the error token */
+ error->code = XML_GetErrorCode(mExpatParser);
+ error->lineNumber = XML_GetCurrentLineNumber(mExpatParser);
+ // Adjust the column number so that it is one based rather than zero based.
+ error->colNumber = XML_GetCurrentColumnNumber(mExpatParser) + 1;
+
+ NS_WARN_IF_FALSE(error->code >= 1, "unexpected XML error code");
+ // Map Expat error code to an error string
+ nsAutoString errorMsg;
+ // XXX Deal with error returns.
+ nsParserMsgUtils::GetLocalizedStringByID(XMLPARSER_PROPERTIES,error->code,errorMsg);
+
+ if (error->code==XML_ERROR_TAG_MISMATCH) {
+ /*
+ * Certain things can be assumed about the token stream because of
+ * the way expat behaves. eg:
+ *
+ * - data:text/xml, is NOT WELL-FORMED
+ * - data:text/xml, is a TAG_MISMATCH.
+ *
+ * We can assume that there is at least one extra open tag (the one we
+ * want), so balance is initially set to one.
+ *
+ * Then loop through the tokens:
+ * - Each time we see eToken_end () increment balance, because
+ * that means there is another pair of tags we don't care about.
+ * - Each time we see eToken_start () decrement balance because it
+ * matches a close tag (perhaps the MISMATCHed tag in which case
+ * balance should hit 0).
+ * - If balance ever hits zero, exit the loop. Because of the way
+ * balance is adjusted, if balance is zero expected *must* be a start
+ * tag.
+ *
+ * We must check expected in the condition in case expat or nsDeque go
+ * crazy and give us 0 (null) before balance reaches 0.
+ */
+ nsDequeIterator current = mState->tokenDeque->End();
+ CToken *expected = NS_STATIC_CAST(CToken*,--current);
+ PRUint32 balance = 1;
+
+ while (expected) {
+ switch (expected->GetTokenType()) {
+ case eToken_start:
+ --balance;
+ break;
+ case eToken_end:
+ ++balance;
+ break;
+ default:
+ break; // we don't care about newlines or other tokens
+ }
+
+ if (!balance) {
+ // if balance is zero, this must be a start tag
+ CStartToken *startToken=NS_STATIC_CAST(CStartToken*,expected);
+
+ nsAutoString expectedMsg;
+ nsParserMsgUtils::GetLocalizedStringByName(XMLPARSER_PROPERTIES,"Expected",expectedMsg);
+
+ // . Expected: %S>.
+ PRUnichar *message = nsTextFormatter::smprintf(expectedMsg.get(),nsAutoString(startToken->GetStringValue()).get());
+ if (!message) {
+ delete error;
+ IF_FREE(errorToken,mState->tokenAllocator);
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ errorMsg.Append(message);
+ nsTextFormatter::smprintf_free(message);
+ break;
+ }
+
+ expected = NS_STATIC_CAST(CToken*,--current);
+ }
+ }
+
+ error->description.Assign(errorMsg);
+
+ error->sourceURL.Assign((PRUnichar*)XML_GetBase(mExpatParser));
+ if (!aIsFinal) {
+ PRInt32 byteIndexRelativeToFile = 0;
+ byteIndexRelativeToFile = XML_GetCurrentByteIndex(mExpatParser);
+ GetLine(aBuffer, aLength, (byteIndexRelativeToFile - mBytesParsed), error->sourceLine);
+ }
+ else {
+ error->sourceLine.Append(mLastLine);
+ }
+
+ errorToken->SetError(error);
+
+ /* Add the error token */
+ CToken* newToken = (CToken*) errorToken;
+ AddToken(newToken, NS_OK, mState->tokenDeque, mState->tokenAllocator);
+
+ /* Add the error message tokens */
+ AddErrorMessageTokens(error);
+
+ return NS_OK;
}
nsresult nsExpatTokenizer::ParseXMLBuffer(const char* aBuffer, PRUint32 aLength, PRBool aIsFinal)
diff --git a/htmlparser/src/nsParserMsgUtils.cpp b/htmlparser/src/nsParserMsgUtils.cpp
new file mode 100644
index 00000000000..5ef5ad87bc2
--- /dev/null
+++ b/htmlparser/src/nsParserMsgUtils.cpp
@@ -0,0 +1,104 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ */
+
+#include "nsIServiceManager.h"
+#include "nsIIOService.h"
+#include "nsIURI.h"
+#include "nsIStringBundle.h"
+#include "nsITextContent.h"
+#include "nsISupportsArray.h"
+#include "nsXPIDLString.h"
+#include "nsParserMsgUtils.h"
+#include "nsNetCID.h"
+
+static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
+static NS_DEFINE_CID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID);
+
+// This code is derived from nsFormControlHelper::GetLocalizedString()
+
+static nsresult GetBundle(const char * aPropFileName, nsIStringBundle **aBundle)
+{
+ NS_ENSURE_ARG_POINTER(aPropFileName);
+ NS_ENSURE_ARG_POINTER(aBundle);
+
+ // Create a URL for the string resource file
+ // Create a bundle for the localization
+ nsresult rv;
+ nsCOMPtr pNetService(do_GetService(kIOServiceCID, &rv));
+ if (NS_SUCCEEDED(rv)) {
+ nsCOMPtr uri;
+ rv = pNetService->NewURI(aPropFileName, nsnull, getter_AddRefs(uri));
+ if (NS_SUCCEEDED(rv)) {
+
+ // Create bundle
+ nsCOMPtr stringService =
+ do_GetService(kStringBundleServiceCID, &rv);
+ if (NS_SUCCEEDED(rv)) {
+ nsXPIDLCString spec;
+ rv = uri->GetSpec(getter_Copies(spec));
+ if (NS_SUCCEEDED(rv) && spec) {
+ rv = stringService->CreateBundle(spec, aBundle);
+ }
+ }
+ }
+ }
+ return rv;
+}
+
+nsresult
+nsParserMsgUtils::GetLocalizedStringByName(const char * aPropFileName, const char* aKey, nsString& oVal)
+{
+ oVal.Truncate();
+
+ NS_ENSURE_ARG_POINTER(aKey);
+
+ nsCOMPtr bundle;
+ nsresult rv = GetBundle(aPropFileName,getter_AddRefs(bundle));
+ if (NS_SUCCEEDED(rv) && bundle) {
+ nsXPIDLString valUni;
+ nsAutoString key; key.AssignWithConversion(aKey);
+ rv = bundle->GetStringFromName(key.get(), getter_Copies(valUni));
+ if (NS_SUCCEEDED(rv) && valUni) {
+ oVal.Assign(valUni);
+ }
+ }
+
+ return rv;
+}
+
+nsresult
+nsParserMsgUtils::GetLocalizedStringByID(const char * aPropFileName, PRUint32 aID, nsString& oVal)
+{
+ oVal.Truncate();
+
+ nsCOMPtr bundle;
+ nsresult rv = GetBundle(aPropFileName,getter_AddRefs(bundle));
+ if (NS_SUCCEEDED(rv) && bundle) {
+ nsXPIDLString valUni;
+ rv = bundle->GetStringFromID(aID, getter_Copies(valUni));
+ if (NS_SUCCEEDED(rv) && valUni) {
+ oVal.Assign(valUni);
+ }
+ }
+
+ return rv;
+}
diff --git a/htmlparser/src/nsParserMsgUtils.h b/htmlparser/src/nsParserMsgUtils.h
new file mode 100644
index 00000000000..ecabfa24aa7
--- /dev/null
+++ b/htmlparser/src/nsParserMsgUtils.h
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ */
+
+#ifndef nsParserMsgUtils_h
+#define nsParserMsgUtils_h
+
+#include "nsString.h"
+
+#define XMLPARSER_PROPERTIES "chrome://communicator/locale/layout/xmlparser.properties"
+
+class nsParserMsgUtils {
+ nsParserMsgUtils(); // Currently this is not meant to be created, use the static methods
+ ~nsParserMsgUtils(); // If perf required, change this to cache values etc.
+public:
+ static nsresult GetLocalizedStringByName(const char * aPropFileName, const char* aKey, nsString& aVal);
+ static nsresult GetLocalizedStringByID(const char * aPropFileName, PRUint32 aID, nsString& aVal);
+};
+
+#endif
diff --git a/htmlparser/src/xmlparser.properties b/htmlparser/src/xmlparser.properties
new file mode 100644
index 00000000000..c8b0f182935
--- /dev/null
+++ b/htmlparser/src/xmlparser.properties
@@ -0,0 +1,53 @@
+# The contents of this file are subject to the Netscape Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/NPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 2001 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+
+# Map Expat error codes to error strings
+1 = out of memory
+2 = syntax error
+3 = no element found
+4 = not well-formed
+5 = unclosed token
+6 = unclosed token
+7 = mismatched tag
+8 = duplicate attribute
+9 = junk after document element
+10 = illegal parameter entity reference
+11 = undefined entity
+12 = recursive entity reference
+13 = asynchronous entity
+14 = reference to invalid character number
+15 = reference to binary entity
+16 = reference to external entity in attribute
+17 = xml processing instruction not at start of external entity
+18 = unknown encoding
+19 = encoding specified in XML declaration is incorrect
+20 = unclosed CDATA section
+21 = error in processing external entity reference
+22 = document is not standalone
+
+# %1$S is replaced by the Expat error string, may be followed by Expected (see below)
+# %2$S is replaced by URL
+# %3$d is replaced by line number
+# %4$d is replaced by column number
+XMLParsingError = XML Parsing Error: %1$S\nLocation: %2$S\nLine Number %3$d, Column %4$d:
+
+# %S is replaced by a tag name.
+# This gets appended to the error string if the error is mismatched tag.
+Expected = . Expected: %S>.
diff --git a/parser/htmlparser/macbuild/htmlparser.mcp b/parser/htmlparser/macbuild/htmlparser.mcp
index 80d03e559f4..3adc6cdeac3 100644
Binary files a/parser/htmlparser/macbuild/htmlparser.mcp and b/parser/htmlparser/macbuild/htmlparser.mcp differ
diff --git a/parser/htmlparser/src/MANIFEST_PROPERTIES b/parser/htmlparser/src/MANIFEST_PROPERTIES
new file mode 100644
index 00000000000..515cf9a5d7d
--- /dev/null
+++ b/parser/htmlparser/src/MANIFEST_PROPERTIES
@@ -0,0 +1 @@
+xmlparse.properties
diff --git a/parser/htmlparser/src/Makefile.in b/parser/htmlparser/src/Makefile.in
index 19a8d36a68e..fbbdf6f9189 100644
--- a/parser/htmlparser/src/Makefile.in
+++ b/parser/htmlparser/src/Makefile.in
@@ -61,6 +61,7 @@ CPPSRCS = \
nsToken.cpp \
nsWellFormedDTD.cpp \
nsViewSourceHTML.cpp\
+ nsParserMsgUtils.cpp\
$(NULL)
ifndef MOZ_DISABLE_DTD_DEBUG
diff --git a/parser/htmlparser/src/jar.mn b/parser/htmlparser/src/jar.mn
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/parser/htmlparser/src/makefile.win b/parser/htmlparser/src/makefile.win
index 305fa030457..dc710fcf4cf 100644
--- a/parser/htmlparser/src/makefile.win
+++ b/parser/htmlparser/src/makefile.win
@@ -48,6 +48,7 @@ CPPSRCS = \
nsWellFormedDTD.cpp \
nsViewSourceHTML.cpp\
nsParserModule.cpp \
+ nsParserMsgUtils.cpp \
!if !defined(MOZ_DISABLE_DTD_DEBUG)
nsLoggingSink.cpp \
nsHTMLNullSink.cpp \
@@ -72,6 +73,7 @@ CPP_OBJS = \
.\$(OBJDIR)\nsWellFormedDTD.obj \
.\$(OBJDIR)\nsViewSourceHTML.obj\
.\$(OBJDIR)\nsParserModule.obj \
+ .\$(OBJDIR)\nsParserMsgUtils.obj \
!if !defined(MOZ_DISABLE_DTD_DEBUG)
.\$(OBJDIR)\nsLoggingSink.obj \
.\$(OBJDIR)\nsHTMLNullSink.obj \
diff --git a/parser/htmlparser/src/nsExpatTokenizer.cpp b/parser/htmlparser/src/nsExpatTokenizer.cpp
index 66154226fe6..ab926f5094e 100644
--- a/parser/htmlparser/src/nsExpatTokenizer.cpp
+++ b/parser/htmlparser/src/nsExpatTokenizer.cpp
@@ -42,6 +42,9 @@
#include "nsSpecialSystemDirectory.h"
#include "nsIURL.h"
+#include "nsParserMsgUtils.h"
+#include "nsTextFormatter.h"
+
typedef struct _XMLParserState {
XML_Parser parser;
nsScanner* scanner;
@@ -278,21 +281,24 @@ void nsExpatTokenizer::GetLine(const char* aSourceBuffer, PRUint32 aLength,
}
}
-
static nsresult
CreateErrorText(const nsParserError* aError, nsString& aErrorString)
{
- aErrorString.AssignWithConversion("XML Parsing Error: ");
+ aErrorString.Truncate();
if (aError) {
- aErrorString.Append(aError->description);
- aErrorString.AppendWithConversion("\nLocation: ");
- aErrorString.Append(aError->sourceURL);
- aErrorString.AppendWithConversion("\nLine Number ");
- aErrorString.AppendInt(aError->lineNumber, 10);
- aErrorString.AppendWithConversion(", Column ");
- aErrorString.AppendInt(aError->colNumber, 10);
- aErrorString.AppendWithConversion(":");
+ nsAutoString msg;
+ nsresult rv = nsParserMsgUtils::GetLocalizedStringByName(XMLPARSER_PROPERTIES,"XMLParsingError",msg);
+ if (NS_FAILED(rv))
+ return rv;
+
+ // XML Parsing Error: %1$S\nLocation: %2$S\nLine Number %3$d, Column %4$d:
+ PRUnichar *message = nsTextFormatter::smprintf(msg.get(),aError->description.get(),aError->sourceURL.get(),aError->lineNumber,aError->colNumber);
+ if (!message) {
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ aErrorString.Assign(message);
+ nsTextFormatter::smprintf_free(message);
}
return NS_OK;
@@ -379,89 +385,109 @@ nsExpatTokenizer::PushXMLErrorTokens(const char *aBuffer, PRUint32 aLength, PRBo
{
CErrorToken* errorToken= (CErrorToken *) mState->tokenAllocator->CreateTokenOfType(eToken_error, eHTMLTag_unknown);
nsParserError *error = new nsParserError;
- nsresult rv = NS_OK;
-
- if (error && errorToken) {
- /* Fill in the values of the error token */
- error->code = XML_GetErrorCode(mExpatParser);
- error->lineNumber = XML_GetCurrentLineNumber(mExpatParser);
- // Adjust the column number so that it is one based rather than zero based.
- error->colNumber = XML_GetCurrentColumnNumber(mExpatParser) + 1;
- error->description.AssignWithConversion(XML_ErrorString(error->code));
- if (error->code==XML_ERROR_TAG_MISMATCH){
- /*
- * Certain things can be assumed about the token stream because of
- * the way expat behaves. eg:
- *
- * - data:text/xml, is NOT WELL-FORMED
- * - data:text/xml, is a TAG_MISMATCH.
- *
- * We can assume that there is at least one extra open tag (the one we
- * want), so balance is initially set to one.
- *
- * Then loop through the tokens:
- * - Each time we see eToken_end () increment balance, because
- * that means there is another pair of tags we don't care about.
- * - Each time we see eToken_start () decrement balance because it
- * matches a close tag (perhaps the MISMATCHed tag in which case
- * balance should hit 0).
- * - If balance ever hits zero, exit the loop. Because of the way
- * balance is adjusted, if balance is zero expected *must* be a start
- * tag.
- *
- * We must check expected in the condition in case expat or nsDeque go
- * crazy and give us 0 (null) before balance reaches 0.
- */
- nsDequeIterator current = mState->tokenDeque->End();
- CToken *expected = NS_STATIC_CAST(CToken*,--current);
- PRUint32 balance = 1;
-
- while (expected) {
- switch (expected->GetTokenType()) {
- case eToken_start:
- --balance;
- break;
- case eToken_end:
- ++balance;
- break;
- default:
- break; // we don't care about newlines or other tokens
- }
-
- if (!balance) {
- // if balance is zero, this must be a start tag
- CStartToken *startToken=NS_STATIC_CAST(CStartToken*,expected);
- error->description.Append(NS_LITERAL_STRING(". Expected: "));
- error->description.Append(startToken->GetStringValue());
- error->description.Append(NS_LITERAL_STRING(">"));
- break;
- }
-
- expected = NS_STATIC_CAST(CToken*,--current);
- }
- }
- error->sourceURL.Assign((PRUnichar*)XML_GetBase(mExpatParser));
- if (!aIsFinal) {
- PRInt32 byteIndexRelativeToFile = 0;
- byteIndexRelativeToFile = XML_GetCurrentByteIndex(mExpatParser);
- GetLine(aBuffer, aLength, (byteIndexRelativeToFile - mBytesParsed), error->sourceLine);
- }
- else {
- error->sourceLine.Append(mLastLine);
- }
-
- errorToken->SetError(error);
-
-
- /* Add the error token */
- CToken* newToken = (CToken*) errorToken;
- AddToken(newToken, NS_OK, mState->tokenDeque, mState->tokenAllocator);
-
- /* Add the error message tokens */
- AddErrorMessageTokens(error);
+ if (!error || !errorToken) {
+ delete error;
+ IF_FREE(errorToken,mState->tokenAllocator);
+ return NS_ERROR_OUT_OF_MEMORY;
}
- return rv;
+ /* Fill in the values of the error token */
+ error->code = XML_GetErrorCode(mExpatParser);
+ error->lineNumber = XML_GetCurrentLineNumber(mExpatParser);
+ // Adjust the column number so that it is one based rather than zero based.
+ error->colNumber = XML_GetCurrentColumnNumber(mExpatParser) + 1;
+
+ NS_WARN_IF_FALSE(error->code >= 1, "unexpected XML error code");
+ // Map Expat error code to an error string
+ nsAutoString errorMsg;
+ // XXX Deal with error returns.
+ nsParserMsgUtils::GetLocalizedStringByID(XMLPARSER_PROPERTIES,error->code,errorMsg);
+
+ if (error->code==XML_ERROR_TAG_MISMATCH) {
+ /*
+ * Certain things can be assumed about the token stream because of
+ * the way expat behaves. eg:
+ *
+ * - data:text/xml, is NOT WELL-FORMED
+ * - data:text/xml, is a TAG_MISMATCH.
+ *
+ * We can assume that there is at least one extra open tag (the one we
+ * want), so balance is initially set to one.
+ *
+ * Then loop through the tokens:
+ * - Each time we see eToken_end () increment balance, because
+ * that means there is another pair of tags we don't care about.
+ * - Each time we see eToken_start () decrement balance because it
+ * matches a close tag (perhaps the MISMATCHed tag in which case
+ * balance should hit 0).
+ * - If balance ever hits zero, exit the loop. Because of the way
+ * balance is adjusted, if balance is zero expected *must* be a start
+ * tag.
+ *
+ * We must check expected in the condition in case expat or nsDeque go
+ * crazy and give us 0 (null) before balance reaches 0.
+ */
+ nsDequeIterator current = mState->tokenDeque->End();
+ CToken *expected = NS_STATIC_CAST(CToken*,--current);
+ PRUint32 balance = 1;
+
+ while (expected) {
+ switch (expected->GetTokenType()) {
+ case eToken_start:
+ --balance;
+ break;
+ case eToken_end:
+ ++balance;
+ break;
+ default:
+ break; // we don't care about newlines or other tokens
+ }
+
+ if (!balance) {
+ // if balance is zero, this must be a start tag
+ CStartToken *startToken=NS_STATIC_CAST(CStartToken*,expected);
+
+ nsAutoString expectedMsg;
+ nsParserMsgUtils::GetLocalizedStringByName(XMLPARSER_PROPERTIES,"Expected",expectedMsg);
+
+ // . Expected: %S>.
+ PRUnichar *message = nsTextFormatter::smprintf(expectedMsg.get(),nsAutoString(startToken->GetStringValue()).get());
+ if (!message) {
+ delete error;
+ IF_FREE(errorToken,mState->tokenAllocator);
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+ errorMsg.Append(message);
+ nsTextFormatter::smprintf_free(message);
+ break;
+ }
+
+ expected = NS_STATIC_CAST(CToken*,--current);
+ }
+ }
+
+ error->description.Assign(errorMsg);
+
+ error->sourceURL.Assign((PRUnichar*)XML_GetBase(mExpatParser));
+ if (!aIsFinal) {
+ PRInt32 byteIndexRelativeToFile = 0;
+ byteIndexRelativeToFile = XML_GetCurrentByteIndex(mExpatParser);
+ GetLine(aBuffer, aLength, (byteIndexRelativeToFile - mBytesParsed), error->sourceLine);
+ }
+ else {
+ error->sourceLine.Append(mLastLine);
+ }
+
+ errorToken->SetError(error);
+
+ /* Add the error token */
+ CToken* newToken = (CToken*) errorToken;
+ AddToken(newToken, NS_OK, mState->tokenDeque, mState->tokenAllocator);
+
+ /* Add the error message tokens */
+ AddErrorMessageTokens(error);
+
+ return NS_OK;
}
nsresult nsExpatTokenizer::ParseXMLBuffer(const char* aBuffer, PRUint32 aLength, PRBool aIsFinal)
diff --git a/parser/htmlparser/src/nsParserMsgUtils.cpp b/parser/htmlparser/src/nsParserMsgUtils.cpp
new file mode 100644
index 00000000000..5ef5ad87bc2
--- /dev/null
+++ b/parser/htmlparser/src/nsParserMsgUtils.cpp
@@ -0,0 +1,104 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ */
+
+#include "nsIServiceManager.h"
+#include "nsIIOService.h"
+#include "nsIURI.h"
+#include "nsIStringBundle.h"
+#include "nsITextContent.h"
+#include "nsISupportsArray.h"
+#include "nsXPIDLString.h"
+#include "nsParserMsgUtils.h"
+#include "nsNetCID.h"
+
+static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
+static NS_DEFINE_CID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID);
+
+// This code is derived from nsFormControlHelper::GetLocalizedString()
+
+static nsresult GetBundle(const char * aPropFileName, nsIStringBundle **aBundle)
+{
+ NS_ENSURE_ARG_POINTER(aPropFileName);
+ NS_ENSURE_ARG_POINTER(aBundle);
+
+ // Create a URL for the string resource file
+ // Create a bundle for the localization
+ nsresult rv;
+ nsCOMPtr pNetService(do_GetService(kIOServiceCID, &rv));
+ if (NS_SUCCEEDED(rv)) {
+ nsCOMPtr uri;
+ rv = pNetService->NewURI(aPropFileName, nsnull, getter_AddRefs(uri));
+ if (NS_SUCCEEDED(rv)) {
+
+ // Create bundle
+ nsCOMPtr stringService =
+ do_GetService(kStringBundleServiceCID, &rv);
+ if (NS_SUCCEEDED(rv)) {
+ nsXPIDLCString spec;
+ rv = uri->GetSpec(getter_Copies(spec));
+ if (NS_SUCCEEDED(rv) && spec) {
+ rv = stringService->CreateBundle(spec, aBundle);
+ }
+ }
+ }
+ }
+ return rv;
+}
+
+nsresult
+nsParserMsgUtils::GetLocalizedStringByName(const char * aPropFileName, const char* aKey, nsString& oVal)
+{
+ oVal.Truncate();
+
+ NS_ENSURE_ARG_POINTER(aKey);
+
+ nsCOMPtr bundle;
+ nsresult rv = GetBundle(aPropFileName,getter_AddRefs(bundle));
+ if (NS_SUCCEEDED(rv) && bundle) {
+ nsXPIDLString valUni;
+ nsAutoString key; key.AssignWithConversion(aKey);
+ rv = bundle->GetStringFromName(key.get(), getter_Copies(valUni));
+ if (NS_SUCCEEDED(rv) && valUni) {
+ oVal.Assign(valUni);
+ }
+ }
+
+ return rv;
+}
+
+nsresult
+nsParserMsgUtils::GetLocalizedStringByID(const char * aPropFileName, PRUint32 aID, nsString& oVal)
+{
+ oVal.Truncate();
+
+ nsCOMPtr bundle;
+ nsresult rv = GetBundle(aPropFileName,getter_AddRefs(bundle));
+ if (NS_SUCCEEDED(rv) && bundle) {
+ nsXPIDLString valUni;
+ rv = bundle->GetStringFromID(aID, getter_Copies(valUni));
+ if (NS_SUCCEEDED(rv) && valUni) {
+ oVal.Assign(valUni);
+ }
+ }
+
+ return rv;
+}
diff --git a/parser/htmlparser/src/nsParserMsgUtils.h b/parser/htmlparser/src/nsParserMsgUtils.h
new file mode 100644
index 00000000000..ecabfa24aa7
--- /dev/null
+++ b/parser/htmlparser/src/nsParserMsgUtils.h
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * The contents of this file are subject to the Netscape Public
+ * License Version 1.1 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.mozilla.org/NPL/
+ *
+ * Software distributed under the License is distributed on an "AS
+ * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+ * implied. See the License for the specific language governing
+ * rights and limitations under the License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is Netscape
+ * Communications Corporation. Portions created by Netscape are
+ * Copyright (C) 1998 Netscape Communications Corporation. All
+ * Rights Reserved.
+ *
+ * Contributor(s):
+ */
+
+#ifndef nsParserMsgUtils_h
+#define nsParserMsgUtils_h
+
+#include "nsString.h"
+
+#define XMLPARSER_PROPERTIES "chrome://communicator/locale/layout/xmlparser.properties"
+
+class nsParserMsgUtils {
+ nsParserMsgUtils(); // Currently this is not meant to be created, use the static methods
+ ~nsParserMsgUtils(); // If perf required, change this to cache values etc.
+public:
+ static nsresult GetLocalizedStringByName(const char * aPropFileName, const char* aKey, nsString& aVal);
+ static nsresult GetLocalizedStringByID(const char * aPropFileName, PRUint32 aID, nsString& aVal);
+};
+
+#endif
diff --git a/parser/htmlparser/src/xmlparser.properties b/parser/htmlparser/src/xmlparser.properties
new file mode 100644
index 00000000000..c8b0f182935
--- /dev/null
+++ b/parser/htmlparser/src/xmlparser.properties
@@ -0,0 +1,53 @@
+# The contents of this file are subject to the Netscape Public
+# License Version 1.1 (the "License"); you may not use this file
+# except in compliance with the License. You may obtain a copy of
+# the License at http://www.mozilla.org/NPL/
+#
+# Software distributed under the License is distributed on an "AS
+# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# rights and limitations under the License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is Netscape
+# Communications Corporation. Portions created by Netscape are
+# Copyright (C) 2001 Netscape Communications Corporation. All
+# Rights Reserved.
+#
+# Contributor(s):
+#
+
+# Map Expat error codes to error strings
+1 = out of memory
+2 = syntax error
+3 = no element found
+4 = not well-formed
+5 = unclosed token
+6 = unclosed token
+7 = mismatched tag
+8 = duplicate attribute
+9 = junk after document element
+10 = illegal parameter entity reference
+11 = undefined entity
+12 = recursive entity reference
+13 = asynchronous entity
+14 = reference to invalid character number
+15 = reference to binary entity
+16 = reference to external entity in attribute
+17 = xml processing instruction not at start of external entity
+18 = unknown encoding
+19 = encoding specified in XML declaration is incorrect
+20 = unclosed CDATA section
+21 = error in processing external entity reference
+22 = document is not standalone
+
+# %1$S is replaced by the Expat error string, may be followed by Expected (see below)
+# %2$S is replaced by URL
+# %3$d is replaced by line number
+# %4$d is replaced by column number
+XMLParsingError = XML Parsing Error: %1$S\nLocation: %2$S\nLine Number %3$d, Column %4$d:
+
+# %S is replaced by a tag name.
+# This gets appended to the error string if the error is mismatched tag.
+Expected = . Expected: %S>.