1 /**
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 /*
21  * XSEC
22  *
23  * XSECNameSpaceExander := Class for expanding out a document's name space axis
24  *							and then shrinking again
25  *
26  * $Id: XSECNameSpaceExpander.cpp 1833341 2018-06-11 16:25:41Z scantor $
27  *
28  */
29 
30 // XSEC Includes
31 #include <xsec/utils/XSECNameSpaceExpander.hpp>
32 #include <xsec/dsig/DSIGConstants.hpp>
33 #include <xsec/framework/XSECError.hpp>
34 
35 #include "XSECDOMUtils.hpp"
36 
37 XERCES_CPP_NAMESPACE_USE
38 
XSECNameSpaceExpander(DOMDocument * d)39 XSECNameSpaceExpander::XSECNameSpaceExpander(DOMDocument *d) {
40 
41 	mp_doc = d;
42 	mp_fragment = d->getDocumentElement();
43 	XSECnew(mp_formatter, XSECSafeBufferFormatter("UTF-8",XMLFormatter::NoEscapes,
44 												XMLFormatter::UnRep_CharRef));
45 
46 	m_expanded = false;
47 
48 }
49 
XSECNameSpaceExpander(DOMElement * f)50 XSECNameSpaceExpander::XSECNameSpaceExpander(DOMElement *f) {
51 
52 	mp_doc = NULL;
53 	mp_fragment = f;
54 	XSECnew(mp_formatter, XSECSafeBufferFormatter("UTF-8",XMLFormatter::NoEscapes,
55 												XMLFormatter::UnRep_CharRef));
56 
57 	m_expanded = false;
58 
59 }
60 
~XSECNameSpaceExpander()61 XSECNameSpaceExpander::~XSECNameSpaceExpander() {
62 
63 	if (mp_formatter != NULL)
64 		delete mp_formatter;
65 
66 }
67 
recurse(DOMElement * n)68 void XSECNameSpaceExpander::recurse(DOMElement *n) {
69 
70 	// Recursively go down the tree adding namespaces
71 
72 	DOMNode *p = n->getParentNode();
73 	if (p->getNodeType() != DOMNode::ELEMENT_NODE)
74 		return;
75 
76 	DOMNamedNodeMap *pmap = p->getAttributes();
77 	XMLSize_t psize = pmap->getLength();
78 
79 	DOMNamedNodeMap *nmap = n->getAttributes();
80 
81 	safeBuffer pname, pURI, nURI;
82 	DOMNode *finder;
83 
84 	XSECNameSpaceEntry * tmpEnt;
85 
86 	for (XMLSize_t i = 0; i < psize; i++) {
87 
88 		// Run through each parent node to find namespaces
89 		pname << (*mp_formatter << pmap->item(i)->getNodeName());
90 
91 		// See if this is an xmlns node
92 
93 		if (pname.sbStrncmp("xmlns", 5) == 0) {
94 
95 			// It is - see if it already exists
96 			finder = nmap->getNamedItem(pname.sbStrToXMLCh());
97 			if (finder == 0) {
98 
99 				// Need to add
100 				n->setAttributeNS(DSIGConstants::s_unicodeStrURIXMLNS,
101 					pmap->item(i)->getNodeName(),
102 					pmap->item(i)->getNodeValue());
103 
104 				// Add it to the list so it can be removed later
105 				XSECnew(tmpEnt, XSECNameSpaceEntry);
106 				tmpEnt->m_name.sbStrcpyIn(pname);
107 				tmpEnt->mp_node = n;
108 				tmpEnt->mp_att = nmap->getNamedItem(pname.sbStrToXMLCh());
109 				m_lst.push_back(tmpEnt);
110 
111 			}
112 
113 		}
114 
115 	}
116 
117 	// Do the children
118 
119 	DOMNode *c;
120 
121 	c = n->getFirstChild();
122 
123 	while (c != NULL) {
124 		if (c->getNodeType() == DOMNode::ELEMENT_NODE)
125 			recurse((DOMElement *) c);
126 		c = c->getNextSibling();
127 	}
128 
129 }
130 
attNodeCount(DOMElement * d)131 int attNodeCount(DOMElement * d) {
132 
133 	XMLSize_t ret;
134 
135 	ret = d->getAttributes()->getLength();
136 
137 	DOMNode *c;
138 
139 	c = d->getFirstChild();
140 
141 	while (c != NULL) {
142 
143 		if (c->getNodeType() == DOMNode::ELEMENT_NODE)
144 			ret += attNodeCount((DOMElement *) c);
145 
146 		c = c->getNextSibling();
147 
148 	}
149 
150 	return (int) ret;
151 
152 }
153 
expandNameSpaces()154 void XSECNameSpaceExpander::expandNameSpaces() {
155 
156 	if (m_expanded)
157 		return;				// Don't do this twice!
158 
159 	DOMElement	*docElt;		// The document element - do not expand it's namespaces
160 
161 	docElt = mp_fragment; //mp_doc->getDocumentElement();
162 
163 	DOMNode *c;
164 
165 	c = docElt->getFirstChild();
166 
167 	while (c != NULL) {
168 		if (c->getNodeType() == DOMNode::ELEMENT_NODE)
169 			recurse((DOMElement *) c);
170 		c = c->getNextSibling();
171 	}
172 
173 	m_expanded = true;
174 
175 }
176 
177 
deleteAddedNamespaces()178 void XSECNameSpaceExpander::deleteAddedNamespaces() {
179 
180 	NameSpaceEntryListVectorType::size_type size = m_lst.size();
181 	XSECNameSpaceEntry *e;
182 
183 	NameSpaceEntryListVectorType::size_type i;
184 
185 	for (i = 0; i < size; ++i) {
186 
187 		// Delete the element attribute, and then this node
188 		e = m_lst[i];
189 		if (e->m_name[5] == ':')
190 			e->mp_node->removeAttributeNS(DSIGConstants::s_unicodeStrURIXMLNS,
191 										MAKE_UNICODE_STRING((char *) &((e->m_name.rawBuffer())[6])));
192 		else
193 			e->mp_node->removeAttributeNS(DSIGConstants::s_unicodeStrURIXMLNS,
194 										MAKE_UNICODE_STRING((char *) e->m_name.rawBuffer()));
195 
196 		// Delete the entry
197 		delete e;
198 
199 	}
200 
201 	// Now done - empty everything
202 	m_lst.clear();
203 	m_expanded = false;
204 
205 }
206 
nodeWasAdded(DOMNode * n) const207 bool XSECNameSpaceExpander::nodeWasAdded(DOMNode *n) const {
208 
209 	NameSpaceEntryListVectorType::size_type size = m_lst.size();
210 	XSECNameSpaceEntry *e;
211 
212 	NameSpaceEntryListVectorType::size_type i;
213 	for (i = 0; i < size; ++i) {
214 
215 		// Delete the element attribute, and then this node
216 		e = m_lst[i];
217 
218 		if (e->mp_att == n)
219 			return true;
220 
221 	}
222 
223 	return false;
224 
225 }
226