source: josm/trunk/src/com/kitfox/svg/xml/cpx/CPXInputStream.java@ 4256

Last change on this file since 4256 was 4256, checked in by bastiK, 14 years ago

see #6560 - basic svg support, includes kitfox svgsalamander, r 98, patched

File size: 9.4 KB
Line 
1/*
2 * CPXInputStream.java
3 *
4 *
5 * The Salamander Project - 2D and 3D graphics libraries in Java
6 * Copyright (C) 2004 Mark McKay
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 * Mark McKay can be contacted at mark@kitfox.com. Salamander and other
23 * projects can be found at http://www.kitfox.com
24 *
25 * Created on February 12, 2004, 10:34 AM
26 */
27
28package com.kitfox.svg.xml.cpx;
29
30import java.io.*;
31import java.util.*;
32import java.util.zip.*;
33import java.security.*;
34import javax.crypto.*;
35
36/**
37 * This class reads/decodes the CPX file format. This format is a simple
38 * compression/encryption transformer for XML data. This stream takes in
39 * encrypted XML and outputs decrypted. It does this by checking for a magic
40 * number at the start of the stream. If absent, it treats the stream as
41 * raw XML data and passes it through unaltered. This is to aid development
42 * in debugging versions, where the XML files will not be in CPX format.
43 *
44 * See http://java.sun.com/developer/technicalArticles/Security/Crypto/
45 *
46 * @author Mark McKay
47 * @author <a href="mailto:mark@kitfox.com">Mark McKay</a>
48 */
49public class CPXInputStream extends FilterInputStream implements CPXConsts {
50
51
52 SecureRandom sec = new SecureRandom();
53
54 Inflater inflater = new Inflater();
55
56 int xlateMode;
57
58 //Keep header bytes in case this stream turns out to be plain text
59 byte[] head = new byte[4];
60 int headSize = 0;
61 int headPtr = 0;
62
63 boolean reachedEOF = false;
64 byte[] inBuffer = new byte[2048];
65 byte[] decryptBuffer = new byte[2048];
66
67 /** Creates a new instance of CPXInputStream */
68 public CPXInputStream(InputStream in) throws IOException {
69 super(in);
70
71 //Determine processing type
72 for (int i = 0; i < 4; i++)
73 {
74 int val = in.read();
75 head[i] = (byte)val;
76 if (val == -1 || head[i] != MAGIC_NUMBER[i])
77 {
78 headSize = i + 1;
79 xlateMode = XL_PLAIN;
80 return;
81 }
82 }
83
84 xlateMode = XL_ZIP_CRYPT;
85 }
86
87 /**
88 * We do not allow marking
89 */
90 public boolean markSupported() { return false; }
91
92 /**
93 * Closes this input stream and releases any system resources
94 * associated with the stream.
95 * This
96 * method simply performs <code>in.close()</code>.
97 *
98 * @exception IOException if an I/O error occurs.
99 * @see java.io.FilterInputStream#in
100 */
101 public void close() throws IOException {
102 reachedEOF = true;
103 in.close();
104 }
105
106 /**
107 * Reads the next byte of data from this input stream. The value
108 * byte is returned as an <code>int</code> in the range
109 * <code>0</code> to <code>255</code>. If no byte is available
110 * because the end of the stream has been reached, the value
111 * <code>-1</code> is returned. This method blocks until input data
112 * is available, the end of the stream is detected, or an exception
113 * is thrown.
114 * <p>
115 * This method
116 * simply performs <code>in.read()</code> and returns the result.
117 *
118 * @return the next byte of data, or <code>-1</code> if the end of the
119 * stream is reached.
120 * @exception IOException if an I/O error occurs.
121 * @see java.io.FilterInputStream#in
122 */
123 public int read() throws IOException
124 {
125 final byte[] b = new byte[1];
126 int retVal = read(b, 0, 1);
127 if (retVal == -1) return -1;
128 return b[0];
129 }
130
131 /**
132 * Reads up to <code>byte.length</code> bytes of data from this
133 * input stream into an array of bytes. This method blocks until some
134 * input is available.
135 * <p>
136 * This method simply performs the call
137 * <code>read(b, 0, b.length)</code> and returns
138 * the result. It is important that it does
139 * <i>not</i> do <code>in.read(b)</code> instead;
140 * certain subclasses of <code>FilterInputStream</code>
141 * depend on the implementation strategy actually
142 * used.
143 *
144 * @param b the buffer into which the data is read.
145 * @return the total number of bytes read into the buffer, or
146 * <code>-1</code> if there is no more data because the end of
147 * the stream has been reached.
148 * @exception IOException if an I/O error occurs.
149 * @see java.io.FilterInputStream#read(byte[], int, int)
150 */
151 public int read(byte[] b) throws IOException
152 {
153 return read(b, 0, b.length);
154 }
155
156 /**
157 * Reads up to <code>len</code> bytes of data from this input stream
158 * into an array of bytes. This method blocks until some input is
159 * available.
160 * <p>
161 * This method simply performs <code>in.read(b, off, len)</code>
162 * and returns the result.
163 *
164 * @param b the buffer into which the data is read.
165 * @param off the start offset of the data.
166 * @param len the maximum number of bytes read.
167 * @return the total number of bytes read into the buffer, or
168 * <code>-1</code> if there is no more data because the end of
169 * the stream has been reached.
170 * @exception IOException if an I/O error occurs.
171 * @see java.io.FilterInputStream#in
172 */
173 public int read(byte[] b, int off, int len) throws IOException
174 {
175 if (reachedEOF) return -1;
176
177 if (xlateMode == XL_PLAIN)
178 {
179 int count = 0;
180 //Write header if appropriate
181 while (headPtr < headSize && len > 0)
182 {
183 b[off++] = head[headPtr++];
184 count++;
185 len--;
186 }
187
188 return (len == 0) ? count : count + in.read(b, off, len);
189 }
190
191 //Decrypt and inflate
192 if (inflater.needsInput() && !decryptChunk())
193 {
194 reachedEOF = true;
195
196 //Read remaining bytes
197 int numRead;
198 try {
199 numRead = inflater.inflate(b, off, len);
200 }
201 catch (Exception e)
202 {
203 e.printStackTrace();
204 return -1;
205 }
206
207 if (!inflater.finished())
208 {
209 new Exception("Inflation incomplete").printStackTrace();
210 }
211
212 return numRead == 0 ? -1 : numRead;
213 }
214
215 try {
216 return inflater.inflate(b, off, len);
217 }
218 catch (DataFormatException e)
219 {
220 e.printStackTrace();
221 return -1;
222 }
223 }
224
225
226 /**
227 * Call when inflater indicates that it needs more bytes.
228 * @return - true if we decrypted more bytes to deflate, false if we
229 * encountered the end of stream
230 */
231 protected boolean decryptChunk() throws IOException
232 {
233 while (inflater.needsInput())
234 {
235 int numInBytes = in.read(inBuffer);
236 if (numInBytes == -1) return false;
237// int numDecryptBytes = cipher.update(inBuffer, 0, numInBytes, decryptBuffer);
238// inflater.setInput(decryptBuffer, 0, numDecryptBytes);
239inflater.setInput(inBuffer, 0, numInBytes);
240 }
241
242 return true;
243 }
244
245 /**
246 * This method returns 1 if we've not reached EOF, 0 if we have. Programs
247 * should not rely on this to determine the number of bytes that can be
248 * read without blocking.
249 */
250 public int available() { return reachedEOF ? 0 : 1; }
251
252 /**
253 * Skips bytes by reading them into a cached buffer
254 */
255 public long skip(long n) throws IOException
256 {
257 int skipSize = (int)n;
258 if (skipSize > inBuffer.length) skipSize = inBuffer.length;
259 return read(inBuffer, 0, skipSize);
260 }
261
262}
263
264/*
265 import java.security.KeyPairGenerator;
266 import java.security.KeyPair;
267 import java.security.KeyPairGenerator;
268 import java.security.PrivateKey;
269 import java.security.PublicKey;
270 import java.security.SecureRandom;
271 import java.security.Cipher;
272
273 ....
274
275 java.security.Security.addProvider(new cryptix.provider.Cryptix());
276
277 SecureRandom random = new SecureRandom(SecureRandom.getSeed(30));
278 KeyPairGenerator keygen = KeyPairGenerator.getInstance("RSA");
279 keygen.initialize(1024, random);
280 keypair = keygen.generateKeyPair();
281
282 PublicKey pubkey = keypair.getPublic();
283 PrivateKey privkey = keypair.getPrivate();
284 */
285
286/*
287 *
288 *Generate key pairs
289KeyPairGenerator keyGen =
290 KeyPairGenerator.getInstance("DSA");
291KeyGen.initialize(1024, new SecureRandom(userSeed));
292KeyPair pair = KeyGen.generateKeyPair();
293 */
Note: See TracBrowser for help on using the repository browser.