string.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  3. * Copyright (C) 2021 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. /* string.c - common string syntax routines */
  13. #include <stdio.h>
  14. #include <string.h>
  15. #include <sys/types.h>
  16. #include "syntax.h"
  17. #if defined(IRIX)
  18. #include <unistd.h>
  19. #endif
  20. #define MAX_VAL(x, y) ((x) > (y) ? (x) : (y))
  21. static int string_filter_approx(struct berval *bvfilter,
  22. Slapi_Value **bvals,
  23. Slapi_Value **retVal);
  24. static void substring_comp_keys(Slapi_Value ***ivals, int *nsubs, char *str, int lenstring, int prepost, int syntax, char *comp_buf, int *substrlens);
  25. int
  26. string_filter_ava(struct berval *bvfilter, Slapi_Value **bvals, int syntax, int ftype, Slapi_Value **retVal)
  27. {
  28. int i, rc;
  29. struct berval bvfilter_norm = {0, NULL};
  30. struct berval *pbvfilter_norm = &bvfilter_norm;
  31. char *alt = NULL;
  32. if (retVal) {
  33. *retVal = NULL;
  34. }
  35. if (ftype == LDAP_FILTER_APPROX) {
  36. return (string_filter_approx(bvfilter, bvals, retVal));
  37. }
  38. if (syntax & SYNTAX_NORM_FILT) {
  39. pbvfilter_norm = bvfilter; /* already normalized */
  40. } else {
  41. slapi_ber_bvcpy(&bvfilter_norm, bvfilter);
  42. /* 3rd arg: 1 - trim leading blanks */
  43. value_normalize_ext(bvfilter_norm.bv_val, syntax, 1, &alt);
  44. if (alt) {
  45. slapi_ber_bvdone(&bvfilter_norm);
  46. bvfilter_norm.bv_val = alt;
  47. alt = NULL;
  48. }
  49. if (bvfilter_norm.bv_val) {
  50. bvfilter_norm.bv_len = strlen(bvfilter_norm.bv_val);
  51. } else {
  52. bvfilter_norm.bv_len = 0;
  53. }
  54. }
  55. for (i = 0; (bvals != NULL) && (bvals[i] != NULL); i++) {
  56. int norm_val = 1; /* normalize the first value only */
  57. /* if the NORMALIZED flag is set, skip normalizing */
  58. if (slapi_value_get_flags(bvals[i]) & SLAPI_ATTR_FLAG_NORMALIZED) {
  59. norm_val = 0;
  60. }
  61. /* note - do not return the normalized value in retVal - the
  62. caller will usually want the "raw" value, and can normalize it later
  63. */
  64. rc = value_cmp((struct berval *)slapi_value_get_berval(bvals[i]), pbvfilter_norm, syntax, norm_val);
  65. switch (ftype) {
  66. case LDAP_FILTER_GE:
  67. if (rc >= 0) {
  68. if (retVal) {
  69. *retVal = bvals[i];
  70. }
  71. slapi_ch_free_string(&bvfilter_norm.bv_val);
  72. return (0);
  73. }
  74. break;
  75. case LDAP_FILTER_LE:
  76. if (rc <= 0) {
  77. if (retVal) {
  78. *retVal = bvals[i];
  79. }
  80. slapi_ch_free_string(&bvfilter_norm.bv_val);
  81. return (0);
  82. }
  83. break;
  84. case LDAP_FILTER_EQUALITY:
  85. if (rc == 0) {
  86. if (retVal) {
  87. *retVal = bvals[i];
  88. }
  89. slapi_ch_free_string(&bvfilter_norm.bv_val);
  90. return (0);
  91. }
  92. break;
  93. }
  94. }
  95. slapi_ch_free_string(&bvfilter_norm.bv_val);
  96. return (-1);
  97. }
  98. /*
  99. * return value: 0 -- approximately matched
  100. * -1 -- did not match
  101. */
  102. static int
  103. string_filter_approx(struct berval *bvfilter, Slapi_Value **bvals, Slapi_Value **retVal)
  104. {
  105. int i, rc;
  106. int ava_wordcount;
  107. char *w1, *w2, *c1, *c2;
  108. slapi_log_err(SLAPI_LOG_TRACE, SYNTAX_PLUGIN_SUBSYSTEM, "=> string_filter_approx\n");
  109. /*
  110. * try to match words in each filter value in order
  111. * in the attribute value.
  112. * XXX should do this once for the filter and save it XXX
  113. */
  114. rc = -1;
  115. if (retVal) {
  116. *retVal = NULL;
  117. }
  118. for (i = 0; (bvals != NULL) && (bvals[i] != NULL); i++) {
  119. w2 = (char *)slapi_value_get_string(bvals[i]); /* JCM cast */
  120. ava_wordcount = 0;
  121. /* for each word in the filter value */
  122. for (w1 = first_word(bvfilter->bv_val); w1 != NULL;
  123. w1 = next_word(w1)) {
  124. ++ava_wordcount;
  125. if ((c1 = phonetic(w1)) == NULL) {
  126. break;
  127. }
  128. /*
  129. * for each word in the attribute value from
  130. * where we left off...
  131. */
  132. for (w2 = first_word(w2); w2 != NULL;
  133. w2 = next_word(w2)) {
  134. c2 = phonetic(w2);
  135. rc = strcmp(c1, c2);
  136. slapi_ch_free((void **)&c2);
  137. if (rc == 0) {
  138. if (retVal) {
  139. *retVal = bvals[i];
  140. }
  141. break;
  142. }
  143. }
  144. slapi_ch_free((void **)&c1);
  145. /*
  146. * if we stopped because we ran out of words
  147. * before making a match, go on to the next
  148. * value. otherwise try to keep matching
  149. * words in this value from where we left off.
  150. */
  151. if (w2 == NULL) {
  152. break;
  153. } else {
  154. w2 = next_word(w2);
  155. }
  156. }
  157. /*
  158. * if we stopped because we ran out of words and
  159. * we found at leasy one word, we have a match.
  160. */
  161. if (w1 == NULL && ava_wordcount > 0) {
  162. rc = 0;
  163. break;
  164. }
  165. }
  166. if (0 != rc) {
  167. rc = -1;
  168. }
  169. slapi_log_err(SLAPI_LOG_TRACE, SYNTAX_PLUGIN_SUBSYSTEM, "<= string_filter_approx %d\n", rc);
  170. return (rc);
  171. }
  172. int
  173. string_filter_sub(Slapi_PBlock *pb, char *initial, char **any, char * final, Slapi_Value **bvals, int syntax)
  174. {
  175. int i, j, rc, size = 0;
  176. char *p, *end, *realval, *tmpbuf = NULL, *bigpat = NULL;
  177. size_t tmpbufsize;
  178. char pat[BUFSIZ];
  179. char buf[BUFSIZ];
  180. struct timespec expire_time = {0};
  181. Operation *op = NULL;
  182. Slapi_Regex *re = NULL;
  183. char *re_result = NULL;
  184. char *alt = NULL;
  185. int filter_normalized = 0;
  186. int free_re = 1;
  187. struct subfilt *sf = NULL;
  188. slapi_log_err(SLAPI_LOG_TRACE, SYNTAX_PLUGIN_SUBSYSTEM, "=> string_filter_sub\n");
  189. if (pb) {
  190. slapi_pblock_get(pb, SLAPI_OPERATION, &op);
  191. }
  192. if (NULL != op) {
  193. int32_t timelimit = -1; /* search timelimit */
  194. slapi_pblock_get(pb, SLAPI_SEARCH_TIMELIMIT, &timelimit);
  195. slapi_operation_time_expiry(op, (time_t)timelimit, &expire_time);
  196. }
  197. if (pb) {
  198. slapi_pblock_get(pb, SLAPI_PLUGIN_SYNTAX_FILTER_NORMALIZED, &filter_normalized);
  199. slapi_pblock_get(pb, SLAPI_PLUGIN_SYNTAX_FILTER_DATA, &sf);
  200. }
  201. if (sf) {
  202. re = (Slapi_Regex *)sf->sf_private;
  203. if (re) {
  204. free_re = 0;
  205. }
  206. }
  207. if (!re) {
  208. /*
  209. * construct a regular expression corresponding to the
  210. * filter and let regex do the work for each value
  211. * XXX should do this once and save it somewhere XXX
  212. */
  213. pat[0] = '\0';
  214. p = pat;
  215. end = pat + sizeof(pat) - 2; /* leave room for null */
  216. if (initial != NULL) {
  217. size = strlen(initial) + 1; /* add 1 for "^" */
  218. }
  219. if (any != NULL) {
  220. i = 0;
  221. while (any[i]) {
  222. size += strlen(any[i++]) + 2; /* add 2 for ".*" */
  223. }
  224. }
  225. if (final != NULL) {
  226. size += strlen(final) + 3; /* add 3 for ".*" and "$" */
  227. }
  228. size *= 2; /* doubled in case all filter chars need escaping */
  229. size++; /* add 1 for null */
  230. if (p + size > end) {
  231. bigpat = slapi_ch_malloc(size);
  232. p = bigpat;
  233. }
  234. if (initial != NULL) {
  235. /* 3rd arg: 1 - trim leading blanks */
  236. if (!filter_normalized) {
  237. value_normalize_ext(initial, syntax, 1, &alt);
  238. }
  239. *p++ = '^';
  240. if (alt) {
  241. filter_strcpy_special_ext(p, alt, FILTER_STRCPY_ESCAPE_RECHARS);
  242. slapi_ch_free_string(&alt);
  243. } else {
  244. filter_strcpy_special_ext(p, initial, FILTER_STRCPY_ESCAPE_RECHARS);
  245. }
  246. p = strchr(p, '\0');
  247. }
  248. if (any != NULL) {
  249. for (i = 0; any[i] != NULL; i++) {
  250. /* 3rd arg: 0 - DO NOT trim leading blanks */
  251. if (!filter_normalized) {
  252. value_normalize_ext(any[i], syntax, 0, &alt);
  253. }
  254. /* ".*" + value */
  255. *p++ = '.';
  256. *p++ = '*';
  257. if (alt) {
  258. filter_strcpy_special_ext(p, alt, FILTER_STRCPY_ESCAPE_RECHARS);
  259. slapi_ch_free_string(&alt);
  260. } else {
  261. filter_strcpy_special_ext(p, any[i], FILTER_STRCPY_ESCAPE_RECHARS);
  262. }
  263. p = strchr(p, '\0');
  264. }
  265. }
  266. if (final != NULL) {
  267. /* 3rd arg: 0 - DO NOT trim leading blanks */
  268. if (!filter_normalized) {
  269. value_normalize_ext(final, syntax, 0, &alt);
  270. }
  271. /* ".*" + value */
  272. *p++ = '.';
  273. *p++ = '*';
  274. if (alt) {
  275. filter_strcpy_special_ext(p, alt, FILTER_STRCPY_ESCAPE_RECHARS);
  276. slapi_ch_free_string(&alt);
  277. } else {
  278. filter_strcpy_special_ext(p, final, FILTER_STRCPY_ESCAPE_RECHARS);
  279. }
  280. strcat(p, "$");
  281. }
  282. /* compile the regex */
  283. p = (bigpat) ? bigpat : pat;
  284. tmpbuf = NULL;
  285. re = slapi_re_comp(p, &re_result);
  286. if (NULL == re) {
  287. slapi_log_err(SLAPI_LOG_ERR, SYNTAX_PLUGIN_SUBSYSTEM,
  288. "string_filter_sub - re_comp (%s) failed (%s): %s\n",
  289. pat, p, re_result ? re_result : "unknown");
  290. slapi_ch_free_string(&re_result);
  291. rc = LDAP_OPERATIONS_ERROR;
  292. goto bailout;
  293. } else if (slapi_is_loglevel_set(SLAPI_LOG_TRACE)) {
  294. char ebuf[BUFSIZ];
  295. slapi_log_err(SLAPI_LOG_TRACE, SYNTAX_PLUGIN_SUBSYSTEM,
  296. "string_filter_sub - re_comp (%s)\n", escape_string(p, ebuf));
  297. }
  298. }
  299. if (slapi_timespec_expire_check(&expire_time) == TIMER_EXPIRED) {
  300. slapi_log_err(SLAPI_LOG_TRACE, SYNTAX_PLUGIN_SUBSYSTEM, "LDAP_TIMELIMIT_EXCEEDED\n");
  301. rc = LDAP_TIMELIMIT_EXCEEDED;
  302. goto bailout;
  303. }
  304. /*
  305. * test the regex against each value
  306. */
  307. rc = -1;
  308. tmpbuf = NULL;
  309. tmpbufsize = 0;
  310. for (j = 0; (bvals != NULL) && (bvals[j] != NULL); j++) {
  311. int tmprc;
  312. size_t len;
  313. const struct berval *bvp = slapi_value_get_berval(bvals[j]);
  314. len = bvp->bv_len;
  315. if (len < sizeof(buf)) {
  316. realval = buf;
  317. memcpy(realval, bvp->bv_val, bvp->bv_len);
  318. realval[bvp->bv_len] = 0;
  319. } else if (len < tmpbufsize) {
  320. realval = tmpbuf;
  321. memcpy(realval, bvp->bv_val, bvp->bv_len);
  322. realval[bvp->bv_len] = 0;
  323. } else {
  324. tmpbufsize = len + 1;
  325. realval = tmpbuf = (char *)slapi_ch_realloc(tmpbuf, tmpbufsize);
  326. memcpy(realval, bvp->bv_val, bvp->bv_len);
  327. realval[bvp->bv_len] = 0;
  328. }
  329. /* 3rd arg: 1 - trim leading blanks */
  330. if (!(slapi_value_get_flags(bvals[j]) & SLAPI_ATTR_FLAG_NORMALIZED)) {
  331. value_normalize_ext(realval, syntax, 1, &alt);
  332. } else if (syntax & SYNTAX_DN) {
  333. slapi_dn_ignore_case(realval);
  334. }
  335. if (alt) {
  336. if (slapi_timespec_expire_check(&expire_time) == TIMER_EXPIRED) {
  337. slapi_log_err(SLAPI_LOG_TRACE, SYNTAX_PLUGIN_SUBSYSTEM, "LDAP_TIMELIMIT_EXCEEDED\n");
  338. rc = LDAP_TIMELIMIT_EXCEEDED;
  339. goto bailout;
  340. }
  341. tmprc = slapi_re_exec_nt(re, alt);
  342. slapi_ch_free_string(&alt);
  343. } else {
  344. if (slapi_timespec_expire_check(&expire_time) == TIMER_EXPIRED) {
  345. slapi_log_err(SLAPI_LOG_TRACE, SYNTAX_PLUGIN_SUBSYSTEM, "LDAP_TIMELIMIT_EXCEEDED\n");
  346. rc = LDAP_TIMELIMIT_EXCEEDED;
  347. goto bailout;
  348. }
  349. tmprc = slapi_re_exec_nt(re, realval);
  350. }
  351. if (slapi_is_loglevel_set(SLAPI_LOG_TRACE)) {
  352. char ebuf[BUFSIZ];
  353. slapi_log_err(SLAPI_LOG_TRACE, SYNTAX_PLUGIN_SUBSYSTEM, "re_exec (%s) %i\n",
  354. escape_string(realval, ebuf), tmprc);
  355. }
  356. if (tmprc == 1) {
  357. rc = 0;
  358. break;
  359. } else if (tmprc != 0) {
  360. rc = tmprc;
  361. break;
  362. }
  363. }
  364. bailout:
  365. if (free_re) {
  366. slapi_re_free(re);
  367. }
  368. slapi_ch_free_string(&alt);
  369. slapi_ch_free((void **)&tmpbuf); /* NULL is fine */
  370. slapi_ch_free((void **)&bigpat); /* NULL is fine */
  371. slapi_log_err(SLAPI_LOG_TRACE, SYNTAX_PLUGIN_SUBSYSTEM, "<= string_filter_sub %d\n", rc);
  372. return (rc);
  373. }
  374. int
  375. string_values2keys(Slapi_PBlock *pb, Slapi_Value **bvals, Slapi_Value ***ivals, int syntax, int ftype)
  376. {
  377. int nsubs, numbvals = 0, n;
  378. Slapi_Value **nbvals, **nbvlp;
  379. Slapi_Value **bvlp;
  380. char *w, *c, *p;
  381. char *alt = NULL;
  382. if (NULL == ivals) {
  383. return 1;
  384. }
  385. *ivals = NULL;
  386. if (NULL == bvals) {
  387. return 1;
  388. }
  389. switch (ftype) {
  390. case LDAP_FILTER_EQUALITY:
  391. /* allocate a new array for the normalized values */
  392. for (bvlp = bvals; bvlp && *bvlp; bvlp++) {
  393. numbvals++;
  394. }
  395. nbvals = (Slapi_Value **)slapi_ch_calloc((numbvals + 1), sizeof(Slapi_Value *));
  396. for (bvlp = bvals, nbvlp = nbvals; bvlp && *bvlp; bvlp++, nbvlp++) {
  397. unsigned long value_flags = slapi_value_get_flags(*bvlp);
  398. c = slapi_ch_strdup(slapi_value_get_string(*bvlp));
  399. /* if the NORMALIZED flag is set, skip normalizing */
  400. if (!(value_flags & SLAPI_ATTR_FLAG_NORMALIZED)) {
  401. /* 3rd arg: 1 - trim leading blanks */
  402. value_normalize_ext(c, syntax, 1, &alt);
  403. value_flags |= SLAPI_ATTR_FLAG_NORMALIZED;
  404. } else if ((syntax & SYNTAX_DN) &&
  405. (value_flags & SLAPI_ATTR_FLAG_NORMALIZED_CES)) {
  406. /* This dn value is normalized, but not case-normalized. */
  407. slapi_dn_ignore_case(c);
  408. /* This dn value is case-normalized */
  409. value_flags &= ~SLAPI_ATTR_FLAG_NORMALIZED_CES;
  410. value_flags |= SLAPI_ATTR_FLAG_NORMALIZED_CIS;
  411. }
  412. if (alt) {
  413. slapi_ch_free_string(&c);
  414. *nbvlp = slapi_value_new_string_passin(alt);
  415. alt = NULL;
  416. } else {
  417. *nbvlp = slapi_value_new_string_passin(c);
  418. c = NULL;
  419. }
  420. /* new value is normalized */
  421. slapi_value_set_flags(*nbvlp, value_flags);
  422. }
  423. *ivals = nbvals;
  424. break;
  425. case LDAP_FILTER_APPROX:
  426. /* XXX should not do this twice! XXX */
  427. /* get an upper bound on the number of ivals */
  428. for (bvlp = bvals; bvlp && *bvlp; bvlp++) {
  429. for (w = first_word((char *)slapi_value_get_string(*bvlp));
  430. w != NULL; w = next_word(w)) {
  431. numbvals++;
  432. }
  433. }
  434. nbvals = (Slapi_Value **)slapi_ch_calloc((numbvals + 1), sizeof(Slapi_Value *));
  435. n = 0;
  436. nbvlp = nbvals;
  437. for (bvlp = bvals; bvlp && *bvlp; bvlp++) {
  438. for (w = first_word((char *)slapi_value_get_string(*bvlp));
  439. w != NULL; w = next_word(w)) {
  440. if ((c = phonetic(w)) != NULL) {
  441. *nbvlp = slapi_value_new_string_passin(c);
  442. nbvlp++;
  443. }
  444. }
  445. }
  446. /* even if (n == 0), we should return the array nbvals w/ NULL items */
  447. *ivals = nbvals;
  448. break;
  449. case LDAP_FILTER_SUBSTRINGS: {
  450. /* XXX should remove duplicates! XXX */
  451. Slapi_Value *bvdup;
  452. const struct berval *bvp;
  453. char *buf;
  454. int i;
  455. int *substrlens = NULL;
  456. int localsublens[3] = {SUBBEGIN, SUBMIDDLE, SUBEND}; /* default values */
  457. int maxsublen;
  458. /*
  459. * Substring key has 3 types:
  460. * begin (e.g., *^a)
  461. * middle (e.g., *abc)
  462. * end (e.g., *xy$)
  463. *
  464. * the each has its own key length, which can be configured as follows:
  465. * Usage: turn an index object to extensibleobject and
  466. * set an integer value for each.
  467. * dn: cn=sn, cn=index, cn=userRoot, cn=ldbm database, cn=plugins,
  468. * cn=config
  469. * objectClass: extensibleObject
  470. * nsSubStrBegin: 2
  471. * nsSubStrMiddle: 3
  472. * nsSubStrEnd: 2
  473. * [...]
  474. *
  475. * By default, begin == 3, middle == 3, end == 3 (defined in syntax.h)
  476. */
  477. /* If nsSubStrLen is specified in each index entry,
  478. respect the length for the substring index key length.
  479. Otherwise, the deafult value SUBLEN is used */
  480. slapi_pblock_get(pb, SLAPI_SYNTAX_SUBSTRLENS, &substrlens);
  481. if (NULL == substrlens) {
  482. substrlens = localsublens;
  483. }
  484. if (0 == substrlens[INDEX_SUBSTRBEGIN]) {
  485. substrlens[INDEX_SUBSTRBEGIN] = SUBBEGIN;
  486. }
  487. if (0 == substrlens[INDEX_SUBSTRMIDDLE]) {
  488. substrlens[INDEX_SUBSTRMIDDLE] = SUBMIDDLE;
  489. }
  490. if (0 == substrlens[INDEX_SUBSTREND]) {
  491. substrlens[INDEX_SUBSTREND] = SUBEND;
  492. }
  493. maxsublen = MAX_VAL(substrlens[INDEX_SUBSTRBEGIN], substrlens[INDEX_SUBSTRMIDDLE]);
  494. maxsublen = MAX_VAL(maxsublen, substrlens[INDEX_SUBSTREND]);
  495. buf = (char *)slapi_ch_calloc(1, maxsublen + 1);
  496. nsubs = 0;
  497. for (bvlp = bvals; bvlp && *bvlp; bvlp++) {
  498. /*
  499. * Note: this calculation may err on the high side,
  500. * because value_normalize_ext(), which is called below
  501. * before we actually create the substring keys, may
  502. * reduce the length of the value in some cases or
  503. * increase the length in other cases. For example,
  504. * spaces are removed when space insensitive strings
  505. * are normalized. Or if the value includes '\"' (2 bytes),
  506. * it's normalized to '\22' (3 bytes). But it's okay
  507. * for nsubs to be too big. Since the ivals array is
  508. * NULL terminated, the only downside is that we
  509. * allocate more space than we really need.
  510. */
  511. nsubs += slapi_value_get_length(*bvlp) - substrlens[INDEX_SUBSTRMIDDLE] + 3;
  512. }
  513. nsubs += substrlens[INDEX_SUBSTRMIDDLE] * 2 - substrlens[INDEX_SUBSTRBEGIN] - substrlens[INDEX_SUBSTREND];
  514. *ivals = (Slapi_Value **)slapi_ch_calloc((nsubs + 1), sizeof(Slapi_Value *));
  515. n = 0;
  516. bvdup = slapi_value_new();
  517. for (bvlp = bvals; bvlp && *bvlp; bvlp++) {
  518. unsigned long value_flags = slapi_value_get_flags(*bvlp);
  519. /* 3rd arg: 1 - trim leading blanks */
  520. if (!(value_flags & SLAPI_ATTR_FLAG_NORMALIZED)) {
  521. c = slapi_ch_strdup(slapi_value_get_string(*bvlp));
  522. value_normalize_ext(c, syntax, 1, &alt);
  523. if (alt) {
  524. slapi_ch_free_string(&c);
  525. slapi_value_set_string_passin(bvdup, alt);
  526. alt = NULL;
  527. } else {
  528. slapi_value_set_string_passin(bvdup, c);
  529. c = NULL;
  530. }
  531. bvp = slapi_value_get_berval(bvdup);
  532. value_flags |= SLAPI_ATTR_FLAG_NORMALIZED;
  533. } else if ((syntax & SYNTAX_DN) &&
  534. (value_flags & SLAPI_ATTR_FLAG_NORMALIZED_CES)) {
  535. /* This dn value is normalized, but not case-normalized. */
  536. c = slapi_ch_strdup(slapi_value_get_string(*bvlp));
  537. slapi_dn_ignore_case(c);
  538. slapi_value_set_string_passin(bvdup, c);
  539. c = NULL;
  540. /* This dn value is case-normalized */
  541. value_flags &= ~SLAPI_ATTR_FLAG_NORMALIZED_CES;
  542. value_flags |= SLAPI_ATTR_FLAG_NORMALIZED_CIS;
  543. bvp = slapi_value_get_berval(bvdup);
  544. } else {
  545. bvp = slapi_value_get_berval(*bvlp);
  546. }
  547. /* leading */
  548. if (bvp->bv_len > substrlens[INDEX_SUBSTRBEGIN] - 2) {
  549. buf[0] = '^';
  550. for (i = 0; i < substrlens[INDEX_SUBSTRBEGIN] - 1; i++) {
  551. buf[i + 1] = bvp->bv_val[i];
  552. }
  553. buf[substrlens[INDEX_SUBSTRBEGIN]] = '\0';
  554. (*ivals)[n] = slapi_value_new_string(buf);
  555. slapi_value_set_flags((*ivals)[n], value_flags);
  556. n++;
  557. }
  558. /* any */
  559. for (p = bvp->bv_val;
  560. p < (bvp->bv_val + bvp->bv_len - substrlens[INDEX_SUBSTRMIDDLE] + 1);
  561. p++) {
  562. for (i = 0; i < substrlens[INDEX_SUBSTRMIDDLE]; i++) {
  563. buf[i] = p[i];
  564. }
  565. buf[substrlens[INDEX_SUBSTRMIDDLE]] = '\0';
  566. (*ivals)[n] = slapi_value_new_string(buf);
  567. slapi_value_set_flags((*ivals)[n], value_flags);
  568. n++;
  569. }
  570. /* trailing */
  571. if (bvp->bv_len > substrlens[INDEX_SUBSTREND] - 2) {
  572. p = bvp->bv_val + bvp->bv_len - substrlens[INDEX_SUBSTREND] + 1;
  573. for (i = 0; i < substrlens[INDEX_SUBSTREND] - 1; i++) {
  574. buf[i] = p[i];
  575. }
  576. buf[substrlens[INDEX_SUBSTREND] - 1] = '$';
  577. buf[substrlens[INDEX_SUBSTREND]] = '\0';
  578. (*ivals)[n] = slapi_value_new_string(buf);
  579. slapi_value_set_flags((*ivals)[n], value_flags);
  580. n++;
  581. }
  582. }
  583. slapi_value_free(&bvdup);
  584. slapi_ch_free_string(&buf);
  585. } break;
  586. }
  587. return (0);
  588. }
  589. /* we've added code to make our equality filter processing faster */
  590. int
  591. string_assertion2keys_ava(
  592. Slapi_PBlock *pb __attribute__((unused)),
  593. Slapi_Value *val,
  594. Slapi_Value ***ivals,
  595. int syntax,
  596. int ftype)
  597. {
  598. int i, numbvals;
  599. size_t len;
  600. char *w, *c;
  601. Slapi_Value *tmpval = NULL;
  602. char *alt = NULL;
  603. unsigned long flags = val ? slapi_value_get_flags(val) : 0;
  604. switch (ftype) {
  605. case LDAP_FILTER_EQUALITY_FAST:
  606. /* this code is trying to avoid multiple malloc/frees */
  607. len = slapi_value_get_length(val);
  608. tmpval = (*ivals)[0];
  609. if (len >= tmpval->bv.bv_len) {
  610. tmpval->bv.bv_val = (char *)slapi_ch_malloc(len + 1);
  611. }
  612. memcpy(tmpval->bv.bv_val, slapi_value_get_string(val), len);
  613. tmpval->bv.bv_val[len] = '\0';
  614. if (!(flags & SLAPI_ATTR_FLAG_NORMALIZED)) {
  615. /* 3rd arg: 1 - trim leading blanks */
  616. value_normalize_ext(tmpval->bv.bv_val, syntax, 1, &alt);
  617. if (alt) {
  618. if (len >= tmpval->bv.bv_len) {
  619. slapi_ch_free_string(&tmpval->bv.bv_val);
  620. }
  621. tmpval->bv.bv_val = alt;
  622. alt = NULL;
  623. }
  624. tmpval->bv.bv_len = strlen(tmpval->bv.bv_val);
  625. flags |= SLAPI_ATTR_FLAG_NORMALIZED;
  626. } else if ((syntax & SYNTAX_DN) &&
  627. (flags & SLAPI_ATTR_FLAG_NORMALIZED_CES)) {
  628. /* This dn value is normalized, but not case-normalized. */
  629. slapi_dn_ignore_case(tmpval->bv.bv_val);
  630. /* This dn value is case-normalized */
  631. flags &= ~SLAPI_ATTR_FLAG_NORMALIZED_CES;
  632. flags |= SLAPI_ATTR_FLAG_NORMALIZED_CIS;
  633. }
  634. slapi_value_set_flags(tmpval, flags);
  635. break;
  636. case LDAP_FILTER_EQUALITY:
  637. (*ivals) = (Slapi_Value **)slapi_ch_malloc(2 * sizeof(Slapi_Value *));
  638. (*ivals)[0] = val ? slapi_value_dup(val) : NULL;
  639. if (val && !(flags & SLAPI_ATTR_FLAG_NORMALIZED)) {
  640. /* 3rd arg: 1 - trim leading blanks */
  641. value_normalize_ext((*ivals)[0]->bv.bv_val, syntax, 1, &alt);
  642. if (alt) {
  643. slapi_ch_free_string(&(*ivals)[0]->bv.bv_val);
  644. (*ivals)[0]->bv.bv_val = alt;
  645. (*ivals)[0]->bv.bv_len = strlen((*ivals)[0]->bv.bv_val);
  646. alt = NULL;
  647. }
  648. flags |= SLAPI_ATTR_FLAG_NORMALIZED;
  649. } else if ((syntax & SYNTAX_DN) &&
  650. (flags & SLAPI_ATTR_FLAG_NORMALIZED_CES)) {
  651. /* This dn value is normalized, but not case-normalized. */
  652. slapi_dn_ignore_case((*ivals)[0]->bv.bv_val);
  653. /* This dn value is case-normalized */
  654. flags &= ~SLAPI_ATTR_FLAG_NORMALIZED_CES;
  655. flags |= SLAPI_ATTR_FLAG_NORMALIZED_CIS;
  656. }
  657. slapi_value_set_flags((*ivals)[0], flags);
  658. (*ivals)[1] = NULL;
  659. break;
  660. case LDAP_FILTER_APPROX:
  661. /* XXX should not do this twice! XXX */
  662. /* get an upper bound on the number of ivals */
  663. numbvals = 0;
  664. for (w = first_word((char *)slapi_value_get_string(val)); w != NULL;
  665. w = next_word(w)) {
  666. numbvals++;
  667. }
  668. (*ivals) = (Slapi_Value **)slapi_ch_malloc((numbvals + 1) *
  669. sizeof(Slapi_Value *));
  670. i = 0;
  671. for (w = first_word((char *)slapi_value_get_string(val)); w != NULL;
  672. w = next_word(w)) {
  673. if ((c = phonetic(w)) != NULL) {
  674. (*ivals)[i] = slapi_value_new_string_passin(c);
  675. i++;
  676. }
  677. }
  678. (*ivals)[i] = NULL;
  679. if (i == 0) {
  680. slapi_ch_free((void **)ivals);
  681. return (0);
  682. }
  683. break;
  684. default:
  685. slapi_log_err(SLAPI_LOG_ERR, SYNTAX_PLUGIN_SUBSYSTEM,
  686. "string_assertion2keys_ava - Unknown ftype 0x%x\n",
  687. ftype);
  688. break;
  689. }
  690. return (0);
  691. }
  692. int
  693. string_assertion2keys_sub(
  694. Slapi_PBlock *pb,
  695. char *initial,
  696. char **any,
  697. char * final,
  698. Slapi_Value ***ivals,
  699. int syntax)
  700. {
  701. int nsubs, i, len;
  702. int initiallen = 0, finallen = 0;
  703. int *substrlens = NULL;
  704. int localsublens[3] = {SUBBEGIN, SUBMIDDLE, SUBEND}; /* default values */
  705. int maxsublen;
  706. char *comp_buf = NULL;
  707. /* altinit|any|final: store alt string from value_normalize_ext if any,
  708. * otherwise the original string. And use for the real job */
  709. char *altinit = NULL;
  710. char **altany = NULL;
  711. char *altfinal = NULL;
  712. /* oaltinit|any|final: prepared to free altinit|any|final if allocated in
  713. * value_normalize_ext */
  714. char *oaltinit = NULL;
  715. char **oaltany = NULL;
  716. char *oaltfinal = NULL;
  717. int anysize = 0;
  718. if (pb) {
  719. slapi_pblock_get(pb, SLAPI_SYNTAX_SUBSTRLENS, &substrlens);
  720. }
  721. if (NULL == substrlens) {
  722. substrlens = localsublens;
  723. }
  724. if (0 == substrlens[INDEX_SUBSTRBEGIN]) {
  725. substrlens[INDEX_SUBSTRBEGIN] = SUBBEGIN;
  726. }
  727. if (0 == substrlens[INDEX_SUBSTRMIDDLE]) {
  728. substrlens[INDEX_SUBSTRMIDDLE] = SUBMIDDLE;
  729. }
  730. if (0 == substrlens[INDEX_SUBSTREND]) {
  731. substrlens[INDEX_SUBSTREND] = SUBEND;
  732. }
  733. *ivals = NULL;
  734. /*
  735. * First figure out how many keys we will return. The answer is based
  736. * on the length of each assertion value. Since normalization may
  737. * reduce the length (such as when spaces are removed from space
  738. * insensitive strings), we call value_normalize_ext() before checking
  739. * the length.
  740. */
  741. nsubs = 0;
  742. if (initial != NULL) {
  743. /* 3rd arg: 0 - DO NOT trim leading blanks */
  744. value_normalize_ext(initial, syntax, 0, &altinit);
  745. oaltinit = altinit;
  746. if (NULL == altinit) {
  747. altinit = initial;
  748. }
  749. initiallen = strlen(altinit);
  750. if (initiallen > substrlens[INDEX_SUBSTRBEGIN] - 2) {
  751. nsubs += 1; /* for the initial begin string key */
  752. /* the rest of the sub keys are "any" keys for this case */
  753. if (initiallen >= substrlens[INDEX_SUBSTRMIDDLE]) {
  754. nsubs += initiallen - substrlens[INDEX_SUBSTRMIDDLE] + 1;
  755. }
  756. } else {
  757. altinit = NULL; /* save some work later */
  758. }
  759. }
  760. for (i = 0; any != NULL && any[i] != NULL; i++) {
  761. anysize++;
  762. }
  763. altany = (char **)slapi_ch_calloc(anysize + 1, sizeof(char *));
  764. oaltany = (char **)slapi_ch_calloc(anysize + 1, sizeof(char *));
  765. for (i = 0; any != NULL && any[i] != NULL; i++) {
  766. /* 3rd arg: 0 - DO NOT trim leading blanks */
  767. value_normalize_ext(any[i], syntax, 0, &altany[i]);
  768. if (NULL == altany[i]) {
  769. altany[i] = any[i];
  770. } else {
  771. oaltany[i] = altany[i];
  772. }
  773. len = strlen(altany[i]);
  774. if (len >= substrlens[INDEX_SUBSTRMIDDLE]) {
  775. nsubs += len - substrlens[INDEX_SUBSTRMIDDLE] + 1;
  776. }
  777. }
  778. if (final != NULL) {
  779. /* 3rd arg: 0 - DO NOT trim leading blanks */
  780. value_normalize_ext(final, syntax, 0, &altfinal);
  781. oaltfinal = altfinal;
  782. if (NULL == altfinal) {
  783. altfinal = final;
  784. }
  785. finallen = strlen(altfinal);
  786. if (finallen > substrlens[INDEX_SUBSTREND] - 2) {
  787. nsubs += 1; /* for the final end string key */
  788. /* the rest of the sub keys are "any" keys for this case */
  789. if (finallen >= substrlens[INDEX_SUBSTRMIDDLE]) {
  790. nsubs += finallen - substrlens[INDEX_SUBSTRMIDDLE] + 1;
  791. }
  792. } else {
  793. altfinal = NULL; /* save some work later */
  794. }
  795. }
  796. if (nsubs == 0) { /* no keys to return */
  797. goto done;
  798. }
  799. /*
  800. * Next, allocated the ivals array and fill it in with the actual
  801. * keys. *ivals is a NULL terminated array of Slapi_Value pointers.
  802. */
  803. *ivals = (Slapi_Value **)slapi_ch_malloc((nsubs + 1) * sizeof(Slapi_Value *));
  804. maxsublen = MAX_VAL(substrlens[INDEX_SUBSTRBEGIN], substrlens[INDEX_SUBSTRMIDDLE]);
  805. maxsublen = MAX_VAL(maxsublen, substrlens[INDEX_SUBSTREND]);
  806. nsubs = 0;
  807. comp_buf = (char *)slapi_ch_malloc(maxsublen + 1);
  808. if (altinit != NULL) {
  809. substring_comp_keys(ivals, &nsubs, altinit, initiallen, '^', syntax,
  810. comp_buf, substrlens);
  811. }
  812. for (i = 0; altany != NULL && altany[i] != NULL; i++) {
  813. len = strlen(altany[i]);
  814. if (len < substrlens[INDEX_SUBSTRMIDDLE]) {
  815. continue;
  816. }
  817. substring_comp_keys(ivals, &nsubs, altany[i], len, 0, syntax,
  818. comp_buf, substrlens);
  819. }
  820. if (altfinal != NULL) {
  821. substring_comp_keys(ivals, &nsubs, altfinal, finallen, '$', syntax,
  822. comp_buf, substrlens);
  823. }
  824. (*ivals)[nsubs] = NULL;
  825. done:
  826. slapi_ch_free_string(&oaltinit);
  827. for (i = 0; altany != NULL && altany[i] != NULL; i++) {
  828. slapi_ch_free_string(&oaltany[i]);
  829. }
  830. slapi_ch_free((void **)&oaltany);
  831. slapi_ch_free_string(&oaltfinal);
  832. slapi_ch_free((void **)&altany);
  833. slapi_ch_free_string(&comp_buf);
  834. return (0);
  835. }
  836. static void
  837. substring_comp_keys(
  838. Slapi_Value ***ivals,
  839. int *nsubs,
  840. char *str,
  841. int lenstring,
  842. int prepost,
  843. int syntax __attribute__((unused)),
  844. char *comp_buf,
  845. int *substrlens)
  846. {
  847. int i, substrlen;
  848. char *p;
  849. PR_ASSERT(NULL != comp_buf);
  850. PR_ASSERT(NULL != substrlens);
  851. slapi_log_err(SLAPI_LOG_TRACE, SYNTAX_PLUGIN_SUBSYSTEM, "=> substring_comp_keys - (%s) %d\n",
  852. str, prepost);
  853. /* prepend ^ for initial substring */
  854. if (prepost == '^') {
  855. substrlen = substrlens[INDEX_SUBSTRBEGIN];
  856. comp_buf[0] = '^';
  857. for (i = 0; i < substrlen - 1; i++) {
  858. comp_buf[i + 1] = str[i];
  859. }
  860. comp_buf[substrlen] = '\0';
  861. (*ivals)[*nsubs] = slapi_value_new_string(comp_buf);
  862. (*nsubs)++;
  863. }
  864. substrlen = substrlens[INDEX_SUBSTRMIDDLE];
  865. for (p = str; p < (str + lenstring - substrlen + 1); p++) {
  866. for (i = 0; i < substrlen; i++) {
  867. comp_buf[i] = p[i];
  868. }
  869. comp_buf[substrlen] = '\0';
  870. (*ivals)[*nsubs] = slapi_value_new_string(comp_buf);
  871. (*nsubs)++;
  872. }
  873. if (prepost == '$') {
  874. substrlen = substrlens[INDEX_SUBSTREND];
  875. p = str + lenstring - substrlen + 1;
  876. for (i = 0; i < substrlen - 1; i++) {
  877. comp_buf[i] = p[i];
  878. }
  879. comp_buf[substrlen - 1] = '$';
  880. comp_buf[substrlen] = '\0';
  881. (*ivals)[*nsubs] = slapi_value_new_string(comp_buf);
  882. (*nsubs)++;
  883. }
  884. slapi_log_err(SLAPI_LOG_TRACE, SYNTAX_PLUGIN_SUBSYSTEM, "<= substring_comp_keys\n");
  885. }