plugin_mr.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation; version 2 of the License.
  5. *
  6. * This Program is distributed in the hope that it will be useful, but WITHOUT
  7. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  9. *
  10. * You should have received a copy of the GNU General Public License along with
  11. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  12. * Place, Suite 330, Boston, MA 02111-1307 USA.
  13. *
  14. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  15. * right to link the code of this Program with code not covered under the GNU
  16. * General Public License ("Non-GPL Code") and to distribute linked combinations
  17. * including the two, subject to the limitations in this paragraph. Non-GPL Code
  18. * permitted under this exception must only link to the code of this Program
  19. * through those well defined interfaces identified in the file named EXCEPTION
  20. * found in the source code files (the "Approved Interfaces"). The files of
  21. * Non-GPL Code may instantiate templates or use macros or inline functions from
  22. * the Approved Interfaces without causing the resulting work to be covered by
  23. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  24. * additions to the list of Approved Interfaces. You must obey the GNU General
  25. * Public License in all respects for all of the Program code and other code used
  26. * in conjunction with the Program except the Non-GPL Code covered by this
  27. * exception. If you modify this file, you may extend this exception to your
  28. * version of the file, but you are not obligated to do so. If you do not wish to
  29. * provide this exception without modification, you must delete this exception
  30. * statement from your version and license this file solely under the GPL without
  31. * exception.
  32. *
  33. *
  34. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  35. * Copyright (C) 2005 Red Hat, Inc.
  36. * All rights reserved.
  37. * END COPYRIGHT BLOCK **/
  38. #ifdef HAVE_CONFIG_H
  39. # include <config.h>
  40. #endif
  41. /*
  42. * plugin_mr.c - routines for calling matching rule plugins
  43. */
  44. #include "slap.h"
  45. /* because extensible_candidates can call an indexing
  46. operation in the middle of a filtering operation,
  47. we have to use a structure that can be used by both
  48. since we can only have 1 SLAPI_PLUGIN_OBJECT in
  49. that case */
  50. struct mr_private {
  51. Slapi_Value **sva; /* if using index_sv_fn */
  52. struct berval **bva; /* if using index_fn */
  53. /* if doing a purely indexing operation, the fields
  54. below are not used */
  55. const struct slapdplugin *pi; /* our plugin */
  56. const char *oid; /* orig oid */
  57. const char *type; /* orig type from filter */
  58. const struct berval *value; /* orig value from filter */
  59. int ftype; /* filter type */
  60. int op; /* query op type */
  61. IFP match_fn; /* match func to use */
  62. /* note - substring matching rules not currently supported */
  63. char *initial; /* these are for substring matches */
  64. char *any[2]; /* at most one value for extensible filter */
  65. char *final; /* these are for substring matches */
  66. const struct berval *values[2]; /* for indexing */
  67. };
  68. static oid_item_t* global_mr_oids = NULL;
  69. static PRLock* global_mr_oids_lock = NULL;
  70. static int default_mr_indexer_create(Slapi_PBlock* pb);
  71. static void
  72. init_global_mr_lock()
  73. {
  74. if(global_mr_oids_lock==NULL)
  75. {
  76. global_mr_oids_lock = PR_NewLock();
  77. }
  78. }
  79. struct slapdplugin *
  80. slapi_get_global_mr_plugins()
  81. {
  82. return get_plugin_list(PLUGIN_LIST_MATCHINGRULE);
  83. }
  84. struct slapdplugin *
  85. plugin_mr_find( const char *nameoroid )
  86. {
  87. struct slapdplugin *pi = NULL;
  88. for ( pi = get_plugin_list(PLUGIN_LIST_MATCHINGRULE); (nameoroid != NULL) && (pi != NULL); pi = pi->plg_next ) {
  89. if ( charray_inlist( pi->plg_mr_names, (char *)nameoroid ) ) {
  90. break;
  91. }
  92. }
  93. if (!nameoroid) {
  94. pi = NULL;
  95. }
  96. if (nameoroid && !pi) {
  97. slapi_log_error(SLAPI_LOG_CONFIG, "plugin_mr_find",
  98. "Error: matching rule plugin for [%s] not found\n", nameoroid);
  99. }
  100. return ( pi );
  101. }
  102. static int
  103. plugin_mr_get_type(struct slapdplugin *pi)
  104. {
  105. int rc = LDAP_FILTER_EQUALITY;
  106. if (pi) {
  107. char **str = pi->plg_mr_names;
  108. for (; str && *str; ++str) {
  109. if (PL_strcasestr(*str, "substr")) {
  110. rc = LDAP_FILTER_SUBSTRINGS;
  111. break;
  112. }
  113. if (PL_strcasestr(*str, "approx")) {
  114. rc = LDAP_FILTER_APPROX;
  115. break;
  116. }
  117. if (PL_strcasestr(*str, "ordering")) {
  118. rc = LDAP_FILTER_GE;
  119. break;
  120. }
  121. }
  122. }
  123. return rc;
  124. }
  125. static struct slapdplugin*
  126. plugin_mr_find_registered (char* oid)
  127. {
  128. oid_item_t* i;
  129. init_global_mr_lock();
  130. PR_Lock (global_mr_oids_lock);
  131. i = global_mr_oids;
  132. PR_Unlock (global_mr_oids_lock);
  133. for (; i != NULL; i = i->oi_next)
  134. {
  135. if (!strcasecmp (oid, i->oi_oid))
  136. {
  137. LDAPDebug (LDAP_DEBUG_FILTER, "plugin_mr_find_registered(%s) != NULL\n", oid, 0, 0);
  138. return i->oi_plugin;
  139. }
  140. }
  141. LDAPDebug (LDAP_DEBUG_FILTER, "plugin_mr_find_registered(%s) == NULL\n", oid, 0, 0);
  142. return NULL;
  143. }
  144. static void
  145. plugin_mr_bind (char* oid, struct slapdplugin* plugin)
  146. {
  147. oid_item_t* i = (oid_item_t*) slapi_ch_malloc (sizeof (oid_item_t));
  148. LDAPDebug (LDAP_DEBUG_FILTER, "=> plugin_mr_bind(%s)\n", oid, 0, 0);
  149. init_global_mr_lock();
  150. i->oi_oid = slapi_ch_strdup (oid);
  151. i->oi_plugin = plugin;
  152. PR_Lock (global_mr_oids_lock);
  153. i->oi_next = global_mr_oids;
  154. global_mr_oids = i;
  155. PR_Unlock (global_mr_oids_lock);
  156. LDAPDebug (LDAP_DEBUG_FILTER, "<= plugin_mr_bind\n", 0, 0, 0);
  157. }
  158. int /* an LDAP error code, hopefully LDAP_SUCCESS */
  159. slapi_mr_indexer_create (Slapi_PBlock* opb)
  160. {
  161. int rc;
  162. char* oid;
  163. if (!(rc = slapi_pblock_get (opb, SLAPI_PLUGIN_MR_OID, &oid)))
  164. {
  165. IFP createFn = NULL;
  166. struct slapdplugin* mrp = plugin_mr_find_registered (oid);
  167. if (mrp != NULL)
  168. {
  169. if (!(rc = slapi_pblock_set (opb, SLAPI_PLUGIN, mrp)) &&
  170. !(rc = slapi_pblock_get (opb, SLAPI_PLUGIN_MR_INDEXER_CREATE_FN, &createFn)) &&
  171. createFn != NULL)
  172. {
  173. rc = createFn (opb);
  174. }
  175. }
  176. else
  177. {
  178. /* call each plugin, until one is able to handle this request. */
  179. rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
  180. for (mrp = get_plugin_list(PLUGIN_LIST_MATCHINGRULE); mrp != NULL; mrp = mrp->plg_next)
  181. {
  182. IFP indexFn = NULL;
  183. Slapi_PBlock pb;
  184. memcpy (&pb, opb, sizeof(Slapi_PBlock));
  185. if (!(rc = slapi_pblock_set (&pb, SLAPI_PLUGIN, mrp)) &&
  186. !(rc = slapi_pblock_get (&pb, SLAPI_PLUGIN_MR_INDEXER_CREATE_FN, &createFn)) &&
  187. createFn != NULL &&
  188. !(rc = createFn (&pb)) &&
  189. ((!(rc = slapi_pblock_get (&pb, SLAPI_PLUGIN_MR_INDEX_FN, &indexFn)) &&
  190. indexFn != NULL) ||
  191. (!(rc = slapi_pblock_get (&pb, SLAPI_PLUGIN_MR_INDEX_SV_FN, &indexFn)) &&
  192. indexFn != NULL)))
  193. {
  194. /* Success: this plugin can handle it. */
  195. memcpy (opb, &pb, sizeof(Slapi_PBlock));
  196. plugin_mr_bind (oid, mrp); /* for future reference */
  197. rc = 0; /* success */
  198. break;
  199. }
  200. }
  201. if (rc != 0) {
  202. /* look for a new syntax-style mr plugin */
  203. struct slapdplugin *pi = plugin_mr_find(oid);
  204. if (pi) {
  205. Slapi_PBlock pb;
  206. memcpy (&pb, opb, sizeof(Slapi_PBlock));
  207. slapi_pblock_set(&pb, SLAPI_PLUGIN, pi);
  208. rc = default_mr_indexer_create(&pb);
  209. if (!rc) {
  210. memcpy (opb, &pb, sizeof(Slapi_PBlock));
  211. plugin_mr_bind (oid, pi); /* for future reference */
  212. }
  213. }
  214. }
  215. }
  216. }
  217. return rc;
  218. }
  219. static struct mr_private *
  220. mr_private_new(const struct slapdplugin *pi, const char *oid, const char *type, const struct berval *value, int ftype, int op)
  221. {
  222. struct mr_private *mrpriv;
  223. mrpriv = (struct mr_private *)slapi_ch_calloc(1, sizeof(struct mr_private));
  224. mrpriv->pi = pi;
  225. mrpriv->oid = oid; /* should be consistent for lifetime of usage - no copy necessary */
  226. mrpriv->type = type; /* should be consistent for lifetime of usage - no copy necessary */
  227. mrpriv->value = value; /* should be consistent for lifetime of usage - no copy necessary */
  228. mrpriv->ftype = ftype;
  229. mrpriv->op = op;
  230. mrpriv->values[0] = mrpriv->value; /* for filter_index */
  231. return mrpriv;
  232. }
  233. static void
  234. mr_private_indexer_done(struct mr_private *mrpriv)
  235. {
  236. if (mrpriv && mrpriv->sva) {
  237. valuearray_free(&mrpriv->sva);
  238. }
  239. if (mrpriv && mrpriv->bva) {
  240. ber_bvecfree(mrpriv->bva);
  241. mrpriv->bva = NULL;
  242. }
  243. }
  244. static void
  245. mr_private_done(struct mr_private *mrpriv)
  246. {
  247. if (mrpriv) {
  248. mrpriv->pi = NULL;
  249. mrpriv->oid = NULL;
  250. mrpriv->type = NULL;
  251. mrpriv->value = NULL;
  252. mrpriv->ftype = 0;
  253. mrpriv->op = 0;
  254. slapi_ch_free_string(&mrpriv->initial);
  255. slapi_ch_free_string(&mrpriv->any[0]);
  256. slapi_ch_free_string(&mrpriv->final);
  257. mrpriv->match_fn = NULL;
  258. mrpriv->values[0] = NULL;
  259. }
  260. mr_private_indexer_done(mrpriv);
  261. }
  262. static void
  263. mr_private_free(struct mr_private **mrpriv)
  264. {
  265. if (mrpriv) {
  266. mr_private_done(*mrpriv);
  267. slapi_ch_free((void **)mrpriv);
  268. }
  269. }
  270. /* this function takes SLAPI_PLUGIN_MR_VALUES as Slapi_Value ** and
  271. returns SLAPI_PLUGIN_MR_KEYS as Slapi_Value **
  272. */
  273. static int
  274. mr_wrap_mr_index_sv_fn(Slapi_PBlock* pb)
  275. {
  276. int rc = -1;
  277. Slapi_Value **in_vals = NULL;
  278. Slapi_Value **out_vals = NULL;
  279. struct slapdplugin *pi = NULL;
  280. slapi_pblock_set(pb, SLAPI_PLUGIN_MR_KEYS, out_vals); /* make sure output is cleared */
  281. slapi_pblock_get(pb, SLAPI_PLUGIN, &pi);
  282. if (!pi) {
  283. LDAPDebug0Args(LDAP_DEBUG_ANY, "mr_wrap_mr_index_sv_fn: error - no plugin specified\n");
  284. } else if (!pi->plg_mr_values2keys) {
  285. LDAPDebug0Args(LDAP_DEBUG_ANY, "mr_wrap_mr_index_sv_fn: error - plugin has no plg_mr_values2keys function\n");
  286. } else {
  287. struct mr_private *mrpriv = NULL;
  288. int ftype = plugin_mr_get_type(pi);
  289. slapi_pblock_get(pb, SLAPI_PLUGIN_MR_VALUES, &in_vals);
  290. (*pi->plg_mr_values2keys)(pb, in_vals, &out_vals, ftype);
  291. slapi_pblock_set(pb, SLAPI_PLUGIN_MR_KEYS, out_vals);
  292. /* we have to save out_vals to free next time or during destroy */
  293. slapi_pblock_get(pb, SLAPI_PLUGIN_OBJECT, &mrpriv);
  294. mr_private_indexer_done(mrpriv); /* free old vals, if any */
  295. mrpriv->sva = out_vals; /* save pointer for later */
  296. rc = 0;
  297. }
  298. return rc;
  299. }
  300. /* this function takes SLAPI_PLUGIN_MR_VALUES as struct berval ** and
  301. returns SLAPI_PLUGIN_MR_KEYS as struct berval **
  302. */
  303. static int
  304. mr_wrap_mr_index_fn(Slapi_PBlock* pb)
  305. {
  306. int rc = -1;
  307. struct berval **in_vals = NULL;
  308. struct berval **out_vals = NULL;
  309. struct mr_private *mrpriv = NULL;
  310. Slapi_Value **in_vals_sv = NULL;
  311. Slapi_Value **out_vals_sv = NULL;
  312. slapi_pblock_get(pb, SLAPI_PLUGIN_MR_VALUES, &in_vals); /* get bervals */
  313. /* convert bervals to sv ary */
  314. valuearray_init_bervalarray(in_vals, &in_vals_sv);
  315. slapi_pblock_set(pb, SLAPI_PLUGIN_MR_VALUES, in_vals_sv); /* use sv */
  316. rc = mr_wrap_mr_index_sv_fn(pb);
  317. /* clean up in_vals_sv */
  318. valuearray_free(&in_vals_sv);
  319. /* restore old in_vals */
  320. slapi_pblock_set(pb, SLAPI_PLUGIN_MR_VALUES, in_vals);
  321. /* get result sv keys */
  322. slapi_pblock_get(pb, SLAPI_PLUGIN_MR_KEYS, &out_vals_sv);
  323. /* convert to bvec */
  324. valuearray_get_bervalarray(out_vals_sv, &out_vals);
  325. /* NOTE: mrpriv owns out_vals_sv (mpriv->sva) - will
  326. get freed by mr_private_indexer_done() */
  327. /* we have to save out_vals to free next time or during destroy */
  328. slapi_pblock_get(pb, SLAPI_PLUGIN_OBJECT, &mrpriv);
  329. mr_private_indexer_done(mrpriv); /* free old vals, if any */
  330. mrpriv->bva = out_vals; /* save pointer for later */
  331. /* set return value berval array for caller */
  332. slapi_pblock_set(pb, SLAPI_PLUGIN_MR_KEYS, out_vals);
  333. return rc;
  334. }
  335. static int
  336. default_mr_filter_destroy(Slapi_PBlock* pb)
  337. {
  338. struct mr_private *mrpriv = NULL;
  339. slapi_pblock_get(pb, SLAPI_PLUGIN_OBJECT, &mrpriv);
  340. mr_private_free(&mrpriv);
  341. mrpriv = NULL;
  342. slapi_pblock_set(pb, SLAPI_PLUGIN_OBJECT, mrpriv);
  343. return 0;
  344. }
  345. static int
  346. default_mr_filter_match(void *obj, Slapi_Entry *e, Slapi_Attr *attr)
  347. {
  348. /* returns: 0 filter matched
  349. * -1 filter did not match
  350. * >0 an LDAP error code
  351. */
  352. int rc = -1;
  353. struct mr_private* mrpriv = (struct mr_private*)obj;
  354. for (; (rc == -1) && (attr != NULL); slapi_entry_next_attr(e, attr, &attr)) {
  355. char* type = NULL;
  356. if (!slapi_attr_get_type (attr, &type) && type != NULL &&
  357. !slapi_attr_type_cmp (mrpriv->type, type, 2/*match subtypes*/)) {
  358. Slapi_Value **vals = attr_get_present_values(attr);
  359. #ifdef SUPPORT_MR_SUBSTRING_MATCHING
  360. if (mrpriv->ftype == LDAP_FILTER_SUBSTRINGS) {
  361. rc = (*mrpriv->match_fn)(pb, mrpriv->initial, mrpriv->any, mrpriv->final, vals);
  362. }
  363. #endif
  364. rc = (*mrpriv->match_fn)(NULL, mrpriv->value, vals, mrpriv->ftype, NULL);
  365. }
  366. }
  367. return rc;
  368. }
  369. /* convert the filter value into an array of values for use
  370. in index key generation */
  371. static int
  372. default_mr_filter_index(Slapi_PBlock *pb)
  373. {
  374. int rc = 0;
  375. struct mr_private* mrpriv = NULL;
  376. slapi_pblock_get(pb, SLAPI_PLUGIN_OBJECT, &mrpriv);
  377. slapi_pblock_set(pb, SLAPI_PLUGIN, (void *)mrpriv->pi);
  378. slapi_pblock_set(pb, SLAPI_PLUGIN_MR_TYPE, (void *)mrpriv->type);
  379. /* extensible_candidates uses struct berval ** indexer */
  380. slapi_pblock_set(pb, SLAPI_PLUGIN_MR_INDEX_FN, mr_wrap_mr_index_fn);
  381. slapi_pblock_set(pb, SLAPI_PLUGIN_MR_VALUES, mrpriv->values);
  382. /* the OID is magic - this is used to calculate the index prefix - it
  383. is the indextype value passed to index_index2prefix - it must be the
  384. same OID as used in the index configuration for the index matching
  385. rule */
  386. slapi_pblock_set(pb, SLAPI_PLUGIN_MR_OID, (void *)mrpriv->oid);
  387. slapi_pblock_set(pb, SLAPI_PLUGIN_MR_QUERY_OPERATOR, &mrpriv->op);
  388. return rc;
  389. }
  390. static int
  391. default_mr_filter_create(Slapi_PBlock *pb)
  392. {
  393. int rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION; /* failed to initialize */
  394. char* mrOID = NULL;
  395. char* mrTYPE = NULL;
  396. struct berval* mrVALUE = NULL;
  397. struct slapdplugin* pi = NULL;
  398. LDAPDebug0Args(LDAP_DEBUG_FILTER, "=> default_mr_filter_create\n");
  399. if (!slapi_pblock_get(pb, SLAPI_PLUGIN_MR_OID, &mrOID) && mrOID != NULL &&
  400. !slapi_pblock_get(pb, SLAPI_PLUGIN_MR_TYPE, &mrTYPE) && mrTYPE != NULL &&
  401. !slapi_pblock_get(pb, SLAPI_PLUGIN_MR_VALUE, &mrVALUE) && mrVALUE != NULL &&
  402. !slapi_pblock_get(pb, SLAPI_PLUGIN, &pi) && pi != NULL) {
  403. int op = SLAPI_OP_EQUAL;
  404. struct mr_private *mrpriv = NULL;
  405. int ftype = 0;
  406. LDAPDebug2Args(LDAP_DEBUG_FILTER, "=> default_mr_filter_create(oid %s; type %s)\n",
  407. mrOID, mrTYPE);
  408. ftype = plugin_mr_get_type(pi);
  409. /* map the ftype to the op type */
  410. if (ftype == LDAP_FILTER_GE) {
  411. /*
  412. * The rule evaluates to TRUE if and only if, in the code point
  413. * collation order, the prepared attribute value character string
  414. * appears earlier than the prepared assertion value character string;
  415. * i.e., the attribute value is "less than" the assertion value.
  416. */
  417. op = SLAPI_OP_LESS;
  418. /*
  419. } else if (ftype == LDAP_FILTER_SUBSTRINGS) {
  420. op = SLAPI_OP_SUBSTRING;
  421. */
  422. } else if (ftype != LDAP_FILTER_EQUALITY) { /* unsupported */
  423. /* NOTE: we cannot currently support substring matching rules - the
  424. reason is that the API provides no way to pass in the search time limit
  425. required by the syntax filter substring match functions
  426. */
  427. LDAPDebug1Arg(LDAP_DEBUG_FILTER, "<= default_mr_filter_create - unsupported filter type %d\n",
  428. ftype);
  429. goto done;
  430. }
  431. slapi_pblock_set(pb, SLAPI_PLUGIN_MR_QUERY_OPERATOR, &op);
  432. mrpriv = mr_private_new(pi, mrOID, mrTYPE, mrVALUE, ftype, op);
  433. #ifdef SUPPORT_MR_SUBSTRING_MATCHING
  434. if ((ftype == LDAP_FILTER_SUBSTRINGS) && (mrVALUE->bv_len > 0) && (mrVALUE->bv_val)) {
  435. char *first, *last;
  436. int have_initial = 0, have_final = 0;
  437. if ((mrVALUE->bv_len > 1) && (mrVALUE->bv_val[0] == '*')) {
  438. first = &mrVALUE->bv_val[1]; /* point at first "real" char */
  439. have_final = 1; /* substring final match */
  440. } else {
  441. first = mrVALUE->bv_val; /* point at beginning */
  442. }
  443. if ((mrVALUE->bv_len > 1) && (mrVALUE->bv_val[mrVALUE->bv_len-1] == '*')) {
  444. last = &mrVALUE->bv_val[mrVALUE->bv_len-2]; /* point at last "real" char */
  445. have_initial = 1; /* substring initial match */
  446. } else {
  447. last = &mrVALUE->bv_val[mrVALUE->bv_len-1]; /* point at end */
  448. }
  449. if (have_initial == have_final) { /* both or none specified - assume any */
  450. mrpriv->any[0] = PL_strndup(first, last-first);
  451. } else if (have_initial) {
  452. mrpriv->initial = PL_strndup(first, last-first);
  453. } else if (have_final) {
  454. mrpriv->final = PL_strndup(first, last-first);
  455. }
  456. }
  457. if (ftype == LDAP_FILTER_SUBSTRINGS) {
  458. mrpriv->match_fn = pi->plg_mr_filter_sub;
  459. } else {
  460. mrpriv->match_fn = pi->plg_mr_filter_ava;
  461. }
  462. #else
  463. mrpriv->match_fn = pi->plg_mr_filter_ava;
  464. #endif
  465. slapi_pblock_set(pb, SLAPI_PLUGIN_OBJECT, mrpriv);
  466. slapi_pblock_set(pb, SLAPI_PLUGIN_MR_FILTER_MATCH_FN, default_mr_filter_match);
  467. slapi_pblock_set(pb, SLAPI_PLUGIN_MR_FILTER_INDEX_FN, default_mr_filter_index);
  468. slapi_pblock_set(pb, SLAPI_PLUGIN_DESTROY_FN, default_mr_filter_destroy);
  469. rc = 0; /* success */
  470. } else {
  471. LDAPDebug(LDAP_DEBUG_FILTER,
  472. "default_mr_filter_create: missing parameter: %s%s%s\n",
  473. mrOID ? "" : " oid",
  474. mrTYPE ? "" : " attribute type",
  475. mrVALUE ? "" : " filter value");
  476. }
  477. done:
  478. LDAPDebug1Arg(LDAP_DEBUG_FILTER, "=> default_mr_filter_create: %d\n", rc);
  479. return rc;
  480. }
  481. static int
  482. attempt_mr_filter_create (mr_filter_t* f, struct slapdplugin* mrp, Slapi_PBlock* pb)
  483. {
  484. int rc;
  485. IFP mrf_create = NULL;
  486. f->mrf_match = NULL;
  487. pblock_init (pb);
  488. if (!(rc = slapi_pblock_set (pb, SLAPI_PLUGIN, mrp)) &&
  489. !(rc = slapi_pblock_get (pb, SLAPI_PLUGIN_MR_FILTER_CREATE_FN, &mrf_create)) &&
  490. mrf_create != NULL &&
  491. !(rc = slapi_pblock_set (pb, SLAPI_PLUGIN_MR_OID, f->mrf_oid)) &&
  492. !(rc = slapi_pblock_set (pb, SLAPI_PLUGIN_MR_TYPE, f->mrf_type)) &&
  493. !(rc = slapi_pblock_set (pb, SLAPI_PLUGIN_MR_VALUE, &(f->mrf_value))) &&
  494. !(rc = mrf_create (pb)) &&
  495. !(rc = slapi_pblock_get (pb, SLAPI_PLUGIN_MR_FILTER_MATCH_FN, &(f->mrf_match)))) {
  496. if (f->mrf_match == NULL)
  497. {
  498. rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
  499. }
  500. }
  501. if (NULL == mrf_create) {
  502. /* no create func - unavailable */
  503. rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
  504. }
  505. return rc;
  506. }
  507. int /* an LDAP error code, hopefully LDAP_SUCCESS */
  508. plugin_mr_filter_create (mr_filter_t* f)
  509. {
  510. int rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
  511. struct slapdplugin* mrp = plugin_mr_find_registered (f->mrf_oid);
  512. Slapi_PBlock pb;
  513. if (mrp != NULL)
  514. {
  515. rc = attempt_mr_filter_create (f, mrp, &pb);
  516. }
  517. else
  518. {
  519. /* call each plugin, until one is able to handle this request. */
  520. for (mrp = get_plugin_list(PLUGIN_LIST_MATCHINGRULE); mrp != NULL; mrp = mrp->plg_next)
  521. {
  522. if (!(rc = attempt_mr_filter_create (f, mrp, &pb)))
  523. {
  524. plugin_mr_bind (f->mrf_oid, mrp); /* for future reference */
  525. break;
  526. }
  527. }
  528. }
  529. if (rc)
  530. {
  531. /* look for a new syntax-style mr plugin */
  532. mrp = plugin_mr_find(f->mrf_oid);
  533. if (mrp)
  534. {
  535. /* set the default index create fn */
  536. pblock_init(&pb);
  537. slapi_pblock_set(&pb, SLAPI_PLUGIN, mrp);
  538. slapi_pblock_set(&pb, SLAPI_PLUGIN_MR_FILTER_CREATE_FN, default_mr_filter_create);
  539. if (!(rc = attempt_mr_filter_create (f, mrp, &pb)))
  540. {
  541. plugin_mr_bind (f->mrf_oid, mrp); /* for future reference */
  542. }
  543. }
  544. }
  545. if (!rc)
  546. {
  547. /* This plugin has created the desired filter. */
  548. slapi_pblock_get (&pb, SLAPI_PLUGIN_MR_FILTER_INDEX_FN, &(f->mrf_index));
  549. slapi_pblock_get (&pb, SLAPI_PLUGIN_MR_FILTER_REUSABLE, &(f->mrf_reusable));
  550. slapi_pblock_get (&pb, SLAPI_PLUGIN_MR_FILTER_RESET_FN, &(f->mrf_reset));
  551. slapi_pblock_get (&pb, SLAPI_PLUGIN_OBJECT, &(f->mrf_object));
  552. slapi_pblock_get (&pb, SLAPI_PLUGIN_DESTROY_FN, &(f->mrf_destroy));
  553. }
  554. return rc;
  555. }
  556. int /* an LDAP error code, hopefully LDAP_SUCCESS */
  557. slapi_mr_filter_index (Slapi_Filter* f, Slapi_PBlock* pb)
  558. {
  559. int rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
  560. if (f->f_choice == LDAP_FILTER_EXTENDED && f->f_mr.mrf_index != NULL &&
  561. !(rc = slapi_pblock_set (pb, SLAPI_PLUGIN_OBJECT, f->f_mr.mrf_object)))
  562. {
  563. rc = f->f_mr.mrf_index (pb);
  564. }
  565. return rc;
  566. }
  567. static int
  568. default_mr_indexer_destroy(Slapi_PBlock* pb)
  569. {
  570. struct mr_private *mrpriv = NULL;
  571. slapi_pblock_get(pb, SLAPI_PLUGIN_OBJECT, &mrpriv);
  572. mr_private_free(&mrpriv);
  573. mrpriv = NULL;
  574. slapi_pblock_set(pb, SLAPI_PLUGIN_OBJECT, mrpriv);
  575. return 0;
  576. }
  577. /* this is the default mr indexer create func
  578. for new syntax-style mr plugins */
  579. static int
  580. default_mr_indexer_create(Slapi_PBlock* pb)
  581. {
  582. int rc = -1;
  583. struct slapdplugin *pi = NULL;
  584. slapi_pblock_get(pb, SLAPI_PLUGIN, &pi);
  585. if (NULL == pi) {
  586. LDAPDebug0Args(LDAP_DEBUG_ANY, "default_mr_indexer_create: error - no plugin specified\n");
  587. goto done;
  588. }
  589. if (NULL == pi->plg_mr_values2keys) {
  590. LDAPDebug1Arg(LDAP_DEBUG_ANY, "default_mr_indexer_create: error - plugin [%s] has no plg_mr_values2keys function\n",
  591. pi->plg_name);
  592. goto done;
  593. }
  594. slapi_pblock_set(pb, SLAPI_PLUGIN_OBJECT, mr_private_new(pi, NULL, NULL, NULL, 0, 0));
  595. slapi_pblock_set(pb, SLAPI_PLUGIN_MR_INDEX_FN, mr_wrap_mr_index_fn);
  596. slapi_pblock_set(pb, SLAPI_PLUGIN_MR_INDEX_SV_FN, mr_wrap_mr_index_sv_fn);
  597. slapi_pblock_set(pb, SLAPI_PLUGIN_DESTROY_FN, default_mr_indexer_destroy);
  598. slapi_pblock_set(pb, SLAPI_PLUGIN_MR_INDEXER_CREATE_FN, default_mr_indexer_create);
  599. rc = 0;
  600. done:
  601. return rc;
  602. }