/*
*
* Paros and its related class files.
*
* Paros is an HTTP/HTTPS proxy for assessing web application security.
* Copyright (C) 2003-2004 Chinotec Technologies Company
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the Clarified Artistic License
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Clarified Artistic License for more details.
*
* You should have received a copy of the Clarified Artistic License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// ZAP: 2012/04/23 Removed unnecessary casts.
// ZAP: 2012/05/02 Changed to set the initial capacity of a List.
// ZAP: 2013/01/23 Clean up of exception handling/logging.
// ZAP: 2013/03/03 Issue 546: Remove all template Javadoc comments
// ZAP: 2013/05/02 Re-arranged all modifiers into Java coding standard order
// ZAP: 2015/08/19 Deprecated; Issue 1804: Disable processing of XML external entities by default
package org.parosproxy.paros.common;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.apache.log4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.zaproxy.zap.utils.XmlUtils;
/**
* @deprecated (2.4.2) Use {@link org.zaproxy.zap.utils.ZapXmlConfiguration} instead.
*/
@Deprecated
public abstract class FileXML {
private static final Logger logger = Logger.getLogger(FileXML.class);
protected Document doc = null;
protected DocumentBuilder docBuilder = null;
protected DocumentBuilderFactory docBuilderFactory = null;
public FileXML(String rootElementName) {
String rootString = "<" + rootElementName + "></" + rootElementName + ">";
try {
docBuilderFactory = XmlUtils.newXxeDisabledDocumentBuilderFactory();
docBuilder = docBuilderFactory.newDocumentBuilder();
doc = docBuilder.parse(new InputSource(new StringReader(rootString)));
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
}
public Document getDocument() {
return doc;
}
/*
* Get a single element (first element) under a base element matching a tag
*/
protected Element getElement(Element base, String childTag) {
Element[] elements = getElements(base, childTag);
if (elements == null) {
return null;
} else {
return elements[0];
}
}
protected Element getElement(String tag) {
Element parent = doc.getDocumentElement();
return getElement(parent, tag);
}
protected Element getElement(String[] path) {
Element[] elements = getElements(path);
if (elements==null) {
return null;
} else {
return elements[0];
}
}
/**
* Get all elements under a base element matching a tag name
* @param base
* @param childTag
* @return
*/
protected Element[] getElements(Element base, String childTag) {
NodeList nodeList = base.getElementsByTagName(childTag);
if (nodeList.getLength() == 0) {
return null;
}
Element[] elements = new Element[nodeList.getLength()];
for (int i=0; i<nodeList.getLength(); i++) {
elements[i] = (Element) nodeList.item(i);
}
return elements;
}
protected Element[] getElements(String tagName) {
Element parent = doc.getDocumentElement();
return getElements(parent, tagName);
}
protected Element[] getElements(String[] path) {
NodeList nodeList = null;
Element element = doc.getDocumentElement();
for (int i=0; i<path.length-1; i++) {
nodeList = element.getElementsByTagName(path[i]);
if (nodeList.getLength() > 0) {
element = (Element) nodeList.item(i);
} else {
return null;
}
}
nodeList = element.getElementsByTagName(path[path.length-1]);
if (nodeList.getLength() == 0) {
return null;
}
Element[] elements = new Element[nodeList.getLength()];
for (int i=0; i<nodeList.getLength(); i++) {
elements[i] = (Element) nodeList.item(0);
}
return elements;
}
/**
Get the text in text node from the element.
@param element Element to get text from
@return Text in the text node under the element
*/
private String getText(Element element) {
try {
for (int i = 0; i < element.getChildNodes().getLength(); i++) {
Node node = element.getChildNodes().item(i);
if (node.getNodeType() == Node.TEXT_NODE) {
return node.getNodeValue();
}
}
} catch (Exception e) {
}
return "";
}
/**
* Get the value of the tag under a base element
* @param base
* @param tag
* @return
*/
protected String getValue(Element base, String tag) {
Element element = null;
String result = "";
try {
// ZAP: Removed unnecessary cast.
element = getElement(base, tag);
result = getText(element);
} catch (Exception e) {
}
return result;
}
protected String getValue(String tag) {
Element element = doc.getDocumentElement();
return getValue(element, tag);
}
protected List<String> getValues(String tag) {
// ZAP: Removed unnecessary cast.
NodeList nodeList = doc.getElementsByTagName(tag);
// ZAP: Added variable "length".
final int length = nodeList.getLength();
// ZAP: Changed to set the initial capacity.
ArrayList<String> resultList = new ArrayList<>(length);
Element element = null;
// ZAP: Changed to use the variable "length".
for (int i = 0; i < length; i++) {
element = (Element) nodeList.item(i);
resultList.add(getText(element));
}
return resultList;
}
protected abstract void parse() throws Exception;
public void readAndParseFile(String fileName) throws SAXException, IOException, Exception {
readFile(fileName);
parse();
}
protected void readFile(String fileName) throws SAXException, IOException {
// xml document processing
DocumentBuilderFactory factory = null;
DocumentBuilder builder = null;
try {
factory = XmlUtils.newXxeDisabledDocumentBuilderFactory();
factory.setValidating(false);
builder = factory.newDocumentBuilder();
//builder.setErrorHandler(new ErrorHandler() {
//});
} catch (ParserConfigurationException e) {
}
doc = builder.parse(fileName);
}
public void saveFile(String fileName) {
// DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
//factory.setNamespaceAware(true);
//factory.setValidating(true);
File file = null;
FileOutputStream outFile = null;
try {
file = new File(fileName);
outFile = new FileOutputStream(file);
// Use a Transformer for output
TransformerFactory tFactory = TransformerFactory.newInstance();
Transformer transformer = tFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(outFile);
//StreamResult result = new StreamResult(System.out);
transformer.transform(source, result);
} catch (TransformerException | IOException e) {
logger.error(e.getMessage(), e);
} finally {
if (outFile != null) {
try {
outFile.close();
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
}
}
}
public void setDocument(Document doc) throws Exception {
this.doc = doc;
parse();
}
protected void setValue(String tagName, String value) {
Element element = null;
try {
// set only the first tag
element = getElement(tagName);
if (element == null) {
// if not found, add to root element
element = doc.createElement(tagName);
doc.getDocumentElement().appendChild(element);
}
for (int i=0; i<element.getChildNodes().getLength(); i++) {
Node node = element.getChildNodes().item(i);
if (node.getNodeType() == Node.TEXT_NODE) {
node.setNodeValue(value);
return;
}
}
Node newNode = doc.createTextNode(value);
element.appendChild(newNode);
} catch (Exception e) {
}
}
protected void setValue(String[] path, String value) {
Element element = doc.getDocumentElement();
NodeList nodeList = null;
Element newElement = null;
Node newNode = null;
for (int i=0; i<path.length; i++) {
// ZAP: Removed unnecessary cast.
nodeList = doc.getElementsByTagName(path[i]);
if (nodeList.getLength() == 0) {
// create element if not found
newElement = doc.createElement(path[i]);
element.appendChild(newElement);
element = newElement;
} else {
// point to new element
element = (Element) nodeList.item(0);
}
}
// element located
try {
// search for text node and set value
for (int i = 0; i < element.getChildNodes().getLength(); i++) {
Node node = element.getChildNodes().item(i);
if (node.getNodeType() == Node.TEXT_NODE) {
node.setNodeValue(value);
return;
}
}
// if not found, create text node
newNode = doc.createTextNode(value);
element.appendChild(newNode);
} catch (Exception e) {
}
}
protected void removeElement(Element base, String tag) {
Element[] elements = getElements(base, tag);
if (elements== null) return;
for (int i=0; i<elements.length; i++) {
try {
base.removeChild(elements[i]);
} catch (Exception e) {}
}
}
protected void removeElement(String tag) {
Element base = doc.getDocumentElement();
removeElement(base, tag);
}
/**
*
* @param base
* @param tag
* @param value
* @return added element
*/
protected Element addElement(Element base, String tag, String value) {
Element element = doc.createElement(tag);
base.appendChild(element);
for (int i=0; i<element.getChildNodes().getLength(); i++) {
Node node = element.getChildNodes().item(i);
if (node.getNodeType() == Node.TEXT_NODE) {
node.setNodeValue(value);
return element;
}
}
Node newNode = doc.createTextNode(value);
element.appendChild(newNode);
return element;
}
protected Element addElement(Element base, String tag) {
Element element = doc.createElement(tag);
base.appendChild(element);
return element;
}
protected Element addElement(String tag) {
Element element = doc.createElement(tag);
doc.getDocumentElement().appendChild(element);
return element;
}
}