1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. 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.tomcat.util.buf;
19
20 import java.io.ByteArrayOutputStream;
21 import org.apache.tomcat.util.res.StringManager;
22
23 /**
24 * Library of utility methods useful in dealing with converting byte arrays
25 * to and from strings of hexadecimal digits.
26 * Code from Ajp11, from Apache's JServ.
27 *
28 * @author Craig R. McClanahan
29 */
30
31 public final class HexUtils {
32
33
34 // -------------------------------------------------------------- Constants
35
36
37 /**
38 * Table for HEX to DEC byte translation.
39 */
40 public static final int[] DEC = {
41 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
42 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
43 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
44 00, 01, 02, 03, 04, 05, 06, 07, 8, 9, -1, -1, -1, -1, -1, -1,
45 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
46 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
47 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
48 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
49 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
50 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
51 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
52 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
53 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
54 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
55 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
56 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
57 };
58
59
60 /**
61 * Table for DEC to HEX byte translation.
62 */
63 public static final byte[] HEX =
64 { (byte) '0', (byte) '1', (byte) '2', (byte) '3', (byte) '4', (byte) '5',
65 (byte) '6', (byte) '7', (byte) '8', (byte) '9', (byte) 'a', (byte) 'b',
66 (byte) 'c', (byte) 'd', (byte) 'e', (byte) 'f' };
67
68
69 /**
70 * The string manager for this package.
71 */
72 private static StringManager sm =
73 StringManager.getManager("org.apache.tomcat.util.buf.res");
74
75
76 // --------------------------------------------------------- Static Methods
77
78
79 /**
80 * Convert a String of hexadecimal digits into the corresponding
81 * byte array by encoding each two hexadecimal digits as a byte.
82 *
83 * @param digits Hexadecimal digits representation
84 *
85 * @exception IllegalArgumentException if an invalid hexadecimal digit
86 * is found, or the input string contains an odd number of hexadecimal
87 * digits
88 */
89 public static byte[] convert(String digits) {
90
91 ByteArrayOutputStream baos = new ByteArrayOutputStream();
92 for (int i = 0; i < digits.length(); i += 2) {
93 char c1 = digits.charAt(i);
94 if ((i+1) >= digits.length())
95 throw new IllegalArgumentException
96 (sm.getString("hexUtil.odd"));
97 char c2 = digits.charAt(i + 1);
98 byte b = 0;
99 if ((c1 >= '0') && (c1 <= '9'))
100 b += ((c1 - '0') * 16);
101 else if ((c1 >= 'a') && (c1 <= 'f'))
102 b += ((c1 - 'a' + 10) * 16);
103 else if ((c1 >= 'A') && (c1 <= 'F'))
104 b += ((c1 - 'A' + 10) * 16);
105 else
106 throw new IllegalArgumentException
107 (sm.getString("hexUtil.bad"));
108 if ((c2 >= '0') && (c2 <= '9'))
109 b += (c2 - '0');
110 else if ((c2 >= 'a') && (c2 <= 'f'))
111 b += (c2 - 'a' + 10);
112 else if ((c2 >= 'A') && (c2 <= 'F'))
113 b += (c2 - 'A' + 10);
114 else
115 throw new IllegalArgumentException
116 (sm.getString("hexUtil.bad"));
117 baos.write(b);
118 }
119 return (baos.toByteArray());
120
121 }
122
123
124 /**
125 * Convert a byte array into a printable format containing a
126 * String of hexadecimal digit characters (two per byte).
127 *
128 * @param bytes Byte array representation
129 */
130 public static String convert(byte bytes[]) {
131
132 StringBuffer sb = new StringBuffer(bytes.length * 2);
133 for (int i = 0; i < bytes.length; i++) {
134 sb.append(convertDigit((int) (bytes[i] >> 4)));
135 sb.append(convertDigit((int) (bytes[i] & 0x0f)));
136 }
137 return (sb.toString());
138
139 }
140
141 /**
142 * Convert 4 hex digits to an int, and return the number of converted
143 * bytes.
144 *
145 * @param hex Byte array containing exactly four hexadecimal digits
146 *
147 * @exception IllegalArgumentException if an invalid hexadecimal digit
148 * is included
149 */
150 public static int convert2Int( byte[] hex ) {
151 // Code from Ajp11, from Apache's JServ
152
153 // assert b.length==4
154 // assert valid data
155 int len;
156 if(hex.length < 4 ) return 0;
157 if( DEC[hex[0]]<0 )
158 throw new IllegalArgumentException(sm.getString("hexUtil.bad"));
159 len = DEC[hex[0]];
160 len = len << 4;
161 if( DEC[hex[1]]<0 )
162 throw new IllegalArgumentException(sm.getString("hexUtil.bad"));
163 len += DEC[hex[1]];
164 len = len << 4;
165 if( DEC[hex[2]]<0 )
166 throw new IllegalArgumentException(sm.getString("hexUtil.bad"));
167 len += DEC[hex[2]];
168 len = len << 4;
169 if( DEC[hex[3]]<0 )
170 throw new IllegalArgumentException(sm.getString("hexUtil.bad"));
171 len += DEC[hex[3]];
172 return len;
173 }
174
175
176
177 /**
178 * [Private] Convert the specified value (0 .. 15) to the corresponding
179 * hexadecimal digit.
180 *
181 * @param value Value to be converted
182 */
183 private static char convertDigit(int value) {
184
185 value &= 0x0f;
186 if (value >= 10)
187 return ((char) (value - 10 + 'a'));
188 else
189 return ((char) (value + '0'));
190
191 }
192
193
194 }