attr.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047
  1. /** BEGIN COPYRIGHT BLOCK
  2. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  3. * Copyright (C) 2005 Red Hat, Inc.
  4. * All rights reserved.
  5. *
  6. * License: GPL (version 3 or any later version).
  7. * See LICENSE for details.
  8. * END COPYRIGHT BLOCK **/
  9. #ifdef HAVE_CONFIG_H
  10. # include <config.h>
  11. #endif
  12. /* attr.c - routines for dealing with attributes */
  13. #include <stdio.h>
  14. #include <string.h>
  15. #include <ctype.h>
  16. #include <sys/types.h>
  17. #include <sys/stat.h>
  18. #include <sys/time.h>
  19. #include <sys/param.h>
  20. #include <fcntl.h>
  21. #include <sys/socket.h>
  22. #include "slap.h"
  23. #undef DEBUG /* disable counters */
  24. #include <prcountr.h>
  25. static int counters_created= 0;
  26. PR_DEFINE_COUNTER(slapi_attr_counter_created);
  27. PR_DEFINE_COUNTER(slapi_attr_counter_deleted);
  28. PR_DEFINE_COUNTER(slapi_attr_counter_exist);
  29. /*
  30. * structure used within AVL value trees.
  31. */
  32. typedef struct slapi_attr_value_index {
  33. int savi_index; /* index into a_vals[] */
  34. struct berval *savi_normval; /* normalized value */
  35. } SlapiAttrValueIndex;
  36. /*
  37. * Utility function used by slapi_attr_type_cmp to
  38. * find the next component of an attribute type.
  39. */
  40. static const char *
  41. next_comp( const char *sp )
  42. {
  43. char *s = (char *)sp;
  44. if (NULL == s) {
  45. return( NULL );
  46. }
  47. while ( *s && *s != ';' ) {
  48. s++;
  49. }
  50. if ( *s == '\0' ) {
  51. return( NULL );
  52. } else {
  53. return( s + 1 );
  54. }
  55. }
  56. /*
  57. * Utility function used by slapi_attr_type_cmp to
  58. * compare two components of an attribute type.
  59. */
  60. static int
  61. comp_cmp( const char *s1p, const char *s2p )
  62. {
  63. char *s1 = (char *)s1p;
  64. char *s2 = (char *)s2p;
  65. if (NULL == s1) {
  66. if (s2) {
  67. return 1;
  68. }
  69. return 0;
  70. }
  71. if (NULL == s2) {
  72. if (s1) {
  73. return 1;
  74. }
  75. }
  76. while ( *s1 && (*s1 != ';') &&
  77. *s2 && (*s2 != ';') &&
  78. tolower( *s1 ) == tolower( *s2 ) ) {
  79. s1++, s2++;
  80. }
  81. if ( *s1 != *s2 ) {
  82. if ((*s1 == '\0' || *s1 == ';') &&
  83. (*s2 == '\0' || *s2 == ';')) {
  84. return( 0 );
  85. } else {
  86. return( 1 );
  87. }
  88. } else {
  89. return( 0 );
  90. }
  91. }
  92. int
  93. slapi_attr_type_cmp( const char *a1, const char *a2, int opt )
  94. {
  95. int rc= 0;
  96. switch ( opt ) {
  97. case SLAPI_TYPE_CMP_EXACT: /* compare base name + options as given */
  98. rc = strcasecmp( a1, a2 );
  99. break;
  100. case SLAPI_TYPE_CMP_BASE: /* ignore options on both names - compare base names only */
  101. rc = comp_cmp( a1, a2 );
  102. break;
  103. case SLAPI_TYPE_CMP_SUBTYPE: /* ignore options on second name that are not in first name */
  104. {
  105. const char *b2 = a2;
  106. /*
  107. * first, check that the base types match
  108. */
  109. if ( comp_cmp( a1, a2 ) != 0 ) {
  110. rc = 1;
  111. break;
  112. }
  113. /*
  114. * next, for each component in a1, make sure there is a
  115. * matching component in a2.
  116. */
  117. rc = 0;
  118. for ( a1 = next_comp( a1 ); a1; a1 = next_comp( a1 ) ) {
  119. for ( b2 = next_comp( b2 ); b2; b2 = next_comp( b2 ) ) {
  120. if ( comp_cmp( a1, b2 ) == 0 ) {
  121. break;
  122. }
  123. }
  124. if ( b2 == NULL ) {
  125. rc = 1;
  126. break;
  127. }
  128. b2 = a2;
  129. }
  130. break;
  131. }
  132. case SLAPI_TYPE_CMP_SUBTYPES: /* Both share the same subtypes */
  133. {
  134. const char *b1 = a1;
  135. const char *b2 = a2;
  136. /*
  137. * first, check that the base types match
  138. */
  139. if (comp_cmp(a1, a2) != 0) {
  140. rc = 1;
  141. break;
  142. }
  143. /*
  144. * next, for each component in a1, make sure there is a
  145. * matching component in a2.
  146. */
  147. rc = 0;
  148. for (b1 = next_comp(b1); b1; b1 = next_comp(b1)) {
  149. for (b2 = next_comp(b2); b2; b2 = next_comp(b2)) {
  150. if (comp_cmp(b1, b2) == 0) {
  151. break;
  152. }
  153. }
  154. if (b2 == NULL) {
  155. rc = 1;
  156. break;
  157. }
  158. b2 = a2;
  159. }
  160. if (0 == rc) {
  161. b1 = a1;
  162. b2 = a2;
  163. /*
  164. * next, for each component in a2, make sure there is a
  165. * matching component in a1.
  166. */
  167. for (b2 = next_comp(b2); b2; b2 = next_comp(b2)) {
  168. for (b1 = next_comp(b1); b1; b1 = next_comp(b1)) {
  169. if (comp_cmp(b1, b2) == 0) {
  170. break;
  171. }
  172. }
  173. if (b1 == NULL) {
  174. rc = 1;
  175. break;
  176. }
  177. b1 = a1;
  178. }
  179. }
  180. } /* SLAPI_TYPE_CMP_SUBTYPES */
  181. } /* switch (opt) */
  182. return( rc );
  183. }
  184. /*
  185. * Return 1 if the two types are equivalent -- either the same type name,
  186. * or aliases for one another, including OIDs.
  187. *
  188. * Objective: don't allocate any memory!
  189. */
  190. int
  191. slapi_attr_types_equivalent(const char *t1, const char *t2)
  192. {
  193. int retval = 0;
  194. struct asyntaxinfo *asi1, *asi2;
  195. if (NULL == t1 || NULL == t2) {
  196. return 0;
  197. }
  198. asi1 = attr_syntax_get_by_name(t1, 0);
  199. asi2 = attr_syntax_get_by_name(t2, 0);
  200. if (NULL != asi1) {
  201. if (NULL != asi2) {
  202. /* Both found - compare normalized names */
  203. if (strcasecmp(asi1->asi_name, asi2->asi_name) == 0) {
  204. retval = 1;
  205. } else {
  206. retval = 0;
  207. }
  208. } else {
  209. /* One found, the other wasn't, so not equivalent */
  210. retval = 0;
  211. }
  212. } else if (NULL != asi2) {
  213. /* One found, the other wasn't, so not equivalent */
  214. retval = 0;
  215. } else {
  216. /* Neither found - perform case-insensitive compare */
  217. if (strcasecmp(t1, t2) == 0) {
  218. retval = 1;
  219. } else {
  220. retval = 0;
  221. }
  222. }
  223. attr_syntax_return( asi1 );
  224. attr_syntax_return( asi2 );
  225. return retval;
  226. }
  227. Slapi_Attr *
  228. slapi_attr_new()
  229. {
  230. Slapi_Attr *a= (Slapi_Attr *)slapi_ch_calloc( 1, sizeof(Slapi_Attr));
  231. if(!counters_created)
  232. {
  233. PR_CREATE_COUNTER(slapi_attr_counter_created,"Slapi_Attr","created","");
  234. PR_CREATE_COUNTER(slapi_attr_counter_deleted,"Slapi_Attr","deleted","");
  235. PR_CREATE_COUNTER(slapi_attr_counter_exist,"Slapi_Attr","exist","");
  236. counters_created= 1;
  237. }
  238. PR_INCREMENT_COUNTER(slapi_attr_counter_created);
  239. PR_INCREMENT_COUNTER(slapi_attr_counter_exist);
  240. return a;
  241. }
  242. Slapi_Attr *
  243. slapi_attr_init(Slapi_Attr *a, const char *type)
  244. {
  245. return slapi_attr_init_locking_optional(a, type, PR_TRUE);
  246. }
  247. int
  248. slapi_attr_init_syntax(Slapi_Attr *a)
  249. {
  250. int rc = 1;
  251. struct asyntaxinfo *asi = NULL;
  252. char *tmp = 0;
  253. const char *basetype= NULL;
  254. char buf[SLAPD_TYPICAL_ATTRIBUTE_NAME_MAX_LENGTH];
  255. basetype = buf;
  256. tmp = slapi_attr_basetype(a->a_type, buf, sizeof(buf));
  257. if (tmp) {
  258. basetype = buf;
  259. }
  260. asi = attr_syntax_get_by_name_with_default (basetype);
  261. if (asi) {
  262. rc = 0;
  263. a->a_plugin = asi->asi_plugin;
  264. a->a_flags = asi->asi_flags;
  265. a->a_mr_eq_plugin = asi->asi_mr_eq_plugin;
  266. a->a_mr_ord_plugin = asi->asi_mr_ord_plugin;
  267. a->a_mr_sub_plugin = asi->asi_mr_sub_plugin;
  268. }
  269. if (tmp)
  270. slapi_ch_free_string(&tmp);
  271. return rc;
  272. }
  273. Slapi_Attr *
  274. slapi_attr_init_locking_optional(Slapi_Attr *a, const char *type, PRBool use_lock)
  275. {
  276. PR_ASSERT(a!=NULL);
  277. if(NULL != a)
  278. {
  279. struct asyntaxinfo *asi= NULL;
  280. const char *basetype= NULL;
  281. char *tmp= NULL;
  282. if(type!=NULL)
  283. {
  284. char buf[SLAPD_TYPICAL_ATTRIBUTE_NAME_MAX_LENGTH];
  285. basetype = buf;
  286. tmp = slapi_attr_basetype(type, buf, sizeof(buf));
  287. if(tmp != NULL)
  288. {
  289. basetype = tmp; /* basetype was malloc'd */
  290. }
  291. asi = attr_syntax_get_by_name_locking_optional(basetype, use_lock, 0);
  292. }
  293. if(NULL == asi)
  294. {
  295. a->a_type = attr_syntax_normalize_no_lookup( type );
  296. /*
  297. * no syntax for this type... return Octet String
  298. * syntax. we accomplish this by looking up a well known
  299. * attribute type that has that syntax.
  300. */
  301. asi = attr_syntax_get_by_name_locking_optional(
  302. ATTR_WITH_OCTETSTRING_SYNTAX, use_lock, 0);
  303. }
  304. else
  305. {
  306. char *attroptions = NULL;
  307. if ( NULL != type ) {
  308. attroptions = strchr( type, ';' );
  309. }
  310. if ( NULL == attroptions ) {
  311. a->a_type = slapi_ch_strdup(asi->asi_name);
  312. } else {
  313. /*
  314. * If the original type includes any attribute options,
  315. * the a_type field is set to the type contained in the
  316. * attribute syntax followed by a normalized copy of the
  317. * options.
  318. */
  319. char *normalized_options;
  320. normalized_options = attr_syntax_normalize_no_lookup( attroptions );
  321. a->a_type = slapi_ch_smprintf("%s%s", asi->asi_name, normalized_options );
  322. slapi_ch_free_string( &normalized_options );
  323. }
  324. }
  325. if ( asi != NULL )
  326. {
  327. a->a_plugin = asi->asi_plugin;
  328. a->a_flags = asi->asi_flags;
  329. a->a_mr_eq_plugin = asi->asi_mr_eq_plugin;
  330. a->a_mr_ord_plugin = asi->asi_mr_ord_plugin;
  331. a->a_mr_sub_plugin = asi->asi_mr_sub_plugin;
  332. }
  333. else
  334. {
  335. a->a_plugin = NULL; /* XXX - should be rare */
  336. a->a_flags = 0; /* XXX - should be rare */
  337. a->a_mr_eq_plugin = NULL;
  338. a->a_mr_ord_plugin = NULL;
  339. a->a_mr_sub_plugin = NULL;
  340. }
  341. attr_syntax_return_locking_optional( asi, use_lock );
  342. if (NULL != tmp)
  343. {
  344. slapi_ch_free_string(&tmp);
  345. }
  346. slapi_valueset_init(&a->a_present_values);
  347. slapi_valueset_init(&a->a_deleted_values);
  348. a->a_listtofree= NULL;
  349. a->a_deletioncsn= NULL;
  350. a->a_next= NULL;
  351. }
  352. return a;
  353. }
  354. Slapi_Attr *
  355. slapi_attr_init_nosyntax(Slapi_Attr *a, const char *type)
  356. {
  357. a->a_type = slapi_ch_strdup(type);
  358. slapi_valueset_init(&a->a_present_values);
  359. slapi_valueset_init(&a->a_deleted_values);
  360. a->a_listtofree= NULL;
  361. a->a_deletioncsn= NULL;
  362. a->a_next= NULL;
  363. return a;
  364. }
  365. Slapi_Attr *
  366. slapi_attr_dup(const Slapi_Attr *attr)
  367. {
  368. Slapi_Attr *newattr= slapi_attr_new();
  369. slapi_attr_init(newattr, attr->a_type);
  370. slapi_valueset_set_valueset( &newattr->a_deleted_values, &attr->a_deleted_values );
  371. slapi_valueset_set_valueset( &newattr->a_present_values, &attr->a_present_values );
  372. newattr->a_deletioncsn= csn_dup(attr->a_deletioncsn);
  373. return newattr;
  374. }
  375. void
  376. slapi_attr_free( Slapi_Attr **ppa )
  377. {
  378. if(ppa!=NULL && *ppa!=NULL)
  379. {
  380. Slapi_Attr *a= *ppa;
  381. attr_done(a);
  382. slapi_ch_free( (void**)&a );
  383. PR_INCREMENT_COUNTER(slapi_attr_counter_deleted);
  384. PR_DECREMENT_COUNTER(slapi_attr_counter_exist);
  385. }
  386. }
  387. void
  388. attr_done(Slapi_Attr *a)
  389. {
  390. if(a!=NULL)
  391. {
  392. slapi_ch_free((void**)&a->a_type);
  393. csn_free(&a->a_deletioncsn);
  394. slapi_valueset_done(&a->a_present_values);
  395. slapi_valueset_done(&a->a_deleted_values);
  396. {
  397. struct bervals2free *freelist;
  398. struct bervals2free *tmp;
  399. freelist = a->a_listtofree;
  400. while(freelist) {
  401. ber_bvecfree(freelist->bvals);
  402. tmp=freelist;
  403. freelist = freelist->next;
  404. slapi_ch_free((void **)&tmp);
  405. }
  406. }
  407. }
  408. }
  409. /*
  410. * slapi_attr_basetype - extracts the attribute base type (without
  411. * any attribute description options) from type. puts the result
  412. * in buf if it can, otherwise, it malloc's and returns the base
  413. * which should be free()'ed later.
  414. */
  415. char *
  416. slapi_attr_basetype( const char *type, char *buf, size_t bufsize )
  417. {
  418. unsigned int i;
  419. i = 0;
  420. while ( *type && *type != ';' && i < bufsize ) {
  421. buf[i++] = *type++;
  422. }
  423. if ( i < bufsize ) {
  424. buf[i] = '\0';
  425. return( NULL );
  426. } else {
  427. int len;
  428. char *tmp;
  429. len = strlen( type );
  430. tmp = slapi_ch_malloc( len + 1 );
  431. slapi_attr_basetype( type, tmp, len + 1 );
  432. return( tmp );
  433. }
  434. }
  435. /*
  436. * returns 0 if "v" is already a value within "a" and non-zero if not.
  437. */
  438. int
  439. slapi_attr_value_find( const Slapi_Attr *a, const struct berval *v )
  440. {
  441. struct ava ava;
  442. unsigned long a_flags;
  443. if ( NULL == a ) {
  444. return( -1 );
  445. }
  446. if ( a->a_flags == 0 && a->a_plugin == NULL ) {
  447. slapi_attr_init_syntax ((Slapi_Attr *)a);
  448. }
  449. ava.ava_type = a->a_type;
  450. ava.ava_value = *v;
  451. if (a->a_flags & SLAPI_ATTR_FLAG_NORMALIZED) {
  452. a_flags = a->a_flags;
  453. ava.ava_private = &a_flags;
  454. } else {
  455. ava.ava_private = NULL;
  456. }
  457. return(plugin_call_syntax_filter_ava( a, LDAP_FILTER_EQUALITY, &ava ));
  458. }
  459. int
  460. slapi_attr_get_type( Slapi_Attr *a, char **type )
  461. {
  462. *type = a->a_type;
  463. return( 0 );
  464. }
  465. /*
  466. * Fetch a copy of the values as an array of struct berval *'s.
  467. * Returns 0 upon success and non-zero on failure.
  468. * Free the array of values by calling ber_bvecfree().
  469. */
  470. int
  471. slapi_attr_get_bervals_copy( Slapi_Attr *a, struct berval ***vals )
  472. {
  473. int retVal= 0;
  474. if ( NULL == vals )
  475. {
  476. return -1;
  477. }
  478. if(NULL==a || valueset_isempty(&a->a_present_values))
  479. {
  480. *vals = NULL;
  481. }
  482. else
  483. {
  484. Slapi_Value **va= valueset_get_valuearray(&a->a_present_values);
  485. valuearray_get_bervalarray(va,vals);
  486. }
  487. return retVal;
  488. }
  489. /*
  490. * JCM: BEWARE.. HIGHLY EVIL.. DO NOT USE THIS FUNCTION.
  491. * XXXmcs: Why not? Because it is only provided as a not-quite-backwards
  492. * compatible interface for older (pre-iDS 5.0) plugins. It works by
  493. * making a copy of the attribute values (the pre-iDS 5.0 function with
  494. * the same name returned a pointer into the Slapi_Attr structure -- no
  495. * copying). Since older users of this interface did not have to free
  496. * the values, this function arranges to free them WHEN THE Slapi_Attr
  497. * IS DESTROYED. This is accomplished by adding a pointer to the newly
  498. * allocated copy to a "to be freed" linked list inside the Slapi_Attr.
  499. * But if the Slapi_Attr is not destroyed very often, and this function
  500. * is called repeatedly, memory usage will grow without bound. Not good.
  501. * The value copies are freed inside attr_done() which is called from
  502. * slapi_attr_free() and a few other places.
  503. *
  504. * If you really want a copy of the values as a struct berval ** array,
  505. * call slapi_attr_get_bervals_copy() and free it yourself by calling
  506. * ber_bvecfree().
  507. */
  508. int
  509. slapi_attr_get_values( Slapi_Attr *a, struct berval ***vals )
  510. {
  511. int retVal = slapi_attr_get_bervals_copy( a, vals );
  512. if ( 0 == retVal )
  513. {
  514. struct bervals2free *newfree;
  515. newfree = (struct bervals2free *)slapi_ch_malloc(sizeof(struct bervals2free));
  516. newfree->next = a->a_listtofree;
  517. newfree->bvals = *vals;
  518. a->a_listtofree = newfree;
  519. }
  520. return retVal;
  521. }
  522. /*
  523. * Fetch a copy of the present valueset.
  524. * Caller must free the valueset.
  525. */
  526. int
  527. slapi_attr_get_valueset(const Slapi_Attr *a, Slapi_ValueSet **vs)
  528. {
  529. int retVal= 0;
  530. if(vs!=NULL)
  531. {
  532. *vs= valueset_dup(&a->a_present_values);
  533. }
  534. return retVal;
  535. }
  536. /*
  537. * Careful... this returns a pointer to the contents!
  538. */
  539. Slapi_Value **
  540. attr_get_present_values(const Slapi_Attr *a)
  541. {
  542. return valueset_get_valuearray(&a->a_present_values);
  543. }
  544. int
  545. slapi_attr_get_flags( const Slapi_Attr *a, unsigned long *flags )
  546. {
  547. if ( a->a_flags == 0 && a->a_plugin == NULL ) {
  548. slapi_attr_init_syntax ((Slapi_Attr *)a);
  549. }
  550. *flags = a->a_flags;
  551. return( 0 );
  552. }
  553. int
  554. slapi_attr_flag_is_set( const Slapi_Attr *a, unsigned long flag )
  555. {
  556. if ( a->a_flags == 0 && a->a_plugin == NULL ) {
  557. slapi_attr_init_syntax ((Slapi_Attr *)a);
  558. }
  559. return( a->a_flags & flag );
  560. }
  561. int
  562. slapi_attr_value_cmp( const Slapi_Attr *a, const struct berval *v1, const struct berval *v2 )
  563. {
  564. Slapi_Attr a2 = *a;
  565. struct ava ava;
  566. Slapi_Value *cvals[2];
  567. Slapi_Value tmpcval;
  568. if ( a->a_flags == 0 && a->a_plugin == NULL ) {
  569. slapi_attr_init_syntax ((Slapi_Attr *)a);
  570. }
  571. cvals[0] = &tmpcval;
  572. cvals[0]->v_csnset = NULL;
  573. cvals[0]->bv = *v1;
  574. cvals[0]->v_flags = 0;
  575. cvals[1] = NULL;
  576. a2.a_present_values.va = cvals; /* JCM - PUKE */
  577. ava.ava_type = a->a_type;
  578. ava.ava_value = *v2;
  579. ava.ava_private = NULL;
  580. return( plugin_call_syntax_filter_ava(&a2, LDAP_FILTER_EQUALITY, &ava));
  581. }
  582. int
  583. slapi_attr_value_cmp_ext(const Slapi_Attr *a, Slapi_Value *v1, Slapi_Value *v2)
  584. {
  585. struct ava ava;
  586. Slapi_Attr a2 = *a;
  587. Slapi_Value *cvals[2];
  588. unsigned long v2_flags = v2->v_flags;
  589. const struct berval *bv2 = slapi_value_get_berval(v2);
  590. if ( a->a_flags == 0 && a->a_plugin == NULL ) {
  591. slapi_attr_init_syntax ((Slapi_Attr *)a);
  592. }
  593. cvals[0] = v1;
  594. cvals[1] = NULL;
  595. a2.a_present_values.va = cvals;
  596. ava.ava_type = a->a_type;
  597. ava.ava_value = *bv2;
  598. if (v2_flags) {
  599. ava.ava_private = &v2_flags;
  600. } else {
  601. ava.ava_private = NULL;
  602. }
  603. return (plugin_call_syntax_filter_ava(&a2, LDAP_FILTER_EQUALITY, &ava));
  604. }
  605. /*
  606. * Set the CSN of all the present values.
  607. */
  608. int
  609. attr_set_csn( Slapi_Attr *a, const CSN *csn)
  610. {
  611. PR_ASSERT(a!=NULL);
  612. valueset_update_csn(&a->a_present_values, CSN_TYPE_VALUE_UPDATED, csn);
  613. return 0;
  614. }
  615. int
  616. attr_set_deletion_csn( Slapi_Attr *a, const CSN *csn)
  617. {
  618. PR_ASSERT(a!=NULL);
  619. if(csn_compare(csn,a->a_deletioncsn)>0)
  620. {
  621. csn_free(&a->a_deletioncsn);
  622. a->a_deletioncsn= csn_dup(csn);
  623. }
  624. return 0;
  625. }
  626. const CSN *
  627. attr_get_deletion_csn(const Slapi_Attr *a)
  628. {
  629. PR_ASSERT(a!=NULL);
  630. return a->a_deletioncsn;
  631. }
  632. int
  633. slapi_attr_first_value( Slapi_Attr *a, Slapi_Value **v )
  634. {
  635. int rc;
  636. if(NULL == a) {
  637. rc = -1;
  638. } else {
  639. rc=slapi_valueset_first_value( &a->a_present_values, v );
  640. }
  641. return rc;
  642. }
  643. int
  644. slapi_attr_next_value( Slapi_Attr *a, int hint, Slapi_Value **v)
  645. {
  646. int rc;
  647. if(NULL == a) {
  648. rc = -1;
  649. } else {
  650. rc=slapi_valueset_next_value( &a->a_present_values, hint, v );
  651. }
  652. return rc;
  653. }
  654. int
  655. slapi_attr_get_numvalues( const Slapi_Attr *a, int *numValues )
  656. {
  657. if(NULL == a) {
  658. *numValues = 0;
  659. } else {
  660. *numValues = slapi_valueset_count(&a->a_present_values);
  661. }
  662. return 0;
  663. }
  664. int
  665. attr_first_deleted_value( Slapi_Attr *a, Slapi_Value **v )
  666. {
  667. return slapi_valueset_first_value( &a->a_deleted_values, v );
  668. }
  669. int
  670. attr_next_deleted_value( Slapi_Attr *a, int hint, Slapi_Value **v)
  671. {
  672. return slapi_valueset_next_value( &a->a_deleted_values, hint, v );
  673. }
  674. /*
  675. * Note: We are passing in the entry so that we may be able to "optimize"
  676. * the csn related information and roll it up higher to the level of entry.
  677. */
  678. void
  679. attr_purge_state_information(Slapi_Entry *entry, Slapi_Attr *attr, const CSN *csnUpTo)
  680. {
  681. if(!valueset_isempty(&attr->a_deleted_values))
  682. {
  683. valueset_purge(&attr->a_deleted_values, csnUpTo);
  684. }
  685. }
  686. /*
  687. * Search an attribute for a value, it could be present, deleted, or not present.
  688. */
  689. int
  690. attr_value_find_wsi(Slapi_Attr *a, const struct berval *bval, Slapi_Value **value)
  691. {
  692. int retVal=0;
  693. struct ava ava;
  694. PR_ASSERT(a!=NULL);
  695. PR_ASSERT(value!=NULL);
  696. /*
  697. * we will first search the present values, and then, if
  698. * necessary, the deleted values.
  699. */
  700. ava.ava_type = a->a_type;
  701. ava.ava_value = *bval;
  702. ava.ava_private = NULL;
  703. retVal = plugin_call_syntax_filter_ava_sv(a, LDAP_FILTER_EQUALITY, &ava, value, 0 /* Present */);
  704. if(retVal==0)
  705. {
  706. /* we found the value, so we don't search the deleted list */
  707. retVal= VALUE_PRESENT;
  708. }
  709. else
  710. {
  711. retVal = plugin_call_syntax_filter_ava_sv(a, LDAP_FILTER_EQUALITY, &ava, value, 1 /* Deleted */);
  712. if(retVal==0)
  713. {
  714. /* It was on the deleted value list */
  715. retVal= VALUE_DELETED;
  716. }
  717. else
  718. {
  719. /* Couldn't find it */
  720. retVal= VALUE_NOTFOUND;
  721. }
  722. }
  723. return retVal;
  724. }
  725. int
  726. slapi_attr_add_value(Slapi_Attr *a, const Slapi_Value *v)
  727. {
  728. slapi_valueset_add_attr_value_ext( a, &a->a_present_values, (Slapi_Value *)v, 0);
  729. return 0;
  730. }
  731. int
  732. slapi_attr_set_type(Slapi_Attr *a, const char *type)
  733. {
  734. int rc = 0;
  735. if((NULL == a) || (NULL == type)) {
  736. rc = -1;
  737. } else {
  738. slapi_ch_free_string(&a->a_type);
  739. a->a_type = slapi_ch_strdup(type);
  740. }
  741. return rc;
  742. }
  743. /* Make the valuset in Slapi_Attr be *vs--not a copy */
  744. int
  745. slapi_attr_set_valueset(Slapi_Attr *a, const Slapi_ValueSet *vs)
  746. {
  747. slapi_valueset_set_valueset( &a->a_present_values, vs);
  748. return 0;
  749. }
  750. int
  751. attr_add_deleted_value(Slapi_Attr *a, const Slapi_Value *v)
  752. {
  753. slapi_valueset_add_attr_value_ext( a, &a->a_deleted_values, (Slapi_Value *)v, 0);
  754. return 0;
  755. }
  756. /*
  757. * Add a value array to an attribute.
  758. * If more than one values are being added, we build an AVL tree of any existing
  759. * values and then update that in parallel with the existing values. This
  760. * AVL tree is used to detect the duplicates not only between the existing
  761. * values and to-be-added values but also among the to-be-added values.
  762. * The AVL tree is created and destroyed all within this function.
  763. *
  764. * Returns
  765. * LDAP_SUCCESS - OK
  766. * LDAP_OPERATIONS_ERROR - Existing duplicates in attribute.
  767. * LDAP_TYPE_OR_VALUE_EXISTS - Duplicate values.
  768. */
  769. int
  770. attr_add_valuearray(Slapi_Attr *a, Slapi_Value **vals, const char *dn)
  771. {
  772. int i = 0;
  773. int numofvals = 0;
  774. int duplicate_index = -1;
  775. int rc = LDAP_SUCCESS;
  776. if (valuearray_isempty(vals)) {
  777. /*
  778. * No values to add (unexpected but acceptable).
  779. */
  780. return rc;
  781. }
  782. /*
  783. * add values and check for duplicate values
  784. */
  785. numofvals = valuearray_count(vals);
  786. rc = slapi_valueset_add_attr_valuearray_ext (a, &a->a_present_values, vals, numofvals, SLAPI_VALUE_FLAG_DUPCHECK, &duplicate_index);
  787. if ( rc != LDAP_SUCCESS) {
  788. #if defined(USE_OLD_UNHASHED)
  789. if (is_type_forbidden(a->a_type)) {
  790. /* If the attr is in the forbidden list
  791. * (e.g., unhashed password),
  792. * we don't return any useful info to the clients. */
  793. rc = LDAP_OTHER;
  794. } else {
  795. rc = LDAP_TYPE_OR_VALUE_EXISTS;
  796. }
  797. #else
  798. rc = LDAP_TYPE_OR_VALUE_EXISTS;
  799. #endif
  800. }
  801. /* In the case of duplicate value, rc == LDAP_TYPE_OR_VALUE_EXISTS or
  802. * LDAP_OPERATIONS_ERROR
  803. */
  804. if ( duplicate_index >= 0 ) {
  805. char bvvalcopy[BUFSIZ];
  806. char *duplicate_string = "null or non-ASCII";
  807. i = 0;
  808. while ( (unsigned int)i < vals[duplicate_index]->bv.bv_len &&
  809. i < BUFSIZ - 1 &&
  810. vals[duplicate_index]->bv.bv_val[i] &&
  811. isascii ( vals[duplicate_index]->bv.bv_val[i] )) {
  812. i++;
  813. }
  814. if ( i ) {
  815. if ( vals[duplicate_index]->bv.bv_val[i] == 0 ) {
  816. duplicate_string = vals[duplicate_index]->bv.bv_val;
  817. }
  818. else {
  819. strncpy ( &bvvalcopy[0], vals[duplicate_index]->bv.bv_val, i );
  820. bvvalcopy[i] = '\0';
  821. duplicate_string = bvvalcopy;
  822. }
  823. }
  824. slapi_log_error( SLAPI_LOG_TRACE, NULL, "add value \"%s\" to "
  825. "attribute type \"%s\" in entry \"%s\" failed: %s\n",
  826. duplicate_string,
  827. a->a_type,
  828. dn ? dn : "<null>",
  829. "value exists");
  830. }
  831. return( rc );
  832. }
  833. /* quickly toss an attribute's values and replace them with new ones
  834. * (used by attrlist_replace_fast)
  835. * Returns
  836. * LDAP_SUCCESS - OK
  837. * LDAP_OPERATIONS_ERROR - Existing duplicates in attribute.
  838. */
  839. int attr_replace(Slapi_Attr *a, Slapi_Value **vals)
  840. {
  841. return valueset_replace_valuearray(a, &a->a_present_values, vals);
  842. }
  843. int
  844. attr_check_onoff ( const char *attr_name, char *value, long minval, long maxval, char *errorbuf )
  845. {
  846. int retVal = LDAP_SUCCESS;
  847. if ( strcasecmp ( value, "on" ) != 0 &&
  848. strcasecmp ( value, "off") != 0 &&
  849. strcasecmp ( value, "1" ) != 0 &&
  850. strcasecmp ( value, "0" ) != 0 &&
  851. strcasecmp ( value, "true" ) != 0 &&
  852. strcasecmp ( value, "false" ) != 0 ) {
  853. PR_snprintf ( errorbuf, BUFSIZ,
  854. "%s: invalid value \"%s\".", attr_name, value );
  855. retVal = LDAP_CONSTRAINT_VIOLATION;
  856. }
  857. return retVal;
  858. }
  859. int
  860. attr_check_minmax ( const char *attr_name, char *value, long minval, long maxval, char *errorbuf )
  861. {
  862. int retVal = LDAP_SUCCESS;
  863. long val;
  864. val = strtol(value, NULL, 0);
  865. if ( (minval != -1 ? (val < minval ? 1 : 0) : 0) ||
  866. (maxval != -1 ? (val > maxval ? 1 : 0) : 0) ) {
  867. PR_snprintf ( errorbuf, BUFSIZ,
  868. "%s: invalid value \"%s\".",
  869. attr_name, value );
  870. retVal = LDAP_CONSTRAINT_VIOLATION;
  871. }
  872. return retVal;
  873. }
  874. /**
  875. Returns the function which can be used to compare (like memcmp/strcmp)
  876. two values of this type of attribute. The comparison function will use
  877. the ORDERING matching rule if available, or the default comparison
  878. function from the syntax plugin.
  879. Note: if there is no ORDERING matching rule, and the syntax does not
  880. provide an ordered compare function, this function will return
  881. LDAP_PROTOCOL_ERROR and compare_fn will be NULL.
  882. Returns LDAP_SUCCESS if successful and sets *compare_fn to the function.
  883. */
  884. int
  885. attr_get_value_cmp_fn(const Slapi_Attr *attr, value_compare_fn_type *compare_fn)
  886. {
  887. int rc = LDAP_PROTOCOL_ERROR;
  888. LDAPDebug0Args(LDAP_DEBUG_TRACE,
  889. "=> slapi_attr_get_value_cmp_fn\n");
  890. *compare_fn = NULL;
  891. if (attr == NULL) {
  892. LDAPDebug0Args(LDAP_DEBUG_TRACE,
  893. "<= slapi_attr_get_value_cmp_fn no attribute given\n");
  894. rc = LDAP_PARAM_ERROR; /* unkonwn */
  895. goto done;
  896. }
  897. if (attr->a_mr_ord_plugin && attr->a_mr_ord_plugin->plg_mr_compare) {
  898. *compare_fn = (value_compare_fn_type) attr->a_mr_ord_plugin->plg_mr_compare;
  899. rc = LDAP_SUCCESS;
  900. goto done;
  901. }
  902. if ((attr->a_plugin->plg_syntax_flags & SLAPI_PLUGIN_SYNTAX_FLAG_ORDERING) == 0) {
  903. LDAPDebug2Args(LDAP_DEBUG_TRACE,
  904. "<= slapi_attr_get_value_cmp_fn syntax [%s] for attribute [%s] does not support ordering\n",
  905. attr->a_plugin->plg_syntax_oid, attr->a_type);
  906. goto done;
  907. }
  908. if (attr->a_plugin->plg_syntax_filter_ava == NULL) {
  909. LDAPDebug2Args(LDAP_DEBUG_TRACE,
  910. "<= slapi_attr_get_value_cmp_fn syntax [%s] for attribute [%s] does not support equality matching\n",
  911. attr->a_plugin->plg_syntax_oid, attr->a_type);
  912. goto done;
  913. }
  914. if (attr->a_plugin->plg_syntax_compare == NULL) {
  915. LDAPDebug2Args(LDAP_DEBUG_TRACE,
  916. "<= slapi_attr_get_value_cmp_fn syntax [%s] for attribute [%s] does not have a compare function\n",
  917. attr->a_plugin->plg_syntax_oid, attr->a_type);
  918. goto done;
  919. }
  920. *compare_fn = (value_compare_fn_type)attr->a_plugin->plg_syntax_compare;
  921. rc = LDAP_SUCCESS;
  922. done:
  923. LDAPDebug0Args(LDAP_DEBUG_TRACE, "<= slapi_attr_get_value_cmp_fn \n");
  924. return rc;
  925. }
  926. const char *
  927. attr_get_syntax_oid(const Slapi_Attr *attr)
  928. {
  929. if (attr->a_plugin) {
  930. return attr->a_plugin->plg_syntax_oid;
  931. } else {
  932. return NULL;
  933. }
  934. }