All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ee.sk.xmlenc.factory.EncryptedDataSAXParser Maven / Gradle / Ivy

/*
 * EncryptedDataSAXParser.java
 * PROJECT: JDigiDoc
 * DESCRIPTION: Digi Doc functions for creating
 *	and reading encrypted documents.  Implementation using SAX parser.
 * AUTHOR:  Veiko Sinivee, S|E|B IT Partner Estonia
 *==================================================
 * Copyright (C) AS Sertifitseerimiskeskus
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * This library 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 GNU
 * Lesser General Public License for more details.
 * GNU Lesser General Public Licence is available at
 * http://www.gnu.org/copyleft/lesser.html
 *==================================================
 */
package ee.sk.xmlenc.factory;

import java.io.InputStream;
import ee.sk.digidoc.DigiDocException;
import ee.sk.digidoc.factory.SAXDigiDocException;
import ee.sk.digidoc.SignedDoc;
import ee.sk.digidoc.Base64Util;
import ee.sk.xmlenc.EncryptedData;
import ee.sk.xmlenc.EncryptedKey;
import ee.sk.xmlenc.EncryptionProperty;

import java.io.FileInputStream;
//import java.io.InputStream;

import java.util.Stack;
import org.xml.sax.SAXException;
import org.xml.sax.Attributes;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.SAXParser;
import java.security.cert.X509Certificate;

import org.apache.log4j.Logger;

/**
 * Implementation class for reading and writing
 * encrypted files using a SAX parser
 * @author  Veiko Sinivee
 * @version 1.0
 */
public class EncryptedDataSAXParser 
	extends DefaultHandler
	implements EncryptedDataParser 
{
	private Stack m_tags;
	private EncryptedData m_doc;
	private StringBuffer m_sbCollectChars;
	/** log4j logger */
	private Logger m_logger = null;
	
	
	/**
	 * Creates new EncyptedDataSAXParser
	 * and initializes the variables
	 */
	public EncryptedDataSAXParser() {
			m_tags = new Stack();
			m_doc = null;
			m_sbCollectChars = null;
			m_logger = Logger.getLogger(EncryptedDataSAXParser.class);
	}
		
	/**
	 * initializes the implementation class
	 * @see ee.sk.xmlenc.factory.EncryptedDataParser#init()
	 */
	public void init() throws DigiDocException {

	}

	/**
	 * Reads in a EncryptedData file (.cdoc)
	 * @param dencStream opened stream with EncrypyedData data
	 * The user must open and close it. 
	 * @return EncryptedData object if successfully parsed
	 * @see ee.sk.xmlenc.factory.EncryptedDataParser#readEncryptedData(java.io.InputStream)
	 */
	public EncryptedData readEncryptedData(InputStream dencStream)
		throws DigiDocException 
	{
		// Use an instance of ourselves as the SAX event handler
		EncryptedDataSAXParser handler = this;
		// Use the default (non-validating) parser
		SAXParserFactory factory = SAXParserFactory.newInstance();
		//factory.setNamespaceAware(true);
		try {
			factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
			factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
			SAXParser saxParser = factory.newSAXParser();
			saxParser.parse(dencStream, handler);
		} catch (SAXDigiDocException ex) {
			throw ex.getDigiDocException();
		} catch (Exception ex) {
			DigiDocException.handleException(ex,
				DigiDocException.ERR_PARSE_XML);
		}
		if (m_doc == null)
			throw new DigiDocException(DigiDocException.ERR_DIGIDOC_FORMAT,
				"This document is not in EncryptedData format", null);
		return m_doc;
	}

	/**
	 * Reads in a EncryptedData file
	 * @param fileName file name
	 * @return EncryptedData document object if successfully parsed
	 */
	public EncryptedData readEncryptedData(String fileName) 
		throws DigiDocException 
	{
		// Use an instance of ourselves as the SAX event handler
		EncryptedDataSAXParser handler = this;
		// Use the default (non-validating) parser
		SAXParserFactory factory = SAXParserFactory.newInstance();
		//factory.setNamespaceAware(true);
		try {
			factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
			factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
			SAXParser saxParser = factory.newSAXParser();
			FileInputStream is = new FileInputStream(fileName);
			saxParser.parse(is, handler);
			is.close();
		} catch (SAXDigiDocException ex) {
			throw ex.getDigiDocException();
		} catch (Exception ex) {
			DigiDocException.handleException(
				ex, DigiDocException.ERR_PARSE_XML);
		}
		if (m_doc == null)
			throw new DigiDocException(
				DigiDocException.ERR_DIGIDOC_FORMAT,
				"This document is not in EncryptedData format", null);
		return m_doc;
	}


	/**
	 * Start Document handler
	 */
	public void startDocument() throws SAXException {
		m_doc = null;
		m_sbCollectChars = null;
	}

	/**
	 * End Document handler
	 */
	public void endDocument() throws SAXException {
	}
	
	/**
	 * Finds the value of an atribute by name
	 * @param atts atributes
	 * @param attName name of atribute
	 * @return value of the atribute
	 */
	private String findAtributeValue(Attributes attrs, String attName) {
		String value = null;
		for (int i = 0; i < attrs.getLength(); i++) {
			String key = attrs.getQName(i);
			if (key.equals(attName) || key.indexOf(attName) != -1) {
				value = attrs.getValue(i);
				break;
			}
		}
		return value;
	}
	
	/**
	 * Checks if this document is in  format
	 * @throws SAXDigiDocException if the document is not in  format
	 */
	private void checkEncryptedData()
		throws SAXDigiDocException
	{
		if(m_doc == null)
			throw new SAXDigiDocException(DigiDocException.ERR_XMLENC_NO_ENCRYPTED_DATA, 
				"This document is not in EncryptedData format!");
	}
	
	/**
	 * Checks if the  objects exists
	 * @throws SAXDigiDocException if the objects  does not exist
	 */
	private void checkEncryptedKey(EncryptedKey key)
		throws SAXDigiDocException
	{
		if(key == null)
			throw new SAXDigiDocException(DigiDocException.ERR_XMLENC_NO_ENCRYPTED_KEY, 
				"This  object does not exist!");
	}

	/**
	 * Start Element handler
	 * @param namespaceURI namespace URI
	 * @param lName local name
	 * @param qName qualified name
	 * @param attrs attributes
	 */
	public void startElement(String namespaceURI, String lName, String qName, Attributes attrs)
		throws SAXDigiDocException 
	{
		String tName = qName;
		if(tName.indexOf(":") != -1)
			tName = qName.substring(qName.indexOf(":")+1);
		if (m_logger.isDebugEnabled())
			m_logger.debug("Start Element: "	+ tName + " qname: " + qName + " lname: "  + lName + " uri: " + namespaceURI);
		m_tags.push(tName);
		if (tName.equals("KeyName") ||
			tName.equals("CarriedKeyName") ||
			tName.equals("X509Certificate") ||
			tName.equals("CipherValue") ||
			tName.equals("EncryptionProperty") )
			m_sbCollectChars = new StringBuffer();
					
		// 
		if(tName.equals("EncryptedData")) {
		    String str = findAtributeValue(attrs, "xmlns");
		    try {
		    	m_doc = new EncryptedData(str);
		    	str = findAtributeValue(attrs, "Id");
		    	if(str != null)
		    		m_doc.setId(str);
				str = findAtributeValue(attrs, "Type");
				if(str != null)
					m_doc.setType(str);
				str = findAtributeValue(attrs, "MimeType");
				if(str != null)
					m_doc.setMimeType(str);		    		
			} catch (DigiDocException ex) {
				SAXDigiDocException.handleException(ex);
			}
		}
		// 
		if(tName.equals("EncryptionMethod")) {
			checkEncryptedData();
			if (m_tags.search("EncryptedKey") != -1) { // child of 
				EncryptedKey ekey = m_doc.getLastEncryptedKey();
				checkEncryptedKey(ekey);
				try {
					ekey.setEncryptionMethod(findAtributeValue(attrs, "Algorithm"));
				} catch (DigiDocException ex) {
					SAXDigiDocException.handleException(ex);
				}
			} else { // child of 
				try {
					m_doc.setEncryptionMethod(findAtributeValue(attrs, "Algorithm"));
				} catch (DigiDocException ex) {
					SAXDigiDocException.handleException(ex);
				}				
			}
		}
		// 
		if(tName.equals("EncryptedKey")) {
			checkEncryptedData();
			EncryptedKey ekey = new EncryptedKey();
			m_doc.addEncryptedKey(ekey);
			String str = findAtributeValue(attrs, "Recipient");
			if(str != null)
				ekey.setRecipient(str);
			str = findAtributeValue(attrs, "Id");
			if(str != null)
				ekey.setId(str);
		}
		// 
		if(tName.equals("EncryptionProperties")) {
			checkEncryptedData();
			String str =findAtributeValue(attrs, "Id");
			if(str != null)
				m_doc.setEncryptionPropertiesId(str);
		}
		// 
		if(tName.equals("EncryptionProperty")) {
			checkEncryptedData();
			EncryptionProperty eprop = new EncryptionProperty();
			m_doc.addProperty(eprop);
			String str =findAtributeValue(attrs, "Id");
			if(str != null)
				eprop.setId(str);
			str =findAtributeValue(attrs, "Target");
			if(str != null)
				eprop.setTarget(str);
			str =findAtributeValue(attrs, "Name");
			try {
				if(str != null)
					eprop.setName(str);
			} catch (DigiDocException ex) {
				SAXDigiDocException.handleException(ex);
			}
		}
	}
	
	/**
	 * End Element handler
	 * @param namespaceURI namespace URI
	 * @param lName local name
	 * @param qName qualified name
	 */
	public void endElement(String namespaceURI, String sName, String qName)
		throws SAXException 
	{
		String tName = qName;
		if(tName.indexOf(":") != -1)
			tName = qName.substring(tName.indexOf(":")+1);
		if(m_logger.isDebugEnabled())
		 	m_logger.debug("End Element: " + tName);
		// remove last tag from stack
		String currTag = (String) m_tags.pop();
		//	
		if(tName.equals("KeyName")) {
			checkEncryptedData();
			EncryptedKey ekey = m_doc.getLastEncryptedKey();
			checkEncryptedKey(ekey);
			ekey.setKeyName(m_sbCollectChars.toString());
			m_sbCollectChars = null; // stop collecting
		}
		//	
		if(tName.equals("CarriedKeyName")) {
			checkEncryptedData();
			EncryptedKey ekey = m_doc.getLastEncryptedKey();
			checkEncryptedKey(ekey);
			ekey.setCarriedKeyName(m_sbCollectChars.toString());
			m_sbCollectChars = null; // stop collecting
		}
		//	
		if(tName.equals("X509Certificate")) {
			checkEncryptedData();
			EncryptedKey ekey = m_doc.getLastEncryptedKey();
			checkEncryptedKey(ekey);
			try {
				X509Certificate cert = SignedDoc.readCertificate(Base64Util.
					decode(m_sbCollectChars.toString().getBytes()));
				ekey.setRecipientsCertificate(cert);
			} catch (DigiDocException ex) {
				SAXDigiDocException.handleException(ex);
			}
			m_sbCollectChars = null; // stop collecting
		}
		//	
		if(tName.equals("CipherValue")) {
			checkEncryptedData();
			if (m_tags.search("EncryptedKey") != -1) { // child of 
				EncryptedKey ekey = m_doc.getLastEncryptedKey();
				checkEncryptedKey(ekey);
				ekey.setTransportKeyData(Base64Util.
					decode(m_sbCollectChars.toString().getBytes()));
			} else { // child of 
				m_doc.setData(Base64Util.
						decode(m_sbCollectChars.toString().getBytes()));
				if(m_doc.getMimeType() != null &&
				   m_doc.getMimeType().equals(EncryptedData.DENC_ENCDATA_MIME_ZLIB))
					m_doc.setDataStatus(EncryptedData.DENC_DATA_STATUS_ENCRYPTED_AND_COMPRESSED);
				else
					m_doc.setDataStatus(EncryptedData.DENC_DATA_STATUS_ENCRYPTED_AND_NOT_COMPRESSED); // ???			
			}
			m_sbCollectChars = null; // stop collecting
		}
		// 
		if(tName.equals("EncryptionProperty")) {
			checkEncryptedData();
			EncryptionProperty eprop = m_doc.getLastProperty();
			try {
				if(eprop != null && m_sbCollectChars != null)
				  eprop.setContent(m_sbCollectChars.toString());
			} catch (DigiDocException ex) {
				SAXDigiDocException.handleException(ex);
			}
			m_sbCollectChars = null; // stop collecting
		}
		
	}
	
	/**
	 * SAX characters event handler
	 * @param buf received bytes array
	 * @param offset offset to the array
	 * @param len length of data
	 */
	public void characters(char buf[], int offset, int len)
		throws SAXException {
		String s = new String(buf, offset, len);
		// just collect the data since it could
		// be on many lines and be processed in many events
		if (s != null) {		
			if (m_sbCollectChars != null)
				m_sbCollectChars.append(s);
		}
	}
		
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy