| /** |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| /* |
| * XSEC |
| * |
| * XSECXMLNSStack := NS Stack for simple canonicalisation |
| * |
| * $Id$ |
| * |
| */ |
| |
| |
| // XSEC |
| #include <xsec/framework/XSECDefs.hpp> |
| #include <xsec/framework/XSECError.hpp> |
| #include <xsec/utils/XSECDOMUtils.hpp> |
| #include <xsec/canon/XSECXMLNSStack.hpp> |
| |
| // Xerces |
| |
| XERCES_CPP_NAMESPACE_USE |
| |
| // -------------------------------------------------------------------------------- |
| // Holder structures |
| // -------------------------------------------------------------------------------- |
| |
| typedef struct XSECNSHolderStruct { |
| |
| XERCES_CPP_NAMESPACE_QUALIFIER DOMNode * mp_ns; // Actual NS attribute |
| XERCES_CPP_NAMESPACE_QUALIFIER DOMNode * mp_owner; // Owner Element |
| |
| struct XSECNSHolderStruct * mp_hides; // WHat does this NS hide? |
| struct XSECNSHolderStruct * mp_next; // Next in list |
| |
| XERCES_CPP_NAMESPACE_QUALIFIER DOMNode * mp_printed; // Node at which it was printed |
| |
| bool m_isDefault; // Is this a default NS? |
| |
| } XSECNSHolder; |
| |
| typedef struct XSECNSElementStruct { |
| |
| XERCES_CPP_NAMESPACE_QUALIFIER DOMNode * mp_elt; // Element |
| struct XSECNSHolderStruct * mp_firstNS; // WHat does this NS hide? |
| |
| } XSECNSElement; |
| |
| // -------------------------------------------------------------------------------- |
| // Construct/Destruct |
| // -------------------------------------------------------------------------------- |
| |
| |
| XSECXMLNSStack::XSECXMLNSStack() { |
| |
| } |
| |
| XSECXMLNSStack::~XSECXMLNSStack() { |
| |
| // Need to iterate through the Stack to |
| XSECNSElement * t; |
| XSECNSHolder * u, *v; |
| |
| while (m_elements.size() > 0) { |
| t = m_elements.top(); |
| u = t->mp_firstNS; |
| while (u != NULL) { |
| v = u->mp_next; |
| delete u; |
| u = v; |
| } |
| delete t; |
| m_elements.pop(); |
| } |
| } |
| |
| |
| // -------------------------------------------------------------------------------- |
| // Stack Functions |
| // -------------------------------------------------------------------------------- |
| void XSECXMLNSStack::pushElement(XERCES_CPP_NAMESPACE_QUALIFIER DOMNode * elt) { |
| |
| XSECNSElement * t; |
| XSECnew(t, XSECNSElement); |
| |
| t->mp_elt = elt; |
| t->mp_firstNS = NULL; |
| |
| m_elements.push(t); |
| |
| } |
| |
| void XSECXMLNSStack::popElement() { |
| |
| // First - are there any namespaces to remove from the currently visible list? |
| XSECNSHolder * t, *u; |
| XSECNSElement * e = m_elements.top(); |
| |
| // Iterate through the current namespaces vector |
| XSECNSHolderVectorType::iterator it = m_currentNS.begin(); |
| |
| while (it != m_currentNS.end()) { |
| |
| t = *it; |
| if (t->mp_owner == e->mp_elt) { |
| |
| // Need to delete this |
| m_currentNS.erase(it); |
| if (t->mp_hides != NULL) { |
| m_currentNS.push_back(t->mp_hides); |
| } |
| // TODO - Fix this, it is naieve and slow |
| it = m_currentNS.begin(); |
| |
| } |
| else { |
| if (t->mp_printed == e->mp_elt) |
| t->mp_printed = NULL; |
| it++; |
| } |
| |
| } |
| |
| // OK - Now we delete the NS nodes |
| t = e->mp_firstNS; |
| while (t != NULL) { |
| u = t->mp_next; |
| delete t; |
| t = u; |
| } |
| |
| // Now delete the element holder itself |
| m_elements.pop(); |
| delete e; |
| |
| } |
| |
| |
| // -------------------------------------------------------------------------------- |
| // NS Addition |
| // -------------------------------------------------------------------------------- |
| |
| void XSECXMLNSStack::addNamespace(XERCES_CPP_NAMESPACE_QUALIFIER DOMNode * ns) { |
| |
| // Create the new entry for this node |
| XSECNSHolder * t, *u; |
| XSECnew(t, XSECNSHolder); |
| |
| t->mp_hides = NULL; |
| t->mp_next = NULL; |
| t->mp_ns = ns; |
| t->mp_owner = (m_elements.top())->mp_elt; |
| t->mp_printed = NULL; |
| |
| t->m_isDefault = strEquals(ns->getNodeName(), DSIGConstants::s_unicodeStrXmlns); |
| |
| // Does this hide something in the current namespace list? |
| XSECNSHolderVectorType::iterator it = m_currentNS.begin(); |
| |
| while (it != m_currentNS.end()) { |
| u = (*it); |
| if (strEquals(u->mp_ns->getNodeName(), ns->getNodeName())) { |
| |
| // This hides a current NS entry |
| t->mp_hides = u; |
| m_currentNS.erase(it); |
| it = m_currentNS.end(); |
| } |
| else |
| it++; |
| } |
| |
| // Now push it onto the namespace vector |
| m_currentNS.push_back(t); |
| |
| // Add me to the current element's namespaces |
| XSECNSElement * e = m_elements.top(); |
| |
| t->mp_next = e->mp_firstNS; |
| e->mp_firstNS = t; |
| |
| } |
| |
| void XSECXMLNSStack::printNamespace(DOMNode * ns, DOMNode * elt) { |
| |
| XSECNSHolder * t; |
| XSECNSHolderVectorType::iterator it = m_currentNS.begin(); |
| |
| while (it != m_currentNS.end()) { |
| t = (*it); |
| // Fix for bug#47353, go ahead and track printing of default namespaces. |
| if (t->mp_ns == ns) { // && t->m_isDefault == false) { |
| t->mp_printed = elt; |
| break; |
| } |
| it++; |
| } |
| } |
| |
| // -------------------------------------------------------------------------------- |
| // NS Searching |
| // -------------------------------------------------------------------------------- |
| |
| DOMNode * XSECXMLNSStack::getFirstNamespace(void) { |
| |
| m_currentNSIterator = m_currentNS.begin(); |
| |
| while (m_currentNSIterator != m_currentNS.end() && |
| (*m_currentNSIterator)->mp_printed != NULL) |
| m_currentNSIterator++; |
| |
| if (m_currentNSIterator != m_currentNS.end()) |
| return (*m_currentNSIterator)->mp_ns; |
| |
| return NULL; |
| |
| } |
| |
| DOMNode * XSECXMLNSStack::getNextNamespace(void) { |
| if (m_currentNSIterator == m_currentNS.end()) |
| return NULL; |
| m_currentNSIterator++; |
| while (m_currentNSIterator != m_currentNS.end() && |
| (*m_currentNSIterator)->mp_printed != NULL) |
| m_currentNSIterator++; |
| |
| if (m_currentNSIterator == m_currentNS.end()) |
| return NULL; |
| |
| return (*m_currentNSIterator)->mp_ns; |
| |
| } |
| |
| // Fix for bug#47353, explicit check for non-empty default NS decl. |
| bool XSECXMLNSStack::isNonEmptyDefaultNS(void) { |
| for (XSECNSHolderVectorType::iterator it = m_currentNS.begin(); it != m_currentNS.end(); ++it) { |
| if ((*it)->m_isDefault) { |
| const XMLCh* val = (*it)->mp_ns->getNodeValue(); |
| if (val && *val) |
| return true; |
| } |
| } |
| return false; |
| } |