blob: 0cf7f8ecb581ca6eb135655274286e84879d03b1 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * reserved comment block
3 * DO NOT REMOVE OR ALTER!
4 */
5
6/*
7 * Copyright 1999-2004 The Apache Software Foundation.
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 */
22package com.sun.org.apache.xml.internal.security.transforms.implementations;
23
24
25
26import java.io.BufferedInputStream;
27import java.io.IOException;
28import java.io.OutputStream;
29
30import javax.xml.parsers.DocumentBuilderFactory;
31import javax.xml.parsers.ParserConfigurationException;
32
33import com.sun.org.apache.xml.internal.security.c14n.CanonicalizationException;
34import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException;
35import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput;
36import com.sun.org.apache.xml.internal.security.transforms.TransformSpi;
37import com.sun.org.apache.xml.internal.security.transforms.TransformationException;
38import com.sun.org.apache.xml.internal.security.transforms.Transforms;
39import com.sun.org.apache.xml.internal.security.utils.Base64;
40import org.w3c.dom.Document;
41import org.w3c.dom.Element;
42import org.w3c.dom.Node;
43import org.w3c.dom.Text;
44import org.xml.sax.SAXException;
45
46
47/**
48 * Implements the <CODE>http://www.w3.org/2000/09/xmldsig#base64</CODE> decoding
49 * transform.
50 *
51 * <p>The normative specification for base64 decoding transforms is
52 * <A HREF="http://www.w3.org/TR/2001/CR-xmldsig-core-20010419/#ref-MIME">[MIME]</A>.
53 * The base64 Transform element has no content. The input
54 * is decoded by the algorithms. This transform is useful if an
55 * application needs to sign the raw data associated with the encoded
56 * content of an element. </p>
57 *
58 * <p>This transform requires an octet stream for input.
59 * If an XPath node-set (or sufficiently functional alternative) is
60 * given as input, then it is converted to an octet stream by
61 * performing operations logically equivalent to 1) applying an XPath
62 * transform with expression self::text(), then 2) taking the string-value
63 * of the node-set. Thus, if an XML element is identified by a barename
64 * XPointer in the Reference URI, and its content consists solely of base64
65 * encoded character data, then this transform automatically strips away the
66 * start and end tags of the identified element and any of its descendant
67 * elements as well as any descendant comments and processing instructions.
68 * The output of this transform is an octet stream.</p>
69 *
70 * @author Christian Geuer-Pollmann
71 * @see com.sun.org.apache.xml.internal.security.utils.Base64
72 */
73public class TransformBase64Decode extends TransformSpi {
74
75 /** Field implementedTransformURI */
76 public static final String implementedTransformURI =
77 Transforms.TRANSFORM_BASE64_DECODE;
78
79 /**
80 * Method engineGetURI
81 *
82 * @inheritDoc
83 */
84 protected String engineGetURI() {
85 return TransformBase64Decode.implementedTransformURI;
86 }
87
88 /**
89 * Method enginePerformTransform
90 *
91 * @param input
92 * @return {@link XMLSignatureInput} as the result of transformation
93 * @inheritDoc
94 * @throws CanonicalizationException
95 * @throws IOException
96 * @throws TransformationException
97 */
98 protected XMLSignatureInput enginePerformTransform(XMLSignatureInput input)
99 throws IOException, CanonicalizationException,
100 TransformationException {
101 return enginePerformTransform(input,null);
102 }
103 protected XMLSignatureInput enginePerformTransform(XMLSignatureInput input,
104 OutputStream os)
105 throws IOException, CanonicalizationException,
106 TransformationException {
107 try {
108 if (input.isElement()) {
109 Node el=input.getSubNode();
110 if (input.getSubNode().getNodeType()==Node.TEXT_NODE) {
111 el=el.getParentNode();
112 }
113 StringBuffer sb=new StringBuffer();
114 traverseElement((Element)el,sb);
115 if (os==null) {
116 byte[] decodedBytes = Base64.decode(sb.toString());
117 return new XMLSignatureInput(decodedBytes);
118 }
119 Base64.decode(sb.toString().getBytes(),os);
120 XMLSignatureInput output=new XMLSignatureInput((byte[])null);
121 output.setOutputStream(os);
122 return output;
123
124 }
125 if (input.isOctetStream() || input.isNodeSet()) {
126
127
128 if (os==null) {
129 byte[] base64Bytes = input.getBytes();
130 byte[] decodedBytes = Base64.decode(base64Bytes);
131 return new XMLSignatureInput(decodedBytes);
132 }
133 if (input.isByteArray() || input.isNodeSet()) {
134 Base64.decode(input.getBytes(),os);
135 } else {
136 Base64.decode(new BufferedInputStream(input.getOctetStreamReal())
137 ,os);
138 }
139 XMLSignatureInput output=new XMLSignatureInput((byte[])null);
140 output.setOutputStream(os);
141 return output;
142
143
144 }
145
146 try {
147 //Exceptional case there is current not text case testing this(Before it was a
148 //a common case).
149 Document doc =
150 DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(
151 input.getOctetStream());
152
153 Element rootNode = doc.getDocumentElement();
154 StringBuffer sb = new StringBuffer();
155 traverseElement(rootNode,sb);
156 byte[] decodedBytes = Base64.decode(sb.toString());
157
158 return new XMLSignatureInput(decodedBytes);
159 } catch (ParserConfigurationException e) {
160 throw new TransformationException("c14n.Canonicalizer.Exception",e);
161 } catch (SAXException e) {
162 throw new TransformationException("SAX exception", e);
163 }
164 } catch (Base64DecodingException e) {
165 throw new TransformationException("Base64Decoding", e);
166 }
167 }
168
169 void traverseElement(org.w3c.dom.Element node,StringBuffer sb) {
170 Node sibling=node.getFirstChild();
171 while (sibling!=null) {
172 switch (sibling.getNodeType()) {
173 case Node.ELEMENT_NODE:
174 traverseElement((Element)sibling,sb);
175 break;
176 case Node.TEXT_NODE:
177 sb.append(((Text)sibling).getData());
178 }
179 sibling=sibling.getNextSibling();
180 }
181 }
182}