From ae5a3731a62de03b4c9b1b0762f34c7be32cbddb Mon Sep 17 00:00:00 2001 From: Rich Megginson Date: Thu, 2 Feb 2012 20:53:49 -0700 Subject: [PATCH] Ticket #279 - filter normalization does not use matching rules https://fedorahosted.org/389/ticket/279 Resolves: Ticket #279 Bug Description: filter normalization does not use matching rules Reviewed by: ??? Branch: master Fix Description: When normalizing the values in a filter, the normalization must take into account the type of filter being used, and the matching rules associated with the attribute, corresponding to the type of filter. Added a mr_normalize function for matching rules. This is primarily needed by the cis and ces associated matching rules, for the case where the normalization function provided by the syntax is different than the one associated with the matching rule. For example, Directory String (cis) by default uses a case insensitive normalization function, but if you are using a caseExact matching rule you must use a case sensitive normalization function. Added the new function slapi_attr_value_normalize_ext() to allow passing in the type of search filter to normalize for. Platforms tested: RHEL6 x86_64 Flag Day: yes - plugin structure size change Doc impact: yes - document the new function --- ldap/servers/plugins/syntaxes/ces.c | 10 +++--- ldap/servers/plugins/syntaxes/cis.c | 26 +++++++------- ldap/servers/plugins/syntaxes/syntax.h | 1 + ldap/servers/plugins/syntaxes/syntax_common.c | 1 + ldap/servers/slapd/filter.c | 9 +++-- ldap/servers/slapd/pblock.c | 12 ++++++ ldap/servers/slapd/plugin_syntax.c | 46 +++++++++++++++++++++++-- ldap/servers/slapd/slap.h | 2 + ldap/servers/slapd/slapi-plugin.h | 35 +++++++++++++++++++ 9 files changed, 117 insertions(+), 25 deletions(-) diff --git a/ldap/servers/plugins/syntaxes/ces.c b/ldap/servers/plugins/syntaxes/ces.c index 626cb7c..ee1b012 100644 --- a/ldap/servers/plugins/syntaxes/ces.c +++ b/ldap/servers/plugins/syntaxes/ces.c @@ -121,7 +121,7 @@ IA5STRING_SYNTAX_OID, 0, caseExactIA5Match_syntaxes}, /* matching rule desc */ {"caseExactIA5Match-mr", VENDOR, DS_PACKAGE_VERSION, "caseExactIA5Match matching rule plugin"}, /* plugin desc */ caseExactIA5Match_names, /* matching rule name/oid/aliases */ NULL, NULL, ces_filter_ava, NULL, ces_values2keys, - ces_assertion2keys_ava, NULL, ces_compare}, + ces_assertion2keys_ava, NULL, ces_compare, ces_normalize}, {{"2.5.13.5", NULL, "caseExactMatch", "The caseExactMatch rule compares an assertion value of the Directory " "String syntax to an attribute value of a syntax (e.g., the Directory " "String, Printable String, Country String, or Telephone Number syntax) " @@ -141,7 +141,7 @@ DIRSTRING_SYNTAX_OID, 0, dirStringCompat_syntaxes}, /* matching rule desc */ {"caseExactMatch-mr", VENDOR, DS_PACKAGE_VERSION, "caseExactMatch matching rule plugin"}, /* plugin desc */ caseExactMatch_names, /* matching rule name/oid/aliases */ NULL, NULL, ces_filter_ava, NULL, ces_values2keys, - ces_assertion2keys_ava, NULL, ces_compare}, + ces_assertion2keys_ava, NULL, ces_compare, ces_normalize}, {{"2.5.13.6", NULL, "caseExactOrderingMatch", "The caseExactOrderingMatch rule compares an assertion value of the " "Directory String syntax to an attribute value of a syntax (e.g., the " "Directory String, Printable String, Country String, or Telephone " @@ -159,7 +159,7 @@ DIRSTRING_SYNTAX_OID, 0, dirStringCompat_syntaxes}, /* matching rule desc */ {"caseExactOrderingMatch-mr", VENDOR, DS_PACKAGE_VERSION, "caseExactOrderingMatch matching rule plugin"}, /* plugin desc */ caseExactOrderingMatch_names, /* matching rule name/oid/aliases */ NULL, NULL, ces_filter_ava, NULL, ces_values2keys, - ces_assertion2keys_ava, NULL, ces_compare}, + ces_assertion2keys_ava, NULL, ces_compare, ces_normalize}, {{"2.5.13.7", NULL, "caseExactSubstringsMatch", "The caseExactSubstringsMatch rule compares an assertion value of the " "Substring Assertion syntax to an attribute value of a syntax (e.g., " "the Directory String, Printable String, Country String, or Telephone " @@ -182,7 +182,7 @@ DIRSTRING_SYNTAX_OID, 0, dirStringCompat_syntaxes}, /* matching rule desc */ {"caseExactSubstringsMatch-mr", VENDOR, DS_PACKAGE_VERSION, "caseExactSubstringsMatch matching rule plugin"}, /* plugin desc */ caseExactSubstringsMatch_names, /* matching rule name/oid/aliases */ NULL, NULL, NULL, ces_filter_sub, ces_values2keys, - NULL, ces_assertion2keys_sub, ces_compare}, + NULL, ces_assertion2keys_sub, ces_compare, ces_normalize}, {{CASEEXACTIA5SUBSTRINGSMATCH_OID, NULL, "caseExactIA5SubstringsMatch", "The caseExactIA5SubstringsMatch rule compares an assertion value of the " "Substring Assertion syntax to an attribute value of a syntax (e.g., " "the IA5 syntax) whose corresponding ASN.1 type is IA5 String or " @@ -204,7 +204,7 @@ DIRSTRING_SYNTAX_OID, 0, dirStringCompat_syntaxes}, /* matching rule desc */ {"caseExactIA5SubstringsMatch-mr", VENDOR, DS_PACKAGE_VERSION, "caseExactIA5SubstringsMatch matching rule plugin"}, /* plugin desc */ caseExactIA5SubstringsMatch_names, /* matching rule name/oid/aliases */ NULL, NULL, NULL, ces_filter_sub, ces_values2keys, - NULL, ces_assertion2keys_sub, ces_compare} + NULL, ces_assertion2keys_sub, ces_compare, ces_normalize} }; static size_t mr_plugin_table_size = sizeof(mr_plugin_table)/sizeof(mr_plugin_table[0]); diff --git a/ldap/servers/plugins/syntaxes/cis.c b/ldap/servers/plugins/syntaxes/cis.c index c914fd6..ead290f 100644 --- a/ldap/servers/plugins/syntaxes/cis.c +++ b/ldap/servers/plugins/syntaxes/cis.c @@ -215,14 +215,14 @@ static struct mr_plugin_def mr_plugin_table[] = { {"generalizedTimeMatch-mr", VENDOR, DS_PACKAGE_VERSION, "generalizedTimeMatch matching rule plugin"}, /* plugin desc */ generalizedTimeMatch_names, /* matching rule name/oid/aliases */ NULL, NULL, cis_filter_ava, NULL, cis_values2keys, - cis_assertion2keys_ava, NULL, cis_compare}, + cis_assertion2keys_ava, NULL, cis_compare, cis_normalize}, {{GENERALIZEDTIMEORDERINGMATCH_OID, NULL /* no alias? */, "generalizedTimeOrderingMatch", "The rule evaluates to TRUE if and only if the attribute value represents a universal coordinated time that is earlier than the universal coordinated time represented by the assertion value.", GENERALIZEDTIME_SYNTAX_OID, 0 /* not obsolete */, NULL /* no other syntaxes supported */ }, {"generalizedTimeOrderingMatch-mr", VENDOR, DS_PACKAGE_VERSION, "generalizedTimeOrderingMatch matching rule plugin"}, /* plugin desc */ generalizedTimeOrderingMatch_names, /* matching rule name/oid/aliases */ NULL, NULL, cis_filter_ava, NULL, cis_values2keys, - cis_assertion2keys_ava, NULL, cis_compare}, + cis_assertion2keys_ava, NULL, cis_compare, cis_normalize}, /* strictly speaking, boolean is case sensitive */ {{"2.5.13.13", NULL, "booleanMatch", "The booleanMatch rule compares an assertion value of the Boolean " "syntax to an attribute value of a syntax (e.g., the Boolean syntax) " @@ -232,7 +232,7 @@ static struct mr_plugin_def mr_plugin_table[] = { {"booleanMatch-mr", VENDOR, DS_PACKAGE_VERSION, "booleanMatch matching rule plugin"}, /* plugin desc */ booleanMatch_names, /* matching rule name/oid/aliases */ NULL, NULL, cis_filter_ava, NULL, cis_values2keys, - cis_assertion2keys_ava, NULL, cis_compare}, + cis_assertion2keys_ava, NULL, cis_compare, cis_normalize}, {{"1.3.6.1.4.1.1466.109.114.2", NULL, "caseIgnoreIA5Match", "The caseIgnoreIA5Match rule compares an assertion value of the IA5 " "String syntax to an attribute value of a syntax (e.g., the IA5 String " "syntax) whose corresponding ASN.1 type is IA5String. " @@ -247,7 +247,7 @@ static struct mr_plugin_def mr_plugin_table[] = { {"caseIgnoreIA5Match-mr", VENDOR, DS_PACKAGE_VERSION, "caseIgnoreIA5Match matching rule plugin"}, /* plugin desc */ caseIgnoreIA5Match_names, /* matching rule name/oid/aliases */ NULL, NULL, cis_filter_ava, NULL, cis_values2keys, - cis_assertion2keys_ava, NULL, cis_compare}, + cis_assertion2keys_ava, NULL, cis_compare, cis_normalize}, {{"1.3.6.1.4.1.1466.109.114.3", NULL, "caseIgnoreIA5SubstringsMatch", "The caseIgnoreIA5SubstringsMatch rule compares an assertion value of " "the Substring Assertion syntax to an attribute value of a syntax " "(e.g., the IA5 String syntax) whose corresponding ASN.1 type is " @@ -268,7 +268,7 @@ static struct mr_plugin_def mr_plugin_table[] = { {"caseIgnoreIA5SubstringsMatch-mr", VENDOR, DS_PACKAGE_VERSION, "caseIgnoreIA5SubstringsMatch matching rule plugin"}, /* plugin desc */ caseIgnoreIA5SubstringsMatch_names, /* matching rule name/oid/aliases */ NULL, NULL, NULL, cis_filter_sub, cis_values2keys, - NULL, cis_assertion2keys_sub, NULL}, + NULL, cis_assertion2keys_sub, NULL, cis_normalize}, {{"2.5.13.2", NULL, "caseIgnoreMatch", "The caseIgnoreMatch rule compares an assertion value of the Directory " "String syntax to an attribute value of a syntax (e.g., the Directory " "String, Printable String, Country String, or Telephone Number syntax) " @@ -285,7 +285,7 @@ static struct mr_plugin_def mr_plugin_table[] = { {"caseIgnoreMatch-mr", VENDOR, DS_PACKAGE_VERSION, "caseIgnoreMatch matching rule plugin"}, /* plugin desc */ caseIgnoreMatch_names, /* matching rule name/oid/aliases */ NULL, NULL, cis_filter_ava, NULL, cis_values2keys, - cis_assertion2keys_ava, NULL, cis_compare}, + cis_assertion2keys_ava, NULL, cis_compare, cis_normalize}, {{"2.5.13.3", NULL, "caseIgnoreOrderingMatch", "The caseIgnoreOrderingMatch rule compares an assertion value of the " "Directory String syntax to an attribute value of a syntax (e.g., the " "Directory String, Printable String, Country String, or Telephone " @@ -302,7 +302,7 @@ static struct mr_plugin_def mr_plugin_table[] = { {"caseIgnoreOrderingMatch-mr", VENDOR, DS_PACKAGE_VERSION, "caseIgnoreOrderingMatch matching rule plugin"}, /* plugin desc */ caseIgnoreOrderingMatch_names, /* matching rule name/oid/aliases */ NULL, NULL, cis_filter_ava, NULL, cis_values2keys, - cis_assertion2keys_ava, NULL, cis_compare}, + cis_assertion2keys_ava, NULL, cis_compare, cis_normalize}, {{"2.5.13.4", NULL, "caseIgnoreSubstringsMatch", "The caseIgnoreSubstringsMatch rule compares an assertion value of the " "Substring Assertion syntax to an attribute value of a syntax (e.g., " "the Directory String, Printable String, Country String, or Telephone " @@ -324,7 +324,7 @@ static struct mr_plugin_def mr_plugin_table[] = { {"caseIgnoreSubstringsMatch-mr", VENDOR, DS_PACKAGE_VERSION, "caseIgnoreSubstringsMatch matching rule plugin"}, /* plugin desc */ caseIgnoreSubstringsMatch_names, /* matching rule name/oid/aliases */ NULL, NULL, NULL, cis_filter_sub, cis_values2keys, - NULL, cis_assertion2keys_sub, cis_compare}, + NULL, cis_assertion2keys_sub, cis_compare, cis_normalize}, {{"2.5.13.11", NULL, "caseIgnoreListMatch", "The caseIgnoreListMatch rule compares an assertion value that is a " "sequence of strings to an attribute value of a syntax (e.g., the " "Postal Address syntax) whose corresponding ASN.1 type is a SEQUENCE " @@ -344,7 +344,7 @@ static struct mr_plugin_def mr_plugin_table[] = { {"caseIgnoreListMatch-mr", VENDOR, DS_PACKAGE_VERSION, "caseIgnoreListMatch matching rule plugin"}, /* plugin desc */ caseIgnoreListMatch_names, /* matching rule name/oid/aliases */ NULL, NULL, cis_filter_ava, NULL, cis_values2keys, - cis_assertion2keys_ava, NULL, cis_compare}, + cis_assertion2keys_ava, NULL, cis_compare, cis_normalize}, {{"2.5.13.12", NULL, "caseIgnoreListSubstringsMatch", "The caseIgnoreListSubstringsMatch rule compares an assertion value of " "the Substring Assertion syntax to an attribute value of a syntax " "(e.g., the Postal Address syntax) whose corresponding ASN.1 type is a " @@ -363,7 +363,7 @@ static struct mr_plugin_def mr_plugin_table[] = { {"caseIgnoreListSubstringsMatch-mr", VENDOR, DS_PACKAGE_VERSION, "caseIgnoreListSubstringsMatch matching rule plugin"}, /* plugin desc */ caseIgnoreListSubstringsMatch_names, /* matching rule name/oid/aliases */ NULL, NULL, NULL, cis_filter_sub, cis_values2keys, - NULL, cis_assertion2keys_sub, cis_compare}, + NULL, cis_assertion2keys_sub, cis_compare, cis_normalize}, {{"2.5.13.0", NULL, "objectIdentifierMatch", "The objectIdentifierMatch rule compares an assertion value of the OID " "syntax to an attribute value of a syntax (e.g., the OID syntax) whose " "corresponding ASN.1 type is OBJECT IDENTIFIER. " @@ -379,7 +379,7 @@ OID_SYNTAX_OID, 0, NULL /* OID syntax only for now */}, /* matching rule desc */ {"objectIdentifierMatch-mr", VENDOR, DS_PACKAGE_VERSION, "objectIdentifierMatch matching rule plugin"}, /* plugin desc */ objectIdentifierMatch_names, /* matching rule name/oid/aliases */ NULL, NULL, cis_filter_ava, NULL, cis_values2keys, - cis_assertion2keys_ava, NULL, cis_compare}, + cis_assertion2keys_ava, NULL, cis_compare, cis_normalize}, {{"2.5.13.31", NULL, "directoryStringFirstComponentMatch", "The directoryStringFirstComponentMatch rule compares an assertion " "value of the Directory String syntax to an attribute value of a " "syntax whose corresponding ASN.1 type is a SEQUENCE with a mandatory " @@ -393,7 +393,7 @@ OID_SYNTAX_OID, 0, NULL /* OID syntax only for now */}, /* matching rule desc */ {"directoryStringFirstComponentMatch-mr", VENDOR, DS_PACKAGE_VERSION, "directoryStringFirstComponentMatch matching rule plugin"}, /* plugin desc */ directoryStringFirstComponentMatch_names, /* matching rule name/oid/aliases */ NULL, NULL, cis_filter_ava, NULL, cis_values2keys, - cis_assertion2keys_ava, NULL, NULL}, + cis_assertion2keys_ava, NULL, NULL, cis_normalize}, {{"2.5.13.30", NULL, "objectIdentifierFirstComponentMatch", "The objectIdentifierFirstComponentMatch rule compares an assertion " "value of the OID syntax to an attribute value of a syntax (e.g., the " @@ -411,7 +411,7 @@ OID_SYNTAX_OID, 0, NULL /* OID syntax only for now */}, /* matching rule desc */ {"objectIdentifierFirstComponentMatch-mr", VENDOR, DS_PACKAGE_VERSION, "objectIdentifierFirstComponentMatch matching rule plugin"}, /* plugin desc */ objectIdentifierFirstComponentMatch_names, /* matching rule name/oid/aliases */ NULL, NULL, cis_filter_ava, NULL, cis_values2keys, - cis_assertion2keys_ava, NULL, NULL} + cis_assertion2keys_ava, NULL, NULL, cis_normalize} }; static size_t mr_plugin_table_size = sizeof(mr_plugin_table)/sizeof(mr_plugin_table[0]); diff --git a/ldap/servers/plugins/syntaxes/syntax.h b/ldap/servers/plugins/syntaxes/syntax.h index e0fee81..04ce70a 100644 --- a/ldap/servers/plugins/syntaxes/syntax.h +++ b/ldap/servers/plugins/syntaxes/syntax.h @@ -143,6 +143,7 @@ struct mr_plugin_def { IFP mr_assertion2keys_ava; /* SLAPI_PLUGIN_MR_ASSERTION2KEYS_AVA */ IFP mr_assertion2keys_sub; /* SLAPI_PLUGIN_MR_ASSERTION2KEYS_SUB */ IFP mr_compare; /* SLAPI_PLUGIN_MR_COMPARE - only for ORDERING */ + VFPV mr_normalize; }; int syntax_register_matching_rule_plugins(struct mr_plugin_def mr_plugin_table[], size_t mr_plugin_table_size, IFP matching_rule_plugin_init); diff --git a/ldap/servers/plugins/syntaxes/syntax_common.c b/ldap/servers/plugins/syntaxes/syntax_common.c index 713d9a0..f206949 100644 --- a/ldap/servers/plugins/syntaxes/syntax_common.c +++ b/ldap/servers/plugins/syntaxes/syntax_common.c @@ -100,6 +100,7 @@ syntax_matching_rule_plugin_init( rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_MR_ASSERTION2KEYS_SUB, mrpd->mr_assertion2keys_sub); rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_MR_NAMES, mrpd->mr_names); rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_MR_COMPARE, mrpd->mr_compare); + rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_MR_NORMALIZE, mrpd->mr_normalize); break; } } diff --git a/ldap/servers/slapd/filter.c b/ldap/servers/slapd/filter.c index f7028dc..36bd419 100644 --- a/ldap/servers/slapd/filter.c +++ b/ldap/servers/slapd/filter.c @@ -1056,7 +1056,8 @@ filter_normalize_ava( struct slapi_filter *f, PRBool norm_values ) char *newval = NULL; /* NOTE: assumes ava->ava_value.bv_val is NULL terminated - get_ava/ber_scanf 'o' will NULL terminate the string by default */ - slapi_attr_value_normalize(NULL, NULL, ava->ava_type, ava->ava_value.bv_val, 1, &newval); + slapi_attr_value_normalize_ext(NULL, NULL, ava->ava_type, + ava->ava_value.bv_val, 1, &newval, f->f_choice); if (newval && (newval != ava->ava_value.bv_val)) { slapi_ch_free_string(&ava->ava_value.bv_val); ava->ava_value.bv_val = newval; @@ -1086,7 +1087,7 @@ filter_normalize_subfilt( struct slapi_filter *f, PRBool norm_values ) int ii; slapi_attr_init(&attr, sf->sf_type); - slapi_attr_value_normalize(NULL, &attr, NULL, sf->sf_initial, 1, &newval); + slapi_attr_value_normalize_ext(NULL, &attr, NULL, sf->sf_initial, 1, &newval, f->f_choice); if (newval && (newval != sf->sf_initial)) { slapi_ch_free_string(&sf->sf_initial); sf->sf_initial = newval; @@ -1094,7 +1095,7 @@ filter_normalize_subfilt( struct slapi_filter *f, PRBool norm_values ) for (ii = 0; sf->sf_any && sf->sf_any[ii]; ++ii) { newval = NULL; /* do not trim spaces of sf_any values - see string_filter_sub() */ - slapi_attr_value_normalize(NULL, &attr, NULL, sf->sf_any[ii], 0, &newval); + slapi_attr_value_normalize_ext(NULL, &attr, NULL, sf->sf_any[ii], 0, &newval, f->f_choice); if (newval && (newval != sf->sf_any[ii])) { slapi_ch_free_string(&sf->sf_any[ii]); sf->sf_any[ii] = newval; @@ -1102,7 +1103,7 @@ filter_normalize_subfilt( struct slapi_filter *f, PRBool norm_values ) } newval = NULL; /* do not trim spaces of sf_final values - see string_filter_sub() */ - slapi_attr_value_normalize(NULL, &attr, NULL, sf->sf_final, 0, &newval); + slapi_attr_value_normalize_ext(NULL, &attr, NULL, sf->sf_final, 0, &newval, f->f_choice); if (newval && (newval != sf->sf_final)) { slapi_ch_free_string(&sf->sf_final); sf->sf_final = newval; diff --git a/ldap/servers/slapd/pblock.c b/ldap/servers/slapd/pblock.c index 86e0451..79d96f0 100644 --- a/ldap/servers/slapd/pblock.c +++ b/ldap/servers/slapd/pblock.c @@ -1595,6 +1595,12 @@ slapi_pblock_get( Slapi_PBlock *pblock, int arg, void *value ) } (*(IFP *)value) = pblock->pb_plugin->plg_mr_compare; break; + case SLAPI_PLUGIN_MR_NORMALIZE: + if ( pblock->pb_plugin->plg_type != SLAPI_PLUGIN_MATCHINGRULE ) { + return( -1 ); + } + (*(VFPV *)value) = pblock->pb_plugin->plg_mr_normalize; + break; /* seq arguments */ case SLAPI_SEQ_TYPE: @@ -3157,6 +3163,12 @@ slapi_pblock_set( Slapi_PBlock *pblock, int arg, void *value ) } pblock->pb_plugin->plg_mr_compare = (IFP) value; break; + case SLAPI_PLUGIN_MR_NORMALIZE: + if ( pblock->pb_plugin->plg_type != SLAPI_PLUGIN_MATCHINGRULE ) { + return( -1 ); + } + pblock->pb_plugin->plg_mr_normalize = (VFPV) value; + break; /* seq arguments */ case SLAPI_SEQ_TYPE: diff --git a/ldap/servers/slapd/plugin_syntax.c b/ldap/servers/slapd/plugin_syntax.c index 9e98b61..0438ceb 100644 --- a/ldap/servers/slapd/plugin_syntax.c +++ b/ldap/servers/slapd/plugin_syntax.c @@ -929,13 +929,14 @@ slapi_attr_assertion2keys_sub( /* JCM SLOW FUNCTION */ } void -slapi_attr_value_normalize( +slapi_attr_value_normalize_ext( Slapi_PBlock *pb, const Slapi_Attr *sattr, /* if sattr is NULL, type must be attr type name */ const char *type, char *val, int trim_spaces, - char **retval + char **retval, + unsigned long filter_type ) { Slapi_Attr myattr; @@ -944,7 +945,33 @@ slapi_attr_value_normalize( if (!sattr) { sattr = slapi_attr_init(&myattr, type); } - norm_fn = sattr->a_plugin->plg_syntax_normalize; + + /* use the filter type to determine which matching rule to use */ + switch (filter_type) { + case LDAP_FILTER_GE: + case LDAP_FILTER_LE: + if (sattr->a_mr_ord_plugin) { + norm_fn = sattr->a_mr_ord_plugin->plg_mr_normalize; + } + break; + case LDAP_FILTER_EQUALITY: + if (sattr->a_mr_eq_plugin) { + norm_fn = sattr->a_mr_eq_plugin->plg_mr_normalize; + } + break; + case LDAP_FILTER_SUBSTRINGS: + if (sattr->a_mr_sub_plugin) { + norm_fn = sattr->a_mr_sub_plugin->plg_mr_normalize; + } + break; + default: + break; + } + + if (!norm_fn) { + /* no matching rule specific normalizer specified - use syntax default */ + norm_fn = sattr->a_plugin->plg_syntax_normalize; + } if (norm_fn) { (*norm_fn)(pb, val, trim_spaces, retval); } @@ -953,3 +980,16 @@ slapi_attr_value_normalize( } return; } + +void +slapi_attr_value_normalize( + Slapi_PBlock *pb, + const Slapi_Attr *sattr, /* if sattr is NULL, type must be attr type name */ + const char *type, + char *val, + int trim_spaces, + char **retval +) +{ + return slapi_attr_value_normalize_ext(pb, sattr, type, val, trim_spaces, retval, 0); +} diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h index c6d342c..b855ff0 100644 --- a/ldap/servers/slapd/slap.h +++ b/ldap/servers/slapd/slap.h @@ -1036,6 +1036,7 @@ struct slapdplugin { int plg_un_mr_flags; char **plg_un_mr_names; IFP plg_un_mr_compare; /* only for ORDERING */ + VFPV plg_un_mr_normalize; } plg_un_mr; #define plg_mr_filter_create plg_un.plg_un_mr.plg_un_mr_filter_create #define plg_mr_indexer_create plg_un.plg_un_mr.plg_un_mr_indexer_create @@ -1047,6 +1048,7 @@ struct slapdplugin { #define plg_mr_flags plg_un.plg_un_mr.plg_un_mr_flags #define plg_mr_names plg_un.plg_un_mr.plg_un_mr_names #define plg_mr_compare plg_un.plg_un_mr.plg_un_mr_compare +#define plg_mr_normalize plg_un.plg_un_mr.plg_un_mr_normalize /* syntax plugin structure */ struct plg_un_syntax_struct { diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h index e684fe0..ce68e76 100644 --- a/ldap/servers/slapd/slapi-plugin.h +++ b/ldap/servers/slapd/slapi-plugin.h @@ -5306,6 +5306,40 @@ void slapi_attr_value_normalize( char **retval ); +/** + * Normalize the given value using the matching rule associated with the + * given attribute and given filter type. It will attempt to normalize + * the value in place. If it cannot, it will return the normalized value + * in retval. If trim_spaces is true, whitepace characters will be trimmed + * from the ends of the string. If sattr is NULL, the type will be used to look + * up the attribute syntax. If sattr is not NULL, type is ignored. If + * retval is set, the caller is responsible for freeing it. The filter_type + * corresponds to the matching rule to use - LDAP_FILTER_GE or LDAP_FILTER_LE + * will use the ORDERING matching rule normalization function - LDAP_FILTER_EQUALITY + * will use the EQUALITY matching rule normalization function - LDAP_FILTER_SUBSTRINGS + * will use the SUBSTRINGS matching rule normalization function. If the given + * filter_type is 0, or some other value other than specified above, or there is no + * matching rule corresponding to the given filter type, the default normalization + * function provided by the attribute syntax will be used. + * + * \param pb Slapi_PBlock to use + * \param sattr attribute to get the syntax from + * \param type attribute to get the syntax from if sattr is NULL + * \param val value to normalize in place - must be NULL terminated + * \param trim_spaces trim whitespace from ends of string + * \param retval if value could not be normalized in place, this is the malloc'd memory containg the new value - caller must free + * \param filter_type one of the values specified above, or 0 + */ +void slapi_attr_value_normalize_ext( + Slapi_PBlock *pb, + const Slapi_Attr *sattr, /* if sattr is NULL, type must be attr type name */ + const char *type, + char *val, + int trim_spaces, + char **retval, + unsigned long filter_type +); + /* * internal operation and plugin callback routines */ @@ -6287,6 +6321,7 @@ typedef struct slapi_plugindesc { #define SLAPI_PLUGIN_MR_FLAGS 623 #define SLAPI_PLUGIN_MR_NAMES 624 #define SLAPI_PLUGIN_MR_COMPARE 625 +#define SLAPI_PLUGIN_MR_NORMALIZE 626 /* Defined values of SLAPI_PLUGIN_MR_QUERY_OPERATOR: */ #define SLAPI_OP_LESS 1 -- 1.7.1