string.c 15 KB

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