string.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970
  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. /* 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, Slapi_Value **retVal );
  23. static void substring_comp_keys( Slapi_Value ***ivals, int *nsubs, char *str,
  24. int lenstr, int prepost, int syntax, char *comp_buf, int *substrlens );
  25. int
  26. string_filter_ava( struct berval *bvfilter, Slapi_Value **bvals, int syntax,
  27. int ftype, Slapi_Value **retVal )
  28. {
  29. int i, rc;
  30. struct berval bvfilter_norm = {0, NULL};
  31. struct berval *pbvfilter_norm = &bvfilter_norm;
  32. char *alt = NULL;
  33. if(retVal) {
  34. *retVal = NULL;
  35. }
  36. if ( ftype == LDAP_FILTER_APPROX ) {
  37. return( string_filter_approx( bvfilter, bvals, retVal ) );
  38. }
  39. if (syntax & SYNTAX_NORM_FILT) {
  40. pbvfilter_norm = bvfilter; /* already normalized */
  41. } else {
  42. slapi_ber_bvcpy(&bvfilter_norm, bvfilter);
  43. /* 3rd arg: 1 - trim leading blanks */
  44. value_normalize_ext( bvfilter_norm.bv_val, syntax, 1, &alt );
  45. if (alt) {
  46. slapi_ber_bvdone(&bvfilter_norm);
  47. bvfilter_norm.bv_val = alt;
  48. alt = NULL;
  49. }
  50. if(bvfilter_norm.bv_val){
  51. bvfilter_norm.bv_len = strlen(bvfilter_norm.bv_val);
  52. } else {
  53. bvfilter_norm.bv_len = 0;
  54. }
  55. }
  56. for ( i = 0; (bvals != NULL) && (bvals[i] != NULL); i++ ) {
  57. int norm_val = 1; /* normalize the first value only */
  58. /* if the NORMALIZED flag is set, skip normalizing */
  59. if (slapi_value_get_flags(bvals[i]) & SLAPI_ATTR_FLAG_NORMALIZED) {
  60. norm_val = 0;
  61. }
  62. /* note - do not return the normalized value in retVal - the
  63. caller will usually want the "raw" value, and can normalize it later
  64. */
  65. rc = value_cmp( (struct berval*)slapi_value_get_berval(bvals[i]), pbvfilter_norm, syntax, norm_val );
  66. switch ( ftype ) {
  67. case LDAP_FILTER_GE:
  68. if ( rc >= 0 ) {
  69. if(retVal) {
  70. *retVal = bvals[i];
  71. }
  72. slapi_ch_free_string(&bvfilter_norm.bv_val);
  73. return( 0 );
  74. }
  75. break;
  76. case LDAP_FILTER_LE:
  77. if ( rc <= 0 ) {
  78. if(retVal) {
  79. *retVal = bvals[i];
  80. }
  81. slapi_ch_free_string(&bvfilter_norm.bv_val);
  82. return( 0 );
  83. }
  84. break;
  85. case LDAP_FILTER_EQUALITY:
  86. if ( rc == 0 ) {
  87. if(retVal) {
  88. *retVal = bvals[i];
  89. }
  90. slapi_ch_free_string(&bvfilter_norm.bv_val);
  91. return( 0 );
  92. }
  93. break;
  94. }
  95. }
  96. slapi_ch_free_string(&bvfilter_norm.bv_val);
  97. return( -1 );
  98. }
  99. /*
  100. * return value: 0 -- approximately matched
  101. * -1 -- did not match
  102. */
  103. static int
  104. string_filter_approx( struct berval *bvfilter, Slapi_Value **bvals,
  105. Slapi_Value **retVal)
  106. {
  107. int i, rc;
  108. int ava_wordcount;
  109. char *w1, *w2, *c1, *c2;
  110. slapi_log_error(SLAPI_LOG_TRACE, SYNTAX_PLUGIN_SUBSYSTEM, "=> string_filter_approx\n");
  111. /*
  112. * try to match words in each filter value in order
  113. * in the attribute value.
  114. * XXX should do this once for the filter and save it XXX
  115. */
  116. rc = -1;
  117. if(retVal) {
  118. *retVal = NULL;
  119. }
  120. for ( i = 0; (bvals != NULL) && (bvals[i] != NULL); i++ ) {
  121. w2 = (char*)slapi_value_get_string(bvals[i]); /* JCM cast */
  122. ava_wordcount = 0;
  123. /* for each word in the filter value */
  124. for ( w1 = first_word( bvfilter->bv_val ); w1 != NULL;
  125. w1 = next_word( w1 ) ) {
  126. ++ava_wordcount;
  127. if ( (c1 = phonetic( w1 )) == NULL ) {
  128. break;
  129. }
  130. /*
  131. * for each word in the attribute value from
  132. * where we left off...
  133. */
  134. for ( w2 = first_word( w2 ); w2 != NULL;
  135. w2 = next_word( w2 ) ) {
  136. c2 = phonetic( w2 );
  137. rc = strcmp( c1, c2 );
  138. slapi_ch_free((void**)&c2 );
  139. if ( rc == 0 ) {
  140. if(retVal) {
  141. *retVal = bvals[i];
  142. }
  143. break;
  144. }
  145. }
  146. slapi_ch_free((void**)&c1 );
  147. /*
  148. * if we stopped because we ran out of words
  149. * before making a match, go on to the next
  150. * value. otherwise try to keep matching
  151. * words in this value from where we left off.
  152. */
  153. if ( w2 == NULL ) {
  154. break;
  155. } else {
  156. w2 = next_word( w2 );
  157. }
  158. }
  159. /*
  160. * if we stopped because we ran out of words and
  161. * we found at leasy one word, we have a match.
  162. */
  163. if ( w1 == NULL && ava_wordcount > 0 ) {
  164. rc = 0;
  165. break;
  166. }
  167. }
  168. if (0 != rc) {
  169. rc = -1;
  170. }
  171. slapi_log_error(SLAPI_LOG_TRACE, SYNTAX_PLUGIN_SUBSYSTEM, "<= string_filter_approx %d\n", rc);
  172. return( rc );
  173. }
  174. int
  175. string_filter_sub( Slapi_PBlock *pb, char *initial, char **any, char *final,
  176. Slapi_Value **bvals, int syntax )
  177. {
  178. int i, j, rc, size=0;
  179. char *p, *end, *realval, *tmpbuf = NULL, *bigpat = NULL;
  180. size_t tmpbufsize;
  181. char pat[BUFSIZ];
  182. char buf[BUFSIZ];
  183. time_t curtime = 0;
  184. time_t time_up = 0;
  185. time_t optime = 0; /* time op was initiated */
  186. int timelimit = 0; /* search timelimit */
  187. Operation *op = NULL;
  188. Slapi_Regex *re = NULL;
  189. const char *re_result = NULL;
  190. char *alt = NULL;
  191. int filter_normalized = 0;
  192. int free_re = 1;
  193. struct subfilt *sf = NULL;
  194. slapi_log_error(SLAPI_LOG_TRACE, SYNTAX_PLUGIN_SUBSYSTEM, "=> string_filter_sub\n");
  195. if (pb) {
  196. slapi_pblock_get( pb, SLAPI_OPERATION, &op );
  197. }
  198. if (NULL != op) {
  199. slapi_pblock_get( pb, SLAPI_SEARCH_TIMELIMIT, &timelimit );
  200. slapi_pblock_get( pb, SLAPI_OPINITIATED_TIME, &optime );
  201. } else {
  202. /* timelimit is not passed via pblock */
  203. timelimit = -1;
  204. }
  205. /*
  206. * (timelimit==-1) means no time limit
  207. */
  208. time_up = ( timelimit==-1 ? -1 : optime + timelimit);
  209. if (pb) {
  210. slapi_pblock_get( pb, SLAPI_PLUGIN_SYNTAX_FILTER_NORMALIZED, &filter_normalized );
  211. slapi_pblock_get( pb, SLAPI_PLUGIN_SYNTAX_FILTER_DATA, &sf );
  212. }
  213. if ( sf ) {
  214. re = (Slapi_Regex *)sf->sf_private;
  215. if ( re ) {
  216. free_re = 0;
  217. }
  218. }
  219. if (!re) {
  220. /*
  221. * construct a regular expression corresponding to the
  222. * filter and let regex do the work for each value
  223. * XXX should do this once and save it somewhere XXX
  224. */
  225. pat[0] = '\0';
  226. p = pat;
  227. end = pat + sizeof(pat) - 2; /* leave room for null */
  228. if ( initial != NULL ) {
  229. size = strlen( initial ) + 1; /* add 1 for "^" */
  230. }
  231. if ( any != NULL ) {
  232. i = 0;
  233. while ( any[i] ) {
  234. size += strlen(any[i++]) + 2; /* add 2 for ".*" */
  235. }
  236. }
  237. if ( final != NULL ) {
  238. size += strlen( final ) + 3; /* add 3 for ".*" and "$" */
  239. }
  240. size *= 2; /* doubled in case all filter chars need escaping */
  241. size++; /* add 1 for null */
  242. if ( p + size > end ) {
  243. bigpat = slapi_ch_malloc( size );
  244. p = bigpat;
  245. }
  246. if ( initial != NULL ) {
  247. /* 3rd arg: 1 - trim leading blanks */
  248. if (!filter_normalized) {
  249. value_normalize_ext( initial, syntax, 1, &alt );
  250. }
  251. *p++ = '^';
  252. if (alt) {
  253. filter_strcpy_special_ext( p, alt, FILTER_STRCPY_ESCAPE_RECHARS );
  254. slapi_ch_free_string(&alt);
  255. } else {
  256. filter_strcpy_special_ext( p, initial, FILTER_STRCPY_ESCAPE_RECHARS );
  257. }
  258. p = strchr( p, '\0' );
  259. }
  260. if ( any != NULL ) {
  261. for ( i = 0; any[i] != NULL; i++ ) {
  262. /* 3rd arg: 0 - DO NOT trim leading blanks */
  263. if (!filter_normalized) {
  264. value_normalize_ext( any[i], syntax, 0, &alt );
  265. }
  266. /* ".*" + value */
  267. *p++ = '.';
  268. *p++ = '*';
  269. if (alt) {
  270. filter_strcpy_special_ext( p, alt, FILTER_STRCPY_ESCAPE_RECHARS );
  271. slapi_ch_free_string(&alt);
  272. } else {
  273. filter_strcpy_special_ext( p, any[i], FILTER_STRCPY_ESCAPE_RECHARS );
  274. }
  275. p = strchr( p, '\0' );
  276. }
  277. }
  278. if ( final != NULL ) {
  279. /* 3rd arg: 0 - DO NOT trim leading blanks */
  280. if (!filter_normalized) {
  281. value_normalize_ext( final, syntax, 0, &alt );
  282. }
  283. /* ".*" + value */
  284. *p++ = '.';
  285. *p++ = '*';
  286. if (alt) {
  287. filter_strcpy_special_ext( p, alt, FILTER_STRCPY_ESCAPE_RECHARS );
  288. slapi_ch_free_string(&alt);
  289. } else {
  290. filter_strcpy_special_ext( p, final, FILTER_STRCPY_ESCAPE_RECHARS );
  291. }
  292. strcat( p, "$" );
  293. }
  294. /* compile the regex */
  295. p = (bigpat) ? bigpat : pat;
  296. tmpbuf = NULL;
  297. re = slapi_re_comp( p, &re_result );
  298. if (NULL == re) {
  299. slapi_log_error(SLAPI_LOG_ERR, SYNTAX_PLUGIN_SUBSYSTEM,
  300. "string_filter_sub - re_comp (%s) failed (%s): %s\n",
  301. pat, p, re_result?re_result:"unknown" );
  302. rc = LDAP_OPERATIONS_ERROR;
  303. goto bailout;
  304. } else if (slapi_is_loglevel_set(SLAPI_LOG_TRACE)) {
  305. char ebuf[BUFSIZ];
  306. slapi_log_error(SLAPI_LOG_TRACE, SYNTAX_PLUGIN_SUBSYSTEM,
  307. "string_filter_sub - re_comp (%s)\n", escape_string(p, ebuf));
  308. }
  309. }
  310. curtime = current_time();
  311. if ( time_up != -1 && curtime > time_up ) {
  312. rc = LDAP_TIMELIMIT_EXCEEDED;
  313. goto bailout;
  314. }
  315. /*
  316. * test the regex against each value
  317. */
  318. rc = -1;
  319. tmpbuf = NULL;
  320. tmpbufsize = 0;
  321. for ( j = 0; (bvals != NULL) && (bvals[j] != NULL); j++ ) {
  322. int tmprc;
  323. size_t len;
  324. const struct berval *bvp = slapi_value_get_berval(bvals[j]);
  325. len = bvp->bv_len;
  326. if ( len < sizeof(buf) ) {
  327. realval = buf;
  328. strncpy( realval, bvp->bv_val, sizeof(buf) );
  329. } else if ( len < tmpbufsize ) {
  330. realval = tmpbuf;
  331. strncpy( realval, bvp->bv_val, tmpbufsize );
  332. } else {
  333. tmpbufsize = len + 1;
  334. realval = tmpbuf = (char *) slapi_ch_realloc( tmpbuf, tmpbufsize );
  335. strncpy( realval, bvp->bv_val, tmpbufsize );
  336. }
  337. /* 3rd arg: 1 - trim leading blanks */
  338. if (!(slapi_value_get_flags(bvals[j]) & SLAPI_ATTR_FLAG_NORMALIZED)) {
  339. value_normalize_ext( realval, syntax, 1, &alt );
  340. } else if (syntax & SYNTAX_DN) {
  341. slapi_dn_ignore_case(realval);
  342. }
  343. if (alt) {
  344. tmprc = slapi_re_exec( re, alt, time_up );
  345. slapi_ch_free_string(&alt);
  346. } else {
  347. tmprc = slapi_re_exec( re, realval, time_up );
  348. }
  349. if (slapi_is_loglevel_set(SLAPI_LOG_TRACE)) {
  350. char ebuf[BUFSIZ];
  351. slapi_log_error(SLAPI_LOG_TRACE, SYNTAX_PLUGIN_SUBSYSTEM,"re_exec (%s) %i\n",
  352. escape_string(realval, ebuf), tmprc);
  353. }
  354. if ( tmprc == 1 ) {
  355. rc = 0;
  356. break;
  357. } else if ( tmprc != 0 ) {
  358. rc = tmprc;
  359. break;
  360. }
  361. }
  362. bailout:
  363. if (free_re) {
  364. slapi_re_free(re);
  365. }
  366. slapi_ch_free((void**)&tmpbuf ); /* NULL is fine */
  367. slapi_ch_free((void**)&bigpat ); /* NULL is fine */
  368. slapi_log_error(SLAPI_LOG_TRACE, SYNTAX_PLUGIN_SUBSYSTEM, "<= string_filter_sub %d\n", rc);
  369. return( rc );
  370. }
  371. int
  372. string_values2keys( Slapi_PBlock *pb, Slapi_Value **bvals,
  373. Slapi_Value ***ivals, int syntax, int ftype )
  374. {
  375. int nsubs, numbvals = 0, n;
  376. Slapi_Value **nbvals, **nbvlp;
  377. Slapi_Value **bvlp;
  378. char *w, *c, *p;
  379. char *alt = NULL;
  380. if (NULL == ivals) {
  381. return 1;
  382. }
  383. *ivals = NULL;
  384. if (NULL == bvals) {
  385. return 1;
  386. }
  387. switch ( ftype ) {
  388. case LDAP_FILTER_EQUALITY:
  389. /* allocate a new array for the normalized values */
  390. for ( bvlp = bvals; bvlp && *bvlp; bvlp++ ) {
  391. numbvals++;
  392. }
  393. nbvals = (Slapi_Value **) slapi_ch_calloc( (numbvals + 1), sizeof(Slapi_Value *));
  394. for ( bvlp = bvals, nbvlp = nbvals; bvlp && *bvlp; bvlp++, nbvlp++ )
  395. {
  396. unsigned long value_flags = slapi_value_get_flags(*bvlp);
  397. c = slapi_ch_strdup(slapi_value_get_string(*bvlp));
  398. /* if the NORMALIZED flag is set, skip normalizing */
  399. if (!(value_flags & SLAPI_ATTR_FLAG_NORMALIZED)) {
  400. /* 3rd arg: 1 - trim leading blanks */
  401. value_normalize_ext( c, syntax, 1, &alt );
  402. value_flags |= SLAPI_ATTR_FLAG_NORMALIZED;
  403. } else if ((syntax & SYNTAX_DN) &&
  404. (value_flags & SLAPI_ATTR_FLAG_NORMALIZED_CES)) {
  405. /* This dn value is normalized, but not case-normalized. */
  406. slapi_dn_ignore_case(c);
  407. /* This dn value is case-normalized */
  408. value_flags &= ~SLAPI_ATTR_FLAG_NORMALIZED_CES;
  409. value_flags |= SLAPI_ATTR_FLAG_NORMALIZED_CIS;
  410. }
  411. if (alt) {
  412. slapi_ch_free_string(&c);
  413. *nbvlp = slapi_value_new_string_passin(alt);
  414. alt = NULL;
  415. } else {
  416. *nbvlp = slapi_value_new_string_passin(c);
  417. c = NULL;
  418. }
  419. /* new value is normalized */
  420. slapi_value_set_flags(*nbvlp, value_flags);
  421. }
  422. *ivals = nbvals;
  423. break;
  424. case LDAP_FILTER_APPROX:
  425. /* XXX should not do this twice! XXX */
  426. /* get an upper bound on the number of ivals */
  427. for ( bvlp = bvals; bvlp && *bvlp; bvlp++ ) {
  428. for ( w = first_word( (char*)slapi_value_get_string(*bvlp) );
  429. w != NULL; w = next_word( w ) ) {
  430. numbvals++;
  431. }
  432. }
  433. nbvals = (Slapi_Value **) slapi_ch_calloc( (numbvals + 1), sizeof(Slapi_Value *) );
  434. n = 0;
  435. nbvlp = nbvals;
  436. for ( bvlp = bvals; bvlp && *bvlp; bvlp++ ) {
  437. for ( w = first_word( (char*)slapi_value_get_string(*bvlp) );
  438. w != NULL; w = next_word( w ) ) {
  439. if ( (c = phonetic( w )) != NULL ) {
  440. *nbvlp = slapi_value_new_string_passin(c);
  441. nbvlp++;
  442. }
  443. }
  444. }
  445. /* even if (n == 0), we should return the array nbvals w/ NULL items */
  446. *ivals = nbvals;
  447. break;
  448. case LDAP_FILTER_SUBSTRINGS:
  449. {
  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. }
  586. break;
  587. }
  588. return( 0 );
  589. }
  590. /* we've added code to make our equality filter processing faster */
  591. int
  592. string_assertion2keys_ava(
  593. Slapi_PBlock *pb,
  594. Slapi_Value *val,
  595. Slapi_Value ***ivals,
  596. int syntax,
  597. int ftype
  598. )
  599. {
  600. int i, numbvals;
  601. size_t len;
  602. char *w, *c;
  603. Slapi_Value *tmpval=NULL;
  604. char *alt = NULL;
  605. unsigned long flags = val ? slapi_value_get_flags(val) : 0;
  606. switch ( ftype ) {
  607. case LDAP_FILTER_EQUALITY_FAST:
  608. /* this code is trying to avoid multiple malloc/frees */
  609. len=slapi_value_get_length(val);
  610. tmpval=(*ivals)[0];
  611. if (len >= tmpval->bv.bv_len) {
  612. tmpval->bv.bv_val=(char *)slapi_ch_malloc(len+1);
  613. }
  614. memcpy(tmpval->bv.bv_val,slapi_value_get_string(val),len);
  615. tmpval->bv.bv_val[len]='\0';
  616. if (!(flags & SLAPI_ATTR_FLAG_NORMALIZED)) {
  617. /* 3rd arg: 1 - trim leading blanks */
  618. value_normalize_ext(tmpval->bv.bv_val, syntax, 1, &alt );
  619. if (alt) {
  620. if (len >= tmpval->bv.bv_len) {
  621. slapi_ch_free_string(&tmpval->bv.bv_val);
  622. }
  623. tmpval->bv.bv_val = alt;
  624. alt = NULL;
  625. }
  626. tmpval->bv.bv_len=strlen(tmpval->bv.bv_val);
  627. flags |= SLAPI_ATTR_FLAG_NORMALIZED;
  628. } else if ((syntax & SYNTAX_DN) &&
  629. (flags & SLAPI_ATTR_FLAG_NORMALIZED_CES)) {
  630. /* This dn value is normalized, but not case-normalized. */
  631. slapi_dn_ignore_case(tmpval->bv.bv_val);
  632. /* This dn value is case-normalized */
  633. flags &= ~SLAPI_ATTR_FLAG_NORMALIZED_CES;
  634. flags |= SLAPI_ATTR_FLAG_NORMALIZED_CIS;
  635. }
  636. slapi_value_set_flags(tmpval, flags);
  637. break;
  638. case LDAP_FILTER_EQUALITY:
  639. (*ivals) = (Slapi_Value **) slapi_ch_malloc( 2 * sizeof(Slapi_Value *) );
  640. (*ivals)[0] = val ? slapi_value_dup( val ) : NULL;
  641. if (val && !(flags & SLAPI_ATTR_FLAG_NORMALIZED)) {
  642. /* 3rd arg: 1 - trim leading blanks */
  643. value_normalize_ext( (*ivals)[0]->bv.bv_val, syntax, 1, &alt );
  644. if (alt) {
  645. slapi_ch_free_string(&(*ivals)[0]->bv.bv_val);
  646. (*ivals)[0]->bv.bv_val = alt;
  647. (*ivals)[0]->bv.bv_len = strlen( (*ivals)[0]->bv.bv_val );
  648. alt = NULL;
  649. }
  650. flags |= SLAPI_ATTR_FLAG_NORMALIZED;
  651. } else if ((syntax & SYNTAX_DN) &&
  652. (flags & SLAPI_ATTR_FLAG_NORMALIZED_CES)) {
  653. /* This dn value is normalized, but not case-normalized. */
  654. slapi_dn_ignore_case((*ivals)[0]->bv.bv_val);
  655. /* This dn value is case-normalized */
  656. flags &= ~SLAPI_ATTR_FLAG_NORMALIZED_CES;
  657. flags |= SLAPI_ATTR_FLAG_NORMALIZED_CIS;
  658. }
  659. slapi_value_set_flags((*ivals)[0], flags);
  660. (*ivals)[1] = NULL;
  661. break;
  662. case LDAP_FILTER_APPROX:
  663. /* XXX should not do this twice! XXX */
  664. /* get an upper bound on the number of ivals */
  665. numbvals = 0;
  666. for ( w = first_word( (char*)slapi_value_get_string(val) ); w != NULL;
  667. w = next_word( w ) ) {
  668. numbvals++;
  669. }
  670. (*ivals) = (Slapi_Value **) slapi_ch_malloc( (numbvals + 1) *
  671. sizeof(Slapi_Value *) );
  672. i = 0;
  673. for ( w = first_word( (char*)slapi_value_get_string(val) ); w != NULL;
  674. w = next_word( w ) ) {
  675. if ( (c = phonetic( w )) != NULL ) {
  676. (*ivals)[i] = slapi_value_new_string_passin(c);
  677. i++;
  678. }
  679. }
  680. (*ivals)[i] = NULL;
  681. if ( i == 0 ) {
  682. slapi_ch_free((void**)ivals );
  683. return( 0 );
  684. }
  685. break;
  686. default:
  687. slapi_log_error(SLAPI_LOG_ERR, SYNTAX_PLUGIN_SUBSYSTEM,
  688. "string_assertion2keys_ava - Unknown ftype 0x%x\n",
  689. ftype);
  690. break;
  691. }
  692. return( 0 );
  693. }
  694. int
  695. string_assertion2keys_sub(
  696. Slapi_PBlock *pb,
  697. char *initial,
  698. char **any,
  699. char *final,
  700. Slapi_Value ***ivals,
  701. int syntax
  702. )
  703. {
  704. int nsubs, i, len;
  705. int initiallen = 0, finallen = 0;
  706. int *substrlens = NULL;
  707. int localsublens[3] = {SUBBEGIN, SUBMIDDLE, SUBEND};/* default values */
  708. int maxsublen;
  709. char *comp_buf = NULL;
  710. /* altinit|any|final: store alt string from value_normalize_ext if any,
  711. * otherwise the original string. And use for the real job */
  712. char *altinit = NULL;
  713. char **altany = NULL;
  714. char *altfinal = NULL;
  715. /* oaltinit|any|final: prepared to free altinit|any|final if allocated in
  716. * value_normalize_ext */
  717. char *oaltinit = NULL;
  718. char **oaltany = NULL;
  719. char *oaltfinal = NULL;
  720. int anysize = 0;
  721. if (pb) {
  722. slapi_pblock_get(pb, SLAPI_SYNTAX_SUBSTRLENS, &substrlens);
  723. }
  724. if (NULL == substrlens) {
  725. substrlens = localsublens;
  726. }
  727. if (0 == substrlens[INDEX_SUBSTRBEGIN]) {
  728. substrlens[INDEX_SUBSTRBEGIN] = SUBBEGIN;
  729. }
  730. if (0 == substrlens[INDEX_SUBSTRMIDDLE]) {
  731. substrlens[INDEX_SUBSTRMIDDLE] = SUBMIDDLE;
  732. }
  733. if (0 == substrlens[INDEX_SUBSTREND]) {
  734. substrlens[INDEX_SUBSTREND] = SUBEND;
  735. }
  736. *ivals = NULL;
  737. /*
  738. * First figure out how many keys we will return. The answer is based
  739. * on the length of each assertion value. Since normalization may
  740. * reduce the length (such as when spaces are removed from space
  741. * insensitive strings), we call value_normalize_ext() before checking
  742. * the length.
  743. */
  744. nsubs = 0;
  745. if ( initial != NULL ) {
  746. /* 3rd arg: 0 - DO NOT trim leading blanks */
  747. value_normalize_ext( initial, syntax, 0, &altinit );
  748. oaltinit = altinit;
  749. if (NULL == altinit) {
  750. altinit = initial;
  751. }
  752. initiallen = strlen( altinit );
  753. if ( initiallen > substrlens[INDEX_SUBSTRBEGIN] - 2 ) {
  754. nsubs += 1; /* for the initial begin string key */
  755. /* the rest of the sub keys are "any" keys for this case */
  756. if ( initiallen >= substrlens[INDEX_SUBSTRMIDDLE] ) {
  757. nsubs += initiallen - substrlens[INDEX_SUBSTRMIDDLE] + 1;
  758. }
  759. } else {
  760. altinit = NULL; /* save some work later */
  761. }
  762. }
  763. for ( i = 0; any != NULL && any[i] != NULL; i++ ) {
  764. anysize++;
  765. }
  766. altany = (char **)slapi_ch_calloc(anysize + 1, sizeof(char *));
  767. oaltany = (char **)slapi_ch_calloc(anysize + 1, sizeof(char *));
  768. for ( i = 0; any != NULL && any[i] != NULL; i++ ) {
  769. /* 3rd arg: 0 - DO NOT trim leading blanks */
  770. value_normalize_ext( any[i], syntax, 0, &altany[i] );
  771. if (NULL == altany[i]) {
  772. altany[i] = any[i];
  773. } else {
  774. oaltany[i] = altany[i];
  775. }
  776. len = strlen( altany[i] );
  777. if ( len >= substrlens[INDEX_SUBSTRMIDDLE] ) {
  778. nsubs += len - substrlens[INDEX_SUBSTRMIDDLE] + 1;
  779. }
  780. }
  781. if ( final != NULL ) {
  782. /* 3rd arg: 0 - DO NOT trim leading blanks */
  783. value_normalize_ext( final, syntax, 0, &altfinal );
  784. oaltfinal = altfinal;
  785. if (NULL == altfinal) {
  786. altfinal = final;
  787. }
  788. finallen = strlen( altfinal );
  789. if ( finallen > substrlens[INDEX_SUBSTREND] - 2 ) {
  790. nsubs += 1; /* for the final end string key */
  791. /* the rest of the sub keys are "any" keys for this case */
  792. if ( finallen >= substrlens[INDEX_SUBSTRMIDDLE] ) {
  793. nsubs += finallen - substrlens[INDEX_SUBSTRMIDDLE] + 1;
  794. }
  795. } else {
  796. altfinal = NULL; /* save some work later */
  797. }
  798. }
  799. if ( nsubs == 0 ) { /* no keys to return */
  800. goto done;
  801. }
  802. /*
  803. * Next, allocated the ivals array and fill it in with the actual
  804. * keys. *ivals is a NULL terminated array of Slapi_Value pointers.
  805. */
  806. *ivals = (Slapi_Value **) slapi_ch_malloc( (nsubs + 1) * sizeof(Slapi_Value *) );
  807. maxsublen = MAX_VAL(substrlens[INDEX_SUBSTRBEGIN], substrlens[INDEX_SUBSTRMIDDLE]);
  808. maxsublen = MAX_VAL(maxsublen, substrlens[INDEX_SUBSTREND]);
  809. nsubs = 0;
  810. comp_buf = (char *)slapi_ch_malloc(maxsublen + 1);
  811. if ( altinit != NULL ) {
  812. substring_comp_keys( ivals, &nsubs, altinit, initiallen, '^', syntax,
  813. comp_buf, substrlens );
  814. }
  815. for ( i = 0; altany != NULL && altany[i] != NULL; i++ ) {
  816. len = strlen( altany[i] );
  817. if ( len < substrlens[INDEX_SUBSTRMIDDLE] ) {
  818. continue;
  819. }
  820. substring_comp_keys( ivals, &nsubs, altany[i], len, 0, syntax,
  821. comp_buf, substrlens );
  822. }
  823. if ( altfinal != NULL ) {
  824. substring_comp_keys( ivals, &nsubs, altfinal, finallen, '$', syntax,
  825. comp_buf, substrlens );
  826. }
  827. (*ivals)[nsubs] = NULL;
  828. done:
  829. slapi_ch_free_string(&oaltinit);
  830. for ( i = 0; altany != NULL && altany[i] != NULL; i++ ) {
  831. slapi_ch_free_string(&oaltany[i]);
  832. }
  833. slapi_ch_free((void **)&oaltany);
  834. slapi_ch_free_string(&oaltfinal);
  835. slapi_ch_free((void **)&altany);
  836. slapi_ch_free_string(&comp_buf);
  837. return( 0 );
  838. }
  839. static void
  840. substring_comp_keys(
  841. Slapi_Value ***ivals,
  842. int *nsubs,
  843. char *str,
  844. int lenstr,
  845. int prepost,
  846. int syntax,
  847. char *comp_buf,
  848. int *substrlens
  849. )
  850. {
  851. int i, substrlen;
  852. char *p;
  853. PR_ASSERT(NULL != comp_buf);
  854. PR_ASSERT(NULL != substrlens);
  855. slapi_log_error(SLAPI_LOG_TRACE, SYNTAX_PLUGIN_SUBSYSTEM, "=> substring_comp_keys - (%s) %d\n",
  856. str, prepost);
  857. /* prepend ^ for initial substring */
  858. if ( prepost == '^' )
  859. {
  860. substrlen = substrlens[INDEX_SUBSTRBEGIN];
  861. comp_buf[0] = '^';
  862. for ( i = 0; i < substrlen - 1; i++ )
  863. {
  864. comp_buf[i + 1] = str[i];
  865. }
  866. comp_buf[substrlen] = '\0';
  867. (*ivals)[*nsubs] = slapi_value_new_string(comp_buf);
  868. (*nsubs)++;
  869. }
  870. substrlen = substrlens[INDEX_SUBSTRMIDDLE];
  871. for ( p = str; p < (str + lenstr - substrlen + 1); p++ )
  872. {
  873. for ( i = 0; i < substrlen; i++ )
  874. {
  875. comp_buf[i] = p[i];
  876. }
  877. comp_buf[substrlen] = '\0';
  878. (*ivals)[*nsubs] = slapi_value_new_string(comp_buf);
  879. (*nsubs)++;
  880. }
  881. if ( prepost == '$' )
  882. {
  883. substrlen = substrlens[INDEX_SUBSTREND];
  884. p = str + lenstr - substrlen + 1;
  885. for ( i = 0; i < substrlen - 1; i++ )
  886. {
  887. comp_buf[i] = p[i];
  888. }
  889. comp_buf[substrlen - 1] = '$';
  890. comp_buf[substrlen] = '\0';
  891. (*ivals)[*nsubs] = slapi_value_new_string(comp_buf);
  892. (*nsubs)++;
  893. }
  894. slapi_log_error(SLAPI_LOG_TRACE, SYNTAX_PLUGIN_SUBSYSTEM, "<= substring_comp_keys\n");
  895. }