1:
38:
39: package ;
40:
41: import ;
42: import ;
43:
44:
50: public final class UTF7imap
51: {
52:
53: private static final String US_ASCII = "US-ASCII";
54:
55: private static final byte[] src = {
56: 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
57: 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54,
58: 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x61, 0x62, 0x63, 0x64,
59: 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e,
60: 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
61: 0x79, 0x7a, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
62: 0x38, 0x39, 0x2b, 0x2c
63: };
64:
65: private static final byte[] dst;
66: static
67: {
68: dst = new byte[0x100];
69: for (int i = 0; i < 0xff; i++)
70: {
71: dst[i] = -1;
72: }
73: for (int i = 0; i < src.length; i++)
74: {
75: dst[src[i]] = (byte) i;
76: }
77:
78: }
79:
80: private UTF7imap()
81: {
82: }
83:
84:
90: static byte[] encode(byte[] bs)
91: {
92: int si = 0, ti = 0;
93: byte[] bt = new byte[(((bs.length + 2) / 3) * 4) -1];
94: for (; si < bs.length; si += 3)
95: {
96: int buflen = bs.length - si;
97: if (buflen == 1)
98: {
99: byte b = bs[si];
100: int i = 0;
101: boolean flag = false;
102: bt[ti++] = src[b >>> 2 & 0x3f];
103: bt[ti++] = src[(b << 4 & 0x30) + (i >>> 4 & 0xf)];
104: }
105: else if (buflen == 2)
106: {
107: byte b1 = bs[si], b2 = bs[si + 1];
108: int i = 0;
109: bt[ti++] = src[b1 >>> 2 & 0x3f];
110: bt[ti++] = src[(b1 << 4 & 0x30) + (b2 >>> 4 & 0xf)];
111: bt[ti++] = src[(b2 << 2 & 0x3c) + (i >>> 6 & 0x3)];
112: }
113: else if (buflen == 3)
114: {
115: byte b1 = bs[si], b2 = bs[si + 1], b3 = bs[si + 2];
116: bt[ti++] = src[b1 >>> 2 & 0x3f];
117: bt[ti++] = src[(b1 << 4 & 0x30) + (b2 >>> 4 & 0xf)];
118: bt[ti++] = src[(b2 << 2 & 0x3c) + (b3 >>> 6 & 0x3)];
119: bt[ti++] = src[b3 & 0x3f];
120: }
121: }
122: return bt;
123: }
124:
125:
131: static int[] decode(byte[] bs)
132: {
133: int[] buffer = new int[bs.length];
134: int buflen = 0;
135: int si = 0;
136: int len = bs.length - si;
137: while (len > 0)
138: {
139: byte b0 = dst[bs[si++] & 0xff];
140: byte b2 = dst[bs[si++] & 0xff];
141: buffer[buflen++] = (b0 << 2 & 0xfc | b2 >>> 4 & 0x3);
142: if (len > 2)
143: {
144: b0 = b2;
145: b2 = dst[bs[si++] & 0xff];
146: buffer[buflen++] = (b0 << 4 & 0xf0 | b2 >>> 2 & 0xf);
147: if (len > 3)
148: {
149: b0 = b2;
150: b2 = dst[bs[si++] & 0xff];
151: buffer[buflen++] = (b0 << 6 & 0xc0 | b2 & 0x3f);
152: }
153: }
154: len = bs.length - si;
155: }
156: int[] bt = new int[buflen];
157: System.arraycopy(buffer, 0, bt, 0, buflen);
158: return bt;
159: }
160:
161:
165: public static String encode(String name)
166: {
167: try
168: {
169: StringBuffer buffer = null;
170: ByteArrayOutputStream encoderSink = null;
171: char[] chars = name.toCharArray();
172: boolean encoding = false;
173: for (int i = 0; i < chars.length; i++)
174: {
175: char c = chars[i];
176: if (c == '&')
177: {
178: if (buffer == null)
179: {
180: buffer = new StringBuffer();
181: for (int j = 0; j < i; j++)
182: {
183: buffer.append(chars[j]);
184: }
185: }
186: buffer.append('&');
187: buffer.append('-');
188: }
189: if (c < 0x1f || c > 0x7f)
190: {
191:
192: if (buffer == null)
193: {
194: buffer = new StringBuffer();
195: for (int j = 0; j < i; j++)
196: {
197: buffer.append(chars[j]);
198: }
199: encoderSink = new ByteArrayOutputStream();
200: }
201: if (!encoding)
202: {
203: encoderSink.reset();
204: buffer.append('&');
205: encoding = true;
206: }
207: encoderSink.write(((int) c) / 0x100);
208: encoderSink.write(((int) c) % 0x100);
209: }
210: else if (encoding)
211: {
212: encoderSink.flush();
213: byte[] encoded = encode(encoderSink.toByteArray());
214: buffer.append(new String(encoded, US_ASCII));
215: buffer.append('-');
216: encoding = false;
217: if (c != '-')
218: {
219: buffer.append(c);
220: }
221: }
222: else if (buffer != null)
223: {
224: buffer.append(c);
225: }
226: }
227: if (encoding)
228: {
229: encoderSink.flush();
230: byte[] encoded = encode(encoderSink.toByteArray());
231: buffer.append(new String(encoded, US_ASCII));
232: buffer.append('-');
233: }
234: if (buffer != null)
235: {
236: return buffer.toString();
237: }
238: }
239: catch (IOException e)
240: {
241:
242: throw new RuntimeException(e.getMessage());
243: }
244: return name;
245: }
246:
247:
251: public static String decode(String name)
252: {
253: StringBuffer buffer = null;
254: ByteArrayOutputStream decoderSink = null;
255: char[] chars = name.toCharArray();
256: boolean encoded = false;
257: for (int i = 0; i < chars.length; i++)
258: {
259: char c = chars[i];
260: if (c == '&')
261: {
262: if (buffer == null)
263: {
264: buffer = new StringBuffer();
265: decoderSink = new ByteArrayOutputStream();
266: for (int j = 0; j < i; j++)
267: {
268: buffer.append(chars[j]);
269: }
270: }
271: decoderSink.reset();
272: encoded = true;
273: }
274: else if (c == '-' && encoded)
275: {
276: if (decoderSink.size() == 0)
277: {
278: buffer.append('&');
279: }
280: else
281: {
282: int[] decoded = decode(decoderSink.toByteArray());
283: for (int j = 0; j < decoded.length - 1; j += 2)
284: {
285: int hibyte = decoded[j];
286: int lobyte = decoded[j + 1];
287: int d = (hibyte * 0x100) | lobyte;
288: buffer.append((char) d);
289: }
290: }
291: encoded = false;
292: }
293: else if (encoded)
294: {
295: decoderSink.write((byte) c);
296: }
297: else if (buffer != null)
298: {
299: buffer.append(c);
300: }
301: }
302: if (buffer != null)
303: {
304: return buffer.toString();
305: }
306: return name;
307: }
308:
309: public static void main(String[] args)
310: {
311: boolean decode = false;
312: for (int i = 0; i < args.length; i++)
313: {
314: if (args[i].equals("-d"))
315: {
316: decode = true;
317: }
318: else
319: {
320: String ret = decode ? decode(args[i]) : encode(args[i]);
321: StringBuffer buf = new StringBuffer(args[i]);
322: buf.append(" = \"");
323: buf.append(ret);
324: buf.append("\"(");
325: for (int j = 0; j < ret.length(); j++)
326: {
327: if (j > 0)
328: {
329: buf.append(' ');
330: }
331: int c = (int) ret.charAt(j);
332: buf.append(Integer.toString(c, 16));
333: }
334: buf.append(")");
335: System.out.println(buf.toString());
336: }
337: }
338: }
339:
340: }