plugin_mr.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681
  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. /* In case SLAPI_PLUGIN_OBJECT is not set
  268. * (e.g. custom index/filter create function did not initialize it
  269. */
  270. if (mrpriv) {
  271. mr_private_indexer_done(mrpriv); /* free old vals, if any */
  272. mrpriv->sva = out_vals; /* save pointer for later */
  273. }
  274. rc = 0;
  275. }
  276. return rc;
  277. }
  278. /* this function takes SLAPI_PLUGIN_MR_VALUES as struct berval ** and
  279. returns SLAPI_PLUGIN_MR_KEYS as struct berval **
  280. */
  281. static int
  282. mr_wrap_mr_index_fn(Slapi_PBlock* pb)
  283. {
  284. int rc = -1;
  285. struct berval **in_vals = NULL;
  286. struct berval **out_vals = NULL;
  287. struct mr_private *mrpriv = NULL;
  288. Slapi_Value **in_vals_sv = NULL;
  289. Slapi_Value **out_vals_sv = NULL;
  290. slapi_pblock_get(pb, SLAPI_PLUGIN_MR_VALUES, &in_vals); /* get bervals */
  291. /* convert bervals to sv ary */
  292. valuearray_init_bervalarray(in_vals, &in_vals_sv);
  293. slapi_pblock_set(pb, SLAPI_PLUGIN_MR_VALUES, in_vals_sv); /* use sv */
  294. rc = mr_wrap_mr_index_sv_fn(pb);
  295. /* clean up in_vals_sv */
  296. valuearray_free(&in_vals_sv);
  297. /* restore old in_vals */
  298. slapi_pblock_set(pb, SLAPI_PLUGIN_MR_VALUES, in_vals);
  299. /* get result sv keys */
  300. slapi_pblock_get(pb, SLAPI_PLUGIN_MR_KEYS, &out_vals_sv);
  301. /* convert to bvec */
  302. valuearray_get_bervalarray(out_vals_sv, &out_vals);
  303. /* NOTE: mrpriv owns out_vals_sv (mpriv->sva) - will
  304. get freed by mr_private_indexer_done() */
  305. /* we have to save out_vals to free next time or during destroy */
  306. slapi_pblock_get(pb, SLAPI_PLUGIN_OBJECT, &mrpriv);
  307. /* In case SLAPI_PLUGIN_OBJECT is not set
  308. * (e.g. custom index/filter create function did not initialize it
  309. */
  310. if (mrpriv) {
  311. mr_private_indexer_done(mrpriv); /* free old vals, if any */
  312. mrpriv->bva = out_vals; /* save pointer for later */
  313. }
  314. /* set return value berval array for caller */
  315. slapi_pblock_set(pb, SLAPI_PLUGIN_MR_KEYS, out_vals);
  316. return rc;
  317. }
  318. static int
  319. default_mr_filter_destroy(Slapi_PBlock* pb)
  320. {
  321. struct mr_private *mrpriv = NULL;
  322. slapi_pblock_get(pb, SLAPI_PLUGIN_OBJECT, &mrpriv);
  323. mr_private_free(&mrpriv);
  324. mrpriv = NULL;
  325. slapi_pblock_set(pb, SLAPI_PLUGIN_OBJECT, mrpriv);
  326. return 0;
  327. }
  328. static int
  329. default_mr_filter_match(void *obj, Slapi_Entry *e, Slapi_Attr *attr)
  330. {
  331. /* returns: 0 filter matched
  332. * -1 filter did not match
  333. * >0 an LDAP error code
  334. */
  335. int rc = -1;
  336. struct mr_private* mrpriv = (struct mr_private*)obj;
  337. /* In case SLAPI_PLUGIN_OBJECT is not set, mrpriv may be NULL */
  338. if (mrpriv == NULL)
  339. return rc;
  340. for (; (rc == -1) && (attr != NULL); slapi_entry_next_attr(e, attr, &attr)) {
  341. char* type = NULL;
  342. if (!slapi_attr_get_type (attr, &type) && type != NULL &&
  343. !slapi_attr_type_cmp ((const char *)mrpriv->type, type, 2/*match subtypes*/)) {
  344. Slapi_Value **vals = attr_get_present_values(attr);
  345. #ifdef SUPPORT_MR_SUBSTRING_MATCHING
  346. if (mrpriv->ftype == LDAP_FILTER_SUBSTRINGS) {
  347. rc = (*mrpriv->match_fn)(pb, mrpriv->initial, mrpriv->any, mrpriv->final, vals);
  348. }
  349. #endif
  350. rc = (*mrpriv->match_fn)(NULL, mrpriv->value, vals, mrpriv->ftype, NULL);
  351. }
  352. }
  353. return rc;
  354. }
  355. /* convert the filter value into an array of values for use
  356. in index key generation */
  357. static int
  358. default_mr_filter_index(Slapi_PBlock *pb)
  359. {
  360. int rc = 0;
  361. struct mr_private* mrpriv = NULL;
  362. slapi_pblock_get(pb, SLAPI_PLUGIN_OBJECT, &mrpriv);
  363. /* In case SLAPI_PLUGIN_OBJECT is not set
  364. * (e.g. custom index/filter create function did not initialize it
  365. */
  366. if (mrpriv == NULL) {
  367. char* mrOID = NULL;
  368. char* mrTYPE = NULL;
  369. slapi_pblock_get(pb, SLAPI_PLUGIN_MR_OID, &mrOID);
  370. slapi_pblock_get(pb, SLAPI_PLUGIN_MR_TYPE, &mrTYPE);
  371. slapi_log_error(SLAPI_LOG_FATAL, "default_mr_filter_index",
  372. "Failure because mrpriv is NULL : %s %s\n",
  373. mrOID ? "" : " oid",
  374. mrTYPE ? "" : " attribute type");
  375. return -1;
  376. }
  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. /* check to make sure this create function is supposed to be used with the
  409. given oid */
  410. if (!charray_inlist(pi->plg_mr_names, mrOID)) {
  411. LDAPDebug2Args(LDAP_DEBUG_FILTER,
  412. "=> default_mr_filter_create: cannot use matching rule %s with plugin %s\n",
  413. mrOID, pi->plg_name);
  414. goto done;
  415. }
  416. ftype = plugin_mr_get_type(pi);
  417. /* map the ftype to the op type */
  418. if (ftype == LDAP_FILTER_GE) {
  419. /*
  420. * The rule evaluates to TRUE if and only if, in the code point
  421. * collation order, the prepared attribute value character string
  422. * appears earlier than the prepared assertion value character string;
  423. * i.e., the attribute value is "less than" the assertion value.
  424. */
  425. op = SLAPI_OP_LESS;
  426. /*
  427. } else if (ftype == LDAP_FILTER_SUBSTRINGS) {
  428. op = SLAPI_OP_SUBSTRING;
  429. */
  430. } else if (ftype != LDAP_FILTER_EQUALITY) { /* unsupported */
  431. /* NOTE: we cannot currently support substring matching rules - the
  432. reason is that the API provides no way to pass in the search time limit
  433. required by the syntax filter substring match functions
  434. */
  435. LDAPDebug1Arg(LDAP_DEBUG_FILTER, "<= default_mr_filter_create - unsupported filter type %d\n",
  436. ftype);
  437. goto done;
  438. }
  439. slapi_pblock_set(pb, SLAPI_PLUGIN_MR_QUERY_OPERATOR, &op);
  440. mrpriv = mr_private_new(pi, mrOID, mrTYPE, mrVALUE, ftype, op);
  441. #ifdef SUPPORT_MR_SUBSTRING_MATCHING
  442. if ((ftype == LDAP_FILTER_SUBSTRINGS) && (mrVALUE->bv_len > 0) && (mrVALUE->bv_val)) {
  443. char *first, *last;
  444. int have_initial = 0, have_final = 0;
  445. if ((mrVALUE->bv_len > 1) && (mrVALUE->bv_val[0] == '*')) {
  446. first = &mrVALUE->bv_val[1]; /* point at first "real" char */
  447. have_final = 1; /* substring final match */
  448. } else {
  449. first = mrVALUE->bv_val; /* point at beginning */
  450. }
  451. if ((mrVALUE->bv_len > 1) && (mrVALUE->bv_val[mrVALUE->bv_len-1] == '*')) {
  452. last = &mrVALUE->bv_val[mrVALUE->bv_len-2]; /* point at last "real" char */
  453. have_initial = 1; /* substring initial match */
  454. } else {
  455. last = &mrVALUE->bv_val[mrVALUE->bv_len-1]; /* point at end */
  456. }
  457. if (have_initial == have_final) { /* both or none specified - assume any */
  458. mrpriv->any[0] = PL_strndup(first, last-first);
  459. } else if (have_initial) {
  460. mrpriv->initial = PL_strndup(first, last-first);
  461. } else if (have_final) {
  462. mrpriv->final = PL_strndup(first, last-first);
  463. }
  464. }
  465. if (ftype == LDAP_FILTER_SUBSTRINGS) {
  466. mrpriv->match_fn = pi->plg_mr_filter_sub;
  467. } else {
  468. mrpriv->match_fn = pi->plg_mr_filter_ava;
  469. }
  470. #else
  471. mrpriv->match_fn = pi->plg_mr_filter_ava;
  472. #endif
  473. slapi_pblock_set(pb, SLAPI_PLUGIN_OBJECT, mrpriv);
  474. slapi_pblock_set(pb, SLAPI_PLUGIN_MR_FILTER_MATCH_FN, default_mr_filter_match);
  475. slapi_pblock_set(pb, SLAPI_PLUGIN_MR_FILTER_INDEX_FN, default_mr_filter_index);
  476. slapi_pblock_set(pb, SLAPI_PLUGIN_DESTROY_FN, default_mr_filter_destroy);
  477. rc = 0; /* success */
  478. } else {
  479. LDAPDebug(LDAP_DEBUG_FILTER,
  480. "default_mr_filter_create: missing parameter: %s%s%s\n",
  481. mrOID ? "" : " oid",
  482. mrTYPE ? "" : " attribute type",
  483. mrVALUE ? "" : " filter value");
  484. }
  485. done:
  486. LDAPDebug1Arg(LDAP_DEBUG_FILTER, "=> default_mr_filter_create: %d\n", rc);
  487. return rc;
  488. }
  489. static int
  490. attempt_mr_filter_create (mr_filter_t* f, struct slapdplugin* mrp, Slapi_PBlock* pb)
  491. {
  492. int rc;
  493. IFP mrf_create = NULL;
  494. f->mrf_match = NULL;
  495. pblock_init (pb);
  496. if (!(rc = slapi_pblock_set (pb, SLAPI_PLUGIN, mrp)) &&
  497. !(rc = slapi_pblock_get (pb, SLAPI_PLUGIN_MR_FILTER_CREATE_FN, &mrf_create)) &&
  498. mrf_create != NULL &&
  499. !(rc = slapi_pblock_set (pb, SLAPI_PLUGIN_MR_OID, f->mrf_oid)) &&
  500. !(rc = slapi_pblock_set (pb, SLAPI_PLUGIN_MR_TYPE, f->mrf_type)) &&
  501. !(rc = slapi_pblock_set (pb, SLAPI_PLUGIN_MR_VALUE, &(f->mrf_value))) &&
  502. !(rc = mrf_create (pb)) &&
  503. !(rc = slapi_pblock_get (pb, SLAPI_PLUGIN_MR_FILTER_MATCH_FN, &(f->mrf_match)))) {
  504. if (f->mrf_match == NULL)
  505. {
  506. rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
  507. }
  508. }
  509. if (NULL == mrf_create) {
  510. /* no create func - unavailable */
  511. rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
  512. }
  513. return rc;
  514. }
  515. int /* an LDAP error code, hopefully LDAP_SUCCESS */
  516. plugin_mr_filter_create (mr_filter_t* f)
  517. {
  518. int rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
  519. struct slapdplugin* mrp = plugin_mr_find_registered (f->mrf_oid);
  520. Slapi_PBlock pb;
  521. if (mrp != NULL)
  522. {
  523. rc = attempt_mr_filter_create (f, mrp, &pb);
  524. }
  525. else
  526. {
  527. /* call each plugin, until one is able to handle this request. */
  528. for (mrp = get_plugin_list(PLUGIN_LIST_MATCHINGRULE); mrp != NULL; mrp = mrp->plg_next)
  529. {
  530. if (!(rc = attempt_mr_filter_create (f, mrp, &pb)))
  531. {
  532. plugin_mr_bind (f->mrf_oid, mrp); /* for future reference */
  533. break;
  534. }
  535. }
  536. }
  537. if (rc)
  538. {
  539. /* look for a new syntax-style mr plugin */
  540. mrp = plugin_mr_find(f->mrf_oid);
  541. if (mrp)
  542. {
  543. /* set the default index create fn */
  544. pblock_init(&pb);
  545. slapi_pblock_set(&pb, SLAPI_PLUGIN, mrp);
  546. slapi_pblock_set(&pb, SLAPI_PLUGIN_MR_FILTER_CREATE_FN, default_mr_filter_create);
  547. slapi_pblock_set(&pb, SLAPI_PLUGIN_MR_INDEXER_CREATE_FN, default_mr_indexer_create);
  548. if (!(rc = attempt_mr_filter_create (f, mrp, &pb)))
  549. {
  550. plugin_mr_bind (f->mrf_oid, mrp); /* for future reference */
  551. }
  552. }
  553. }
  554. if (!rc)
  555. {
  556. /* This plugin has created the desired filter. */
  557. slapi_pblock_get (&pb, SLAPI_PLUGIN_MR_FILTER_INDEX_FN, &(f->mrf_index));
  558. slapi_pblock_get (&pb, SLAPI_PLUGIN_MR_FILTER_REUSABLE, &(f->mrf_reusable));
  559. slapi_pblock_get (&pb, SLAPI_PLUGIN_MR_FILTER_RESET_FN, &(f->mrf_reset));
  560. slapi_pblock_get (&pb, SLAPI_PLUGIN_OBJECT, &(f->mrf_object));
  561. slapi_pblock_get (&pb, SLAPI_PLUGIN_DESTROY_FN, &(f->mrf_destroy));
  562. }
  563. return rc;
  564. }
  565. int /* an LDAP error code, hopefully LDAP_SUCCESS */
  566. slapi_mr_filter_index (Slapi_Filter* f, Slapi_PBlock* pb)
  567. {
  568. int rc = LDAP_UNAVAILABLE_CRITICAL_EXTENSION;
  569. if (f->f_choice == LDAP_FILTER_EXTENDED && f->f_mr.mrf_index != NULL &&
  570. !(rc = slapi_pblock_set (pb, SLAPI_PLUGIN_OBJECT, f->f_mr.mrf_object)))
  571. {
  572. rc = f->f_mr.mrf_index (pb);
  573. }
  574. return rc;
  575. }
  576. static int
  577. default_mr_indexer_destroy(Slapi_PBlock* pb)
  578. {
  579. struct mr_private *mrpriv = NULL;
  580. slapi_pblock_get(pb, SLAPI_PLUGIN_OBJECT, &mrpriv);
  581. mr_private_free(&mrpriv);
  582. mrpriv = NULL;
  583. slapi_pblock_set(pb, SLAPI_PLUGIN_OBJECT, mrpriv);
  584. /* keys destroyed in mr_private_free */
  585. slapi_pblock_set(pb, SLAPI_PLUGIN_MR_KEYS, NULL);
  586. return 0;
  587. }
  588. /* this is the default mr indexer create func
  589. for new syntax-style mr plugins */
  590. static int
  591. default_mr_indexer_create(Slapi_PBlock* pb)
  592. {
  593. int rc = -1;
  594. struct slapdplugin *pi = NULL;
  595. slapi_pblock_get(pb, SLAPI_PLUGIN, &pi);
  596. if (NULL == pi) {
  597. LDAPDebug0Args(LDAP_DEBUG_ANY, "default_mr_indexer_create: error - no plugin specified\n");
  598. goto done;
  599. }
  600. if (NULL == pi->plg_mr_values2keys) {
  601. LDAPDebug1Arg(LDAP_DEBUG_ANY, "default_mr_indexer_create: error - plugin [%s] has no plg_mr_values2keys function\n",
  602. pi->plg_name);
  603. goto done;
  604. }
  605. slapi_pblock_set(pb, SLAPI_PLUGIN_OBJECT, mr_private_new(pi, NULL, NULL, NULL, 0, 0));
  606. slapi_pblock_set(pb, SLAPI_PLUGIN_MR_INDEX_FN, mr_wrap_mr_index_fn);
  607. slapi_pblock_set(pb, SLAPI_PLUGIN_MR_INDEX_SV_FN, mr_wrap_mr_index_sv_fn);
  608. slapi_pblock_set(pb, SLAPI_PLUGIN_DESTROY_FN, default_mr_indexer_destroy);
  609. slapi_pblock_set(pb, SLAPI_PLUGIN_MR_INDEXER_CREATE_FN, default_mr_indexer_create);
  610. slapi_pblock_set(pb, SLAPI_PLUGIN_MR_FILTER_CREATE_FN, default_mr_filter_create);
  611. rc = 0;
  612. done:
  613. return rc;
  614. }