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  * TXFMEnvelope := Class that calculates an Envelope with an XPath evaluator
24  *
25  * $Id: TXFMEnvelope.cpp 1833341 2018-06-11 16:25:41Z scantor $
26  *
27  */
28 
29 #include <xsec/framework/XSECException.hpp>
30 #include <xsec/transformers/TXFMEnvelope.hpp>
31 
32 #include "../utils/XSECDOMUtils.hpp"
33 
34 #include <xercesc/util/XMLString.hpp>
35 #include <xercesc/util/XMLUniDefs.hpp>
36 
37 XERCES_CPP_NAMESPACE_USE
38 
39 
TXFMEnvelope(DOMDocument * doc)40 TXFMEnvelope::TXFMEnvelope(DOMDocument *doc) :
41 TXFMBase(doc) {
42 
43 
44 }
45 
~TXFMEnvelope()46 TXFMEnvelope::~TXFMEnvelope() {
47 
48 
49 }
50 
51 // Methods to set the inputs
52 
setInput(TXFMBase * newInput)53 void TXFMEnvelope::setInput(TXFMBase *newInput) {
54 
55 	input = newInput;
56 
57 	if (newInput->getOutputType() != TXFMBase::DOM_NODES) {
58 
59 		throw XSECException(XSECException::TransformInputOutputFail, "XPath requires DOM_NODES input type");
60 
61 	}
62 
63 	// Expand if necessary
64 	//this->expandNameSpaces();
65 
66 	keepComments = input->getCommentsStatus();
67 
68 	// Set up for the new document
69 	mp_document = input->getDocument();
70 
71 	// Now work out what we have to set up in the new processing
72 
73 	TXFMBase::nodeType inputType = input->getNodeType();
74 
75 
76 	switch (inputType) {
77 
78 	case DOM_NODE_DOCUMENT :
79 
80 		mp_startNode = mp_document;
81 		break;
82 
83 	case DOM_NODE_DOCUMENT_FRAGMENT :
84 
85 		mp_startNode = input->getFragmentNode();
86 		break;
87 
88 	default :
89 
90 		throw XSECException(XSECException::EnvelopeError);	// Should never get here
91 
92 	}
93 
94 	// Ready to evaluate
95 
96 }
97 
98 
99 // Methods to get tranform output type and input requirement
100 
getInputType(void) const101 TXFMBase::ioType TXFMEnvelope::getInputType(void) const {
102 
103 	return TXFMBase::DOM_NODES;
104 
105 }
106 
getOutputType(void) const107 TXFMBase::ioType TXFMEnvelope::getOutputType(void) const {
108 
109 	return TXFMBase::DOM_NODES;
110 
111 }
112 
getNodeType(void) const113 TXFMBase::nodeType TXFMEnvelope::getNodeType(void) const {
114 
115 	return TXFMBase::DOM_NODE_XPATH_NODESET;
116 
117 }
118 
119 // Envelope (and XPath) unique
120 
addEnvelopeNode(DOMNode * startNode,XSECXPathNodeList & XPathMap,DOMNode * sigNode)121 void addEnvelopeNode(DOMNode *startNode, XSECXPathNodeList & XPathMap, DOMNode * sigNode) {
122 
123 	XSEC_USING_XERCES(DOMNamedNodeMap);
124 
125 	DOMNode *tmp;
126 	DOMNamedNodeMap *atts;
127 	XMLSize_t attsSize, i;
128 
129 	if (startNode == sigNode)
130 		return;
131 
132 	XPathMap.addNode(startNode);
133 
134 	if (startNode->getNodeType() == DOMNode::ELEMENT_NODE) {
135 
136 		atts = startNode->getAttributes();
137 		if (atts != NULL)
138 			attsSize = atts->getLength();
139 		else
140 			attsSize = 0;
141 
142 		for (i = 0; i < attsSize; ++i) {
143 
144 			tmp = atts->item(i);
145 			XPathMap.addNode(tmp);
146 
147 		}
148 
149 	}
150 
151 	// Now do any childeren
152 
153 	tmp = startNode->getFirstChild();
154 
155 	while (tmp != NULL) {
156 
157 		addEnvelopeNode(tmp, XPathMap, sigNode);
158 		tmp = tmp->getNextSibling();
159 
160 	}
161 }
162 
addEnvelopeParentNSNodes(DOMNode * startNode,XSECXPathNodeList & XPathMap)163 void addEnvelopeParentNSNodes(DOMNode *startNode, XSECXPathNodeList & XPathMap) {
164 
165 	XSEC_USING_XERCES(DOMNamedNodeMap);
166 
167 	DOMNode *tmp;
168 	DOMNamedNodeMap *atts;
169 	XMLSize_t attsSize, i;
170 
171 	if (startNode == NULL)
172 		return;
173 
174 	if (startNode->getNodeType() == DOMNode::ELEMENT_NODE) {
175 
176 		atts = startNode->getAttributes();
177 		if (atts != NULL)
178 			attsSize = atts->getLength();
179 		else
180 			attsSize = 0;
181 
182 		for (i = 0; i < attsSize; ++i) {
183 
184 			tmp = atts->item(i);
185 			if (XMLString::compareNString(tmp->getNodeName(), DSIGConstants::s_unicodeStrXmlns, 5) == 0 &&
186 				(tmp->getNodeName()[5] == chNull || tmp->getNodeName()[5] == chColon))
187 				XPathMap.addNode(tmp);
188 
189 		}
190 
191 	}
192 
193 	// Now do parent
194 	addEnvelopeParentNSNodes(startNode->getParentNode(), XPathMap);
195 
196 }
197 
evaluateEnvelope(DOMNode * t)198 void TXFMEnvelope::evaluateEnvelope(DOMNode *t) {
199 
200 	DOMNode *sigNode;
201 
202 	// Find the signature node
203 	sigNode = t->getParentNode();
204 
205 	while (sigNode != NULL && !strEquals(getDSIGLocalName(sigNode), "Signature"))
206 		sigNode = sigNode->getParentNode();
207 
208 	if (sigNode == NULL) {
209 
210 		throw XSECException(XSECException::EnvelopeError,
211 			"Unable to find signature owner of node passed to Envelope Transform");
212 
213 	}
214 
215 	// Check if sigNode is an ancestor of mp_startNode - if so, just return
216 	DOMNode * c = mp_startNode;
217 	while (c != NULL) {
218 
219 		if (c == sigNode)
220 			return;
221 
222 		c = c->getParentNode();
223 
224 	}
225 
226 	addEnvelopeNode(mp_startNode, m_XPathMap, sigNode);
227 	addEnvelopeParentNSNodes(mp_startNode->getParentNode(), m_XPathMap);
228 
229 }
230 
231 // Methods to get output data
232 
readBytes(XMLByte * const toFill,unsigned int maxToFill)233 unsigned int TXFMEnvelope::readBytes(XMLByte * const toFill, unsigned int maxToFill) {
234 
235 	return 0;
236 
237 }
238 
getDocument() const239 DOMDocument *TXFMEnvelope::getDocument() const {
240 
241 	return mp_document;
242 
243 }
244