001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020package org.apache.mina.proxy.utils; 021 022import java.io.UnsupportedEncodingException; 023 024/** 025 * ByteUtilities.java - Byte manipulation functions. 026 * 027 * @author <a href="http://mina.apache.org">Apache MINA Project</a> 028 * @since MINA 2.0.0-M3 029 */ 030public class ByteUtilities { 031 032 /** 033 * Returns the integer represented by up to 4 bytes in network byte order. 034 * 035 * @param buf the buffer to read the bytes from 036 * @param start The starting position 037 * @param count The number of bytes to in the buffer 038 * @return the integer value 039 */ 040 public static int networkByteOrderToInt(byte[] buf, int start, int count) { 041 if (count > 4) { 042 throw new IllegalArgumentException("Cannot handle more than 4 bytes"); 043 } 044 045 int result = 0; 046 047 for (int i = 0; i < count; i++) { 048 result <<= 8; 049 result |= (buf[start + i] & 0xff); 050 } 051 052 return result; 053 } 054 055 /** 056 * Encodes an integer into up to 4 bytes in network byte order. 057 * 058 * @param num the int to convert to a byte array 059 * @param count the number of reserved bytes for the write operation 060 * @return the resulting byte array 061 */ 062 public static byte[] intToNetworkByteOrder(int num, int count) { 063 byte[] buf = new byte[count]; 064 intToNetworkByteOrder(num, buf, 0, count); 065 066 return buf; 067 } 068 069 /** 070 * Encodes an integer into up to 4 bytes in network byte order in the 071 * supplied buffer starting at <code>start</code> offset and writing 072 * <code>count</code> bytes. 073 * 074 * @param num the int to convert to a byte array 075 * @param buf the buffer to write the bytes to 076 * @param start the offset from beginning for the write operation 077 * @param count the number of reserved bytes for the write operation 078 */ 079 public static void intToNetworkByteOrder(int num, byte[] buf, int start, int count) { 080 if (count > 4) { 081 throw new IllegalArgumentException("Cannot handle more than 4 bytes"); 082 } 083 084 for (int i = count - 1; i >= 0; i--) { 085 buf[start + i] = (byte) (num & 0xff); 086 num >>>= 8; 087 } 088 } 089 090 /** 091 * Write a 16 bit short as LITTLE_ENDIAN. 092 * 093 * @param v the short to write 094 * @return the Short in a byte[] 095 */ 096 public final static byte[] writeShort(short v) { 097 return writeShort(v, new byte[2], 0); 098 } 099 100 /** 101 * Write a 16 bit short as LITTLE_ENDIAN to 102 * the given array <code>b</code> at offset <code>offset</code>. 103 * 104 * @param v the short to write 105 * @param b the byte array to write to 106 * @param offset the offset at which to start writing in the array 107 * @return the Short in a byte[] 108 */ 109 public final static byte[] writeShort(short v, byte[] b, int offset) { 110 b[offset] = (byte) v; 111 b[offset + 1] = (byte) (v >> 8); 112 113 return b; 114 } 115 116 /** 117 * Write a 32 bit int as LITTLE_ENDIAN. 118 * 119 * @param v the int to write 120 * @return the Int in a byte[] 121 */ 122 public final static byte[] writeInt(int v) { 123 return writeInt(v, new byte[4], 0); 124 } 125 126 /** 127 * Write a 32 bit int as LITTLE_ENDIAN to 128 * the given array <code>b</code> at offset <code>offset</code>. 129 * 130 * @param v the int to write 131 * @param b the byte array to write to 132 * @param offset the offset at which to start writing in the array 133 * @return the Int in a byte[] 134 */ 135 public final static byte[] writeInt(int v, byte[] b, int offset) { 136 b[offset] = (byte) v; 137 b[offset + 1] = (byte) (v >> 8); 138 b[offset + 2] = (byte) (v >> 16); 139 b[offset + 3] = (byte) (v >> 24); 140 141 return b; 142 } 143 144 /** 145 * Invert the endianness of words (4 bytes) in the given byte array 146 * starting at the given offset and repeating length/4 times. 147 * eg: b0b1b2b3 -> b3b2b1b0 148 * 149 * @param b the byte array 150 * @param offset the offset at which to change word start 151 * @param length the number of bytes on which to operate 152 * (should be a multiple of 4) 153 */ 154 public final static void changeWordEndianess(byte[] b, int offset, int length) { 155 byte tmp; 156 157 for (int i = offset; i < offset + length; i += 4) { 158 tmp = b[i]; 159 b[i] = b[i + 3]; 160 b[i + 3] = tmp; 161 tmp = b[i + 1]; 162 b[i + 1] = b[i + 2]; 163 b[i + 2] = tmp; 164 } 165 } 166 167 /** 168 * Invert two bytes in the given byte array starting at the given 169 * offset and repeating the inversion length/2 times. 170 * eg: b0b1 -@gt; b1b0 171 * 172 * @param b the byte array 173 * @param offset the offset at which to change word start 174 * @param length the number of bytes on which to operate 175 * (should be a multiple of 2) 176 */ 177 public final static void changeByteEndianess(byte[] b, int offset, int length) { 178 byte tmp; 179 180 for (int i = offset; i < offset + length; i += 2) { 181 tmp = b[i]; 182 b[i] = b[i + 1]; 183 b[i + 1] = tmp; 184 } 185 } 186 187 /** 188 * Converts an OEM string as defined in NTLM protocol (eg ASCII charset) 189 * to a byte array. 190 * 191 * @param s the string to convert 192 * @return the result byte array 193 * @throws UnsupportedEncodingException if the string is not an OEM string 194 */ 195 public final static byte[] getOEMStringAsByteArray(String s) throws UnsupportedEncodingException { 196 return s.getBytes("ASCII"); 197 } 198 199 /** 200 * Converts an UTF-16LE string as defined in NTLM protocol to a byte array. 201 * 202 * @param s the string to convert 203 * @return the result byte array 204 * @throws UnsupportedEncodingException if the string is not an UTF-16LE string 205 */ 206 public final static byte[] getUTFStringAsByteArray(String s) throws UnsupportedEncodingException { 207 return s.getBytes("UTF-16LE"); 208 } 209 210 /** 211 * Encodes the string to a byte array using UTF-16LE or the ASCII charset 212 * in function of the <code>useUnicode</code> argument. 213 * 214 * @param s the string to encode 215 * @param useUnicode if true then string is encoded to UTF-16LE 216 * otherwise to ASCII 217 * @return the encoded string as a byte array 218 * @throws UnsupportedEncodingException if encoding fails 219 */ 220 public final static byte[] encodeString(String s, boolean useUnicode) throws UnsupportedEncodingException { 221 if (useUnicode) { 222 return getUTFStringAsByteArray(s); 223 } 224 225 return getOEMStringAsByteArray(s); 226 } 227 228 /** 229 * Returns a hexadecimal representation of the given byte array. 230 * 231 * @param bytes the array to output to an hex string 232 * @return the hex representation as a string 233 */ 234 public static String asHex(byte[] bytes) { 235 return asHex(bytes, null); 236 } 237 238 /** 239 * Returns a hexadecimal representation of the given byte array. 240 * 241 * @param bytes the array to output to an hex string 242 * @param separator the separator to use between each byte in the output 243 * string. If null no char is inserted between each byte value. 244 * @return the hex representation as a string 245 */ 246 public static String asHex(byte[] bytes, String separator) { 247 StringBuilder sb = new StringBuilder(); 248 for (int i = 0; i < bytes.length; i++) { 249 String code = Integer.toHexString(bytes[i] & 0xFF); 250 if ((bytes[i] & 0xFF) < 16) { 251 sb.append('0'); 252 } 253 254 sb.append(code); 255 256 if (separator != null && i < bytes.length - 1) { 257 sb.append(separator); 258 } 259 } 260 261 return sb.toString(); 262 } 263 264 /** 265 * Converts a hex string representation to a byte array. 266 * 267 * @param hex the string holding the hex values 268 * @return the resulting byte array 269 */ 270 public static byte[] asByteArray(String hex) { 271 byte[] bts = new byte[hex.length() / 2]; 272 for (int i = 0; i < bts.length; i++) { 273 bts[i] = (byte) Integer.parseInt(hex.substring(2 * i, 2 * i + 2), 16); 274 } 275 276 return bts; 277 } 278 279 /** 280 * Reads an int from 4 bytes of the given array at offset 0. 281 * 282 * @param b the byte array to read 283 * @return the integer value 284 */ 285 public static final int makeIntFromByte4(byte[] b) { 286 return makeIntFromByte4(b, 0); 287 } 288 289 /** 290 * Reads an int from 4 bytes of the given array at the given offset. 291 * 292 * @param b the byte array to read 293 * @param offset the offset at which to start 294 * @return the int value 295 */ 296 public static final int makeIntFromByte4(byte[] b, int offset) { 297 return b[offset] << 24 | (b[offset + 1] & 0xff) << 16 | (b[offset + 2] & 0xff) << 8 | (b[offset + 3] & 0xff); 298 } 299 300 /** 301 * Reads an int from 2 bytes of the given array at offset 0. 302 * 303 * @param b the byte array to read 304 * @return the int value 305 */ 306 public static final int makeIntFromByte2(byte[] b) { 307 return makeIntFromByte2(b, 0); 308 } 309 310 /** 311 * Reads an int from 2 bytes of the given array at the given offset. 312 * 313 * @param b the byte array to read 314 * @param offset the offset at which to start 315 * @return the int value 316 */ 317 public static final int makeIntFromByte2(byte[] b, int offset) { 318 return (b[offset] & 0xff) << 8 | (b[offset + 1] & 0xff); 319 } 320 321 /** 322 * Returns true if the flag <code>testFlag</code> is set in the 323 * <code>flags</code> flagset. 324 * 325 * @param flagSet the flagset to test 326 * @param testFlag the flag we search the presence of 327 * @return true if testFlag is present in the flagset, false otherwise. 328 */ 329 public final static boolean isFlagSet(int flagSet, int testFlag) { 330 return (flagSet & testFlag) > 0; 331 } 332}