diff --git a/extensions/transformiix/source/base/txExpandedNameMap.cpp b/extensions/transformiix/source/base/txExpandedNameMap.cpp index c2926e6145e..bc13bc7dc91 100644 --- a/extensions/transformiix/source/base/txExpandedNameMap.cpp +++ b/extensions/transformiix/source/base/txExpandedNameMap.cpp @@ -64,7 +64,7 @@ txExpandedNameMap::~txExpandedNameMap() * @param aValue value of item to add * @return errorcode */ -nsresult txExpandedNameMap::add(txExpandedName& aKey, TxObject* aValue) +nsresult txExpandedNameMap::add(const txExpandedName& aKey, TxObject* aValue) { int i; // Check if there already is an item with this key @@ -88,6 +88,7 @@ nsresult txExpandedNameMap::add(txExpandedName& aKey, TxObject* aValue) mItems[mItemCount].mNamespaceID = aKey.mNamespaceID; mItems[mItemCount].mLocalName = aKey.mLocalName; + TX_IF_ADDREF_ATOM(mItems[mItemCount].mLocalName); mItems[mItemCount].mValue = aValue; ++mItemCount; @@ -101,7 +102,7 @@ nsresult txExpandedNameMap::add(txExpandedName& aKey, TxObject* aValue) * @param aValue value of item to set * @return errorcode */ -nsresult txExpandedNameMap::set(txExpandedName& aKey, TxObject* aValue) +nsresult txExpandedNameMap::set(const txExpandedName& aKey, TxObject* aValue) { int i; // Check if there already is an item with this key @@ -129,6 +130,7 @@ nsresult txExpandedNameMap::set(txExpandedName& aKey, TxObject* aValue) mItems[mItemCount].mNamespaceID = aKey.mNamespaceID; mItems[mItemCount].mLocalName = aKey.mLocalName; + TX_IF_ADDREF_ATOM(mItems[mItemCount].mLocalName); mItems[mItemCount].mValue = aValue; ++mItemCount; @@ -140,7 +142,7 @@ nsresult txExpandedNameMap::set(txExpandedName& aKey, TxObject* aValue) * @param aKey key for item to get * @return item with specified key, or null if no such item exists */ -TxObject* txExpandedNameMap::get(txExpandedName& aKey) +TxObject* txExpandedNameMap::get(const txExpandedName& aKey) { int i; for (i = 0; i < mItemCount; ++i) { diff --git a/extensions/transformiix/source/base/txExpandedNameMap.h b/extensions/transformiix/source/base/txExpandedNameMap.h index 96603b6246d..670a7033e53 100644 --- a/extensions/transformiix/source/base/txExpandedNameMap.h +++ b/extensions/transformiix/source/base/txExpandedNameMap.h @@ -56,7 +56,7 @@ public: * @param aValue value of item to add * @return errorcode */ - nsresult add(txExpandedName& aKey, TxObject* aValue); + nsresult add(const txExpandedName& aKey, TxObject* aValue); /* * Sets an item, if an item with this key already exists it is overwritten @@ -65,14 +65,14 @@ public: * @param aValue value of item to set * @return errorcode */ - nsresult set(txExpandedName& aKey, TxObject* aValue); + nsresult set(const txExpandedName& aKey, TxObject* aValue); /* * Gets an item * @param aKey key for item to get * @return item with specified key, or null if no such item exists */ - TxObject* get(txExpandedName& aKey); + TxObject* get(const txExpandedName& aKey); class iterator { public: diff --git a/extensions/transformiix/source/xslt/ProcessorState.cpp b/extensions/transformiix/source/xslt/ProcessorState.cpp index fef4bc467f0..cea58b88ecb 100644 --- a/extensions/transformiix/source/xslt/ProcessorState.cpp +++ b/extensions/transformiix/source/xslt/ProcessorState.cpp @@ -53,7 +53,9 @@ ProcessorState::ProcessorState(Document* aSourceDocument, Document* aXslDocument, Document* aResultDocument) - : mEvalContext(0), + : mXslKeys(MB_TRUE), + mDecimalFormats(MB_TRUE), + mEvalContext(0), mSourceDocument(aSourceDocument), xslDocument(aXslDocument), resultDocument(aResultDocument) @@ -82,16 +84,8 @@ ProcessorState::ProcessorState(Document* aSourceDocument, loadedDocuments.put(xslDocument->getBaseURI(), xslDocument); } - // make sure all keys are deleted - xslKeys.setObjectDeletion(MB_TRUE); - // Make sure all loaded documents get deleted loadedDocuments.setObjectDeletion(MB_TRUE); - - // add predefined default decimal format - defaultDecimalFormatSet = MB_FALSE; - decimalFormats.put(String(), new txDecimalFormat); - decimalFormats.setObjectDeletion(MB_TRUE); } /** @@ -130,10 +124,12 @@ void ProcessorState::addAttributeSet(Element* aAttributeSet, if (!aAttributeSet) return; - String name; - if (!aAttributeSet->getAttr(txXSLTAtoms::name, - kNameSpaceID_None, name)) { - String err("missing required name attribute for xsl:attribute-set"); + String nameStr; + txExpandedName name; + aAttributeSet->getAttr(txXSLTAtoms::name, kNameSpaceID_None, nameStr); + nsresult rv = name.init(nameStr, aAttributeSet, MB_FALSE); + if (NS_FAILED(rv)) { + String err("missing or malformed name for xsl:attribute-set"); receiveError(err); return; } @@ -141,7 +137,7 @@ void ProcessorState::addAttributeSet(Element* aAttributeSet, NodeSet* attSet = (NodeSet*)aImportFrame->mNamedAttributeSets.get(name); if (!attSet) { attSet = new NodeSet(); - aImportFrame->mNamedAttributeSets.put(name, attSet); + aImportFrame->mNamedAttributeSets.add(name, attSet); } // Add xsl:attribute elements to attSet @@ -178,19 +174,29 @@ void ProcessorState::addTemplate(Element* aXslTemplate, ImportFrame* aImportFrame) { NS_ASSERTION(aXslTemplate, "missing template"); - - String name; + + nsresult rv = NS_OK; + String nameStr; if (aXslTemplate->getAttr(txXSLTAtoms::name, - kNameSpaceID_None, name)) { - // check for duplicates - Element* tmp = (Element*)aImportFrame->mNamedTemplates.get(name); - if (tmp) { - String err("Duplicate template name: "); - err.append(name); - receiveError(err); + kNameSpaceID_None, nameStr)) { + txExpandedName name; + rv = name.init(nameStr, aXslTemplate, MB_FALSE); + if (NS_FAILED(rv)) { + String err("missing or malformed template name: '"); + err.append(nameStr); + err.append('\''); + receiveError(err, NS_ERROR_FAILURE); + return; + } + + rv = aImportFrame->mNamedTemplates.add(name, aXslTemplate); + if (NS_FAILED(rv)) { + String err("Unable to add template named '"); + err.append(nameStr); + err.append("'. Does that name already exist?"); + receiveError(err, NS_ERROR_FAILURE); return; } - aImportFrame->mNamedTemplates.put(name, aXslTemplate); } String match; @@ -198,9 +204,20 @@ void ProcessorState::addTemplate(Element* aXslTemplate, // This is no error, see section 6 Named Templates return; } + // get the txList for the right mode - String mode; - aXslTemplate->getAttr(txXSLTAtoms::mode, kNameSpaceID_None, mode); + String modeStr; + txExpandedName mode; + if (aXslTemplate->getAttr(txXSLTAtoms::mode, kNameSpaceID_None, modeStr)) { + rv = mode.init(modeStr, aXslTemplate, MB_FALSE); + if (NS_FAILED(rv)) { + String err("malformed template-mode name: '"); + err.append(modeStr); + err.append('\''); + receiveError(err, NS_ERROR_FAILURE); + return; + } + } txList* templates = (txList*)aImportFrame->mMatchableTemplates.get(mode); @@ -210,7 +227,11 @@ void ProcessorState::addTemplate(Element* aXslTemplate, NS_ASSERTION(0, "out of memory"); return; } - aImportFrame->mMatchableTemplates.put(mode, templates); + rv = aImportFrame->mMatchableTemplates.add(mode, templates); + if (NS_FAILED(rv)) { + delete templates; + return; + } } // Check for explicit default priority @@ -284,8 +305,9 @@ void ProcessorState::addLREStylesheet(Document* aStylesheet, NS_ASSERTION(aStylesheet, "missing stylesheet"); // get the txList for null mode + txExpandedName nullMode; txList* templates = - (txList*)aImportFrame->mMatchableTemplates.get(NULL_STRING); + (txList*)aImportFrame->mMatchableTemplates.get(nullMode); if (!templates) { templates = new txList; @@ -293,14 +315,14 @@ void ProcessorState::addLREStylesheet(Document* aStylesheet, // XXX ErrorReport: out of memory return; } - aImportFrame->mMatchableTemplates.put(NULL_STRING, templates); + aImportFrame->mMatchableTemplates.add(nullMode, templates); } // Add the template to the list of templates txPattern* root = new txRootPattern(MB_TRUE); MatchableTemplate* nt = 0; if (root) - nt = new MatchableTemplate(aStylesheet, root, Double::NaN); + nt = new MatchableTemplate(aStylesheet, root, 0.5); if (!nt) { delete root; // XXX ErrorReport: out of memory @@ -383,21 +405,6 @@ List* ProcessorState::getImportFrames() return &mImportFrames; } -/* - * Find template in specified mode matching the supplied node - * @param aNode node to find matching template for - * @param aMode mode of the template - * @param aImportFrame out-param, is set to the ImportFrame containing - * the found template - * @return root-node of found template, null if none is found - */ -Node* ProcessorState::findTemplate(Node* aNode, - const String& aMode, - ImportFrame** aImportFrame) -{ - return findTemplate(aNode, aMode, 0, aImportFrame); -} - /* * Find template in specified mode matching the supplied node. Only search * templates imported by a specific ImportFrame @@ -410,7 +417,7 @@ Node* ProcessorState::findTemplate(Node* aNode, * @return root-node of found template, null if none is found */ Node* ProcessorState::findTemplate(Node* aNode, - const String& aMode, + const txExpandedName& aMode, ImportFrame* aImportedBy, ImportFrame** aImportFrame) { @@ -463,13 +470,17 @@ Node* ProcessorState::findTemplate(Node* aNode, #ifdef PR_LOGGING char *nodeBuf = 0, *modeBuf = 0; + String mode; + if (aMode.mLocalName) { + TX_GET_ATOM_STRING(aMode.mLocalName, mode); + } if (matchTemplate) { char *matchBuf = 0, *uriBuf = 0; PR_LOG(txLog::xslt, PR_LOG_DEBUG, ("MatchTemplate, Pattern %s, Mode %s, Stylesheet %s, " \ "Node %s\n", (matchBuf = ((Element*)matchTemplate)->getAttribute(String("match")).toCharArray()), - (modeBuf = aMode.toCharArray()), + (modeBuf = mode.toCharArray()), (uriBuf = matchTemplate->getBaseURI().toCharArray()), (nodeBuf = aNode->getNodeName().toCharArray()))); #ifdef TX_EXE @@ -484,7 +495,7 @@ Node* ProcessorState::findTemplate(Node* aNode, PR_LOG(txLog::xslt, PR_LOG_DEBUG, ("No match, Node %s, Mode %s\n", (nodeBuf = aNode->getNodeName().toCharArray()), - (modeBuf = aMode.toCharArray()))); + (modeBuf = mode.toCharArray()))); } #ifdef TX_EXE delete [] nodeBuf; @@ -517,7 +528,7 @@ void ProcessorState::setCurrentTemplateRule(TemplateRule* aTemplateRule) * Returns the AttributeSet associated with the given name * or null if no AttributeSet is found */ -NodeSet* ProcessorState::getAttributeSet(const String& aName) +NodeSet* ProcessorState::getAttributeSet(const txExpandedName& aName) { NodeSet* attset = new NodeSet; if (!attset) @@ -586,7 +597,7 @@ txPattern* ProcessorState::getPattern(Element* aElem, PatternAttr aAttr) return pattern; } String attr; - MBool hasAttr; + MBool hasAttr = MB_FALSE; switch (aAttr) { case CountAttr: hasAttr = aElem->getAttr(txXSLTAtoms::count, kNameSpaceID_None, @@ -620,7 +631,7 @@ txPattern* ProcessorState::getPattern(Element* aElem, PatternAttr aAttr) * Returns the template associated with the given name, or * null if not template is found */ -Element* ProcessorState::getNamedTemplate(String& aName) +Element* ProcessorState::getNamedTemplate(const txExpandedName& aName) { ImportFrame* frame; txListIterator frameIter(&mImportFrames); @@ -735,16 +746,22 @@ void ProcessorState::shouldStripSpace(String& aNames, Element* aElement, **/ MBool ProcessorState::addKey(Element* aKeyElem) { - String keyName; - aKeyElem->getAttr(txXSLTAtoms::name, kNameSpaceID_None, keyName); - if (!XMLUtils::isValidQName(keyName)) + nsresult rv = NS_OK; + String keyQName; + aKeyElem->getAttr(txXSLTAtoms::name, kNameSpaceID_None, keyQName); + txExpandedName keyName; + rv = keyName.init(keyQName, aKeyElem, MB_FALSE); + if (NS_FAILED(rv)) return MB_FALSE; - txXSLKey* xslKey = (txXSLKey*)xslKeys.get(keyName); + + txXSLKey* xslKey = (txXSLKey*)mXslKeys.get(keyName); if (!xslKey) { xslKey = new txXSLKey(this); if (!xslKey) return MB_FALSE; - xslKeys.put(keyName, xslKey); + rv = mXslKeys.add(keyName, xslKey); + if (NS_FAILED(rv)) + return MB_FALSE; } txPattern* match = 0; txPSParseContext pContext(this, aKeyElem); @@ -769,8 +786,9 @@ MBool ProcessorState::addKey(Element* aKeyElem) * Adds the supplied xsl:key to the set of keys * returns NULL if no such key exists **/ -txXSLKey* ProcessorState::getKey(String& keyName) { - return (txXSLKey*)xslKeys.get(keyName); +txXSLKey* ProcessorState::getKey(txExpandedName& keyName) +{ + return (txXSLKey*)mXslKeys.get(keyName); } /* @@ -780,13 +798,20 @@ txXSLKey* ProcessorState::getKey(String& keyName) { MBool ProcessorState::addDecimalFormat(Element* element) { // build new DecimalFormat structure + nsresult rv = NS_OK; MBool success = MB_TRUE; txDecimalFormat* format = new txDecimalFormat; if (!format) return MB_FALSE; - String formatName, attValue; - element->getAttr(txXSLTAtoms::name, kNameSpaceID_None, formatName); + String formatNameStr, attValue; + txExpandedName formatName; + if (element->getAttr(txXSLTAtoms::name, kNameSpaceID_None, + formatNameStr)) { + rv = formatName.init(formatNameStr, element, MB_FALSE); + if (NS_FAILED(rv)) + return MB_FALSE; + } if (element->getAttr(txXSLTAtoms::decimalSeparator, kNameSpaceID_None, attValue)) { @@ -866,26 +891,18 @@ MBool ProcessorState::addDecimalFormat(Element* element) } // Does an existing format with that name exist? - // (name="" means default format) - - txDecimalFormat* existing = NULL; - - if (defaultDecimalFormatSet || !formatName.isEmpty()) { - existing = (txDecimalFormat*)decimalFormats.get(formatName); - } - else { - // We are overriding the predefined default format which is always - // allowed - delete decimalFormats.remove(formatName); - defaultDecimalFormatSet = MB_TRUE; - } - + txDecimalFormat* existing = + (txDecimalFormat*)mDecimalFormats.get(formatName); if (existing) { success = existing->isEqual(format); delete format; } else { - decimalFormats.put(formatName, format); + rv = mDecimalFormats.add(formatName, format); + if (NS_FAILED(rv)) { + delete format; + success = MB_FALSE; + } } return success; @@ -894,9 +911,13 @@ MBool ProcessorState::addDecimalFormat(Element* element) /* * Returns a decimal format or NULL if no such format exists. */ -txDecimalFormat* ProcessorState::getDecimalFormat(String& name) +txDecimalFormat* ProcessorState::getDecimalFormat(const txExpandedName& aName) { - return (txDecimalFormat*)decimalFormats.get(name); + txDecimalFormat* format = (txDecimalFormat*)mDecimalFormats.get(aName); + if (!format && !aName.mLocalName && + aName.mNamespaceID == kNameSpaceID_None) + return &mDefaultDecimalFormat; + return format; } /** @@ -1006,11 +1027,11 @@ nsresult ProcessorState::resolveFunctionCall(txAtom* aName, PRInt32 aID, return NS_OK; } if (CHECK_FN(key)) { - aFunction = new txKeyFunctionCall(this); + aFunction = new txKeyFunctionCall(this, aElem); return NS_OK; } if (CHECK_FN(formatNumber)) { - aFunction = new txFormatNumberFunctionCall(this); + aFunction = new txFormatNumberFunctionCall(this, aElem); return NS_OK; } if (CHECK_FN(current)) { @@ -1081,9 +1102,11 @@ ProcessorState::XMLSpaceMode ProcessorState::getXMLSpaceMode(Node* aNode) } ProcessorState::ImportFrame::ImportFrame(ImportFrame* aFirstNotImported) + : mNamedTemplates(MB_FALSE), + mMatchableTemplates(MB_TRUE), + mNamedAttributeSets(MB_TRUE), + mFirstNotImported(aFirstNotImported) { - mNamedAttributeSets.setObjectDeletion(MB_TRUE); - mFirstNotImported = aFirstNotImported; } ProcessorState::ImportFrame::~ImportFrame() @@ -1094,22 +1117,15 @@ ProcessorState::ImportFrame::~ImportFrame() delete (txNameTestItem*)whiteIter.next(); // Delete templates in mMatchableTemplates - StringList* templKeys = mMatchableTemplates.keys(); - if (templKeys) { - StringListIterator keysIter(templKeys); - String* key; - while ((key = keysIter.next())) { - txList* templList = (txList*)mMatchableTemplates.get(*key); - txListIterator templIter(templList); - MatchableTemplate* templ; - while ((templ = (MatchableTemplate*)templIter.next())) { - delete templ->mMatch; - delete templ; - } - delete templList; + txExpandedNameMap::iterator iter(mMatchableTemplates); + while (iter.next()) { + txListIterator templIter((txList*)iter.value()); + MatchableTemplate* templ; + while ((templ = (MatchableTemplate*)templIter.next())) { + delete templ->mMatch; + delete templ; } } - delete templKeys; } /* diff --git a/extensions/transformiix/source/xslt/ProcessorState.h b/extensions/transformiix/source/xslt/ProcessorState.h index 03bffd09032..4198f6341c1 100644 --- a/extensions/transformiix/source/xslt/ProcessorState.h +++ b/extensions/transformiix/source/xslt/ProcessorState.h @@ -39,9 +39,10 @@ #include "txOutputFormat.h" #include "Map.h" #include "txIXPathContext.h" +#include "txExpandedNameMap.h" +#include "XSLTFunctions.h" class txXSLKey; -class txDecimalFormat; /** * Class used for keeping the current state of the XSL Processor @@ -71,17 +72,17 @@ public: ~ImportFrame(); // Map of named templates - NamedMap mNamedTemplates; + txExpandedNameMap mNamedTemplates; // Map of template modes, each item in the map is a list // of templates - NamedMap mMatchableTemplates; + txExpandedNameMap mMatchableTemplates; // List of whitespace preserving and stripping nametests txList mWhiteNameTests; // Map of named attribute sets - NamedMap mNamedAttributeSets; + txExpandedNameMap mNamedAttributeSets; // Output format, as specified by the xsl:output elements txOutputFormat mOutputFormat; @@ -128,7 +129,7 @@ public: * Returns the AttributeSet associated with the given name * or null if no AttributeSet is found **/ - NodeSet* getAttributeSet(const String& aName); + NodeSet* getAttributeSet(const txExpandedName& aName); /** * Returns the source node currently being processed @@ -139,7 +140,7 @@ public: * Returns the template associated with the given name, or * null if not template is found */ - Element* getNamedTemplate(String& aName); + Element* getNamedTemplate(const txExpandedName& aName); /** * Returns the OutputFormat which contains information on how @@ -203,8 +204,11 @@ public: * @return root-node of found template, null if none is found */ Node* findTemplate(Node* aNode, - const String& aMode, - ImportFrame** aImportFrame); + const txExpandedName& aMode, + ImportFrame** aImportFrame) + { + return findTemplate(aNode, aMode, 0, aImportFrame); + } /* * Find template in specified mode matching the supplied node. Only search @@ -218,7 +222,7 @@ public: * @return root-node of found template, null if none is found */ Node* findTemplate(Node* aNode, - const String& aMode, + const txExpandedName& aMode, ImportFrame* aImportedBy, ImportFrame** aImportFrame); @@ -227,7 +231,7 @@ public: */ struct TemplateRule { ImportFrame* mFrame; - const String* mMode; + const txExpandedName* mMode; NamedMap* mParams; }; @@ -274,7 +278,7 @@ public: * Returns the key with the supplied name * returns NULL if no such key exists **/ - txXSLKey* getKey(String& keyName); + txXSLKey* getKey(txExpandedName& keyName); /* * Adds a decimal format. Returns false if the format already exists @@ -285,7 +289,7 @@ public: /** * Returns a decimal format or NULL if no such format exists. **/ - txDecimalFormat* getDecimalFormat(String& name); + txDecimalFormat* getDecimalFormat(const txExpandedName& name); /* * Virtual methods from txIEvalContext @@ -372,18 +376,17 @@ private: /** * The set of all available keys **/ - NamedMap xslKeys; + txExpandedNameMap mXslKeys; /* - * A list of all avalible decimalformats + * The set of all avalible decimalformats */ - NamedMap decimalFormats; + txExpandedNameMap mDecimalFormats; /* - * bool indicating if the default decimal format has been explicitly set - * by the stylesheet + * Default decimal-format */ - MBool defaultDecimalFormatSet; + txDecimalFormat mDefaultDecimalFormat; /* * List of hashes with parsed expression. Every listitem holds the diff --git a/extensions/transformiix/source/xslt/XSLTProcessor.cpp b/extensions/transformiix/source/xslt/XSLTProcessor.cpp index b9723b7dfbb..1d638737e4a 100644 --- a/extensions/transformiix/source/xslt/XSLTProcessor.cpp +++ b/extensions/transformiix/source/xslt/XSLTProcessor.cpp @@ -1018,14 +1018,16 @@ void XSLTProcessor::process(Node* node, return; ProcessorState::ImportFrame *frame; - Node* xslTemplate = ps->findTemplate(node, mode, &frame); - processMatchedTemplate(xslTemplate, node, 0, NULL_STRING, frame, ps); + txExpandedName nullMode; + Node* xslTemplate = ps->findTemplate(node, nullMode, &frame); + processMatchedTemplate(xslTemplate, node, 0, nullMode, frame, ps); } //-- process void XSLTProcessor::processAction(Node* aNode, Node* aXSLTAction, ProcessorState* aPs) { + nsresult rv = NS_OK; NS_ASSERTION(aXSLTAction, "We need an action to process."); if (!aXSLTAction) return; @@ -1152,9 +1154,20 @@ void XSLTProcessor::processAction(Node* aNode, // Process xsl:with-param elements NamedMap* actualParams = processParameters(actionElement, aNode, aPs); - String mode; - actionElement->getAttr(txXSLTAtoms::mode, - kNameSpaceID_None, mode); + // Get mode + String modeStr; + txExpandedName mode; + if (actionElement->getAttr(txXSLTAtoms::mode, + kNameSpaceID_None, modeStr)) { + rv = mode.init(modeStr, actionElement, MB_FALSE); + if (NS_FAILED(rv)) { + String err("malformed mode-name in xsl:apply-templates"); + aPs->receiveError(err); + TX_IF_RELEASE_ATOM(localName); + delete actualParams; + return; + } + } txNodeSetContext evalContext(nodeSet, aPs); txIEvalContext* priorEC = @@ -1255,16 +1268,20 @@ void XSLTProcessor::processAction(Node* aNode, } // xsl:call-template else if (localName == txXSLTAtoms::callTemplate) { - String templateName; - if (actionElement->getAttr(txXSLTAtoms::name, - kNameSpaceID_None, templateName)) { + String nameStr; + txExpandedName templateName; + actionElement->getAttr(txXSLTAtoms::name, + kNameSpaceID_None, nameStr); + + rv = templateName.init(nameStr, actionElement, MB_FALSE); + if (NS_SUCCEEDED(rv)) { Element* xslTemplate = aPs->getNamedTemplate(templateName); if (xslTemplate) { #ifdef PR_LOGGING char *nameBuf = 0, *uriBuf = 0; PR_LOG(txLog::xslt, PR_LOG_DEBUG, ("CallTemplate, Name %s, Stylesheet %s\n", - (nameBuf = templateName.toCharArray()), + (nameBuf = nameStr.toCharArray()), (uriBuf = xslTemplate->getBaseURI().toCharArray()))); delete nameBuf; delete uriBuf; @@ -1275,7 +1292,7 @@ void XSLTProcessor::processAction(Node* aNode, } } else { - String err("missing required name attribute for xsl:call-template"); + String err("missing or malformed name in xsl:call-template"); aPs->receiveError(err, NS_ERROR_FAILURE); } } @@ -1507,7 +1524,6 @@ void XSLTProcessor::processAction(Node* aNode, #ifdef TX_EXE cout << "xsl:message - "<< message << endl; #else - nsresult rv; nsCOMPtr consoleSvc = do_GetService("@mozilla.org/consoleservice;1", &rv); NS_ASSERTION(NS_SUCCEEDED(rv), "xsl:message couldn't get console service"); @@ -1640,6 +1656,7 @@ void XSLTProcessor::processAction(Node* aNode, **/ void XSLTProcessor::processAttributeSets(Element* aElement, Node* aNode, ProcessorState* aPs) { + nsresult rv = NS_OK; String names; PRInt32 namespaceID; if (aElement->getNamespaceID() == kNameSpaceID_XSLT) @@ -1651,14 +1668,24 @@ void XSLTProcessor::processAttributeSets(Element* aElement, Node* aNode, Process // Split names txTokenizer tokenizer(names); - String name; + String nameStr; while (tokenizer.hasMoreTokens()) { - tokenizer.nextToken(name); + tokenizer.nextToken(nameStr); + txExpandedName name; + rv = name.init(nameStr, aElement, MB_FALSE); + if (NS_FAILED(rv)) { + String err("missing or malformed name in use-attribute-sets"); + aPs->receiveError(err); + return; + } + txStackIterator attributeSets(&mAttributeSetStack); while (attributeSets.hasNext()) { - String* test = (String*)attributeSets.next(); - if (test->isEqual(name)) + if (name == *(txExpandedName*)attributeSets.next()) { + String err("circular inclusion detected in use-attribute-sets"); + aPs->receiveError(err); return; + } } NodeSet* attSet = aPs->getAttributeSet(name); @@ -1835,7 +1862,7 @@ void XSLTProcessor::processTemplate(Node* node, Node* xslTemplate, ProcessorStat void XSLTProcessor::processMatchedTemplate(Node* aXslTemplate, Node* aNode, NamedMap* aParams, - const String& aMode, + const txExpandedName& aMode, ProcessorState::ImportFrame* aFrame, ProcessorState* aPs) { @@ -1864,7 +1891,7 @@ void XSLTProcessor::processMatchedTemplate(Node* aXslTemplate, **/ void XSLTProcessor::processDefaultTemplate(Node* node, ProcessorState* ps, - const String& mode) + const txExpandedName& mode) { NS_ASSERTION(node, "context node is NULL in call to XSLTProcessor::processTemplate!"); diff --git a/extensions/transformiix/source/xslt/XSLTProcessor.h b/extensions/transformiix/source/xslt/XSLTProcessor.h index 13d0ea0c7c0..cba5eca7f49 100644 --- a/extensions/transformiix/source/xslt/XSLTProcessor.h +++ b/extensions/transformiix/source/xslt/XSLTProcessor.h @@ -298,7 +298,7 @@ private: void processMatchedTemplate(Node* aXslTemplate, Node* aNode, NamedMap* aParams, - const String& aMode, + const txExpandedName& aMode, ProcessorState::ImportFrame* aFrame, ProcessorState* aPs); /** @@ -309,7 +309,7 @@ private: **/ void processDefaultTemplate(Node* node, ProcessorState* ps, - const String& mode); + const txExpandedName& mode); void processStylesheet(Document* aSource, Document* aStylesheet, diff --git a/extensions/transformiix/source/xslt/functions/CurrentFunctionCall.cpp b/extensions/transformiix/source/xslt/functions/CurrentFunctionCall.cpp index 04de602ef6b..9d5c5f1ddb5 100644 --- a/extensions/transformiix/source/xslt/functions/CurrentFunctionCall.cpp +++ b/extensions/transformiix/source/xslt/functions/CurrentFunctionCall.cpp @@ -1,4 +1,5 @@ #include "XSLTFunctions.h" +#include "ProcessorState.h" #include "Names.h" /* diff --git a/extensions/transformiix/source/xslt/functions/DocumentFunctionCall.cpp b/extensions/transformiix/source/xslt/functions/DocumentFunctionCall.cpp index c865c2c09da..26453864de6 100644 --- a/extensions/transformiix/source/xslt/functions/DocumentFunctionCall.cpp +++ b/extensions/transformiix/source/xslt/functions/DocumentFunctionCall.cpp @@ -37,6 +37,7 @@ */ #include "XSLTFunctions.h" +#include "ProcessorState.h" #include "XMLDOMUtils.h" #include "Names.h" #include "txIXPathContext.h" diff --git a/extensions/transformiix/source/xslt/functions/SystemPropertyFunctionCall.cpp b/extensions/transformiix/source/xslt/functions/SystemPropertyFunctionCall.cpp index 80de5e2e952..401480d2263 100644 --- a/extensions/transformiix/source/xslt/functions/SystemPropertyFunctionCall.cpp +++ b/extensions/transformiix/source/xslt/functions/SystemPropertyFunctionCall.cpp @@ -1,4 +1,5 @@ #include "XSLTFunctions.h" +#include "ProcessorState.h" #include "XMLUtils.h" #include "Names.h" #include "txIXPathContext.h" diff --git a/extensions/transformiix/source/xslt/functions/XSLTFunctions.h b/extensions/transformiix/source/xslt/functions/XSLTFunctions.h index 27f87ad856c..b7e7e6a689c 100644 --- a/extensions/transformiix/source/xslt/functions/XSLTFunctions.h +++ b/extensions/transformiix/source/xslt/functions/XSLTFunctions.h @@ -34,10 +34,12 @@ #include "Expr.h" #include "ExprResult.h" #include "TxString.h" -#include "ProcessorState.h" #include "Map.h" +#include "NamedMap.h" #include "List.h" +#include "txXSLTPatterns.h" +class ProcessorState; /** * The definition for the XSLT document() function **/ @@ -70,7 +72,7 @@ public: /* * Creates a new key() function call */ - txKeyFunctionCall(ProcessorState* aPs); + txKeyFunctionCall(ProcessorState* aPs, Node* aQNameResolveNode); /* * Evaluates a key() xslt-functioncall. First argument is name of key @@ -82,6 +84,7 @@ public: private: ProcessorState* mProcessorState; + Node* mQNameResolveNode; }; /* @@ -181,7 +184,7 @@ public: /** * Creates a new format-number() function call **/ - txFormatNumberFunctionCall(ProcessorState* aPs); + txFormatNumberFunctionCall(ProcessorState* aPs, Node* aQNameResolveNode); /** * Virtual function from FunctionCall @@ -202,6 +205,7 @@ private: }; ProcessorState* mPs; + Node* mQNameResolveNode; }; /** diff --git a/extensions/transformiix/source/xslt/functions/txFormatNumberFunctionCall.cpp b/extensions/transformiix/source/xslt/functions/txFormatNumberFunctionCall.cpp index efae7aa06ce..bf4d885b7f6 100644 --- a/extensions/transformiix/source/xslt/functions/txFormatNumberFunctionCall.cpp +++ b/extensions/transformiix/source/xslt/functions/txFormatNumberFunctionCall.cpp @@ -37,6 +37,7 @@ * ***** END LICENSE BLOCK ***** */ #include "XSLTFunctions.h" +#include "ProcessorState.h" #include "primitives.h" #include "Names.h" #include "txIXPathContext.h" @@ -58,10 +59,12 @@ const UNICODE_CHAR txFormatNumberFunctionCall::FORMAT_QUOTE = '\''; /* * Creates a new format-number function call */ -txFormatNumberFunctionCall::txFormatNumberFunctionCall(ProcessorState* aPs) : - FunctionCall(FORMAT_NUMBER_FN) +txFormatNumberFunctionCall::txFormatNumberFunctionCall(ProcessorState* aPs, + Node* aQNameResolveNode) + : FunctionCall(FORMAT_NUMBER_FN), + mPs(aPs), + mQNameResolveNode(aQNameResolveNode) { - mPs = aPs; } /* @@ -73,6 +76,7 @@ txFormatNumberFunctionCall::txFormatNumberFunctionCall(ProcessorState* aPs) : */ ExprResult* txFormatNumberFunctionCall::evaluate(txIEvalContext* aContext) { + nsresult rv = NS_OK; if (!requireParams(2, 3, aContext)) return new StringResult(); @@ -81,12 +85,17 @@ ExprResult* txFormatNumberFunctionCall::evaluate(txIEvalContext* aContext) double value; String formatStr; - String formatName; + txExpandedName formatName; value = evaluateToNumber((Expr*)iter.next(), aContext); evaluateToString((Expr*)iter.next(), aContext, formatStr); - if (iter.hasNext()) - evaluateToString((Expr*)iter.next(), aContext, formatName); + if (iter.hasNext()) { + String formatQName; + evaluateToString((Expr*)iter.next(), aContext, formatQName); + rv = formatName.init(formatQName, mQNameResolveNode, MB_FALSE); + if (NS_FAILED(rv)) + formatName.mNamespaceID = kNameSpaceID_Unknown; + } txDecimalFormat* format = mPs->getDecimalFormat(formatName); if (!format) { diff --git a/extensions/transformiix/source/xslt/functions/txKeyFunctionCall.cpp b/extensions/transformiix/source/xslt/functions/txKeyFunctionCall.cpp index b2db472b14a..9f3c07c8ea0 100644 --- a/extensions/transformiix/source/xslt/functions/txKeyFunctionCall.cpp +++ b/extensions/transformiix/source/xslt/functions/txKeyFunctionCall.cpp @@ -19,6 +19,7 @@ */ #include "XSLTFunctions.h" +#include "ProcessorState.h" #include "Names.h" #include "XMLDOMUtils.h" #include "txSingleNodeContext.h" @@ -31,10 +32,12 @@ /* * Creates a new key function call */ -txKeyFunctionCall::txKeyFunctionCall(ProcessorState* aPs) : - FunctionCall(KEY_FN) +txKeyFunctionCall::txKeyFunctionCall(ProcessorState* aPs, + Node* aQNameResolveNode) : + FunctionCall(KEY_FN), + mProcessorState(aPs), + mQNameResolveNode(aQNameResolveNode) { - mProcessorState = aPs; } /* @@ -57,11 +60,17 @@ ExprResult* txKeyFunctionCall::evaluate(txIEvalContext* aContext) } txListIterator iter(¶ms); - String keyName; - evaluateToString((Expr*)iter.next(), aContext, keyName); + String keyQName; + evaluateToString((Expr*)iter.next(), aContext, keyQName); Expr* param = (Expr*) iter.next(); - txXSLKey* key = mProcessorState->getKey(keyName); + txExpandedName keyName; + txXSLKey* key = 0; + nsresult rv = keyName.init(keyQName, mQNameResolveNode, MB_FALSE); + if (NS_SUCCEEDED(rv)) { + key = mProcessorState->getKey(keyName); + } + if (!key) { String err("No key with that name in: "); toString(err); diff --git a/extensions/transformiix/source/xslt/txPatternParser.cpp b/extensions/transformiix/source/xslt/txPatternParser.cpp index 7077631eef3..3ffa190357d 100644 --- a/extensions/transformiix/source/xslt/txPatternParser.cpp +++ b/extensions/transformiix/source/xslt/txPatternParser.cpp @@ -250,7 +250,6 @@ nsresult txPatternParser::createKeyPattern(ExprLexer& aLexer, ProcessorState* aPs, txPattern*& aPattern) { - nsresult rv = NS_OK; // check for '(' Literal, Literal ')' if (aLexer.nextToken()->type != Token::L_PAREN && aLexer.peek()->type != Token::LITERAL) @@ -262,7 +261,19 @@ nsresult txPatternParser::createKeyPattern(ExprLexer& aLexer, const String& value = aLexer.nextToken()->value; if (aLexer.nextToken()->type != Token::R_PAREN) return NS_ERROR_XPATH_PARSE_FAILED; - aPattern = new txKeyPattern(aPs, key, value); + + if (!XMLUtils::isValidQName(key)) + return NS_ERROR_XPATH_PARSE_FAILED; + txAtom *prefix = 0, *localName = 0; + PRInt32 namespaceID; + nsresult rv = resolveQName(key, prefix, aContext, localName, namespaceID); + if (NS_FAILED(rv)) + return rv; + + aPattern = new txKeyPattern(aPs, prefix, localName, namespaceID, value); + TX_IF_RELEASE_ATOM(prefix); + TX_RELEASE_ATOM(localName); + return aPattern ? NS_OK : NS_ERROR_OUT_OF_MEMORY; } diff --git a/extensions/transformiix/source/xslt/txXSLTPatterns.cpp b/extensions/transformiix/source/xslt/txXSLTPatterns.cpp index 0ce5f65bd2b..da66f537c51 100644 --- a/extensions/transformiix/source/xslt/txXSLTPatterns.cpp +++ b/extensions/transformiix/source/xslt/txXSLTPatterns.cpp @@ -40,6 +40,7 @@ #include "txNodeSetContext.h" #include "txForwardContext.h" #include "XSLTFunctions.h" +#include "ProcessorState.h" #ifndef TX_EXE #include "nsReadableUtils.h" #include "nsIContent.h" @@ -459,7 +460,14 @@ void txKeyPattern::toString(String& aDest) aDest.append("txKeyPattern{"); #endif aDest.append("key('"); - aDest.append(mName); + String tmp; + if (mPrefix) { + TX_GET_ATOM_STRING(mPrefix, tmp); + aDest.append(tmp); + aDest.append(':'); + } + TX_GET_ATOM_STRING(mName.mLocalName, tmp); + aDest.append(tmp); aDest.append(", "); aDest.append(mValue); aDest.append("')"); diff --git a/extensions/transformiix/source/xslt/txXSLTPatterns.h b/extensions/transformiix/source/xslt/txXSLTPatterns.h index d9c0ee865ff..54973d7af57 100644 --- a/extensions/transformiix/source/xslt/txXSLTPatterns.h +++ b/extensions/transformiix/source/xslt/txXSLTPatterns.h @@ -40,6 +40,7 @@ #define TX_XSLT_PATTERNS_H #include "Expr.h" +#include "XMLUtils.h" class ProcessorState; class txPattern : public TxObject @@ -175,9 +176,10 @@ private: class txKeyPattern : public txPattern { public: - txKeyPattern(ProcessorState* aPs, const String& aName, - const String& aValue) - : mProcessorState(aPs), mName(aName), mValue(aValue) + txKeyPattern(ProcessorState* aPs, txAtom* aPrefix, txAtom* aLocalName, + PRInt32 aNSID, const String& aValue) + : mProcessorState(aPs), mName(aNSID, aLocalName), mPrefix(aPrefix), + mValue(aValue) { } @@ -187,7 +189,9 @@ public: private: ProcessorState* mProcessorState; - String mName, mValue; + txExpandedName mName; + txAtom* mPrefix; + String mValue; }; class txStepPattern : public PredicateList, public txPattern