string.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641
  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. /* string.c - common string syntax routines */
  39. #include <stdio.h>
  40. #include <string.h>
  41. #include <sys/types.h>
  42. #include "syntax.h"
  43. #if defined(IRIX)
  44. #include <unistd.h>
  45. #endif
  46. static int string_filter_approx( struct berval *bvfilter,
  47. Slapi_Value **bvals, Slapi_Value **retVal );
  48. static void substring_comp_keys( Slapi_Value ***ivals, int *nsubs, char *str,
  49. int prepost, int syntax );
  50. int
  51. string_filter_ava( struct berval *bvfilter, Slapi_Value **bvals, int syntax,
  52. int ftype, Slapi_Value **retVal )
  53. {
  54. int i, rc;
  55. struct berval bvfilter_norm;
  56. if(retVal) {
  57. *retVal = NULL;
  58. }
  59. if ( ftype == LDAP_FILTER_APPROX ) {
  60. return( string_filter_approx( bvfilter, bvals, retVal ) );
  61. }
  62. bvfilter_norm.bv_val = slapi_ch_malloc( bvfilter->bv_len + 1 );
  63. SAFEMEMCPY( bvfilter_norm.bv_val, bvfilter->bv_val, bvfilter->bv_len );
  64. bvfilter_norm.bv_val[bvfilter->bv_len] = '\0';
  65. value_normalize( bvfilter_norm.bv_val, syntax, 1 /* trim leading blanks */ );
  66. for ( i = 0; bvals[i] != NULL; i++ ) {
  67. rc = value_cmp( (struct berval*)slapi_value_get_berval(bvals[i]), &bvfilter_norm, syntax, 1/* Normalise the first value only */ );
  68. switch ( ftype ) {
  69. case LDAP_FILTER_GE:
  70. if ( rc >= 0 ) {
  71. if(retVal) {
  72. *retVal = bvals[i];
  73. }
  74. slapi_ch_free ((void**)&bvfilter_norm.bv_val);
  75. return( 0 );
  76. }
  77. break;
  78. case LDAP_FILTER_LE:
  79. if ( rc <= 0 ) {
  80. if(retVal) {
  81. *retVal = bvals[i];
  82. }
  83. slapi_ch_free ((void**)&bvfilter_norm.bv_val);
  84. return( 0 );
  85. }
  86. break;
  87. case LDAP_FILTER_EQUALITY:
  88. if ( rc == 0 ) {
  89. if(retVal) {
  90. *retVal = bvals[i];
  91. }
  92. slapi_ch_free ((void**)&bvfilter_norm.bv_val);
  93. return( 0 );
  94. }
  95. break;
  96. }
  97. }
  98. slapi_ch_free ((void**)&bvfilter_norm.bv_val);
  99. return( -1 );
  100. }
  101. static int
  102. string_filter_approx( struct berval *bvfilter, Slapi_Value **bvals,
  103. Slapi_Value **retVal)
  104. {
  105. int i, rc;
  106. int ava_wordcount;
  107. char *w1, *w2, *c1, *c2;
  108. /*
  109. * try to match words in each filter value in order
  110. * in the attribute value.
  111. * XXX should do this once for the filter and save it XXX
  112. */
  113. rc = -1;
  114. if(retVal) {
  115. *retVal = NULL;
  116. }
  117. for ( i = 0; bvals[i] != NULL; i++ ) {
  118. w2 = (char*)slapi_value_get_string(bvals[i]); /* JCM cast */
  119. ava_wordcount = 0;
  120. /* for each word in the filter value */
  121. for ( w1 = first_word( bvfilter->bv_val ); w1 != NULL;
  122. w1 = next_word( w1 ) ) {
  123. ++ava_wordcount;
  124. if ( (c1 = phonetic( w1 )) == NULL ) {
  125. break;
  126. }
  127. /*
  128. * for each word in the attribute value from
  129. * where we left off...
  130. */
  131. for ( w2 = first_word( w2 ); w2 != NULL;
  132. w2 = next_word( w2 ) ) {
  133. c2 = phonetic( w2 );
  134. rc = strcmp( c1, c2 );
  135. slapi_ch_free((void**)&c2 );
  136. if ( rc == 0 ) {
  137. if(retVal) {
  138. *retVal = bvals[i];
  139. }
  140. break;
  141. }
  142. }
  143. slapi_ch_free((void**)&c1 );
  144. /*
  145. * if we stopped because we ran out of words
  146. * before making a match, go on to the next
  147. * value. otherwise try to keep matching
  148. * words in this value from where we left off.
  149. */
  150. if ( w2 == NULL ) {
  151. break;
  152. } else {
  153. w2 = next_word( w2 );
  154. }
  155. }
  156. /*
  157. * if we stopped because we ran out of words and
  158. * we found at leasy one word, we have a match.
  159. */
  160. if ( w1 == NULL && ava_wordcount > 0 ) {
  161. rc = 0;
  162. break;
  163. }
  164. }
  165. LDAPDebug( LDAP_DEBUG_TRACE, "<= string_filter_approx %d\n",
  166. rc, 0, 0 );
  167. return( rc );
  168. }
  169. int
  170. string_filter_sub( Slapi_PBlock *pb, char *initial, char **any, char *final,
  171. Slapi_Value **bvals, int syntax )
  172. {
  173. int i, j, rc;
  174. char *p, *end, *realval, *tmpbuf;
  175. size_t tmpbufsize;
  176. char pat[BUFSIZ];
  177. char buf[BUFSIZ];
  178. char ebuf[BUFSIZ];
  179. LDAPDebug( LDAP_DEBUG_FILTER, "=> string_filter_sub\n",
  180. 0, 0, 0 );
  181. /*
  182. * construct a regular expression corresponding to the
  183. * filter and let regex do the work for each value
  184. * XXX should do this once and save it somewhere XXX
  185. */
  186. pat[0] = '\0';
  187. p = pat;
  188. end = pat + sizeof(pat) - 2; /* leave room for null */
  189. if ( initial != NULL ) {
  190. value_normalize( initial, syntax, 1 /* trim leading blanks */ );
  191. strcpy( p, "^" );
  192. p = strchr( p, '\0' );
  193. /* 2 * in case every char is special */
  194. if ( p + 2 * strlen( initial ) > end ) {
  195. LDAPDebug( LDAP_DEBUG_ANY, "not enough pattern space\n",
  196. 0, 0, 0 );
  197. return( -1 );
  198. }
  199. filter_strcpy_special( p, initial );
  200. p = strchr( p, '\0' );
  201. }
  202. if ( any != NULL ) {
  203. for ( i = 0; any[i] != NULL; i++ ) {
  204. value_normalize( any[i], syntax, 0 /* DO NOT trim leading blanks */ );
  205. /* ".*" + value */
  206. if ( p + 2 * strlen( any[i] ) + 2 > end ) {
  207. LDAPDebug( LDAP_DEBUG_ANY,
  208. "not enough pattern space\n", 0, 0, 0 );
  209. return( -1 );
  210. }
  211. strcpy( p, ".*" );
  212. p = strchr( p, '\0' );
  213. filter_strcpy_special( p, any[i] );
  214. p = strchr( p, '\0' );
  215. }
  216. }
  217. if ( final != NULL ) {
  218. value_normalize( final, syntax, 0 /* DO NOT trim leading blanks */ );
  219. /* ".*" + value */
  220. if ( p + 2 * strlen( final ) + 2 > end ) {
  221. LDAPDebug( LDAP_DEBUG_ANY, "not enough pattern space\n",
  222. 0, 0, 0 );
  223. return( -1 );
  224. }
  225. strcpy( p, ".*" );
  226. p = strchr( p, '\0' );
  227. filter_strcpy_special( p, final );
  228. p = strchr( p, '\0' );
  229. strcpy( p, "$" );
  230. }
  231. /* compile the regex */
  232. slapd_re_lock();
  233. if ( (p = slapd_re_comp( pat )) != 0 ) {
  234. LDAPDebug( LDAP_DEBUG_ANY, "re_comp (%s) failed (%s)\n",
  235. pat, p, 0 );
  236. slapd_re_unlock();
  237. return( -1 );
  238. } else {
  239. LDAPDebug( LDAP_DEBUG_TRACE, "re_comp (%s)\n",
  240. escape_string( pat, ebuf ), 0, 0 );
  241. }
  242. /*
  243. * test the regex against each value
  244. */
  245. rc = -1;
  246. tmpbuf = NULL;
  247. tmpbufsize = 0;
  248. for ( j = 0; bvals[j] != NULL; j++ ) {
  249. int tmprc;
  250. size_t len;
  251. const struct berval *bvp = slapi_value_get_berval(bvals[j]);
  252. len = bvp->bv_len;
  253. if ( len < sizeof(buf) ) {
  254. strcpy( buf, bvp->bv_val );
  255. realval = buf;
  256. } else if ( len < tmpbufsize ) {
  257. strcpy( buf, bvp->bv_val );
  258. realval = tmpbuf;
  259. } else {
  260. tmpbuf = (char *) slapi_ch_realloc( tmpbuf, len + 1 );
  261. strcpy( tmpbuf, bvp->bv_val );
  262. realval = tmpbuf;
  263. }
  264. value_normalize( realval, syntax, 1 /* trim leading blanks */ );
  265. tmprc = slapd_re_exec( realval );
  266. LDAPDebug( LDAP_DEBUG_TRACE, "re_exec (%s) %i\n",
  267. escape_string( realval, ebuf ), tmprc, 0 );
  268. if ( tmprc != 0 ) {
  269. rc = 0;
  270. break;
  271. }
  272. }
  273. slapd_re_unlock();
  274. if ( tmpbuf != NULL ) {
  275. slapi_ch_free((void**)&tmpbuf );
  276. }
  277. LDAPDebug( LDAP_DEBUG_FILTER, "<= string_filter_sub %d\n",
  278. rc, 0, 0 );
  279. return( rc );
  280. }
  281. int
  282. string_values2keys( Slapi_PBlock *pb, Slapi_Value **bvals,
  283. Slapi_Value ***ivals, int syntax, int ftype )
  284. {
  285. int nsubs, numbvals, i, n, j;
  286. Slapi_Value **nbvals;
  287. char *w, *c, *p;
  288. char buf[SUBLEN+1];
  289. switch ( ftype ) {
  290. case LDAP_FILTER_EQUALITY:
  291. /* allocate a new array for the normalized values */
  292. for ( numbvals = 0; bvals[numbvals] != NULL; numbvals++ ) {
  293. /* NULL */
  294. }
  295. nbvals = (Slapi_Value **) slapi_ch_malloc( (numbvals+1) * sizeof(Slapi_Value *));
  296. for ( i = 0; i < numbvals; i++ )
  297. {
  298. c = slapi_ch_strdup(slapi_value_get_string(bvals[i]));
  299. value_normalize( c, syntax, 1 /* trim leading blanks */ );
  300. nbvals[i] = slapi_value_new_string_passin(c);
  301. }
  302. nbvals[i] = NULL;
  303. *ivals = nbvals;
  304. break;
  305. case LDAP_FILTER_APPROX:
  306. /* XXX should not do this twice! XXX */
  307. /* get an upper bound on the number of ivals */
  308. numbvals = 0;
  309. for ( i = 0; bvals[i] != NULL; i++ ) {
  310. for ( w = first_word( (char*)slapi_value_get_string(bvals[i]) ); w != NULL;
  311. w = next_word( w ) ) {
  312. numbvals++;
  313. }
  314. }
  315. nbvals = (Slapi_Value **) slapi_ch_malloc( (numbvals + 1) * sizeof(Slapi_Value *) );
  316. n = 0;
  317. for ( i = 0; bvals[i] != NULL; i++ ) {
  318. for ( w = first_word( (char*)slapi_value_get_string(bvals[i]) ); w != NULL;
  319. w = next_word( w ) ) {
  320. if ( (c = phonetic( w )) != NULL ) {
  321. nbvals[n] = slapi_value_new_string_passin(c);
  322. n++;
  323. }
  324. }
  325. }
  326. nbvals[n] = NULL;
  327. if ( n == 0 ) {
  328. slapi_ch_free((void**)ivals );
  329. return( 0 );
  330. }
  331. *ivals = nbvals;
  332. break;
  333. case LDAP_FILTER_SUBSTRINGS:
  334. {
  335. /* XXX should remove duplicates! XXX */
  336. Slapi_Value *bvdup;
  337. const struct berval *bvp;
  338. nsubs = 0;
  339. for ( i = 0; bvals[i] != NULL; i++ ) {
  340. /*
  341. * Note: this calculation may err on the high side,
  342. * because value_normalize(), which is called below
  343. * before we actually create the substring keys, may
  344. * reduce the length of the value in some cases. For
  345. * example, spaces are removed when space insensitive
  346. * strings are normalized. But it's okay for nsubs to
  347. * be too big. Since the ivals array is NULL terminated,
  348. * the only downside is that we allocate more space than
  349. * we really need.
  350. */
  351. nsubs += slapi_value_get_length(bvals[i]) - SUBLEN + 3;
  352. }
  353. *ivals = (Slapi_Value **) slapi_ch_malloc( (nsubs + 1) * sizeof(Slapi_Value *) );
  354. buf[SUBLEN] = '\0';
  355. n = 0;
  356. bvdup= slapi_value_new();
  357. for ( i = 0; bvals[i] != NULL; i++ )
  358. {
  359. c = slapi_ch_strdup(slapi_value_get_string(bvals[i]));
  360. value_normalize( c, syntax, 1 /* trim leading blanks */ );
  361. slapi_value_set_string_passin(bvdup, c);
  362. bvp = slapi_value_get_berval(bvdup);
  363. /* leading */
  364. if ( bvp->bv_len > SUBLEN - 2 ) {
  365. buf[0] = '^';
  366. for ( j = 0; j < SUBLEN - 1; j++ ) {
  367. buf[j + 1] = bvp->bv_val[j];
  368. }
  369. (*ivals)[n] = slapi_value_new_string(buf);
  370. n++;
  371. }
  372. /* any */
  373. for ( p = bvp->bv_val;
  374. p < (bvp->bv_val + bvp->bv_len - SUBLEN + 1);
  375. p++ ) {
  376. for ( j = 0; j < SUBLEN; j++ ) {
  377. buf[j] = p[j];
  378. }
  379. buf[SUBLEN] = '\0';
  380. (*ivals)[n] = slapi_value_new_string(buf);
  381. n++;
  382. }
  383. /* trailing */
  384. if ( bvp->bv_len > SUBLEN - 2 ) {
  385. p = bvp->bv_val + bvp->bv_len - SUBLEN + 1;
  386. for ( j = 0; j < SUBLEN - 1; j++ ) {
  387. buf[j] = p[j];
  388. }
  389. buf[SUBLEN - 1] = '$';
  390. (*ivals)[n] = slapi_value_new_string(buf);
  391. n++;
  392. }
  393. }
  394. slapi_value_free(&bvdup);
  395. (*ivals)[n] = NULL;
  396. }
  397. break;
  398. }
  399. return( 0 );
  400. }
  401. /* we've added code to make our equality filter processing faster */
  402. int
  403. string_assertion2keys_ava(
  404. Slapi_PBlock *pb,
  405. Slapi_Value *val,
  406. Slapi_Value ***ivals,
  407. int syntax,
  408. int ftype
  409. )
  410. {
  411. int i, numbvals;
  412. size_t len;
  413. char *w, *c;
  414. Slapi_Value *tmpval=NULL;
  415. switch ( ftype ) {
  416. case LDAP_FILTER_EQUALITY_FAST:
  417. /* this code is trying to avoid multiple malloc/frees */
  418. len=slapi_value_get_length(val);
  419. tmpval=(*ivals)[0];
  420. if (len >= tmpval->bv.bv_len) {
  421. tmpval->bv.bv_val=(char *)slapi_ch_malloc(len+1);
  422. }
  423. memcpy(tmpval->bv.bv_val,slapi_value_get_string(val),len);
  424. tmpval->bv.bv_val[len]='\0';
  425. value_normalize(tmpval->bv.bv_val, syntax, 1 /* trim leading blanks */ );
  426. tmpval->bv.bv_len=strlen(tmpval->bv.bv_val);
  427. break;
  428. case LDAP_FILTER_EQUALITY:
  429. (*ivals) = (Slapi_Value **) slapi_ch_malloc( 2 * sizeof(Slapi_Value *) );
  430. (*ivals)[0] = slapi_value_dup( val );
  431. value_normalize( (*ivals)[0]->bv.bv_val, syntax, 1 /* trim leading blanks */ );
  432. (*ivals)[0]->bv.bv_len = strlen( (*ivals)[0]->bv.bv_val );
  433. (*ivals)[1] = NULL;
  434. break;
  435. case LDAP_FILTER_APPROX:
  436. /* XXX should not do this twice! XXX */
  437. /* get an upper bound on the number of ivals */
  438. numbvals = 0;
  439. for ( w = first_word( (char*)slapi_value_get_string(val) ); w != NULL;
  440. w = next_word( w ) ) {
  441. numbvals++;
  442. }
  443. (*ivals) = (Slapi_Value **) slapi_ch_malloc( (numbvals + 1) *
  444. sizeof(Slapi_Value *) );
  445. i = 0;
  446. for ( w = first_word( (char*)slapi_value_get_string(val) ); w != NULL;
  447. w = next_word( w ) ) {
  448. if ( (c = phonetic( w )) != NULL ) {
  449. (*ivals)[i] = slapi_value_new_string_passin(c);
  450. i++;
  451. }
  452. }
  453. (*ivals)[i] = NULL;
  454. if ( i == 0 ) {
  455. slapi_ch_free((void**)ivals );
  456. return( 0 );
  457. }
  458. break;
  459. default:
  460. LDAPDebug( LDAP_DEBUG_ANY,
  461. "string_assertion2keys_ava: unknown ftype 0x%x\n",
  462. ftype, 0, 0 );
  463. break;
  464. }
  465. return( 0 );
  466. }
  467. int
  468. string_assertion2keys_sub(
  469. Slapi_PBlock *pb,
  470. char *initial,
  471. char **any,
  472. char *final,
  473. Slapi_Value ***ivals,
  474. int syntax
  475. )
  476. {
  477. int nsubs, i, len;
  478. *ivals = NULL;
  479. /*
  480. * First figure out how many keys we will return. The answer is based
  481. * on the length of each assertion value. Since normalization may
  482. * reduce the length (such as when spaces are removed from space
  483. * insensitive strings), we call value_normalize() before checking
  484. * the length.
  485. */
  486. nsubs = 0;
  487. if ( initial != NULL ) {
  488. value_normalize( initial, syntax, 0 /* do not trim leading blanks */ );
  489. if ( strlen( initial ) > SUBLEN - 2 ) {
  490. nsubs += strlen( initial ) - SUBLEN + 2;
  491. } else {
  492. initial = NULL; /* save some work later */
  493. }
  494. }
  495. for ( i = 0; any != NULL && any[i] != NULL; i++ ) {
  496. value_normalize( any[i], syntax, 0 /* do not trim leading blanks */ );
  497. len = strlen( any[i] );
  498. if ( len >= SUBLEN ) {
  499. nsubs += len - SUBLEN + 1;
  500. }
  501. }
  502. if ( final != NULL ) {
  503. value_normalize( final, syntax, 0 /* do not trim leading blanks */ );
  504. if ( strlen( final ) > SUBLEN - 2 ) {
  505. nsubs += strlen( final ) - SUBLEN + 2;
  506. } else {
  507. final = NULL; /* save some work later */
  508. }
  509. }
  510. if ( nsubs == 0 ) { /* no keys to return */
  511. return( 0 );
  512. }
  513. /*
  514. * Next, allocated the ivals array and fill it in with the actual
  515. * keys. *ivals is a NULL terminated array of Slapi_Value pointers.
  516. */
  517. *ivals = (Slapi_Value **) slapi_ch_malloc( (nsubs + 1) * sizeof(Slapi_Value *) );
  518. nsubs = 0;
  519. if ( initial != NULL ) {
  520. substring_comp_keys( ivals, &nsubs, initial, '^', syntax );
  521. }
  522. for ( i = 0; any != NULL && any[i] != NULL; i++ ) {
  523. if ( strlen( any[i] ) < SUBLEN ) {
  524. continue;
  525. }
  526. substring_comp_keys( ivals, &nsubs, any[i], 0, syntax );
  527. }
  528. if ( final != NULL ) {
  529. substring_comp_keys( ivals, &nsubs, final, '$', syntax );
  530. }
  531. (*ivals)[nsubs] = NULL;
  532. return( 0 );
  533. }
  534. static void
  535. substring_comp_keys(
  536. Slapi_Value ***ivals,
  537. int *nsubs,
  538. char *str,
  539. int prepost,
  540. int syntax
  541. )
  542. {
  543. int i, len;
  544. char *p;
  545. char buf[SUBLEN + 1];
  546. LDAPDebug( LDAP_DEBUG_TRACE, "=> substring_comp_keys (%s) %d\n",
  547. str, prepost, 0 );
  548. len = strlen( str );
  549. /* prepend ^ for initial substring */
  550. if ( prepost == '^' )
  551. {
  552. buf[0] = '^';
  553. for ( i = 0; i < SUBLEN - 1; i++ )
  554. {
  555. buf[i + 1] = str[i];
  556. }
  557. buf[SUBLEN] = '\0';
  558. (*ivals)[*nsubs] = slapi_value_new_string(buf);
  559. (*nsubs)++;
  560. }
  561. for ( p = str; p < (str + len - SUBLEN + 1); p++ )
  562. {
  563. for ( i = 0; i < SUBLEN; i++ )
  564. {
  565. buf[i] = p[i];
  566. }
  567. buf[SUBLEN] = '\0';
  568. (*ivals)[*nsubs] = slapi_value_new_string(buf);
  569. (*nsubs)++;
  570. }
  571. if ( prepost == '$' )
  572. {
  573. p = str + len - SUBLEN + 1;
  574. for ( i = 0; i < SUBLEN - 1; i++ )
  575. {
  576. buf[i] = p[i];
  577. }
  578. buf[SUBLEN - 1] = '$';
  579. buf[SUBLEN] = '\0';
  580. (*ivals)[*nsubs] = slapi_value_new_string(buf);
  581. (*nsubs)++;
  582. }
  583. LDAPDebug( LDAP_DEBUG_TRACE, "<= substring_comp_keys\n", 0, 0, 0 );
  584. }