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 */ 020 package org.apache.directory.shared.ldap.util; 021 022 023 /** 024 * Utility class used by the DN Parser. 025 * 026 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 027 * @version $Rev: 918756 $, $Date: 2010-03-04 00:05:29 +0100 (Thu, 04 Mar 2010) $ 028 */ 029 public class DNUtils 030 { 031 // ~ Static fields/initializers 032 // ----------------------------------------------------------------- 033 /** A value if we got an error while parsing */ 034 public static final int PARSING_ERROR = -1; 035 036 /** A value if we got a correct parsing */ 037 public static final int PARSING_OK = 0; 038 039 /** If an hex pair contains only one char, this value is returned */ 040 public static final int BAD_HEX_PAIR = -2; 041 042 /** A constant representing one char length */ 043 public static final int ONE_CHAR = 1; 044 045 /** A constant representing two chars length */ 046 public static final int TWO_CHARS = 2; 047 048 /** A constant representing one byte length */ 049 public static final int ONE_BYTE = 1; 050 051 /** A constant representing two bytes length */ 052 public static final int TWO_BYTES = 2; 053 054 /** 055 * <safe-init-char> ::= [0x01-0x09] | 0x0B | 0x0C | [0x0E-0x1F] | 056 * [0x21-0x39] | 0x3B | [0x3D-0x7F] 057 */ 058 private static final boolean[] SAFE_INIT_CHAR = 059 { 060 false, true, true, true, true, true, true, true, 061 true, true, false, true, true, false, true, true, 062 true, true, true, true, true, true, true, true, 063 true, true, true, true, true, true, true, true, 064 false, true, true, true, true, true, true, true, 065 true, true, true, true, true, true, true, true, 066 true, true, true, true, true, true, true, true, 067 true, true, false, true, false, true, true, true, 068 true, true, true, true, true, true, true, true, 069 true, true, true, true, true, true, true, true, 070 true, true, true, true, true, true, true, true, 071 true, true, true, true, true, true, true, true, 072 true, true, true, true, true, true, true, true, 073 true, true, true, true, true, true, true, true, 074 true, true, true, true, true, true, true, true, 075 true, true, true, true, true, true, true, true 076 }; 077 078 /** <safe-char> ::= [0x01-0x09] | 0x0B | 0x0C | [0x0E-0x7F] */ 079 private static final boolean[] SAFE_CHAR = 080 { 081 false, true, true, true, true, true, true, true, 082 true, true, false, true, true, false, true, true, 083 true, true, true, true, true, true, true, true, 084 true, true, true, true, true, true, true, true, 085 true, true, true, true, true, true, true, true, 086 true, true, true, true, true, true, true, true, 087 true, true, true, true, true, true, true, true, 088 true, true, true, true, true, true, true, true, 089 true, true, true, true, true, true, true, true, 090 true, true, true, true, true, true, true, true, 091 true, true, true, true, true, true, true, true, 092 true, true, true, true, true, true, true, true, 093 true, true, true, true, true, true, true, true, 094 true, true, true, true, true, true, true, true, 095 true, true, true, true, true, true, true, true, 096 true, true, true, true, true, true, true, true, 097 }; 098 099 /** 100 * <base64-char> ::= 0x2B | 0x2F | [0x30-0x39] | 0x3D | [0x41-0x5A] | 101 * [0x61-0x7A] 102 */ 103 private static final boolean[] BASE64_CHAR = 104 { 105 false, false, false, false, false, false, false, false, 106 false, false, false, false, false, false, false, false, 107 false, false, false, false, false, false, false, false, 108 false, false, false, false, false, false, false, false, 109 false, false, false, false, false, false, false, false, 110 false, false, false, true, false, false, false, true, 111 true, true, true, true, true, true, true, true, 112 true, true, false, false, false, true, false, false, 113 false, true, true, true, true, true, true, true, 114 true, true, true, true, true, true, true, true, 115 true, true, true, true, true, true, true, true, 116 true, true, true, false, false, false, false, false, 117 false, true, true, true, true, true, true, true, 118 true, true, true, true, true, true, true, true, 119 true, true, true, true, true, true, true, true, 120 true, true, true, false, false, false, false, false 121 }; 122 123 /** 124 * ' ' | '"' | '#' | '+' | ',' | [0-9] | ';' | '<' | '=' | '>' | [A-F] | '\' | [a-f] 125 * 0x22 | 0x23 | 0x2B | 0x2C | [0x30-0x39] | 0x3B | 0x3C | 0x3D | 0x3E | 126 * [0x41-0x46] | 0x5C | [0x61-0x66] 127 */ 128 private static final boolean[] PAIR_CHAR = 129 { 130 false, false, false, false, false, false, false, false, // 00 -> 07 131 false, false, false, false, false, false, false, false, // 08 -> 0F 132 false, false, false, false, false, false, false, false, // 10 -> 17 133 false, false, false, false, false, false, false, false, // 18 -> 1F 134 true, false, true, true, false, false, false, false, // 20 -> 27 ( ' ', '"', '#' ) 135 false, false, false, true, true, false, false, false, // 28 -> 2F ( '+', ',' ) 136 true, true, true, true, true, true, true, true, // 30 -> 37 ( '0'..'7' ) 137 true, true, false, true, true, true, true, false, // 38 -> 3F ( '8', '9', ';', '<', '=', '>' ) 138 false, true, true, true, true, true, true, false, // 40 -> 47 ( 'A', 'B', 'C', 'D', 'E', 'F' ) 139 false, false, false, false, false, false, false, false, // 48 -> 4F 140 false, false, false, false, false, false, false, false, // 50 -> 57 141 false, false, false, false, true, false, false, false, // 58 -> 5F ( '\' ) 142 false, true, true, true, true, true, true, false, // 60 -> 67 ( 'a', 'b', 'c', 'd', 'e', 'f' ) 143 false, false, false, false, false, false, false, false, // 68 -> 6F 144 false, false, false, false, false, false, false, false, // 70 -> 77 145 false, false, false, false, false, false, false, false // 78 -> 7F 146 }; 147 148 149 /** 150 * [0x01-0x1F] | 0x21 | [0x24-0x2A] | [0x2D-0x3A] | 0x3D | [0x3F-0x5B] | [0x5D-0x7F] 151 */ 152 private static final boolean[] LUTF1 = 153 { 154 false, true, true, true, true, true, true, true, // 00 -> 07 '\0' 155 true, true, true, true, true, true, true, true, // 08 -> 0F 156 true, true, true, true, true, true, true, true, // 10 -> 17 157 true, true, true, true, true, true, true, true, // 18 -> 1F 158 false, true, false, false, true, true, true, true, // 20 -> 27 ( ' ', '"', '#' ) 159 true, true, true, false, false, true, true, true, // 28 -> 2F ( '+', ',' ) 160 true, true, true, true, true, true, true, true, // 30 -> 37 161 true, true, true, false, false, true, false, true, // 38 -> 3F ( ';', '<', '>' ) 162 true, true, true, true, true, true, true, true, // 40 -> 47 163 true, true, true, true, true, true, true, true, // 48 -> 4F 164 true, true, true, true, true, true, true, true, // 50 -> 57 165 true, true, true, true, false, true, true, true, // 58 -> 5F ( '\' ) 166 true, true, true, true, true, true, true, true, // 60 -> 67 167 true, true, true, true, true, true, true, true, // 68 -> 6F 168 true, true, true, true, true, true, true, true, // 70 -> 77 169 true, true, true, true, true, true, true, true // 78 -> 7F 170 }; 171 172 173 /** 174 * [0x01-0x21] | [0x23-0x2A] | [0x2D-0x3A] | 0x3D | [0x3F-0x5B] | [0x5D-0x7F] 175 */ 176 private static final boolean[] SUTF1 = 177 { 178 false, true, true, true, true, true, true, true, // 00 -> 07 '\0' 179 true, true, true, true, true, true, true, true, // 08 -> 0F 180 true, true, true, true, true, true, true, true, // 10 -> 17 181 true, true, true, true, true, true, true, true, // 18 -> 1F 182 true, true, false, true, true, true, true, true, // 20 -> 27 ( '"' ) 183 true, true, true, false, false, true, true, true, // 28 -> 2F ( '+', ',' ) 184 true, true, true, true, true, true, true, true, // 30 -> 37 185 true, true, true, false, false, true, false, true, // 38 -> 3F ( ';', '<', '>' ) 186 true, true, true, true, true, true, true, true, // 40 -> 47 187 true, true, true, true, true, true, true, true, // 48 -> 4F 188 true, true, true, true, true, true, true, true, // 50 -> 57 189 true, true, true, true, false, true, true, true, // 58 -> 5F ( '\' ) 190 true, true, true, true, true, true, true, true, // 60 -> 67 191 true, true, true, true, true, true, true, true, // 68 -> 6F 192 true, true, true, true, true, true, true, true, // 70 -> 77 193 true, true, true, true, true, true, true, true // 78 -> 7F 194 }; 195 196 197 /** 198 * ' ' | '"' | '#' | '+' | ',' | ';' | '<' | '=' | '>' | '\' | 199 * 0x22 | 0x23 | 0x2B | 0x2C | 0x3B | 0x3C | 0x3D | 0x3E | 0x5C 200 */ 201 private static final boolean[] PAIR_CHAR_ONLY = 202 { 203 false, false, false, false, false, false, false, false, // 00 -> 07 204 false, false, false, false, false, false, false, false, // 08 -> 0F 205 false, false, false, false, false, false, false, false, // 10 -> 17 206 false, false, false, false, false, false, false, false, // 18 -> 1F 207 true, false, true, true, false, false, false, false, // 20 -> 27 ( ' ', '"', '#' ) 208 false, false, false, true, true, false, false, false, // 28 -> 2F ( '+', ',' ) 209 false, false, false, false, false, false, false, false, // 30 -> 37 210 false, false, false, true, true, true, true, false, // 38 -> 3F ( ';', '<', '=', '>' ) 211 false, false, false, false, false, false, false, false, // 40 -> 47 212 false, false, false, false, false, false, false, false, // 48 -> 4F 213 false, false, false, false, false, false, false, false, // 50 -> 57 214 false, false, false, false, true, false, false, false, // 58 -> 5F ( '\' ) 215 false, false, false, false, false, false, false, false, // 60 -> 67 216 false, false, false, false, false, false, false, false, // 68 -> 6F 217 false, false, false, false, false, false, false, false, // 70 -> 77 218 false, false, false, false, false, false, false, false // 78 -> 7F 219 }; 220 221 /** 222 * '"' | '#' | '+' | ',' | [0-9] | ';' | '<' | '=' | '>' | [A-F] | '\' | 223 * [a-f] 0x22 | 0x23 | 0x2B | 0x2C | [0x30-0x39] | 0x3B | 0x3C | 0x3D | 0x3E | 224 * [0x41-0x46] | 0x5C | [0x61-0x66] 225 */ 226 private static final int[] STRING_CHAR = 227 { 228 ONE_CHAR, ONE_CHAR, ONE_CHAR, ONE_CHAR, // 00 -> 03 229 ONE_CHAR, ONE_CHAR, ONE_CHAR, ONE_CHAR, // 04 -> 07 230 ONE_CHAR, ONE_CHAR, PARSING_ERROR, ONE_CHAR, // 08 -> 0B 231 ONE_CHAR, PARSING_ERROR, ONE_CHAR, ONE_CHAR, // 0C -> 0F 232 ONE_CHAR, ONE_CHAR, ONE_CHAR, ONE_CHAR, // 10 -> 13 233 ONE_CHAR, ONE_CHAR, ONE_CHAR, ONE_CHAR, // 14 -> 17 234 ONE_CHAR, ONE_CHAR, ONE_CHAR, ONE_CHAR, // 18 -> 1B 235 ONE_CHAR, ONE_CHAR, ONE_CHAR, ONE_CHAR, // 1C -> 1F 236 ONE_CHAR, ONE_CHAR, PARSING_ERROR, ONE_CHAR, // 20 -> 23 237 ONE_CHAR, ONE_CHAR, ONE_CHAR, ONE_CHAR, // 24 -> 27 238 ONE_CHAR, ONE_CHAR, ONE_CHAR, PARSING_ERROR,// 28 -> 2B 239 PARSING_ERROR, ONE_CHAR, ONE_CHAR, ONE_CHAR, // 2C -> 2F 240 ONE_CHAR, ONE_CHAR, ONE_CHAR, ONE_CHAR, // 30 -> 33 241 ONE_CHAR, ONE_CHAR, ONE_CHAR, ONE_CHAR, // 34 -> 37 242 ONE_CHAR, ONE_CHAR, ONE_CHAR, PARSING_ERROR,// 38 -> 3B 243 PARSING_ERROR, ONE_CHAR, PARSING_ERROR, ONE_CHAR // 3C -> 3F 244 }; 245 246 /** "oid." static */ 247 public static final String OID_LOWER = "oid."; 248 249 /** "OID." static */ 250 public static final String OID_UPPER = "OID."; 251 252 // ~ Methods 253 // ------------------------------------------------------------------------------------ 254 255 /** 256 * Walk the buffer while characters are Safe String characters : 257 * <safe-string> ::= <safe-init-char> <safe-chars> <safe-init-char> ::= 258 * [0x01-0x09] | 0x0B | 0x0C | [0x0E-0x1F] | [0x21-0x39] | 0x3B | 259 * [0x3D-0x7F] <safe-chars> ::= <safe-char> <safe-chars> | <safe-char> ::= 260 * [0x01-0x09] | 0x0B | 0x0C | [0x0E-0x7F] 261 * 262 * @param bytes The buffer which contains the data 263 * @param index Current position in the buffer 264 * @return The position of the first character which is not a Safe Char 265 */ 266 public static int parseSafeString( byte[] bytes, int index ) 267 { 268 if ( ( bytes == null ) || ( bytes.length == 0 ) || ( index < 0 ) || ( index >= bytes.length ) ) 269 { 270 return -1; 271 } 272 else 273 { 274 byte c = bytes[index]; 275 276 if ( ( ( c | 0x7F ) != 0x7F ) || ( !SAFE_INIT_CHAR[c] ) ) 277 { 278 return -1; 279 } 280 281 index++; 282 283 while ( index < bytes.length ) 284 { 285 c = bytes[index]; 286 287 if ( ( ( c | 0x7F ) != 0x7F ) || ( !SAFE_CHAR[c] ) ) 288 { 289 break; 290 } 291 292 index++; 293 } 294 295 return index; 296 } 297 } 298 299 300 /** 301 * Walk the buffer while characters are Alpha characters : <alpha> ::= 302 * [0x41-0x5A] | [0x61-0x7A] 303 * 304 * @param bytes The buffer which contains the data 305 * @param index Current position in the buffer 306 * @return The position of the first character which is not an Alpha Char 307 */ 308 public static int parseAlphaASCII( byte[] bytes, int index ) 309 { 310 if ( ( bytes == null ) || ( bytes.length == 0 ) || ( index < 0 ) || ( index >= bytes.length ) ) 311 { 312 return -1; 313 } 314 else 315 { 316 byte b = bytes[index++]; 317 318 if ( StringTools.isAlpha( b ) ) 319 { 320 return index-1; 321 } 322 else 323 { 324 return -1; 325 } 326 } 327 } 328 329 330 /** 331 * Check if the current character is a LUTF1 (Lead UTF ascii char)<br/> 332 * <LUTF1> ::= 0x01-1F | 0x21 | 0x24-2A | 0x2D-3A | 0x3D | 0x3F-5B | 0x5D-7F 333 * 334 * @param bytes The buffer containing the data 335 * @param index Current position in the buffer 336 * @return <code>true</code> if the current character is a LUTF1 337 */ 338 public static boolean isLUTF1( byte[] bytes, int index ) 339 { 340 if ( ( bytes == null ) || ( bytes.length == 0 ) || ( index < 0 ) || ( index >= bytes.length ) ) 341 { 342 return false; 343 } 344 345 byte c = bytes[index]; 346 return ( ( ( c | 0x7F ) == 0x7F ) && LUTF1[c & 0x7f] ); 347 } 348 349 350 /** 351 * Check if the current character is a SUTF1 (Stringchar UTF ascii char)<br/> 352 * <LUTF1> ::= 0x01-20 | 0x23-2A | 0x2D-3A | 0x3D | 0x3F-5B | 0x5D-7F 353 * 354 * @param bytes The buffer containing the data 355 * @param index Current position in the buffer 356 * @return <code>true</code> if the current character is a SUTF1 357 */ 358 public static boolean isSUTF1( byte[] bytes, int index ) 359 { 360 if ( ( bytes == null ) || ( bytes.length == 0 ) || ( index < 0 ) || ( index >= bytes.length ) ) 361 { 362 return false; 363 } 364 365 byte c = bytes[index]; 366 return ( ( ( c | 0x7F ) == 0x7F ) && SUTF1[c & 0x7f] ); 367 } 368 369 370 /** 371 * Check if the given char is a pair char only 372 * <pairCharOnly> ::= ' ' | ',' | '=' | '+' | '<' | '>' | '#' | ';' | '\' | '"' 373 * 374 * @param c the char we want to test 375 * @return true if the char is a pair char only 376 */ 377 public static boolean isPairCharOnly( char c ) 378 { 379 return ( ( ( c | 0x7F ) == 0x7F ) && PAIR_CHAR_ONLY[c & 0x7f] ); 380 } 381 382 383 /** 384 * Check if the current character is a Pair Char 385 * <pairchar> ::= ' ' | ',' | '=' | '+' | '<' | '>' | '#' | ';' | '\' | '"' | [0-9a-fA-F] [0-9a-fA-F] 386 * 387 * @param bytes The buffer which contains the data 388 * @param index Current position in the buffer 389 * @return <code>true</code> if the current character is a Pair Char 390 */ 391 public static boolean isPairChar( byte[] bytes, int index ) 392 { 393 if ( ( bytes == null ) || ( bytes.length == 0 ) || ( index < 0 ) || ( index >= bytes.length ) ) 394 { 395 return false; 396 } 397 else 398 { 399 byte c = bytes[index]; 400 401 if ( ( ( c | 0x7F ) != 0x7F ) || ( !PAIR_CHAR[c] ) ) 402 { 403 return false; 404 } 405 else 406 { 407 if ( PAIR_CHAR_ONLY[c] ) 408 { 409 return true; 410 } 411 else if ( StringTools.isHex( bytes, index++ ) ) 412 { 413 return StringTools.isHex( bytes, index ); 414 } 415 else 416 { 417 return false; 418 } 419 } 420 } 421 } 422 423 424 /** 425 * Check if the current character is a Pair Char 426 * 427 * <pairchar> ::= ' ' | ',' | '=' | '+' | '<' | '>' | '#' | ';' | 428 * '\' | '"' | [0-9a-fA-F] [0-9a-fA-F] 429 * 430 * @param bytes The byte array which contains the data 431 * @param index Current position in the byte array 432 * @return <code>true</code> if the current byte is a Pair Char 433 */ 434 public static int countPairChar( byte[] bytes, int index ) 435 { 436 if ( bytes == null ) 437 { 438 return PARSING_ERROR; 439 } 440 441 int length = bytes.length; 442 443 if ( ( length == 0 ) || ( index < 0 ) || ( index >= length ) ) 444 { 445 return PARSING_ERROR; 446 } 447 else 448 { 449 byte c = bytes[index]; 450 451 if ( ( ( c | 0x7F ) != 0x7F ) || ( !PAIR_CHAR[c] ) ) 452 { 453 return PARSING_ERROR; 454 } 455 else 456 { 457 if ( PAIR_CHAR_ONLY[c] ) 458 { 459 return 1; 460 } 461 else if ( StringTools.isHex( bytes, index++ ) ) 462 { 463 return StringTools.isHex( bytes, index ) ? 2 : PARSING_ERROR; 464 } 465 else 466 { 467 return PARSING_ERROR; 468 } 469 } 470 } 471 } 472 473 474 /** 475 * Check if the current character is a String Char. Chars are Unicode, not 476 * ASCII. <stringchar> ::= [0x00-0xFFFF] - [,=+<>#;\"\n\r] 477 * 478 * @param bytes The buffer which contains the data 479 * @param index Current position in the buffer 480 * @return The current char if it is a String Char, or '#' (this is simpler 481 * than throwing an exception :) 482 */ 483 public static int isStringChar( byte[] bytes, int index ) 484 { 485 if ( ( bytes == null ) || ( bytes.length == 0 ) || ( index < 0 ) || ( index >= bytes.length ) ) 486 { 487 return -1; 488 } 489 else 490 { 491 byte c = bytes[index]; 492 493 if ( ( c | 0x3F ) == 0x3F ) 494 { 495 return STRING_CHAR[ c ]; 496 } 497 else 498 { 499 return StringTools.countBytesPerChar( bytes, index ); 500 } 501 } 502 } 503 504 505 /** 506 * Check if the current character is an ascii String Char.<br/> 507 * <p> 508 * <asciistringchar> ::= [0x00-0x7F] - [,=+<>#;\"\n\r] 509 * </p> 510 * 511 * @param bytes The buffer which contains the data 512 * @param index Current position in the buffer 513 * @return The current char if it is a String Char, or '#' (this is simpler 514 * than throwing an exception :) 515 */ 516 public static int isAciiStringChar( byte[] bytes, int index ) 517 { 518 if ( ( bytes == null ) || ( bytes.length == 0 ) || ( index < 0 ) || ( index >= bytes.length ) ) 519 { 520 return -1; 521 } 522 else 523 { 524 byte c = bytes[index]; 525 526 if ( ( c | 0x3F ) == 0x3F ) 527 { 528 return STRING_CHAR[ c ]; 529 } 530 else 531 { 532 return StringTools.countBytesPerChar( bytes, index ); 533 } 534 } 535 } 536 537 538 /** 539 * Check if the current character is a Quote Char We are testing Unicode 540 * chars <quotechar> ::= [0x00-0xFFFF] - [\"] 541 * 542 * @param bytes The buffer which contains the data 543 * @param index Current position in the buffer 544 * 545 * @return <code>true</code> if the current character is a Quote Char 546 */ 547 public static int isQuoteChar( byte[] bytes, int index ) 548 { 549 if ( ( bytes == null ) || ( bytes.length == 0 ) || ( index < 0 ) || ( index >= bytes.length ) ) 550 { 551 return -1; 552 } 553 else 554 { 555 byte c = bytes[index]; 556 557 if ( ( c == '\\' ) || ( c == '"' ) ) 558 { 559 return -1; 560 } 561 else 562 { 563 return StringTools.countBytesPerChar( bytes, index ); 564 } 565 } 566 } 567 568 569 /** 570 * Parse an hex pair <hexpair> ::= <hex> <hex> 571 * 572 * @param bytes The buffer which contains the data 573 * @param index Current position in the buffer 574 * @return The new position, -1 if the buffer does not contain an HexPair, 575 * -2 if the buffer contains an hex byte but not two. 576 */ 577 public static int parseHexPair( byte[] bytes, int index ) 578 { 579 if ( StringTools.isHex( bytes, index ) ) 580 { 581 if ( StringTools.isHex( bytes, index + 1 ) ) 582 { 583 return index + 2; 584 } 585 else 586 { 587 return -2; 588 } 589 } 590 else 591 { 592 return -1; 593 } 594 } 595 596 597 /** 598 * Parse an hex pair <hexpair> ::= <hex> <hex> 599 * 600 * @param bytes The byte array which contains the data 601 * @param index Current position in the byte array 602 * @return The new position, -1 if the byte array does not contain an HexPair, 603 * -2 if the byte array contains an hex byte but not two. 604 */ 605 private static byte getHexPair( byte[] bytes, int index ) 606 { 607 return StringTools.getHexValue( bytes[index], bytes[index + 1] ); 608 } 609 610 611 /** 612 * Parse an hex string, which is a list of hex pairs <hexstring> ::= 613 * <hexpair> <hexpairs> <hexpairs> ::= <hexpair> <hexpairs> | e 614 * 615 * @param bytes The buffer which contains the data 616 * @param index Current position in the buffer 617 * @return Return the first position which is not an hex pair, or -1 if 618 * there is no hexpair at the beginning or if an hexpair is invalid 619 * (if we have only one hex instead of 2) 620 */ 621 public static int parseHexString( byte[] bytes, int index ) 622 { 623 int result = parseHexPair( bytes, index ); 624 625 if ( result < 0 ) 626 { 627 return -1; 628 } 629 else 630 { 631 index += 2; 632 } 633 634 while ( ( result = parseHexPair( bytes, index ) ) >= 0 ) 635 { 636 index += 2; 637 } 638 639 return ( ( result == -2 ) ? -1 : index ); 640 } 641 642 643 /** 644 * Parse an hex string, which is a list of hex pairs <hexstring> ::= 645 * <hexpair> <hexpairs> <hexpairs> ::= <hexpair> <hexpairs> | e 646 * 647 * @param bytes The byte array which contains the data 648 * @param hex The result as a byte array 649 * @param pos Current position in the string 650 * @return Return the first position which is not an hex pair, or -1 if 651 * there is no hexpair at the beginning or if an hexpair is invalid 652 * (if we have only one hex instead of 2) 653 */ 654 public static int parseHexString( byte[] bytes, byte[] hex, Position pos ) 655 { 656 int i = 0; 657 pos.end = pos.start; 658 int result = parseHexPair( bytes, pos.start ); 659 660 if ( result < 0 ) 661 { 662 return PARSING_ERROR; 663 } 664 else 665 { 666 hex[i++] = getHexPair( bytes, pos.end ); 667 pos.end += TWO_CHARS; 668 } 669 670 while ( ( result = parseHexPair( bytes, pos.end ) ) >= 0 ) 671 { 672 hex[i++] = getHexPair( bytes, pos.end ); 673 pos.end += TWO_CHARS; 674 } 675 676 return ( ( result == BAD_HEX_PAIR ) ? PARSING_ERROR : PARSING_OK ); 677 } 678 679 680 /** 681 * Walk the buffer while characters are Base64 characters : <base64-string> 682 * ::= <base64-char> <base64-chars> <base64-chars> ::= <base64-char> 683 * <base64-chars> | <base64-char> ::= 0x2B | 0x2F | [0x30-0x39] | 0x3D | 684 * [0x41-0x5A] | [0x61-0x7A] 685 * 686 * @param bytes The buffer which contains the data 687 * @param index Current position in the buffer 688 * @return The position of the first character which is not a Base64 Char 689 */ 690 public static int parseBase64String( byte[] bytes, int index ) 691 { 692 if ( ( bytes == null ) || ( bytes.length == 0 ) || ( index < 0 ) || ( index >= bytes.length ) ) 693 { 694 return -1; 695 } 696 else 697 { 698 byte c = bytes[index]; 699 700 if ( ( ( c | 0x7F ) != 0x7F ) || ( !BASE64_CHAR[c] ) ) 701 { 702 return -1; 703 } 704 705 index++; 706 707 while ( index < bytes.length ) 708 { 709 c = bytes[index]; 710 711 if ( ( ( c | 0x7F ) != 0x7F ) || ( !BASE64_CHAR[c] ) ) 712 { 713 break; 714 } 715 716 index++; 717 } 718 719 return index; 720 } 721 } 722 }