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: 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: . + 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: . 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: 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: . + 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: .