353 ftype = LDAP_FILTER_EXT; |
354 ftype = LDAP_FILTER_EXT; |
354 typeEnd = eq - 1; |
355 typeEnd = eq - 1; |
355 break; |
356 break; |
356 default: |
357 default: |
357 typeEnd = eq; |
358 typeEnd = eq; |
|
359 //initializing ftype to make the compiler happy |
|
360 ftype = 0x00; |
|
361 break; |
|
362 } |
|
363 |
|
364 if (dbg) { |
|
365 System.err.println("type: " + typeStart + ", " + typeEnd); |
|
366 System.err.println("value: " + valueStart + ", " + valueEnd); |
|
367 } |
|
368 |
|
369 // check validity of type |
|
370 // |
|
371 // RFC4512 defines the type as the following ABNF: |
|
372 // attr = attributedescription |
|
373 // attributedescription = attributetype options |
|
374 // attributetype = oid |
|
375 // oid = descr / numericoid |
|
376 // descr = keystring |
|
377 // keystring = leadkeychar *keychar |
|
378 // leadkeychar = ALPHA |
|
379 // keychar = ALPHA / DIGIT / HYPHEN |
|
380 // numericoid = number 1*( DOT number ) |
|
381 // number = DIGIT / ( LDIGIT 1*DIGIT ) |
|
382 // options = *( SEMI option ) |
|
383 // option = 1*keychar |
|
384 // |
|
385 // And RFC4515 defines the extensible type as the following ABNF: |
|
386 // attr [dnattrs] [matchingrule] / [dnattrs] matchingrule |
|
387 int optionsStart = -1; |
|
388 int extensibleStart = -1; |
|
389 if ((filter[typeStart] >= '0' && filter[typeStart] <= '9') || |
|
390 (filter[typeStart] >= 'A' && filter[typeStart] <= 'Z') || |
|
391 (filter[typeStart] >= 'a' && filter[typeStart] <= 'z')) { |
|
392 |
|
393 boolean isNumericOid = |
|
394 filter[typeStart] >= '0' && filter[typeStart] <= '9'; |
|
395 for (int i = typeStart + 1; i < typeEnd; i++) { |
|
396 // ';' is an indicator of attribute options |
|
397 if (filter[i] == ';') { |
|
398 if (isNumericOid && filter[i - 1] == '.') { |
|
399 throw new InvalidSearchFilterException( |
|
400 "invalid attribute description"); |
|
401 } |
|
402 |
|
403 // attribute options |
|
404 optionsStart = i; |
|
405 break; |
|
406 } |
|
407 |
|
408 // ':' is an indicator of extensible rules |
|
409 if (filter[i] == ':' && ftype == LDAP_FILTER_EXT) { |
|
410 if (isNumericOid && filter[i - 1] == '.') { |
|
411 throw new InvalidSearchFilterException( |
|
412 "invalid attribute description"); |
|
413 } |
|
414 |
|
415 // extensible matching |
|
416 extensibleStart = i; |
|
417 break; |
|
418 } |
|
419 |
|
420 if (isNumericOid) { |
|
421 // numeric object identifier |
|
422 if ((filter[i] == '.' && filter[i - 1] == '.') || |
|
423 (filter[i] != '.' && |
|
424 !(filter[i] >= '0' && filter[i] <= '9'))) { |
|
425 throw new InvalidSearchFilterException( |
|
426 "invalid attribute description"); |
|
427 } |
|
428 } else { |
|
429 // descriptor |
|
430 if (filter[i] != '-' && |
|
431 !(filter[i] >= '0' && filter[i] <= '9') && |
|
432 !(filter[i] >= 'A' && filter[i] <= 'Z') && |
|
433 !(filter[i] >= 'a' && filter[i] <= 'z')) { |
|
434 throw new InvalidSearchFilterException( |
|
435 "invalid attribute description"); |
|
436 } |
|
437 } |
|
438 } |
|
439 } else if (ftype == LDAP_FILTER_EXT && filter[typeStart] == ':') { |
|
440 // extensible matching |
|
441 extensibleStart = typeStart; |
|
442 } else { |
|
443 throw new InvalidSearchFilterException( |
|
444 "invalid attribute description"); |
|
445 } |
|
446 |
|
447 // check attribute options |
|
448 if (optionsStart > 0) { |
|
449 for (int i = optionsStart + 1; i < typeEnd; i++) { |
|
450 if (filter[i] == ';') { |
|
451 if (filter[i - 1] == ';') { |
|
452 throw new InvalidSearchFilterException( |
|
453 "invalid attribute description"); |
|
454 } |
|
455 continue; |
|
456 } |
|
457 |
|
458 // ':' is an indicator of extensible rules |
|
459 if (filter[i] == ':' && ftype == LDAP_FILTER_EXT) { |
|
460 if (filter[i - 1] == ';') { |
|
461 throw new InvalidSearchFilterException( |
|
462 "invalid attribute description"); |
|
463 } |
|
464 |
|
465 // extensible matching |
|
466 extensibleStart = i; |
|
467 break; |
|
468 } |
|
469 |
|
470 if (filter[i] != '-' && |
|
471 !(filter[i] >= '0' && filter[i] <= '9') && |
|
472 !(filter[i] >= 'A' && filter[i] <= 'Z') && |
|
473 !(filter[i] >= 'a' && filter[i] <= 'z')) { |
|
474 throw new InvalidSearchFilterException( |
|
475 "invalid attribute description"); |
|
476 } |
|
477 } |
|
478 } |
|
479 |
|
480 // check extensible matching |
|
481 if (extensibleStart > 0) { |
|
482 boolean isMatchingRule = false; |
|
483 for (int i = extensibleStart + 1; i < typeEnd; i++) { |
|
484 if (filter[i] == ':') { |
|
485 throw new InvalidSearchFilterException( |
|
486 "invalid attribute description"); |
|
487 } else if ((filter[i] >= '0' && filter[i] <= '9') || |
|
488 (filter[i] >= 'A' && filter[i] <= 'Z') || |
|
489 (filter[i] >= 'a' && filter[i] <= 'z')) { |
|
490 boolean isNumericOid = filter[i] >= '0' && filter[i] <= '9'; |
|
491 i++; |
|
492 for (int j = i; j < typeEnd; j++, i++) { |
|
493 // allows no more than two extensible rules |
|
494 if (filter[j] == ':') { |
|
495 if (isMatchingRule) { |
|
496 throw new InvalidSearchFilterException( |
|
497 "invalid attribute description"); |
|
498 } |
|
499 if (isNumericOid && filter[j - 1] == '.') { |
|
500 throw new InvalidSearchFilterException( |
|
501 "invalid attribute description"); |
|
502 } |
|
503 |
|
504 isMatchingRule = true; |
|
505 break; |
|
506 } |
|
507 |
|
508 if (isNumericOid) { |
|
509 // numeric object identifier |
|
510 if ((filter[j] == '.' && filter[j - 1] == '.') || |
|
511 (filter[j] != '.' && |
|
512 !(filter[j] >= '0' && filter[j] <= '9'))) { |
|
513 throw new InvalidSearchFilterException( |
|
514 "invalid attribute description"); |
|
515 } |
|
516 } else { |
|
517 // descriptor |
|
518 if (filter[j] != '-' && |
|
519 !(filter[j] >= '0' && filter[j] <= '9') && |
|
520 !(filter[j] >= 'A' && filter[j] <= 'Z') && |
|
521 !(filter[j] >= 'a' && filter[j] <= 'z')) { |
|
522 throw new InvalidSearchFilterException( |
|
523 "invalid attribute description"); |
|
524 } |
|
525 } |
|
526 } |
|
527 } else { |
|
528 throw new InvalidSearchFilterException( |
|
529 "invalid attribute description"); |
|
530 } |
|
531 } |
|
532 } |
|
533 |
|
534 // ensure the latest byte is not isolated |
|
535 if (filter[typeEnd - 1] == '.' || filter[typeEnd - 1] == ';' || |
|
536 filter[typeEnd - 1] == ':') { |
|
537 throw new InvalidSearchFilterException( |
|
538 "invalid attribute description"); |
|
539 } |
|
540 |
|
541 if (typeEnd == eq) { // filter type is of "equal" |
358 if (findUnescaped(filter, '*', valueStart, valueEnd) == -1) { |
542 if (findUnescaped(filter, '*', valueStart, valueEnd) == -1) { |
359 ftype = LDAP_FILTER_EQUALITY; |
543 ftype = LDAP_FILTER_EQUALITY; |
360 } else if (filter[valueStart] == '*' && valueStart == (valueEnd - 1)) { |
544 } else if (filter[valueStart] == '*' && |
|
545 valueStart == (valueEnd - 1)) { |
361 ftype = LDAP_FILTER_PRESENT; |
546 ftype = LDAP_FILTER_PRESENT; |
362 } else { |
547 } else { |
363 encodeSubstringFilter(ber, filter, |
548 encodeSubstringFilter(ber, filter, |
364 typeStart, typeEnd, valueStart, valueEnd); |
549 typeStart, typeEnd, valueStart, valueEnd); |
365 return; |
550 return; |
366 } |
551 } |
367 break; |
|
368 } |
|
369 if (dbg) { |
|
370 System.err.println("type: " + typeStart + ", " + typeEnd); |
|
371 System.err.println("value: " + valueStart + ", " + valueEnd); |
|
372 } |
552 } |
373 |
553 |
374 if (ftype == LDAP_FILTER_PRESENT) { |
554 if (ftype == LDAP_FILTER_PRESENT) { |
375 ber.encodeOctetString(filter, ftype, typeStart, typeEnd-typeStart); |
555 ber.encodeOctetString(filter, ftype, typeStart, typeEnd-typeStart); |
376 } else if (ftype == LDAP_FILTER_EXT) { |
556 } else if (ftype == LDAP_FILTER_EXT) { |
377 encodeExtensibleMatch(ber, filter, |
557 encodeExtensibleMatch(ber, filter, |
378 typeStart, typeEnd, valueStart, valueEnd); |
558 typeStart, typeEnd, valueStart, valueEnd); |
379 } else { |
559 } else { |
380 ber.beginSeq(ftype); |
560 ber.beginSeq(ftype); |
381 ber.encodeOctetString(filter, Ber.ASN_OCTET_STR, |
561 ber.encodeOctetString(filter, Ber.ASN_OCTET_STR, |
382 typeStart, typeEnd-typeStart); |
562 typeStart, typeEnd - typeStart); |
383 ber.encodeOctetString( |
563 ber.encodeOctetString( |
384 unescapeFilterValue(filter, valueStart, valueEnd), |
564 unescapeFilterValue(filter, valueStart, valueEnd), |
385 Ber.ASN_OCTET_STR); |
565 Ber.ASN_OCTET_STR); |
386 ber.endSeq(); |
566 ber.endSeq(); |
387 } |
567 } |