source: other-projects/trunk/gs3-release-maker/tasks/sshtaskdef/src/mindbright/util/ASCIIArmour.java@ 14627

Last change on this file since 14627 was 14627, checked in by oranfry, 17 years ago

initial import of the gs3-release-maker

File size: 9.0 KB
Line 
1/******************************************************************************
2 *
3 * Copyright (c) 2000 by Mindbright Technology AB, Stockholm, Sweden.
4 * www.mindbright.se, [email protected]
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 *****************************************************************************
17 * $Author: mats $
18 * $Date: 2000/04/25 07:57:35 $
19 * $Name: rel1-2-1 $
20 *****************************************************************************/
21package mindbright.util;
22
23import java.io.InputStream;
24import java.io.OutputStream;
25import java.io.IOException;
26
27import java.util.Hashtable;
28import java.util.Enumeration;
29import java.util.StringTokenizer;
30
31public final class ASCIIArmour {
32 public final static int DEFAULT_LINE_LENGTH = 70;
33
34 String EOL;
35 String headerLine;
36 Hashtable headerFields;
37 String tailLine;
38
39 boolean blankHeaderSep;
40 int lineLen;
41 boolean haveChecksum;
42
43
44 boolean unknownHeaderLines;
45 String headerLinePrePostFix;
46
47 public ASCIIArmour(String headerLine, String tailLine,
48 boolean blankHeaderSep, int lineLen) {
49 this.EOL = "\r\n";
50 this.headerLine = headerLine;
51 this.tailLine = tailLine;
52 this.blankHeaderSep = blankHeaderSep;
53 this.lineLen = lineLen;
54 this.unknownHeaderLines = false;
55 this.headerFields = new Hashtable();
56 }
57
58 public ASCIIArmour(String headerLine, String tailLine) {
59 this(headerLine, tailLine, false, DEFAULT_LINE_LENGTH);
60 }
61
62 public ASCIIArmour(String headerLinePrePostFix) {
63 this(headerLinePrePostFix, headerLinePrePostFix);
64 this.unknownHeaderLines = true;
65 }
66
67 public void setCanonicalLineEnd(boolean value) {
68 if(value) {
69 EOL = "\r\n";
70 } else {
71 EOL = "\n";
72 }
73 }
74
75 public Hashtable getHeaderFields() {
76 return headerFields;
77 }
78
79 public String getHeaderField(String headerName) {
80 return (String)headerFields.get(headerName);
81 }
82
83 public void setHeaderField(String headerName, String value) {
84 headerFields.put(headerName, value);
85 }
86
87 public byte[] encode(byte[] data) {
88 return encode(data, 0, data.length);
89 }
90
91 public byte[] encode(byte[] data, int offset, int length) {
92 if(unknownHeaderLines) {
93 return null;
94 }
95 int n = ((length / 3) * 4);
96 StringBuffer buf = new StringBuffer(headerLine.length() +
97 tailLine.length() +
98 n + (n / lineLen) + 512);
99 buf.append(headerLine);
100 buf.append(EOL);
101
102 buf.append(printHeaders());
103
104 if(blankHeaderSep)
105 buf.append(EOL);
106 byte[] base64 = Base64.encode(data, offset, length);
107 for(int i = 0; i < base64.length; i += lineLen) {
108 int j = lineLen;
109 if(i + j > base64.length)
110 j = base64.length - i;
111 String line = new String(base64, i, j);
112 buf.append(line);
113 buf.append(EOL);
114 }
115 if(haveChecksum) {
116 // !!! TODO:
117 }
118 buf.append(tailLine);
119 buf.append(EOL);
120
121 return buf.toString().getBytes();
122 }
123
124 public void encode(OutputStream out, byte[] data, int off, int len)
125 throws IOException
126 {
127 byte[] outData = encode(data, off, len);
128 out.write(outData);
129 }
130
131 public void encode(OutputStream out, byte[] data) throws IOException {
132 encode(out, data, 0, data.length);
133 }
134
135 public byte[] decode(byte[] data) {
136 return decode(data, 0, data.length);
137 }
138
139 public byte[] decode(byte[] data, int offset, int length) {
140 String armourChunk = new String(data, offset, length);
141 StringTokenizer st = new StringTokenizer(armourChunk, "\n");
142 boolean foundHeader = false;
143 boolean foundData = false;
144 boolean foundTail = false;
145 String line = "";
146 while(!foundHeader && st.hasMoreTokens()) {
147 line = st.nextToken();
148 if(line.startsWith(headerLine)) {
149 foundHeader = true;
150 // !!! TODO: if(unknownHeaderLines) {
151 }
152 }
153 headerFields = new Hashtable();
154 String lastName = null;
155 while(!foundData && st.hasMoreTokens()) {
156 line = st.nextToken();
157 if(lastName != null) {
158 String val = (String)headerFields.get(lastName);
159 headerFields.put(lastName, val + StringUtil.trimRight(line));
160 lastName = null;
161 continue;
162 }
163 int i = line.indexOf(':');
164 if(i < 0) {
165 foundData = true;
166 } else {
167 String name = line.substring(0, i).trim();
168 String value = line.substring(i + 1).trim();
169 if(value.charAt(0) == '"' &&
170 value.charAt(value.length() - 1) == '\\') {
171 lastName = name;
172 value = value.substring(0, value.length() - 1);
173 }
174 headerFields.put(name, value);
175 }
176 }
177 if(blankHeaderSep) {
178 // !!!
179 }
180 StringBuffer base64Data = new StringBuffer();
181 while(!foundTail) {
182 if(line.startsWith(tailLine)) {
183 foundTail = true;
184 // !!! TODO: if(unknownHeaderLines) {
185 } else {
186 base64Data.append(line);
187 if(st.hasMoreTokens())
188 line = st.nextToken();
189 else
190 return null;
191 }
192 }
193
194 data = Base64.decode(base64Data.toString().getBytes());
195
196 return data;
197 }
198
199 public byte[] decode(InputStream in) throws IOException {
200 StringBuffer lineBuf = new StringBuffer();
201 StringBuffer dataBuf = new StringBuffer();
202 int found = 0;
203 int c;
204 while(found < 2) {
205 c = in.read();
206 if(c == -1)
207 throw new IOException("Premature EOF, corrupt ascii-armour");
208 if(c == '\r')
209 continue;
210 if(c != '\n') {
211 lineBuf.append((char)c);
212 } else {
213 String line = new String(lineBuf);
214 if(found == 0) {
215 if(line.startsWith(headerLine)) {
216 dataBuf.append(line);
217 dataBuf.append(EOL);
218 found++;
219 }
220 } else {
221 dataBuf.append(line);
222 dataBuf.append(EOL);
223 if(line.startsWith(tailLine)) {
224 found++;
225 }
226 }
227 lineBuf.setLength(0);
228 }
229 }
230 return decode(dataBuf.toString().getBytes());
231 }
232
233 public String printHeaders() {
234 Enumeration headerNames = headerFields.keys();
235 StringBuffer buf = new StringBuffer();
236 while(headerNames.hasMoreElements()) {
237 String fieldName = (String)headerNames.nextElement();
238 buf.append(fieldName);
239 buf.append(": ");
240 String val = (String)headerFields.get(fieldName);
241 if(val.charAt(0) == '"' &&
242 fieldName.length() + 2 + val.length() > lineLen) {
243 int n = lineLen - (fieldName.length() + 2);
244 buf.append(val.substring(0, n));
245 buf.append("\\");
246 buf.append(EOL);
247 val = val.substring(n);
248 }
249 buf.append(val);
250 buf.append(EOL);
251 }
252 return buf.toString();
253 }
254
255 public static void main(String[] argv) {
256 byte[] data = "Hej svejs i lingonskogen!!!".getBytes();
257 ASCIIArmour armour =
258 new ASCIIArmour("---- BEGIN GARBAGE ----",
259 "---- END GARBAGE ----");
260 armour.setHeaderField("Subject", "mats");
261 armour.setHeaderField("Comment", "\"this is a comment\"");
262
263 byte[] encoded = armour.encode(data);
264
265 System.out.println("Encoded block:");
266 System.out.println(new String(encoded));
267
268 System.out.println("Decoded: " + new String(armour.decode(encoded)));
269 System.out.println("Headers:");
270 System.out.println(armour.printHeaders());
271
272 encoded = ("---- BEGIN SSH2 PUBLIC KEY ----\r\n" +
273 "Subject: root\r\n" +
274 "Comment: \"host key for hal, accepted by root Mon Sep 20 1999 10:10:02 +0100\"\r\n" +
275 "AAAAB3NzaC1kc3MAAACBAKpCbpj86G+05T53tn6Y+tJ1N87Kx2RbQTDC48LWHYNRZ3c4He\r\n" +
276 "0tmQNFbyg14m/dYrdBI0GxPWQH0RYuyL5YLhBrcscmdz7Ca8buEgehcQULlAJ1P0gZ3hvW\r\n" +
277 "qru55vgU8O0kZVNGSsA+cmXRpq689W6RU0u9qaW03FNdeH7tTq/1AAAAFQDCLg54vUWNe0\r\n" +
278 "n5kMFnEH/DiV5dgQAAAIEAmlOAXHQ/3nrFDnLiTIfCkCvAj/P2rMQUViYXXi9cQ+Qd8Ie5\r\n" +
279 "TmyFJ6t9iJQZ6x3HlScGfQOJcD4h4ydxuXr+rRd6yi48kSB5/g3EscL+6+LMYdMGSGA2ni\r\n" +
280 "l1Vpjm49xZHxHlvTQ+KExk6Pcyb9D5zTW9uoOTBA08SPpYAlbZ4+MAAACAKEeiebGmZg5x\r\n" +
281 "sbxQt6HUPU3Cov9KeXw98qmn4Rr2ENWSTriwl8uxoD8wCuURHaJ61YX5spAj4QkVESqc7Y\r\n" +
282 "NBcZgpST0sUWCF0rNPZm8D6K0hgaUmtfrUJ6EzwxqfKH3YduMHFz5RSv492TSZvKKv+Ucb\r\n" +
283 "X4hEjfmP6SKc+Q4wGaQ=\r\n" +
284 "---- END SSH2 PUBLIC KEY ----\r\n").getBytes();
285 armour =
286 new ASCIIArmour("---- BEGIN SSH2 PUBLIC KEY ----",
287 "---- END SSH2 PUBLIC KEY ----");
288
289 byte[] decoded = null;
290 try {
291 armour =
292 new ASCIIArmour("---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----",
293 "---- END SSH2 ENCRYPTED PRIVATE KEY ----");
294 decoded = armour.decode(new java.io.FileInputStream("/home/matsa/tstkey.prv"));
295 } catch (Exception e) {
296 System.out.println("Error: " + e);
297 }
298
299 System.out.println("Decoded: ");
300 mindbright.util.HexDump.hexDump(decoded, 0, decoded.length);
301 System.out.println("Headers:");
302 System.out.println(armour.printHeaders());
303
304 try {
305 java.io.FileOutputStream f =
306 new java.io.FileOutputStream("/home/matsa/tstkey2.prv");
307 armour.setCanonicalLineEnd(false);
308 armour.encode(f, decoded);
309 f.close();
310 } catch (Exception e) {
311 System.out.println("Error: " + e);
312 }
313 }
314
315}
316
Note: See TracBrowser for help on using the repository browser.