string.c 29 KB

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