string.c 22 KB

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