string.c 27 KB

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