1 /**
2 *
3 * Copyright 2003-2004 The Apache Software Foundation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 package org.apache.geronimo.mail.util;
19
20 import java.io.IOException;
21 import java.io.OutputStream;
22
23 public class HexEncoder
24 implements Encoder
25 {
26 protected final byte[] encodingTable =
27 {
28 (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', (byte)'6', (byte)'7',
29 (byte)'8', (byte)'9', (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f'
30 };
31
32
33
34
35 protected final byte[] decodingTable = new byte[128];
36
37 protected void initialiseDecodingTable()
38 {
39 for (int i = 0; i < encodingTable.length; i++)
40 {
41 decodingTable[encodingTable[i]] = (byte)i;
42 }
43
44 decodingTable['A'] = decodingTable['a'];
45 decodingTable['B'] = decodingTable['b'];
46 decodingTable['C'] = decodingTable['c'];
47 decodingTable['D'] = decodingTable['d'];
48 decodingTable['E'] = decodingTable['e'];
49 decodingTable['F'] = decodingTable['f'];
50 }
51
52 public HexEncoder()
53 {
54 initialiseDecodingTable();
55 }
56
57 /**
58 * encode the input data producing a Hex output stream.
59 *
60 * @return the number of bytes produced.
61 */
62 public int encode(
63 byte[] data,
64 int off,
65 int length,
66 OutputStream out)
67 throws IOException
68 {
69 for (int i = off; i < (off + length); i++)
70 {
71 int v = data[i] & 0xff;
72
73 out.write(encodingTable[(v >>> 4)]);
74 out.write(encodingTable[v & 0xf]);
75 }
76
77 return length * 2;
78 }
79
80 private boolean ignore(
81 char c)
82 {
83 return (c == '\n' || c =='\r' || c == '\t' || c == ' ');
84 }
85
86 /**
87 * decode the Hex encoded byte data writing it to the given output stream,
88 * whitespace characters will be ignored.
89 *
90 * @return the number of bytes produced.
91 */
92 public int decode(
93 byte[] data,
94 int off,
95 int length,
96 OutputStream out)
97 throws IOException
98 {
99 byte[] bytes;
100 byte b1, b2;
101 int outLen = 0;
102
103 int end = off + length;
104
105 while (end > 0)
106 {
107 if (!ignore((char)data[end - 1]))
108 {
109 break;
110 }
111
112 end--;
113 }
114
115 int i = off;
116 while (i < end)
117 {
118 while (i < end && ignore((char)data[i]))
119 {
120 i++;
121 }
122
123 b1 = decodingTable[data[i++]];
124
125 while (i < end && ignore((char)data[i]))
126 {
127 i++;
128 }
129
130 b2 = decodingTable[data[i++]];
131
132 out.write((b1 << 4) | b2);
133
134 outLen++;
135 }
136
137 return outLen;
138 }
139
140 /**
141 * decode the Hex encoded String data writing it to the given output stream,
142 * whitespace characters will be ignored.
143 *
144 * @return the number of bytes produced.
145 */
146 public int decode(
147 String data,
148 OutputStream out)
149 throws IOException
150 {
151 byte[] bytes;
152 byte b1, b2, b3, b4;
153 int length = 0;
154
155 int end = data.length();
156
157 while (end > 0)
158 {
159 if (!ignore(data.charAt(end - 1)))
160 {
161 break;
162 }
163
164 end--;
165 }
166
167 int i = 0;
168 while (i < end)
169 {
170 while (i < end && ignore(data.charAt(i)))
171 {
172 i++;
173 }
174
175 b1 = decodingTable[data.charAt(i++)];
176
177 while (i < end && ignore(data.charAt(i)))
178 {
179 i++;
180 }
181
182 b2 = decodingTable[data.charAt(i++)];
183
184 out.write((b1 << 4) | b2);
185
186 length++;
187 }
188
189 return length;
190 }
191 }