plugin_mr.c 20 KB

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