blob: 349899be66ef8305e3fa345b7e31f96cc17d2392 [file]
/*
* Copyright 2005 The Apache Software Foundation.
*
* Licensed 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);
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;
}