/****************************************************************************
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
*
* The Original Code is TEAM Engine.
*
* The Initial Developer of the Original Code is Intecs SPA. Portions created by
* Intecs SPA are Copyright (C) 2008-2009, Intecs SPA. All Rights Reserved.
*
* Contributor(s):
* C. Heazel (WiSC): Added Fortify adjudication changes
*
****************************************************************************/
package com.occamlab.te.util;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.XMLConstants; // Addition for Fortify modifications
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.transform.OutputKeys;
/**
*
* @author Simone Gianfranceschi
*/
public class SoapUtils {
public static final String SOAP_V_1_1 = "1.1";
public static final String SOAP_V_1_2 = "1.2";
/**
* A method to get the SOAP message from the input stream.
*
* @param in
* the input stream to be used to get the SOAP message.
*
* @return the SOAP message
*
* @author Simone Gianfranceschi
*/
public static Document getSOAPMessage(InputStream in) throws Exception {
/*
* ByteArrayOutputStream out = new ByteArrayOutputStream(); int b; while
* ((b = in.read()) != -1) { out.write(b); }
*
* System.out.println("OUT:" + out.toString());
*/
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
// Fortify Mod: Disable entity expansion to foil External Entity Injections
dbf.setExpandEntityReferences(false);
DocumentBuilder db = dbf.newDocumentBuilder();
Document soapMessage = db.newDocument();
// Fortify Mod: prevent external entity injection
TransformerFactory tf = TransformerFactory.newInstance();
tf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
Transformer t = tf.newTransformer();
// End Fortify Mod
t.transform(new StreamSource(in), new DOMResult(soapMessage));
return soapMessage;
}
/**
* A method to extract the content of the SOAP body.
*
* @param soapMessage
* the SOAP message.
*
* @return the content of the body of the input SOAP message.
*
* @author Simone Gianfranceschi
*/
public static Document getSoapBody(Document soapMessage) throws Exception {
Element envelope = soapMessage.getDocumentElement();
Element body = DomUtils.getChildElement(DomUtils.getElementByTagName(
envelope, envelope.getPrefix() + ":Body"));
Document content = DomUtils.createDocument(body);
Element documentRoot = content.getDocumentElement();
addNSdeclarations(envelope, documentRoot);
addNSdeclarations(body, documentRoot);
return content;
}
/**
* A method to copy namespaces declarations.
*
* @param source
* the source message containing the namespaces to be copied on
* the target message.
* @param target
* the target message.
*
* @author Simone Gianfranceschi
*/
public static void addNSdeclarations(Element source, Element target)
throws Exception {
NamedNodeMap sourceAttributes = source.getAttributes();
Attr attribute;
String attributeName;
for (int i = 0; i <= sourceAttributes.getLength() - 1; i++) {
attribute = (Attr) sourceAttributes.item(i);
attributeName = attribute.getName();
if (attributeName.startsWith("xmlns")
&& !attributeName.startsWith("xmlns:soap-env")) {
// System.out.println("XMLNS:" +
// attributeName+":"+attribute.getValue());
target.setAttribute(attributeName, attribute.getValue());
}
}
}
/**
* A method to create a SOAP message and retrieve it as byte.
*
* @param version
* the SOAP version to be used (1.1 or 1.2).
* @param headerBlocks
* the list of Header Blocks to be included in the SOAP Header .
* @param body
* the XML message to be included in the SOAP BODY element.
* @param encoding
* the encoding to be used for the message creation.
*
* @return The created SOAP message as byte.
*
* @author Simone Gianfranceschi
*/
public static byte[] getSoapMessageAsByte(String version,
List headerBlocks, Element body, String encoding) throws Exception {
Document message = createSoapMessage(version, headerBlocks, body);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
TransformerFactory tf = TransformerFactory.newInstance();
// Fortify Mod: prevent external entity injection
tf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
Transformer t = tf.newTransformer();
// End Fortify Mod
t.setOutputProperty(OutputKeys.ENCODING, encoding);
t.transform(new DOMSource(message), new StreamResult(baos));
// System.out.println("SOAP MESSAGE : " + baos.toString());
return baos.toByteArray();
}
/**
* A method to create a SOAP message. The SOAP message, including the Header
* is created and returned as DOM Document.
*
* @param version
* the SOAP version to be used (1.1 or 1.2).
* @param headerBlocks
* the list of Header Blocks to be included in the SOAP Header .
* @param body
* the XML message to be included in the SOAP BODY element.
*
* @return The created SOAP message as document.
*
* @author Simone Gianfranceschi
*/
public static Document createSoapMessage(String version, List headerBlocks,
Element body) throws Exception {
Document message = null;
NodeList children = body.getChildNodes();
// Loop in order to remove dummy nodes (spaces, CR)
for (int i = 0; i < children.getLength(); i++) {
if (children.item(i).getNodeType() == Node.ELEMENT_NODE) {
if (version.equals(SOAP_V_1_1)) {
message = Soap11MessageBuilder.getSoapMessage(headerBlocks,
body);
} else {
message = Soap12MessageBuilder.getSoapMessage(headerBlocks,
body);
}
}
break;
}
return message;
}
}