1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.geronimo.mail.util;
21
22 import java.io.IOException;
23 import java.io.OutputStream;
24 import java.io.UnsupportedEncodingException;
25
26 public class UUEncoder implements Encoder {
27
28
29
30 static private final int MAX_CHARS_PER_LINE = 45;
31
32
33 public UUEncoder()
34 {
35 }
36
37
38
39
40
41
42
43
44
45
46
47 public int encode(byte[] data, int off, int length, OutputStream out) throws IOException
48 {
49 int byteCount = 0;
50
51 while (true) {
52
53 if (length > MAX_CHARS_PER_LINE) {
54
55 byteCount += encodeLine(data, off, MAX_CHARS_PER_LINE, out);
56 length -= MAX_CHARS_PER_LINE;
57 off += MAX_CHARS_PER_LINE;
58 }
59 else {
60
61 byteCount += encodeLine(data, off, MAX_CHARS_PER_LINE, out);
62 break;
63 }
64 }
65 return byteCount;
66 }
67
68
69
70
71
72
73
74
75
76
77
78
79
80 private int encodeLine(byte[] data, int offset, int length, OutputStream out) throws IOException {
81
82 out.write((byte)((length & 0x3F) + ' '));
83 byte a;
84 byte b;
85 byte c;
86
87
88 int bytesWritten = 2;
89
90 for (int i = 0; i < length;) {
91
92 b = 1;
93 c = 1;
94
95 a = data[offset + i++];
96 if (i < length) {
97 b = data[offset + i++];
98 if (i < length) {
99 c = data[offset + i++];
100 }
101 }
102
103 byte d1 = (byte)(((a >>> 2) & 0x3F) + ' ');
104 byte d2 = (byte)(((( a << 4) & 0x30) | ((b >>> 4) & 0x0F)) + ' ');
105 byte d3 = (byte)((((b << 2) & 0x3C) | ((c >>> 6) & 0x3)) + ' ');
106 byte d4 = (byte)((c & 0x3F) + ' ');
107
108 out.write(d1);
109 out.write(d2);
110 out.write(d3);
111 out.write(d4);
112
113 bytesWritten += 4;
114 }
115
116
117 out.write('\n');
118
119 return bytesWritten;
120 }
121
122
123
124
125
126
127
128
129
130
131
132
133
134 public int decode(byte[] data, int off, int length, OutputStream out) throws IOException
135 {
136 int bytesWritten = 0;
137
138 while (length > 0) {
139 int lineOffset = off;
140
141
142 while (length > 0 && data[off] != '\n') {
143 off++;
144 length--;
145 }
146
147
148 bytesWritten += decodeLine(data, lineOffset, off - lineOffset, out);
149
150
151
152 off++;
153 length--;
154 }
155 return bytesWritten;
156 }
157
158
159
160
161
162
163
164
165
166
167
168
169
170 private int decodeLine(byte[] data, int off, int length, OutputStream out) throws IOException {
171 int count = data[off++];
172
173
174 if (count < ' ') {
175 throw new IOException("Invalid UUEncode line length");
176 }
177
178 count = (count - ' ') & 0x3F;
179
180
181
182 int requiredLength = (((count * 8) + 5) / 6) + 1;
183 if (length < requiredLength) {
184 throw new IOException("UUEncoded data and length do not match");
185 }
186
187 int bytesWritten = 0;
188
189 while (bytesWritten < count) {
190
191 byte a = (byte)((data[off++] - ' ') & 0x3F);
192 byte b = (byte)((data[off++] - ' ') & 0x3F);
193 byte c = 0;
194 byte d = 0;
195
196
197 byte first = (byte)(((a << 2) & 0xFC) | ((b >>> 4) & 3));
198 out.write(first);
199 bytesWritten++;
200
201
202
203 if (bytesWritten < count) {
204 c = (byte)((data[off++] - ' ') & 0x3F);
205 byte second = (byte)(((b << 4) & 0xF0) | ((c >>> 2) & 0x0F));
206 out.write(second);
207 bytesWritten++;
208
209
210 if (bytesWritten < count) {
211 d = (byte)((data[off++] - ' ') & 0x3F);
212 byte third = (byte)(((c << 6) & 0xC0) | (d & 0x3F));
213 out.write(third);
214 bytesWritten++;
215 }
216 }
217 }
218 return bytesWritten;
219 }
220
221
222
223
224
225
226
227
228
229
230
231 public int decode(String data, OutputStream out) throws IOException
232 {
233 try {
234
235 byte[] bytes = data.getBytes("US-ASCII");
236 return decode(bytes, 0, bytes.length, out);
237 } catch (UnsupportedEncodingException e) {
238 throw new IOException("Invalid UUEncoding");
239 }
240 }
241 }
242
243