001: /*
002: * $Id: Type1Decode.java,v 1.2 2007/12/20 18:33:32 rbair Exp $
003: *
004: * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
005: * Santa Clara, California 95054, U.S.A. All rights reserved.
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2.1 of the License, or (at your option) any later version.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this library; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
020: */
021:
022: package test;
023:
024: /*
025: * Type1Decode.java
026: *
027: * Created on August 28, 2003, 11:54 AM
028: */
029:
030: import com.sun.pdfview.HexDump;
031:
032: import java.io.*;
033:
034: /**
035: *
036: * @author jkaplan
037: */
038: public class Type1Decode {
039: private static byte[] decrypt(byte[] d, int start, int end,
040: int key, int skip) {
041: if (end - start - skip < 0) {
042: skip = 0;
043: }
044: byte[] o = new byte[end - start - skip];
045: int r = key;
046: int ipos;
047: int c1 = 52845;
048: int c2 = 22719;
049: for (ipos = start; ipos < end; ipos++) {
050: int c = d[ipos] & 0xff;
051: int p = (c ^ (r >> 8)) & 0xff;
052:
053: if (ipos - start < 16) {
054: System.out.println("c = " + Integer.toHexString(c)
055: + ", p = " + Integer.toHexString(p) + ", r = "
056: + Integer.toHexString(r));
057: }
058:
059: r = ((c + r) * c1 + c2) & 0xffff;
060: if (ipos - start - skip >= 0) {
061: o[ipos - start - skip] = (byte) p;
062: }
063: }
064: return o;
065: }
066:
067: private static byte[] readASCII(byte[] data, int start, int end) {
068: // each byte of output is derived from one character (two bytes) of
069: // input
070: byte[] o = new byte[(end - start) / 2];
071:
072: int count = 0;
073: int bit = 0;
074:
075: for (int loc = start; loc < end; loc++) {
076: char c = (char) (data[loc] & 0xff);
077: byte b = (byte) 0;
078:
079: if (c >= '0' && c <= '9') {
080: b = (byte) (c - '0');
081: } else if (c >= 'a' && c <= 'f') {
082: b = (byte) (10 + (c - 'a'));
083: } else if (c >= 'A' && c <= 'F') {
084: b = (byte) (10 + (c - 'A'));
085: } else {
086: // linefeed or something. Skip.
087: continue;
088: }
089:
090: // which half of the byte are we?
091: if ((bit++ % 2) == 0) {
092: o[count] = (byte) (b << 4);
093: } else {
094: o[count++] |= b;
095: }
096: }
097:
098: return o;
099: }
100:
101: private static boolean isASCII(byte[] data, int start) {
102: // look at the first 4 bytes
103: for (int i = start; i < start + 4; i++) {
104: // get the byte as a character
105: char c = (char) (data[i] & 0xff);
106:
107: if (c >= '0' && c <= '9') {
108: continue;
109: } else if (c >= 'a' && c <= 'f') {
110: continue;
111: } else if (c >= 'A' && c <= 'F') {
112: continue;
113: } else {
114: // out of range
115: return false;
116: }
117: }
118:
119: // all were in range, so it is ASCII
120: return true;
121: }
122:
123: /**
124: * @param args the command line arguments
125: */
126: public static void main(String[] args) {
127: if (args.length < 1) {
128: System.out.println("Usage:");
129: System.out
130: .println(" Type1Decode <filename> <decode-start>");
131: System.exit(-1);
132: }
133:
134: try {
135: File file = new File(args[0]);
136:
137: if (!file.exists() || !file.canRead()) {
138: System.out.println("Can't read file: " + args[0]);
139: System.exit(-1);
140: }
141:
142: FileInputStream fis = new FileInputStream(file);
143:
144: byte[] data = new byte[(int) file.length()];
145: int cur = 0;
146: while (cur < file.length()) {
147: cur += fis.read(data, cur, data.length - cur);
148: }
149:
150: int start = 0;
151:
152: if ((data[0] & 0xff) == 0x80) {
153: start = (data[2] & 0xff);
154: start |= (data[3] & 0xff) << 8;
155: start |= (data[4] & 0xff) << 16;
156: start |= (data[5] & 0xff) << 24;
157:
158: start += 6;
159: } else if (args.length > 1) {
160: start = Integer.parseInt(args[1]);
161: } else {
162: System.out.println("Unable to read size");
163: System.exit(-1);
164: }
165:
166: int size = data.length - start;
167:
168: if (isASCII(data, start)) {
169: data = readASCII(data, start, size);
170: start = 0;
171: size = data.length;
172: } else if ((data[start] & 0xff) == 0x80) {
173: size = (data[start + 2] & 0xff);
174: size |= (data[start + 3] & 0xff) << 8;
175: size |= (data[start + 4] & 0xff) << 16;
176: size |= (data[start + 5] & 0xff) << 24;
177:
178: start += 6;
179: }
180:
181: byte[] outData = decrypt(data, start, start + size, 55665,
182: 4);
183:
184: HexDump.printData(outData);
185:
186: } catch (Exception ex) {
187: ex.printStackTrace();
188: }
189: }
190:
191: }
|