jdk/src/share/classes/com/sun/jndi/ldap/Filter.java
changeset 4978 6bee79de5db6
parent 3325 0e7d9c6c9994
child 5506 202f599c92aa
equal deleted inserted replaced
4977:81902a400bbf 4978:6bee79de5db6
     1 /*
     1 /*
     2  * Copyright 1999-2007 Sun Microsystems, Inc.  All Rights Reserved.
     2  * Copyright 1999-2010 Sun Microsystems, Inc.  All Rights Reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Sun designates this
     7  * published by the Free Software Foundation.  Sun designates this
    31 import java.io.IOException;
    31 import java.io.IOException;
    32 
    32 
    33 /**
    33 /**
    34  * LDAP (RFC-1960) and LDAPv3 (RFC-2254) search filters.
    34  * LDAP (RFC-1960) and LDAPv3 (RFC-2254) search filters.
    35  *
    35  *
       
    36  * @author Xuelei Fan
    36  * @author Vincent Ryan
    37  * @author Vincent Ryan
    37  * @author Jagane Sundar
    38  * @author Jagane Sundar
    38  * @author Rosanna Lee
    39  * @author Rosanna Lee
    39  */
    40  */
    40 
    41 
   256             }
   257             }
   257         }
   258         }
   258         byte[] answer = new byte[j];
   259         byte[] answer = new byte[j];
   259         System.arraycopy(tbuf, 0, answer, 0, j);
   260         System.arraycopy(tbuf, 0, answer, 0, j);
   260         if (dbg) {
   261         if (dbg) {
   261             Ber.dumpBER(System.err, null, answer, 0, j);
   262             Ber.dumpBER(System.err, "", answer, 0, j);
   262         }
   263         }
   263         return answer;
   264         return answer;
   264     }
   265     }
   265 
   266 
   266     private static int indexOf(byte[] str, char ch, int start, int end) {
   267     private static int indexOf(byte[] str, char ch, int start, int end) {
   328         if ((eq = indexOf(filter, '=', filtStart, filtEnd)) == -1) {
   329         if ((eq = indexOf(filter, '=', filtStart, filtEnd)) == -1) {
   329             throw new InvalidSearchFilterException("Missing 'equals'");
   330             throw new InvalidSearchFilterException("Missing 'equals'");
   330         }
   331         }
   331 
   332 
   332 
   333 
   333         valueStart = eq + 1;            // value starts after equal sign
   334         valueStart = eq + 1;        // value starts after equal sign
   334         valueEnd = filtEnd;
   335         valueEnd = filtEnd;
   335         typeStart = filtStart;      // beginning of string
   336         typeStart = filtStart;      // beginning of string
   336 
   337 
   337         int ftype;
   338         int ftype;
   338 
   339 
   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         }
   621     // some debug print code that does indenting. Useful for debugging
   801     // some debug print code that does indenting. Useful for debugging
   622     // the filter generation code
   802     // the filter generation code
   623     //
   803     //
   624     ////////////////////////////////////////////////////////////////////////////
   804     ////////////////////////////////////////////////////////////////////////////
   625 
   805 
   626     private static final boolean dbg = false;
   806     // private static final boolean dbg = false;
       
   807     private static final boolean dbg = true;
   627     private static int dbgIndent = 0;
   808     private static int dbgIndent = 0;
   628 
   809 
   629     private static void dprint(String msg) {
   810     private static void dprint(String msg) {
   630         dprint(msg, new byte[0], 0, 0);
   811         dprint(msg, new byte[0], 0, 0);
   631     }
   812     }