001 /* 002 * Licensed under the Apache License, Version 2.0 (the "License"); 003 * you may not use this file except in compliance with the License. 004 * You may obtain a copy of the License at 005 * 006 * http://www.apache.org/licenses/LICENSE-2.0 007 * 008 * Unless required by applicable law or agreed to in writing, software 009 * distributed under the License is distributed on an "AS IS" BASIS, 010 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 011 * See the License for the specific language governing permissions and 012 * limitations under the License. 013 */ 014 package org.apache.catalina.util; 015 016 import java.io.ByteArrayOutputStream; 017 018 /** 019 * Library of utility methods useful in dealing with converting byte arrays 020 * to and from strings of hexadecimal digits. 021 * 022 * Note: this package has been stripped of its localization capabilities, 023 * to lessen library dependencies and increase portability. 024 * - ARJ, 4/04 025 * 026 * @since 2.3 027 */ 028 029 public final class HexUtils 030 { 031 // Code from Ajp11, from Apache's JServ 032 033 // Table for HEX to DEC byte translation 034 static final int[] DEC = 035 { 036 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 037 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 038 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 039 00, 01, 02, 03, 04, 05, 06, 07, 8, 9, -1, -1, -1, -1, -1, -1, 040 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, 041 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 042 -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, 043 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 044 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 045 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 046 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 047 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 048 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 049 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 050 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 051 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 052 }; 053 054 /** 055 * Convert a String of hexadecimal digits into the corresponding 056 * byte array by encoding each two hexadecimal digits as a byte. 057 * 058 * @param digits Hexadecimal digits representation 059 * 060 * @exception IllegalArgumentException if an invalid hexadecimal digit 061 * is found, or the input string contains an odd number of hexadecimal 062 * digits 063 */ 064 public static byte[] convert(String digits) 065 { 066 067 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 068 for (int i = 0; i < digits.length(); i += 2) 069 { 070 char c1 = digits.charAt(i); 071 if ((i+1) >= digits.length()) 072 throw new IllegalArgumentException 073 ("Odd number of hexadecimal digits"); 074 char c2 = digits.charAt(i + 1); 075 byte b = 0; 076 if ((c1 >= '0') && (c1 <= '9')) 077 b += (c1 - '0') * 16; 078 else if ((c1 >= 'a') && (c1 <= 'f')) 079 b += (c1 - 'a' + 10) * 16; 080 else if ((c1 >= 'A') && (c1 <= 'F')) 081 b += (c1 - 'A' + 10) * 16; 082 else 083 throw new IllegalArgumentException 084 ("Bad hexadecimal digit"); 085 if ((c2 >= '0') && (c2 <= '9')) 086 b += c2 - '0'; 087 else if ((c2 >= 'a') && (c2 <= 'f')) 088 b += c2 - 'a' + 10; 089 else if ((c2 >= 'A') && (c2 <= 'F')) 090 b += c2 - 'A' + 10; 091 else 092 throw new IllegalArgumentException 093 ("Bad hexadecimal digit"); 094 baos.write(b); 095 } 096 return baos.toByteArray(); 097 098 } 099 100 101 /** 102 * Convert a byte array into a printable format containing a 103 * String of hexadecimal digit characters (two per byte). 104 * 105 * @param bytes Byte array representation 106 */ 107 public static String convert(byte[] bytes) 108 { 109 110 StringBuffer sb = new StringBuffer(bytes.length * 2); 111 for (int i = 0; i < bytes.length; i++) 112 { 113 sb.append(convertDigit(bytes[i] >> 4)); 114 sb.append(convertDigit(bytes[i] & 0x0f)); 115 } 116 return sb.toString(); 117 118 } 119 120 /** 121 * Convert 4 hex digits to an int, and return the number of converted 122 * bytes. 123 * 124 * @param hex Byte array containing exactly four hexadecimal digits 125 * 126 * @exception IllegalArgumentException if an invalid hexadecimal digit 127 * is included 128 */ 129 public static int convert2Int( byte[] hex ) 130 { 131 // Code from Ajp11, from Apache's JServ 132 133 // assert b.length==4 134 // assert valid data 135 int len; 136 if(hex.length < 4 ) return 0; 137 if( DEC[hex[0]]<0 ) 138 throw new IllegalArgumentException("Bad hexadecimal digit"); 139 len = DEC[hex[0]]; 140 len = len << 4; 141 if( DEC[hex[1]]<0 ) 142 throw new IllegalArgumentException("Bad hexadecimal digit"); 143 len += DEC[hex[1]]; 144 len = len << 4; 145 if( DEC[hex[2]]<0 ) 146 throw new IllegalArgumentException("Bad hexadecimal digit"); 147 len += DEC[hex[2]]; 148 len = len << 4; 149 if( DEC[hex[3]]<0 ) 150 throw new IllegalArgumentException("Bad hexadecimal digit"); 151 len += DEC[hex[3]]; 152 return len; 153 } 154 155 /** 156 * [Private] Convert the specified value (0 .. 15) to the corresponding 157 * hexadecimal digit. 158 * 159 * @param value Value to be converted 160 */ 161 private static char convertDigit(int value) 162 { 163 164 value &= 0x0f; 165 if (value >= 10) 166 { 167 return (char) (value - 10 + 'a'); 168 } 169 return (char) (value + '0'); 170 } 171 172 }