|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
package com.sun.jndi.ldap; |
|
|
|
import javax.naming.NamingException; |
|
import javax.naming.directory.InvalidSearchFilterException; |
|
|
|
import java.io.IOException; |
|
|
|
/** |
|
* LDAP (RFC-1960) and LDAPv3 (RFC-2254) search filters. |
|
* |
|
* @author Xuelei Fan |
|
* @author Vincent Ryan |
|
* @author Jagane Sundar |
|
* @author Rosanna Lee |
|
*/ |
|
|
|
final class Filter { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
static void encodeFilterString(BerEncoder ber, String filterStr, |
|
boolean isLdapv3) throws IOException, NamingException { |
|
|
|
if ((filterStr == null) || (filterStr.equals(""))) { |
|
throw new InvalidSearchFilterException("Empty filter"); |
|
} |
|
byte[] filter; |
|
int filterLen; |
|
if (isLdapv3) { |
|
filter = filterStr.getBytes("UTF8"); |
|
} else { |
|
filter = filterStr.getBytes("8859_1"); |
|
} |
|
filterLen = filter.length; |
|
if (dbg) { |
|
dbgIndent = 0; |
|
System.err.println("String filter: " + filterStr); |
|
System.err.println("size: " + filterLen); |
|
dprint("original: ", filter, 0, filterLen); |
|
} |
|
|
|
encodeFilter(ber, filter, 0, filterLen); |
|
} |
|
|
|
private static void encodeFilter(BerEncoder ber, byte[] filter, |
|
int filterStart, int filterEnd) throws IOException, NamingException { |
|
|
|
if (dbg) { |
|
dprint("encFilter: ", filter, filterStart, filterEnd); |
|
dbgIndent++; |
|
} |
|
|
|
if ((filterEnd - filterStart) <= 0) { |
|
throw new InvalidSearchFilterException("Empty filter"); |
|
} |
|
|
|
int nextOffset; |
|
int parens, balance; |
|
boolean escape; |
|
|
|
parens = 0; |
|
|
|
int filtOffset[] = new int[1]; |
|
|
|
for (filtOffset[0] = filterStart; filtOffset[0] < filterEnd;) { |
|
switch (filter[filtOffset[0]]) { |
|
case '(': |
|
filtOffset[0]++; |
|
parens++; |
|
switch (filter[filtOffset[0]]) { |
|
case '&': |
|
encodeComplexFilter(ber, filter, |
|
LDAP_FILTER_AND, filtOffset, filterEnd); |
|
|
|
parens--; |
|
break; |
|
|
|
case '|': |
|
encodeComplexFilter(ber, filter, |
|
LDAP_FILTER_OR, filtOffset, filterEnd); |
|
|
|
parens--; |
|
break; |
|
|
|
case '!': |
|
encodeComplexFilter(ber, filter, |
|
LDAP_FILTER_NOT, filtOffset, filterEnd); |
|
|
|
parens--; |
|
break; |
|
|
|
default: |
|
balance = 1; |
|
escape = false; |
|
nextOffset = filtOffset[0]; |
|
while (nextOffset < filterEnd && balance > 0) { |
|
if (!escape) { |
|
if (filter[nextOffset] == '(') |
|
balance++; |
|
else if (filter[nextOffset] == ')') |
|
balance--; |
|
} |
|
if (filter[nextOffset] == '\\' && !escape) |
|
escape = true; |
|
else |
|
escape = false; |
|
if (balance > 0) |
|
nextOffset++; |
|
} |
|
if (balance != 0) |
|
throw new InvalidSearchFilterException( |
|
"Unbalanced parenthesis"); |
|
|
|
encodeSimpleFilter(ber, filter, filtOffset[0], nextOffset); |
|
|
|
|
|
filtOffset[0] = nextOffset + 1; |
|
|
|
parens--; |
|
break; |
|
|
|
} |
|
break; |
|
|
|
case ')': |
|
// |
|
// End of sequence |
|
|
|
ber.endSeq(); |
|
filtOffset[0]++; |
|
parens--; |
|
break; |
|
|
|
case ' ': |
|
filtOffset[0]++; |
|
break; |
|
|
|
default: |
|
encodeSimpleFilter(ber, filter, filtOffset[0], filterEnd); |
|
filtOffset[0] = filterEnd; |
|
break; |
|
} |
|
|
|
if (parens < 0) { |
|
throw new InvalidSearchFilterException( |
|
"Unbalanced parenthesis"); |
|
} |
|
} |
|
|
|
if (parens != 0) { |
|
throw new InvalidSearchFilterException("Unbalanced parenthesis"); |
|
} |
|
|
|
if (dbg) { |
|
dbgIndent--; |
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
private static int hexchar2int( byte c ) { |
|
if ( c >= '0' && c <= '9' ) { |
|
return( c - '0' ); |
|
} |
|
if ( c >= 'A' && c <= 'F' ) { |
|
return( c - 'A' + 10 ); |
|
} |
|
if ( c >= 'a' && c <= 'f' ) { |
|
return( c - 'a' + 10 ); |
|
} |
|
return( -1 ); |
|
} |
|
|
|
|
|
static byte[] unescapeFilterValue(byte[] orig, int start, int end) |
|
throws NamingException { |
|
boolean escape = false, escStart = false; |
|
int ival; |
|
byte ch; |
|
|
|
if (dbg) { |
|
dprint("unescape: " , orig, start, end); |
|
} |
|
|
|
int len = end - start; |
|
byte tbuf[] = new byte[len]; |
|
int j = 0; |
|
for (int i = start; i < end; i++) { |
|
ch = orig[i]; |
|
if (escape) { |
|
|
|
if ((ival = hexchar2int(ch)) < 0) { |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
if (escStart) { |
|
|
|
escape = false; |
|
tbuf[j++] = ch; |
|
} else { |
|
|
|
throw new InvalidSearchFilterException("invalid escape sequence: " + orig); |
|
} |
|
} else { |
|
if (escStart) { |
|
tbuf[j] = (byte)(ival<<4); |
|
escStart = false; |
|
} else { |
|
tbuf[j++] |= (byte)ival; |
|
escape = false; |
|
} |
|
} |
|
} else if (ch != '\\') { |
|
tbuf[j++] = ch; |
|
escape = false; |
|
} else { |
|
escStart = escape = true; |
|
} |
|
} |
|
byte[] answer = new byte[j]; |
|
System.arraycopy(tbuf, 0, answer, 0, j); |
|
if (dbg) { |
|
Ber.dumpBER(System.err, "", answer, 0, j); |
|
} |
|
return answer; |
|
} |
|
|
|
private static int indexOf(byte[] str, char ch, int start, int end) { |
|
for (int i = start; i < end; i++) { |
|
if (str[i] == ch) |
|
return i; |
|
} |
|
return -1; |
|
} |
|
|
|
private static int indexOf(byte[] str, String target, int start, int end) { |
|
int where = indexOf(str, target.charAt(0), start, end); |
|
if (where >= 0) { |
|
for (int i = 1; i < target.length(); i++) { |
|
if (str[where+i] != target.charAt(i)) { |
|
return -1; |
|
} |
|
} |
|
} |
|
return where; |
|
} |
|
|
|
private static int findUnescaped(byte[] str, char ch, int start, int end) { |
|
while (start < end) { |
|
int where = indexOf(str, ch, start, end); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
int backSlashPos; |
|
int backSlashCnt = 0; |
|
for (backSlashPos = where - 1; |
|
((backSlashPos >= start) && (str[backSlashPos] == '\\')); |
|
backSlashPos--, backSlashCnt++); |
|
|
|
|
|
if (where == start || where == -1 || ((backSlashCnt % 2) == 0)) |
|
return where; |
|
|
|
|
|
start = where + 1; |
|
} |
|
return -1; |
|
} |
|
|
|
|
|
private static void encodeSimpleFilter(BerEncoder ber, byte[] filter, |
|
int filtStart, int filtEnd) throws IOException, NamingException { |
|
|
|
if (dbg) { |
|
dprint("encSimpleFilter: ", filter, filtStart, filtEnd); |
|
dbgIndent++; |
|
} |
|
|
|
String type, value; |
|
int valueStart, valueEnd, typeStart, typeEnd; |
|
|
|
int eq; |
|
if ((eq = indexOf(filter, '=', filtStart, filtEnd)) == -1) { |
|
throw new InvalidSearchFilterException("Missing 'equals'"); |
|
} |
|
|
|
|
|
valueStart = eq + 1; |
|
valueEnd = filtEnd; |
|
typeStart = filtStart; |
|
|
|
int ftype; |
|
|
|
switch (filter[eq - 1]) { |
|
case '<': |
|
ftype = LDAP_FILTER_LE; |
|
typeEnd = eq - 1; |
|
break; |
|
case '>': |
|
ftype = LDAP_FILTER_GE; |
|
typeEnd = eq - 1; |
|
break; |
|
case '~': |
|
ftype = LDAP_FILTER_APPROX; |
|
typeEnd = eq - 1; |
|
break; |
|
case ':': |
|
ftype = LDAP_FILTER_EXT; |
|
typeEnd = eq - 1; |
|
break; |
|
default: |
|
typeEnd = eq; |
|
|
|
ftype = 0x00; |
|
break; |
|
} |
|
|
|
if (dbg) { |
|
System.err.println("type: " + typeStart + ", " + typeEnd); |
|
System.err.println("value: " + valueStart + ", " + valueEnd); |
|
} |
|
|
|
// check validity of type |
|
// |
|
// RFC4512 defines the type as the following ABNF: |
|
// attr = attributedescription |
|
// attributedescription = attributetype options |
|
// attributetype = oid |
|
// oid = descr / numericoid |
|
// descr = keystring |
|
// keystring = leadkeychar *keychar |
|
// leadkeychar = ALPHA |
|
// keychar = ALPHA / DIGIT / HYPHEN |
|
// numericoid = number 1*( DOT number ) |
|
// number = DIGIT / ( LDIGIT 1*DIGIT ) |
|
// options = *( SEMI option ) |
|
// option = 1*keychar |
|
// |
|
// And RFC4515 defines the extensible type as the following ABNF: |
|
|
|
int optionsStart = -1; |
|
int extensibleStart = -1; |
|
if ((filter[typeStart] >= '0' && filter[typeStart] <= '9') || |
|
(filter[typeStart] >= 'A' && filter[typeStart] <= 'Z') || |
|
(filter[typeStart] >= 'a' && filter[typeStart] <= 'z')) { |
|
|
|
boolean isNumericOid = |
|
filter[typeStart] >= '0' && filter[typeStart] <= '9'; |
|
for (int i = typeStart + 1; i < typeEnd; i++) { |
|
|
|
if (filter[i] == ';') { |
|
if (isNumericOid && filter[i - 1] == '.') { |
|
throw new InvalidSearchFilterException( |
|
"invalid attribute description"); |
|
} |
|
|
|
|
|
optionsStart = i; |
|
break; |
|
} |
|
|
|
|
|
if (filter[i] == ':' && ftype == LDAP_FILTER_EXT) { |
|
if (isNumericOid && filter[i - 1] == '.') { |
|
throw new InvalidSearchFilterException( |
|
"invalid attribute description"); |
|
} |
|
|
|
|
|
extensibleStart = i; |
|
break; |
|
} |
|
|
|
if (isNumericOid) { |
|
|
|
if ((filter[i] == '.' && filter[i - 1] == '.') || |
|
(filter[i] != '.' && |
|
!(filter[i] >= '0' && filter[i] <= '9'))) { |
|
throw new InvalidSearchFilterException( |
|
"invalid attribute description"); |
|
} |
|
} else { |
|
// descriptor |
|
// The underscore ("_") character is not allowed by |
|
// the LDAP specification. We allow it here to |
|
|
|
if (filter[i] != '-' && filter[i] != '_' && |
|
!(filter[i] >= '0' && filter[i] <= '9') && |
|
!(filter[i] >= 'A' && filter[i] <= 'Z') && |
|
!(filter[i] >= 'a' && filter[i] <= 'z')) { |
|
throw new InvalidSearchFilterException( |
|
"invalid attribute description"); |
|
} |
|
} |
|
} |
|
} else if (ftype == LDAP_FILTER_EXT && filter[typeStart] == ':') { |
|
|
|
extensibleStart = typeStart; |
|
} else { |
|
throw new InvalidSearchFilterException( |
|
"invalid attribute description"); |
|
} |
|
|
|
|
|
if (optionsStart > 0) { |
|
for (int i = optionsStart + 1; i < typeEnd; i++) { |
|
if (filter[i] == ';') { |
|
if (filter[i - 1] == ';') { |
|
throw new InvalidSearchFilterException( |
|
"invalid attribute description"); |
|
} |
|
continue; |
|
} |
|
|
|
|
|
if (filter[i] == ':' && ftype == LDAP_FILTER_EXT) { |
|
if (filter[i - 1] == ';') { |
|
throw new InvalidSearchFilterException( |
|
"invalid attribute description"); |
|
} |
|
|
|
|
|
extensibleStart = i; |
|
break; |
|
} |
|
|
|
// The underscore ("_") character is not allowed by |
|
// the LDAP specification. We allow it here to |
|
|
|
if (filter[i] != '-' && filter[i] != '_' && |
|
!(filter[i] >= '0' && filter[i] <= '9') && |
|
!(filter[i] >= 'A' && filter[i] <= 'Z') && |
|
!(filter[i] >= 'a' && filter[i] <= 'z')) { |
|
throw new InvalidSearchFilterException( |
|
"invalid attribute description"); |
|
} |
|
} |
|
} |
|
|
|
|
|
if (extensibleStart > 0) { |
|
boolean isMatchingRule = false; |
|
for (int i = extensibleStart + 1; i < typeEnd; i++) { |
|
if (filter[i] == ':') { |
|
throw new InvalidSearchFilterException( |
|
"invalid attribute description"); |
|
} else if ((filter[i] >= '0' && filter[i] <= '9') || |
|
(filter[i] >= 'A' && filter[i] <= 'Z') || |
|
(filter[i] >= 'a' && filter[i] <= 'z')) { |
|
boolean isNumericOid = filter[i] >= '0' && filter[i] <= '9'; |
|
i++; |
|
for (int j = i; j < typeEnd; j++, i++) { |
|
|
|
if (filter[j] == ':') { |
|
if (isMatchingRule) { |
|
throw new InvalidSearchFilterException( |
|
"invalid attribute description"); |
|
} |
|
if (isNumericOid && filter[j - 1] == '.') { |
|
throw new InvalidSearchFilterException( |
|
"invalid attribute description"); |
|
} |
|
|
|
isMatchingRule = true; |
|
break; |
|
} |
|
|
|
if (isNumericOid) { |
|
|
|
if ((filter[j] == '.' && filter[j - 1] == '.') || |
|
(filter[j] != '.' && |
|
!(filter[j] >= '0' && filter[j] <= '9'))) { |
|
throw new InvalidSearchFilterException( |
|
"invalid attribute description"); |
|
} |
|
} else { |
|
// descriptor |
|
// The underscore ("_") character is not allowed by |
|
// the LDAP specification. We allow it here to |
|
|
|
if (filter[j] != '-' && filter[j] != '_' && |
|
!(filter[j] >= '0' && filter[j] <= '9') && |
|
!(filter[j] >= 'A' && filter[j] <= 'Z') && |
|
!(filter[j] >= 'a' && filter[j] <= 'z')) { |
|
throw new InvalidSearchFilterException( |
|
"invalid attribute description"); |
|
} |
|
} |
|
} |
|
} else { |
|
throw new InvalidSearchFilterException( |
|
"invalid attribute description"); |
|
} |
|
} |
|
} |
|
|
|
|
|
if (filter[typeEnd - 1] == '.' || filter[typeEnd - 1] == ';' || |
|
filter[typeEnd - 1] == ':') { |
|
throw new InvalidSearchFilterException( |
|
"invalid attribute description"); |
|
} |
|
|
|
if (typeEnd == eq) { |
|
if (findUnescaped(filter, '*', valueStart, valueEnd) == -1) { |
|
ftype = LDAP_FILTER_EQUALITY; |
|
} else if (filter[valueStart] == '*' && |
|
valueStart == (valueEnd - 1)) { |
|
ftype = LDAP_FILTER_PRESENT; |
|
} else { |
|
encodeSubstringFilter(ber, filter, |
|
typeStart, typeEnd, valueStart, valueEnd); |
|
return; |
|
} |
|
} |
|
|
|
if (ftype == LDAP_FILTER_PRESENT) { |
|
ber.encodeOctetString(filter, ftype, typeStart, typeEnd-typeStart); |
|
} else if (ftype == LDAP_FILTER_EXT) { |
|
encodeExtensibleMatch(ber, filter, |
|
typeStart, typeEnd, valueStart, valueEnd); |
|
} else { |
|
ber.beginSeq(ftype); |
|
ber.encodeOctetString(filter, Ber.ASN_OCTET_STR, |
|
typeStart, typeEnd - typeStart); |
|
ber.encodeOctetString( |
|
unescapeFilterValue(filter, valueStart, valueEnd), |
|
Ber.ASN_OCTET_STR); |
|
ber.endSeq(); |
|
} |
|
|
|
if (dbg) { |
|
dbgIndent--; |
|
} |
|
} |
|
|
|
private static void encodeSubstringFilter(BerEncoder ber, byte[] filter, |
|
int typeStart, int typeEnd, int valueStart, int valueEnd) |
|
throws IOException, NamingException { |
|
|
|
if (dbg) { |
|
dprint("encSubstringFilter: type ", filter, typeStart, typeEnd); |
|
dprint(", val : ", filter, valueStart, valueEnd); |
|
dbgIndent++; |
|
} |
|
|
|
ber.beginSeq(LDAP_FILTER_SUBSTRINGS); |
|
ber.encodeOctetString(filter, Ber.ASN_OCTET_STR, |
|
typeStart, typeEnd-typeStart); |
|
ber.beginSeq(LdapClient.LBER_SEQUENCE); |
|
int index; |
|
int previndex = valueStart; |
|
while ((index = findUnescaped(filter, '*', previndex, valueEnd)) != -1) { |
|
if (previndex == valueStart) { |
|
if (previndex < index) { |
|
if (dbg) |
|
System.err.println( |
|
"initial: " + previndex + "," + index); |
|
ber.encodeOctetString( |
|
unescapeFilterValue(filter, previndex, index), |
|
LDAP_SUBSTRING_INITIAL); |
|
} |
|
} else { |
|
if (previndex < index) { |
|
if (dbg) |
|
System.err.println("any: " + previndex + "," + index); |
|
ber.encodeOctetString( |
|
unescapeFilterValue(filter, previndex, index), |
|
LDAP_SUBSTRING_ANY); |
|
} |
|
} |
|
previndex = index + 1; |
|
} |
|
if (previndex < valueEnd) { |
|
if (dbg) |
|
System.err.println("final: " + previndex + "," + valueEnd); |
|
ber.encodeOctetString( |
|
unescapeFilterValue(filter, previndex, valueEnd), |
|
LDAP_SUBSTRING_FINAL); |
|
} |
|
ber.endSeq(); |
|
ber.endSeq(); |
|
|
|
if (dbg) { |
|
dbgIndent--; |
|
} |
|
} |
|
|
|
// The complex filter types look like: |
|
// "&(type=val)(type=val)" |
|
// "|(type=val)(type=val)" |
|
// "!(type=val)" |
|
// |
|
// The filtOffset[0] pointing to the '&', '|', or '!'. |
|
|
|
private static void encodeComplexFilter(BerEncoder ber, byte[] filter, |
|
int filterType, int filtOffset[], int filtEnd) |
|
throws IOException, NamingException { |
|
|
|
if (dbg) { |
|
dprint("encComplexFilter: ", filter, filtOffset[0], filtEnd); |
|
dprint(", type: " + Integer.toString(filterType, 16)); |
|
dbgIndent++; |
|
} |
|
|
|
filtOffset[0]++; |
|
|
|
ber.beginSeq(filterType); |
|
|
|
int[] parens = findRightParen(filter, filtOffset, filtEnd); |
|
encodeFilterList(ber, filter, filterType, parens[0], parens[1]); |
|
|
|
ber.endSeq(); |
|
|
|
if (dbg) { |
|
dbgIndent--; |
|
} |
|
|
|
} |
|
|
|
// |
|
// filter at filtOffset[0] - 1 points to a (. Find ) that matches it |
|
// and return substring between the parens. Adjust filtOffset[0] to |
|
// point to char after right paren |
|
|
|
private static int[] findRightParen(byte[] filter, int filtOffset[], int end) |
|
throws IOException, NamingException { |
|
|
|
int balance = 1; |
|
boolean escape = false; |
|
int nextOffset = filtOffset[0]; |
|
|
|
while (nextOffset < end && balance > 0) { |
|
if (!escape) { |
|
if (filter[nextOffset] == '(') |
|
balance++; |
|
else if (filter[nextOffset] == ')') |
|
balance--; |
|
} |
|
if (filter[nextOffset] == '\\' && !escape) |
|
escape = true; |
|
else |
|
escape = false; |
|
if (balance > 0) |
|
nextOffset++; |
|
} |
|
if (balance != 0) { |
|
throw new InvalidSearchFilterException("Unbalanced parenthesis"); |
|
} |
|
|
|
// String tmp = filter.substring(filtOffset[0], nextOffset); |
|
|
|
int[] tmp = new int[] {filtOffset[0], nextOffset}; |
|
|
|
filtOffset[0] = nextOffset + 1; |
|
|
|
return tmp; |
|
|
|
} |
|
|
|
// |
|
// Encode filter list of type "(filter1)(filter2)..." |
|
|
|
private static void encodeFilterList(BerEncoder ber, byte[] filter, |
|
int filterType, int start, int end) throws IOException, NamingException { |
|
|
|
if (dbg) { |
|
dprint("encFilterList: ", filter, start, end); |
|
dbgIndent++; |
|
} |
|
|
|
int filtOffset[] = new int[1]; |
|
int listNumber = 0; |
|
for (filtOffset[0] = start; filtOffset[0] < end; filtOffset[0]++) { |
|
if (Character.isSpaceChar((char)filter[filtOffset[0]])) |
|
continue; |
|
|
|
if ((filterType == LDAP_FILTER_NOT) && (listNumber > 0)) { |
|
throw new InvalidSearchFilterException( |
|
"Filter (!) cannot be followed by more than one filters"); |
|
} |
|
|
|
if (filter[filtOffset[0]] == '(') { |
|
continue; |
|
} |
|
|
|
int[] parens = findRightParen(filter, filtOffset, end); |
|
|
|
|
|
int len = parens[1]-parens[0]; |
|
byte[] newfilter = new byte[len+2]; |
|
System.arraycopy(filter, parens[0], newfilter, 1, len); |
|
newfilter[0] = (byte)'('; |
|
newfilter[len+1] = (byte)')'; |
|
encodeFilter(ber, newfilter, 0, newfilter.length); |
|
|
|
listNumber++; |
|
} |
|
|
|
if (dbg) { |
|
dbgIndent--; |
|
} |
|
|
|
} |
|
|
|
// |
|
// Encode extensible match |
|
|
|
private static void encodeExtensibleMatch(BerEncoder ber, byte[] filter, |
|
int matchStart, int matchEnd, int valueStart, int valueEnd) |
|
throws IOException, NamingException { |
|
|
|
boolean matchDN = false; |
|
int colon; |
|
int colon2; |
|
int i; |
|
|
|
ber.beginSeq(LDAP_FILTER_EXT); |
|
|
|
|
|
if ((colon = indexOf(filter, ':', matchStart, matchEnd)) >= 0) { |
|
|
|
|
|
if ((i = indexOf(filter, ":dn", colon, matchEnd)) >= 0) { |
|
matchDN = true; |
|
} |
|
|
|
|
|
if (((colon2 = indexOf(filter, ':', colon + 1, matchEnd)) >= 0) |
|
|| (i == -1)) { |
|
|
|
if (i == colon) { |
|
ber.encodeOctetString(filter, LDAP_FILTER_EXT_RULE, |
|
colon2 + 1, matchEnd - (colon2 + 1)); |
|
|
|
} else if ((i == colon2) && (i >= 0)) { |
|
ber.encodeOctetString(filter, LDAP_FILTER_EXT_RULE, |
|
colon + 1, colon2 - (colon + 1)); |
|
|
|
} else { |
|
ber.encodeOctetString(filter, LDAP_FILTER_EXT_RULE, |
|
colon + 1, matchEnd - (colon + 1)); |
|
} |
|
} |
|
|
|
|
|
if (colon > matchStart) { |
|
ber.encodeOctetString(filter, |
|
LDAP_FILTER_EXT_TYPE, matchStart, colon - matchStart); |
|
} |
|
} else { |
|
ber.encodeOctetString(filter, LDAP_FILTER_EXT_TYPE, matchStart, |
|
matchEnd - matchStart); |
|
} |
|
|
|
ber.encodeOctetString( |
|
unescapeFilterValue(filter, valueStart, valueEnd), |
|
LDAP_FILTER_EXT_VAL); |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
ber.encodeBoolean(matchDN, LDAP_FILTER_EXT_DN); |
|
|
|
ber.endSeq(); |
|
} |
|
|
|
//////////////////////////////////////////////////////////////////////////// |
|
// |
|
// some debug print code that does indenting. Useful for debugging |
|
// the filter generation code |
|
// |
|
//////////////////////////////////////////////////////////////////////////// |
|
|
|
private static final boolean dbg = false; |
|
private static int dbgIndent = 0; |
|
|
|
private static void dprint(String msg) { |
|
dprint(msg, new byte[0], 0, 0); |
|
} |
|
|
|
private static void dprint(String msg, byte[] str) { |
|
dprint(msg, str, 0, str.length); |
|
} |
|
|
|
private static void dprint(String msg, byte[] str, int start, int end) { |
|
String dstr = " "; |
|
int i = dbgIndent; |
|
while (i-- > 0) { |
|
dstr += " "; |
|
} |
|
dstr += msg; |
|
|
|
System.err.print(dstr); |
|
for (int j = start; j < end; j++) { |
|
System.err.print((char)str[j]); |
|
} |
|
System.err.println(); |
|
} |
|
|
|
/////////////// Constants used for encoding filter ////////////// |
|
|
|
static final int LDAP_FILTER_AND = 0xa0; |
|
static final int LDAP_FILTER_OR = 0xa1; |
|
static final int LDAP_FILTER_NOT = 0xa2; |
|
static final int LDAP_FILTER_EQUALITY = 0xa3; |
|
static final int LDAP_FILTER_SUBSTRINGS = 0xa4; |
|
static final int LDAP_FILTER_GE = 0xa5; |
|
static final int LDAP_FILTER_LE = 0xa6; |
|
static final int LDAP_FILTER_PRESENT = 0x87; |
|
static final int LDAP_FILTER_APPROX = 0xa8; |
|
static final int LDAP_FILTER_EXT = 0xa9; |
|
|
|
static final int LDAP_FILTER_EXT_RULE = 0x81; |
|
static final int LDAP_FILTER_EXT_TYPE = 0x82; |
|
static final int LDAP_FILTER_EXT_VAL = 0x83; |
|
static final int LDAP_FILTER_EXT_DN = 0x84; |
|
|
|
static final int LDAP_SUBSTRING_INITIAL = 0x80; |
|
static final int LDAP_SUBSTRING_ANY = 0x81; |
|
static final int LDAP_SUBSTRING_FINAL = 0x82; |
|
} |