/* * (C) Copyright IBM Corp. 1999-2000 All rights reserved. * * US Government Users Restricted Rights Use, duplication or * disclosure restricted by GSA ADP Schedule Contract with IBM Corp. * * The program is provided "as is" without any warranty express or * implied, including the warranty of non-infringement and the implied * warranties of merchantibility and fitness for a particular purpose. * IBM will not be liable for any damages suffered by you as a result * of using the Program. In no event will IBM be liable for any * special, indirect or consequential damages or lost profits even if * IBM has been advised of the possibility of their occurrence. IBM * will not be liable for any third party claims against you. */ package asn1; import com.ibm.xml.asn1.SAXEventDumper; import com.ibm.xml.asn1.LabelSAX; import com.ibm.xml.parser.Parser; import com.ibm.xml.parser.DTD; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.Reader; import java.io.Writer; import org.apache.xerces.parsers.SAXParser; import org.xml.sax.Attributes; import org.xml.sax.ContentHandler; import org.xml.sax.ErrorHandler; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import org.xml.sax.helpers.DefaultHandler; /** * Sample of cascading LabelSAX *
 *  Usage: java asn1.LabelPKCS7 XER
 *         where XER is unlabeled XML representation of PKCS7 data
 *
 *  Limitation:
 *         Currently only SignedData is supported. See oid2ElementName() below.
 *
 *
 *  This program works as illustrated below.
 *  When LabelPKCS7 see ContentInfo.content, it "switches" the event flow
 *  the second LabelSAX that is responsible for labeling the contents.
 *  This second LabelSAX receives the name of the root element based on
 *  the contentType field of the outer data structure.  From the application
 *  point of view (SAXDump, in this case), the whole set up looks as if
 *  it is yet another SAX event source.
 *
 *
 *          ================== SAX Event Flow ===================>
 *  
 *   +------+   +--------+   +----------+    ContentInfo        +--------+   
 *   | SAX  |-->|LabelSAX|-->|LabelPKCS7|---------------------->|SAXDump |
 *   |parser|   |  #1    |   |          |--+  +--------+  +---->|        |
 *   +------+   +--------+   +----------+  |  |LabelSAX|  |     +--------+
 *                                         +->|   #2   |--+
 *                                            +--------+   
 *                                            SignedData
 * 
* * @author Hiroshi Maruyama * @author Takeshi Imamura */ public class LabelPKCS7 extends DefaultHandler { static boolean opt_d = false; static String inf; static String dtd = "pkcs7.dtd"; static String rootElement = "root..ContentInfo"; /** * Constructs an object and initializes some variables according to * the specified arguments. * * @param args arguments to this program. */ public LabelPKCS7() { // // Do nothing // } /** * Labels XER encoded ASN.1 data with given DTD * * @exception java.io.IOException - * @exception org.xml.sax.SAXException - */ private void start() throws IOException, SAXException { SAXEventDumper dump = new SAXEventDumper(); Writer out = new OutputStreamWriter(System.out); dump.setWriter(out); dump.setXMLDeclaration("1.0", null); // dump.setDoctypeDeclaration(rootElement, dtd); handler = dump; LabelSAX lsax = new LabelSAX(this); DTD d = readDTD(dtd); lsax.setDTD(d, rootElement); lsax.setEncoding("base64"); SAXParser psr = new SAXParser(); psr.setContentHandler(lsax); psr.setErrorHandler(this); psr.parse(inf); } /** * Reads a DTD from a file. * * @param name the name of the file containing a DTD. * * @return a DTD. * * @exception java.io.IOException - */ private DTD readDTD(String name) throws IOException { Parser psr = new Parser(name); psr.setErrorHandler(this); Reader in = new InputStreamReader((LabelPKCS7.class).getResourceAsStream(name)); DTD dtd = psr.readDTDStream(in); return dtd; } // // Member variables for controling filtering operations // StringBuffer buffer = null; String ContentType; ContentHandler handler; ContentHandler handlerSave; // // The following five methods implements ContentHandler // public void startDocument() throws SAXException { handler.startDocument(); } public void endDocument() throws SAXException { handler.endDocument(); } public void startElement(String uri, String localName, String name, Attributes atts) throws SAXException { try { handler.startElement(uri, localName, name, atts); if (name.equals("ContentInfo.contentType")) { this.buffer = new StringBuffer(); } else if (name.equals("ContentInfo.content")) { // // Start processing Content // 1. Create another LabelSAX // LabelSAX lsaxContents = new LabelSAX(handler); DTD d; d = readDTD(dtd); lsaxContents.setDTD(d, oid2ElementName(ContentType)); lsaxContents.setEncoding("base64"); // // 2. Redirect SAX events // handlerSave = handler; handler = lsaxContents; } } catch (IOException ioe) { ioe.printStackTrace(); } } public void endElement(String uri, String localName, String name) throws SAXException { if (name.equals("ContentInfo.contentType")) { this.ContentType = this.buffer.toString(); // System.err.println("ContentType:"+this.ContentType); this.buffer = null; } else if (name.equals("ContentInfo.content")) { // Restore handler handler = handlerSave; } handler.endElement(uri, localName, name); } public void characters(char chars[], int start, int length) throws SAXException { handler.characters(chars,start,length); if (this.buffer != null) { this.buffer.append(chars, start, length); } } /** * oid2ElementName translation table * This table should be expanded as necessary. */ String oid2ElementName(String oid) { if (oid.equals("1.2.840.113549.1.7.2")) return "root..SignedData"; return ""; } // // The following three methods implements ErrorHandler // /** * Receive notification of a warning. The warning information is * printed. * * @param exc the warning information encapsulated in a * SAX parse exception. */ public void warning(SAXParseException exc) { System.err.println("[Warning] "+getLocation(exc)+": "+exc.getMessage()); } /** * Receive notification of a recoverable error. The error * information is printed. * * @param exc the error information encapsulated in a * SAX parse exception. */ public void error(SAXParseException exc) { System.err.println("[Error] "+getLocation(exc)+": "+exc.getMessage()); } /** * Receive notification of a non-recoverable error. The error * information is printed and the exception is thrown again. * * @param exc the error information encapsulated in a * SAX parse exception. * * @exception org.xml.sax.SAXException - */ public void fatalError(SAXParseException exc) throws SAXException { System.err.println("[Fatal Error] "+getLocation(exc)+": "+exc.getMessage()); throw exc; } /** * Gets the location where the exception is thrown. * * @param exc the warning or error information * encapsulated in a SAX parse exception. */ private String getLocation(SAXParseException exc) { StringBuffer buf = new StringBuffer(); String id = exc.getSystemId(); if (id != null) { int i = id.lastIndexOf('/'); if (i != -1) { id = id.substring(i+1); } if (!id.equals("")) { buf.append(id+", "); } } buf.append(exc.getLineNumber()+", "); buf.append(exc.getColumnNumber()); return buf.toString(); } // // Main // /** * Creates this object and starts a translation. */ public static void main(String args[]) { int i=0; if (args.length<1) { usage(-1); } else if (args[0].equals("-d")) { opt_d = true; i++; } if (args.lengthstat a status of this program. */ private static void usage(int stat) { System.err.println("Usage: java asn1.LabelPKCS7 "); System.exit(stat); } }