1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 * 19 */ 20 package org.apache.mina.proxy.utils; 21 22 import java.io.UnsupportedEncodingException; 23 24 /** 25 * ByteUtilities.java - Byte manipulation functions. 26 * 27 * @author <a href="http://mina.apache.org">Apache MINA Project</a> 28 * @since MINA 2.0.0-M3 29 */ 30 public class ByteUtilities { 31 private ByteUtilities(){ 32 } 33 34 /** 35 * Returns the integer represented by up to 4 bytes in network byte order. 36 * 37 * @param buf the buffer to read the bytes from 38 * @param start The starting position 39 * @param count The number of bytes to in the buffer 40 * @return the integer value 41 */ 42 public static int networkByteOrderToInt(byte[] buf, int start, int count) { 43 if (count > 4) { 44 throw new IllegalArgumentException("Cannot handle more than 4 bytes"); 45 } 46 47 int result = 0; 48 49 for (int i = 0; i < count; i++) { 50 result <<= 8; 51 result |= (buf[start + i] & 0xff); 52 } 53 54 return result; 55 } 56 57 /** 58 * Encodes an integer into up to 4 bytes in network byte order. 59 * 60 * @param num the int to convert to a byte array 61 * @param count the number of reserved bytes for the write operation 62 * @return the resulting byte array 63 */ 64 public static byte[] intToNetworkByteOrder(int num, int count) { 65 byte[] buf = new byte[count]; 66 intToNetworkByteOrder(num, buf, 0, count); 67 68 return buf; 69 } 70 71 /** 72 * Encodes an integer into up to 4 bytes in network byte order in the 73 * supplied buffer starting at <code>start</code> offset and writing 74 * <code>count</code> bytes. 75 * 76 * @param num the int to convert to a byte array 77 * @param buf the buffer to write the bytes to 78 * @param start the offset from beginning for the write operation 79 * @param count the number of reserved bytes for the write operation 80 */ 81 public static void intToNetworkByteOrder(int num, byte[] buf, int start, int count) { 82 if (count > 4) { 83 throw new IllegalArgumentException("Cannot handle more than 4 bytes"); 84 } 85 86 for (int i = count - 1; i >= 0; i--) { 87 buf[start + i] = (byte) (num & 0xff); 88 num >>>= 8; 89 } 90 } 91 92 /** 93 * Write a 16 bit short as LITTLE_ENDIAN. 94 * 95 * @param v the short to write 96 * @return the Short in a byte[] 97 */ 98 public static final byte[] writeShort(short v) { 99 return writeShort(v, new byte[2], 0); 100 } 101 102 /** 103 * Write a 16 bit short as LITTLE_ENDIAN to 104 * the given array <code>b</code> at offset <code>offset</code>. 105 * 106 * @param v the short to write 107 * @param b the byte array to write to 108 * @param offset the offset at which to start writing in the array 109 * @return the Short in a byte[] 110 */ 111 public static final byte[] writeShort(short v, byte[] b, int offset) { 112 b[offset] = (byte) v; 113 b[offset + 1] = (byte) (v >> 8); 114 115 return b; 116 } 117 118 /** 119 * Write a 32 bit int as LITTLE_ENDIAN. 120 * 121 * @param v the int to write 122 * @return the Int in a byte[] 123 */ 124 public static final byte[] writeInt(int v) { 125 return writeInt(v, new byte[4], 0); 126 } 127 128 /** 129 * Write a 32 bit int as LITTLE_ENDIAN to 130 * the given array <code>b</code> at offset <code>offset</code>. 131 * 132 * @param v the int to write 133 * @param b the byte array to write to 134 * @param offset the offset at which to start writing in the array 135 * @return the Int in a byte[] 136 */ 137 public static final byte[] writeInt(int v, byte[] b, int offset) { 138 b[offset] = (byte) v; 139 b[offset + 1] = (byte) (v >> 8); 140 b[offset + 2] = (byte) (v >> 16); 141 b[offset + 3] = (byte) (v >> 24); 142 143 return b; 144 } 145 146 /** 147 * Invert the endianness of words (4 bytes) in the given byte array 148 * starting at the given offset and repeating length/4 times. 149 * eg: b0b1b2b3 -> b3b2b1b0 150 * 151 * @param b the byte array 152 * @param offset the offset at which to change word start 153 * @param length the number of bytes on which to operate 154 * (should be a multiple of 4) 155 */ 156 public static final void changeWordEndianess(byte[] b, int offset, int length) { 157 byte tmp; 158 159 for (int i = offset; i < offset + length; i += 4) { 160 tmp = b[i]; 161 b[i] = b[i + 3]; 162 b[i + 3] = tmp; 163 tmp = b[i + 1]; 164 b[i + 1] = b[i + 2]; 165 b[i + 2] = tmp; 166 } 167 } 168 169 /** 170 * Invert two bytes in the given byte array starting at the given 171 * offset and repeating the inversion length/2 times. 172 * eg: b0b1 -@gt; b1b0 173 * 174 * @param b the byte array 175 * @param offset the offset at which to change word start 176 * @param length the number of bytes on which to operate 177 * (should be a multiple of 2) 178 */ 179 public static final void changeByteEndianess(byte[] b, int offset, int length) { 180 byte tmp; 181 182 for (int i = offset; i < offset + length; i += 2) { 183 tmp = b[i]; 184 b[i] = b[i + 1]; 185 b[i + 1] = tmp; 186 } 187 } 188 189 /** 190 * Converts an OEM string as defined in NTLM protocol (eg ASCII charset) 191 * to a byte array. 192 * 193 * @param s the string to convert 194 * @return the result byte array 195 * @throws UnsupportedEncodingException if the string is not an OEM string 196 */ 197 public static final byte[] getOEMStringAsByteArray(String s) throws UnsupportedEncodingException { 198 return s.getBytes("ASCII"); 199 } 200 201 /** 202 * Converts an UTF-16LE string as defined in NTLM protocol to a byte array. 203 * 204 * @param s the string to convert 205 * @return the result byte array 206 * @throws UnsupportedEncodingException if the string is not an UTF-16LE string 207 */ 208 public static final byte[] getUTFStringAsByteArray(String s) throws UnsupportedEncodingException { 209 return s.getBytes("UTF-16LE"); 210 } 211 212 /** 213 * Encodes the string to a byte array using UTF-16LE or the ASCII charset 214 * in function of the <code>useUnicode</code> argument. 215 * 216 * @param s the string to encode 217 * @param useUnicode if true then string is encoded to UTF-16LE 218 * otherwise to ASCII 219 * @return the encoded string as a byte array 220 * @throws UnsupportedEncodingException if encoding fails 221 */ 222 public static final byte[] encodeString(String s, boolean useUnicode) throws UnsupportedEncodingException { 223 if (useUnicode) { 224 return getUTFStringAsByteArray(s); 225 } 226 227 return getOEMStringAsByteArray(s); 228 } 229 230 /** 231 * Returns a hexadecimal representation of the given byte array. 232 * 233 * @param bytes the array to output to an hex string 234 * @return the hex representation as a string 235 */ 236 public static String asHex(byte[] bytes) { 237 return asHex(bytes, null); 238 } 239 240 /** 241 * Returns a hexadecimal representation of the given byte array. 242 * 243 * @param bytes the array to output to an hex string 244 * @param separator the separator to use between each byte in the output 245 * string. If null no char is inserted between each byte value. 246 * @return the hex representation as a string 247 */ 248 public static String asHex(byte[] bytes, String separator) { 249 StringBuilder sb = new StringBuilder(); 250 for (int i = 0; i < bytes.length; i++) { 251 String code = Integer.toHexString(bytes[i] & 0xFF); 252 if ((bytes[i] & 0xFF) < 16) { 253 sb.append('0'); 254 } 255 256 sb.append(code); 257 258 if (separator != null && i < bytes.length - 1) { 259 sb.append(separator); 260 } 261 } 262 263 return sb.toString(); 264 } 265 266 /** 267 * Converts a hex string representation to a byte array. 268 * 269 * @param hex the string holding the hex values 270 * @return the resulting byte array 271 */ 272 public static byte[] asByteArray(String hex) { 273 byte[] bts = new byte[hex.length() / 2]; 274 for (int i = 0; i < bts.length; i++) { 275 bts[i] = (byte) Integer.parseInt(hex.substring(2 * i, 2 * i + 2), 16); 276 } 277 278 return bts; 279 } 280 281 /** 282 * Reads an int from 4 bytes of the given array at offset 0. 283 * 284 * @param b the byte array to read 285 * @return the integer value 286 */ 287 public static final int makeIntFromByte4(byte[] b) { 288 return makeIntFromByte4(b, 0); 289 } 290 291 /** 292 * Reads an int from 4 bytes of the given array at the given offset. 293 * 294 * @param b the byte array to read 295 * @param offset the offset at which to start 296 * @return the int value 297 */ 298 public static final int makeIntFromByte4(byte[] b, int offset) { 299 return b[offset] << 24 | (b[offset + 1] & 0xff) << 16 | (b[offset + 2] & 0xff) << 8 | (b[offset + 3] & 0xff); 300 } 301 302 /** 303 * Reads an int from 2 bytes of the given array at offset 0. 304 * 305 * @param b the byte array to read 306 * @return the int value 307 */ 308 public static final int makeIntFromByte2(byte[] b) { 309 return makeIntFromByte2(b, 0); 310 } 311 312 /** 313 * Reads an int from 2 bytes of the given array at the given offset. 314 * 315 * @param b the byte array to read 316 * @param offset the offset at which to start 317 * @return the int value 318 */ 319 public static final int makeIntFromByte2(byte[] b, int offset) { 320 return (b[offset] & 0xff) << 8 | (b[offset + 1] & 0xff); 321 } 322 323 /** 324 * Returns true if the flag <code>testFlag</code> is set in the 325 * <code>flags</code> flagset. 326 * 327 * @param flagSet the flagset to test 328 * @param testFlag the flag we search the presence of 329 * @return true if testFlag is present in the flagset, false otherwise. 330 */ 331 public static final boolean isFlagSet(int flagSet, int testFlag) { 332 return (flagSet & testFlag) > 0; 333 } 334 }