in xsec/canon/XSECC14n20010315.cpp [924:1621]
XMLSize_t XSECC14n20010315::processNextNode() {
// The information currently in the buffer has all been used. We now process the
// next node.
DOMNode *next; // For working (had *ns)
DOMNamedNodeMap *tmpAtts; // " "
safeBuffer currentName(128), currentValue(1024), sbWork;
bool done, xmlnsFound;
if (m_allNodesDone) {
return 0; // No bytes copied because nothing more to be done
}
// Always zeroise buffers to make work simpler
m_bufferLength = m_bufferPoint = 0;
m_buffer.sbStrcpyIn("");
// Find out if this is a node to process
bool processNode;
int nodeT;
if (mp_nextNode == 0) {
// Dummy element - we need to insert a default namespace
nodeT = DOMNode::ATTRIBUTE_NODE;
processNode = true;
}
else {
processNode = ((!m_XPathSelection) || (m_XPathMap.hasNode(mp_nextNode)));
nodeT = mp_nextNode->getNodeType();
}
switch (nodeT) {
case DOMNode::DOCUMENT_NODE : // Start of a document
// Check if finished
if (m_returnedFromChild) {
// All done!
m_allNodesDone = true;
return 0;
}
// In c14n we don't actually do anything for a document node except
// process the childeren
mp_firstElementNode = ((DOMDocument *) mp_nextNode)->getDocumentElement();
next = mp_nextNode->getFirstChild();
if (next == NULL) {
// Empty document?
m_allNodesDone = true;
}
mp_nextNode = next;
m_bufferLength = m_bufferPoint = 0; // To ensure nobody copies "nothing"
return 0;
case DOMNode::DOCUMENT_TYPE_NODE : // Ignore me
m_returnedFromChild = true;
m_buffer.sbStrcpyIn("");
break;
case DOMNode::PROCESSING_INSTRUCTION_NODE : // Just print
if (processNode) {
if ((mp_nextNode->getParentNode() == mp_doc) && m_firstElementProcessed) {
// this is a top level node and first element done
m_buffer.sbStrcpyIn("\x00A<?");
}
else
m_buffer.sbStrcpyIn("<?");
m_formatBuffer << (*mp_formatter << mp_nextNode->getNodeName());
m_buffer.sbStrcatIn(m_formatBuffer);
m_formatBuffer << (*mp_formatter << ((DOMProcessingInstruction *) mp_nextNode)->getData());
if (m_formatBuffer.sbStrlen() > 0) {
m_buffer.sbStrcatIn(" ");
m_buffer.sbStrcatIn(m_formatBuffer);
}
m_buffer.sbStrcatIn("?>");
if ((mp_nextNode->getParentNode() == mp_doc) && !m_firstElementProcessed) {
// this is a top level node and first element done
m_buffer.sbStrcatIn("\x00A");
}
}
// Node fully processed
m_returnedFromChild = true;
break;
case DOMNode::COMMENT_NODE : // Just print out
if (processNode && m_processComments) {
if ((mp_nextNode->getParentNode() == mp_doc) && m_firstElementProcessed) {
// this is a top level node and first element done
m_buffer.sbStrcpyIn("\x00A<!--");
}
else
m_buffer.sbStrcpyIn("<!--");
m_formatBuffer << (*mp_formatter << mp_nextNode->getNodeValue());
if (m_formatBuffer.sbStrlen() > 0) {
m_buffer.sbStrcatIn(m_formatBuffer);
}
m_buffer.sbStrcatIn("-->");
if ((mp_nextNode->getParentNode() == mp_doc) && !m_firstElementProcessed) {
// this is a top level node and first element done
m_buffer.sbStrcatIn("\x00A");
}
}
m_returnedFromChild = true; // Fool the tree processor
break;
case DOMNode::CDATA_SECTION_NODE :
case DOMNode::TEXT_NODE : // Straight copy for now
if (processNode) {
m_formatBuffer << (*mp_formatter << mp_nextNode->getNodeValue());
// Do c14n cleaning on the text string
m_buffer = c14nCleanText(m_formatBuffer);
}
// Fall through
m_returnedFromChild = true; // Fool the tree processor
break;
case DOMNode::ELEMENT_NODE : // This is an element that we can easily process
// If we are going "up" then we simply close off the element
if (m_returnedFromChild) {
if (processNode) {
m_buffer.sbStrcpyIn ("</");
m_formatBuffer << (*mp_formatter << mp_nextNode->getNodeName());
m_buffer.sbStrcatIn(m_formatBuffer);
m_buffer.sbStrcatIn(">");
}
if (m_useNamespaceStack)
m_nsStack.popElement();
break;
}
if (processNode) {
m_buffer.sbStrcpyIn("<");
m_formatBuffer << (*mp_formatter << mp_nextNode->getNodeName());
m_buffer.sbStrcatIn(m_formatBuffer);
}
// We now set up for attributes and name spaces
if (m_useNamespaceStack)
m_nsStack.pushElement(mp_nextNode);
mp_attributes = NULL;
tmpAtts = mp_nextNode->getAttributes();
next = mp_nextNode;
done = false;
xmlnsFound = false;
while (!done) {
// Need to sort the attributes
XMLSize_t size;
if (tmpAtts != NULL)
size = tmpAtts->getLength();
else
size = 0;
XSECNodeListElt *toIns;
XMLSize_t i;
for (i = 0; i < size; ++i) {
// Get the name and value of the attribute
currentName << (*mp_formatter << tmpAtts->item(i)->getNodeName());
currentValue << (*mp_formatter << tmpAtts->item(i)->getNodeValue());
// Build the string used to sort this node
if ((next == mp_nextNode) && currentName.sbStrncmp("xmlns", 5) == 0) {
// Are we using the namespace stack? If so - store this for later
// processing
if (m_useNamespaceStack) {
m_nsStack.addNamespace(tmpAtts->item(i));
}
else {
// Is this the default?
if (currentName.sbStrcmp("xmlns") == 0 &&
(!m_XPathSelection || m_XPathMap.hasNode(tmpAtts->item(i))) &&
!currentValue.sbStrcmp("") == 0)
xmlnsFound = true;
// A namespace node - See if we need to output
if (checkRenderNameSpaceNode(mp_nextNode, tmpAtts->item(i))) {
// Add to the list
m_formatBuffer << (*mp_formatter << tmpAtts->item(i)->getNodeName());
if (m_formatBuffer[5] == ':')
currentName.sbStrcpyIn((char *) &m_formatBuffer[6]);
else
currentName.sbStrcpyIn("");
toIns = new XSECNodeListElt;
toIns->element = tmpAtts->item(i);
// Build and insert name space node
toIns->sortString.sbStrcpyIn(XMLNS_PREFIX);
toIns->sortString.sbStrcatIn(currentName);
// Insert node
mp_attributes = insertNodeIntoList(mp_attributes, toIns);
}
}
}
else {
// A "normal" attribute - only process if selected or no XPath or is an
// XML node from a previously un-printed Element node
bool XMLElement = (next != mp_nextNode) && (!m_exclusive) && !currentName.sbStrncmp("xml:", 4) &&
(!m_incl11 || currentName.sbStrcmp("xml:id"));
// If we have an XML element, make sure it was not printed between this
// node and the node currently being worked on
if (XMLElement) {
DOMNode *t = mp_nextNode->getParentNode();
if (m_XPathSelection && m_XPathMap.hasNode(t))
XMLElement = false;
else {
// This is a real node that we have to check
t = mp_nextNode;
while (t != next) {
DOMNamedNodeMap *ta;
XMLSize_t sz;
ta = t->getAttributes();
if (ta != NULL)
sz = ta->getLength();
else
sz = 0;
for (XMLSize_t j = 0; j < sz; ++j) {
if (strEquals(ta->item(j)->getNodeName(),
tmpAtts->item(i)->getNodeName()) == true) {
XMLElement = false;
break;
}
}
t = t->getParentNode();
}
}
}
if ((!m_XPathSelection && next == mp_nextNode) || XMLElement || ((next == mp_nextNode) && m_XPathMap.hasNode(tmpAtts->item(i)))) {
toIns = new XSECNodeListElt;
toIns->element = tmpAtts->item(i);
// First the correct prefix to ensure will be sorted
// in correct placing against XMLNS nodes
toIns->sortString.sbStrcpyIn(ATTRIBUTE_PREFIX);
// Find the namespace URI
const XMLCh * nsURI =
tmpAtts->item(i)->getNamespaceURI();
if (nsURI == NULL) {
toIns->sortString.sbStrcatIn(NOURI_PREFIX);
}
else {
m_formatBuffer << (*mp_formatter << nsURI);
toIns->sortString.sbStrcatIn(HAVEURI_PREFIX);
toIns->sortString.sbStrcatIn(m_formatBuffer);
}
// Append the local name as the secondary key
const XMLCh * ln = tmpAtts->item(i)->getNodeName();
int index = XMLString::indexOf(ln, chColon);
if (index >= 0)
ln = &ln[index+1];
m_formatBuffer << (*mp_formatter << ln);
toIns->sortString.sbStrcatIn(m_formatBuffer);
// Insert node
mp_attributes = insertNodeIntoList(mp_attributes, toIns);
} /* else (sbStrCmp xmlns) */
}
} /* for */
#if 1
// Now go upwards and find parent for xml name spaces
if (processNode && (m_XPathSelection || mp_nextNode == mp_firstElementNode)) {
next = next->getParentNode();
if (next == 0) // || NodeInList(mp_XPathMap, next))
done = true;
else
tmpAtts = next->getAttributes();
}
else
#endif
done = true;
} /* while tmpAtts != NULL */
// Now add namespace nodes - but only if we are using the namespace stack
// (They have already been added otherwise
if (m_useNamespaceStack) {
DOMNode * nsnode = m_nsStack.getFirstNamespace();
while (nsnode != NULL) {
// Get the name and value of the attribute
currentName << (*mp_formatter << nsnode->getNodeName());
currentValue << (*mp_formatter << nsnode->getNodeValue());
// Is this the default?
if (currentName.sbStrcmp("xmlns") == 0 &&
(!m_XPathSelection || m_XPathMap.hasNode(nsnode)) &&
!currentValue.sbStrcmp("") == 0)
xmlnsFound = true;
// A namespace node - See if we need to output
if (checkRenderNameSpaceNode(mp_nextNode, nsnode)) {
// Add to the list
XSECNodeListElt *toIns;
m_formatBuffer << (*mp_formatter << nsnode->getNodeName());
if (m_formatBuffer[5] == ':')
currentName.sbStrcpyIn((char *) &m_formatBuffer[6]);
else
currentName.sbStrcpyIn("");
toIns = new XSECNodeListElt;
toIns->element = nsnode;
// Build and insert name space node
toIns->sortString.sbStrcpyIn(XMLNS_PREFIX);
toIns->sortString.sbStrcatIn(currentName);
// Insert node
mp_attributes = insertNodeIntoList(mp_attributes, toIns);
// Mark as printed in the NS Stack
m_nsStack.printNamespace(nsnode, mp_nextNode);
}
nsnode = m_nsStack.getNextNamespace();
}
// Fix for bug#47353, make sure we set xmlnsFound regardless of what the printing process saw.
if (!xmlnsFound)
xmlnsFound = m_nsStack.isNonEmptyDefaultNS();
} /* if (m_useNamespaceStack) */
// Check to see if we add xmlns=""
if (processNode && !xmlnsFound && mp_nextNode != mp_firstElementNode) {
// Is this exclusive?
safeBuffer sbLocalName("");
if (m_exclusiveDefault) {
if (visiblyUtilises(mp_nextNode, sbLocalName)) {
// May have to output!
next = mp_nextNode->getParentNode();
while (next != NULL) {
if (!m_XPathSelection || m_useNamespaceStack || m_XPathMap.hasNode(next)) {
DOMNode *tmpAtt;
// An output ancestor
if (visiblyUtilises(next, sbLocalName)) {
DOMNode * nextAttParent = next;
while (nextAttParent != NULL) {
// Have a hit!
tmpAtts = nextAttParent->getAttributes();
if (tmpAtts != NULL)
tmpAtt = tmpAtts->getNamedItem(DSIGConstants::s_unicodeStrXmlns);
if (tmpAtts != NULL && tmpAtt != NULL && (!m_XPathSelection || m_useNamespaceStack || m_XPathMap.hasNode(tmpAtt))) {
// Check URI is the same
if (!strEquals(tmpAtt->getNodeValue(), "")) {
xmlnsFound = true;
nextAttParent = NULL;
}
}
else {
// Doesn't have a default namespace in the node-set
next = nextAttParent = NULL;
break;
}
if (m_useNamespaceStack && nextAttParent)
nextAttParent = nextAttParent->getParentNode();
else
nextAttParent = NULL;
}
}
}
if (next)
next = next->getParentNode();
}
}
} /* m_exclusiveDefault */
else {
//DOM_Node next;
next = mp_nextNode->getParentNode();
while (!xmlnsFound && next != NULL) {
while (next != NULL && !m_useNamespaceStack && (m_XPathSelection && !m_XPathMap.hasNode(next)))
next = next->getParentNode();
XMLSize_t size;
if (next != NULL)
tmpAtts = next->getAttributes();
if (next != NULL && tmpAtts != NULL)
size = tmpAtts->getLength();
else
size = 0;
for (XMLSize_t i = 0; i < size; ++i) {
currentName << (*mp_formatter << tmpAtts->item(i)->getNodeName());
currentValue << (*mp_formatter << tmpAtts->item(i)->getNodeValue());
if ((currentName.sbStrcmp("xmlns") == 0) &&
(m_useNamespaceStack || !m_XPathSelection || m_XPathMap.hasNode(tmpAtts->item(i)))) {
if (currentValue.sbStrcmp("") != 0) {
xmlnsFound = true;
}
else {
xmlnsFound = false;
next = NULL;
}
}
}
if (m_useNamespaceStack && next != NULL)
next = next->getParentNode();
else
next = NULL;
}
}
// Did we find a non empty namespace?
if (xmlnsFound) {
currentName.sbStrcpyIn(""); // Don't include xmlns prefix
XSECNodeListElt * toIns;
toIns = new XSECNodeListElt;
toIns->element = NULL; // To trigger the state engine
// Build and insert name space node
toIns->sortString.sbStrcpyIn(XMLNS_PREFIX);
toIns->sortString.sbStrcatIn(currentName);
// Insert node
mp_attributes = insertNodeIntoList(mp_attributes, toIns);
}
}
if (mp_attributes != NULL) {
// Now we have set up the attribute list, set next node and return!
mp_attributeParent = mp_nextNode;
mp_nextNode = mp_attributes->element;
mp_currentAttribute = mp_attributes;
m_bufferLength = m_buffer.sbStrlen();
m_bufferPoint = 0;
return m_bufferLength;
} /* attrributes != NULL */
if (processNode)
m_buffer.sbStrcatIn(">");
// Fall through to find next node
break;
case DOMNode::ATTRIBUTE_NODE : // Output attr_name="value"
// Always process an attribute node as we have already checked they should
// be printed
m_buffer.sbStrcpyIn(" ");
if (mp_nextNode != 0) {
m_formatBuffer << (*mp_formatter << mp_nextNode->getNodeName());
m_buffer.sbStrcatIn(m_formatBuffer);
m_buffer.sbStrcatIn("=\"");
m_formatBuffer << (*mp_formatter << mp_nextNode->getNodeValue());
sbWork = c14nCleanAttribute(m_formatBuffer);
m_buffer.sbStrcatIn(sbWork);
m_buffer.sbStrcatIn("\"");
}
else {
m_buffer.sbStrcatIn("xmlns");
m_buffer.sbStrcatIn("=\"");
m_buffer.sbStrcatIn("\"");
}
// Now see if next node is an attribute
mp_currentAttribute = mp_currentAttribute->next;
if (mp_currentAttribute != NULL) {
// Easy case
mp_nextNode = mp_currentAttribute->element;
m_bufferLength = m_buffer.sbStrlen();
m_bufferPoint = 0;
return m_bufferLength;
} /* if mp_currentAttributes != NULL) */
// need to clear out the node list
while (mp_attributes != NULL) {
mp_currentAttribute = mp_attributes->next;
delete mp_attributes;
mp_attributes = mp_currentAttribute;
}
mp_attributes = mp_currentAttribute = mp_firstNonNsAttribute = NULL;
// return us to the element node
mp_nextNode = mp_attributeParent;
// End the element definition
if (!m_XPathSelection || (m_XPathMap.hasNode(mp_nextNode)))
m_buffer.sbStrcatIn(">");
m_returnedFromChild = false;
break;
default:
break;
}
// A node has fallen through to the default case for finding the next node.
m_bufferLength = m_buffer.sbStrlen();;
m_bufferPoint = 0;
// Firstly, was the last piece of processing because we "came up" from a child node?
if (m_returnedFromChild) {
if (mp_nextNode == mp_startNode) {
// we have closed off the document!
m_allNodesDone = true;
return m_bufferLength;
}
if (mp_nextNode == mp_firstElementNode) {
// we have closed off the main mp_doc elt
m_firstElementProcessed = true;
}
}
else {
// Going down - so check for children nodes
next = mp_nextNode->getFirstChild();
if (next != NULL)
mp_nextNode = next;
else
// No children, so need to close this node off!
m_returnedFromChild = true;
return m_bufferLength;
}
// If we get here all childeren (if there are any) are done
next = mp_nextNode->getNextSibling();
if (next != NULL) {
m_returnedFromChild = false;
mp_nextNode = next;
return m_bufferLength;
}
// No more nodes at this level either!
mp_nextNode = mp_nextNode->getParentNode();
m_returnedFromChild = true;
return m_bufferLength;
}