~ubuntu-branches/ubuntu/utopic/389-ds-base/utopic-proposed

« back to all changes in this revision

Viewing changes to ldap/servers/slapd/entrywsi.c

  • Committer: Package Import Robot
  • Author(s): Timo Aaltonen
  • Date: 2014-02-03 11:08:50 UTC
  • mfrom: (0.2.1)
  • Revision ID: package-import@ubuntu.com-20140203110850-tjzx85elnke9fiu3
Tags: 1.3.2.9-1
* New upstream release.
  - fixes CVE-2013-0336 (Closes: #704077)
  - fixes CVE-2013-1897 (Closes: #704421)
  - fixes CVE-2013-2219 (Closes: #718325)
  - fixes CVE-2013-4283 (Closes: #721222)
  - fixes CVE-2013-4485 (Closes: #730115)
* Drop fix-CVE-2013-0312.diff, upstream.
* rules: Add new scripts to rename.
* fix-sasl-path.diff: Use a triplet path to find libsasl2. (LP:
  #1088822)
* admin_scripts.diff: Add patch from upstream #47511 to fix bashisms.
* control: Add ldap-utils to -base depends.
* rules, rename-online-scripts.diff: Some scripts with .pl suffix are
  meant for an online server, so instead of overwriting the offline
  scripts use -online suffix.
* rules: Enable parallel build, but limit the jobs to 1 for
  dh_auto_install.
* control: Bump policy to 3.9.5, no changes.
* rules: Add get-orig-source target.
* lintian-overrides: Drop obsolete entries, add comments for the rest.

Show diffs side-by-side

added added

removed removed

Lines of Context:
46
46
#include "slap.h"
47
47
#include "slapi-plugin.h"
48
48
 
49
 
static void resolve_attribute_state(Slapi_Entry *e, Slapi_Attr *a, int attribute_state, int delete_priority);
50
 
 
51
49
static int
52
50
entry_present_value_to_deleted_value(Slapi_Attr *a, Slapi_Value *v)
53
51
{
419
417
 * Preserves LDAP Information Model constraints,
420
418
 * returning an LDAP result code.
421
419
 */
 
420
static void resolve_attribute_state_single_valued(Slapi_Entry *e, Slapi_Attr *a, int attribute_state);
 
421
static void resolve_attribute_state_deleted_to_present(Slapi_Entry *e, Slapi_Attr *a, Slapi_Value **valuestoupdate);
 
422
static void resolve_attribute_state_present_to_deleted(Slapi_Entry *e, Slapi_Attr *a, Slapi_Value **valuestoupdate);
 
423
static void resolve_attribute_state_to_present_or_deleted(Slapi_Entry *e, Slapi_Attr *a, Slapi_Value **valuestoupdate, int attribute_state);
 
424
static int entry_add_present_values_wsi_single_valued(Slapi_Entry *e, const char *type, struct berval **bervals, const CSN *csn, int urp, long flags);
 
425
static int entry_add_present_values_wsi_multi_valued(Slapi_Entry *e, const char *type, struct berval **bervals, const CSN *csn, int urp, long flags);
422
426
static int
423
427
entry_add_present_values_wsi(Slapi_Entry *e, const char *type, struct berval **bervals, const CSN *csn, int urp, long flags)
424
428
{
 
429
        int retVal = LDAP_SUCCESS;
 
430
        Slapi_Attr *a= NULL;
 
431
        int attr_state= entry_attr_find_wsi(e, type, &a);
 
432
        if (ATTRIBUTE_NOTFOUND == attr_state)
 
433
        {
 
434
                /* Create a new attribute */
 
435
                a = slapi_attr_new();
 
436
                slapi_attr_init(a, type);
 
437
                attrlist_add(&e->e_attrs, a);
 
438
        }
 
439
 
 
440
        if(slapi_attr_flag_is_set(a,SLAPI_ATTR_FLAG_SINGLE))
 
441
        {
 
442
                retVal = entry_add_present_values_wsi_single_valued( e, type, bervals, csn, urp, 0 );
 
443
        }
 
444
        else
 
445
        {
 
446
                retVal = entry_add_present_values_wsi_multi_valued( e, type, bervals, csn, urp, 0 );
 
447
        }
 
448
        return retVal;
 
449
}
 
450
 
 
451
static int
 
452
entry_add_present_values_wsi_single_valued(Slapi_Entry *e, const char *type, struct berval **bervals, const CSN *csn, int urp, long flags)
 
453
{
425
454
        int retVal= LDAP_SUCCESS;
426
 
    Slapi_Value **valuestoadd = NULL;
427
 
    valuearray_init_bervalarray(bervals,&valuestoadd); /* JCM SLOW FUNCTION */
 
455
        Slapi_Value **valuestoadd = NULL;
 
456
 
 
457
        valuearray_init_bervalarray(bervals,&valuestoadd); /* JCM SLOW FUNCTION */
428
458
        if(!valuearray_isempty(valuestoadd))
429
459
        {
430
460
                Slapi_Attr *a= NULL;
431
461
                long a_flags_orig;
432
462
                int attr_state= entry_attr_find_wsi(e, type, &a);
433
 
                if (ATTRIBUTE_NOTFOUND == attr_state)
434
 
                {
435
 
                        /* Create a new attribute */
436
 
                        a = slapi_attr_new();
437
 
                        slapi_attr_init(a, type);
438
 
                        attrlist_add(&e->e_attrs, a);
439
 
                }
440
 
        a_flags_orig = a->a_flags;
 
463
 
 
464
                a_flags_orig = a->a_flags;
 
465
                a->a_flags |= flags;
 
466
                /* Check if the type of the to-be-added values has DN syntax or not. */
 
467
                if (slapi_attr_is_dn_syntax_attr(a)) {
 
468
                        valuearray_dn_normalize_value(valuestoadd);
 
469
                        a->a_flags |= SLAPI_ATTR_FLAG_NORMALIZED_CES;
 
470
                }
 
471
                if(urp)
 
472
                {
 
473
                        valueset_remove_valuearray (&a->a_present_values, a, valuestoadd,
 
474
                                                SLAPI_VALUE_FLAG_IGNOREERROR |
 
475
                                                SLAPI_VALUE_FLAG_PRESERVECSNSET, NULL);
 
476
                        valueset_remove_valuearray (&a->a_deleted_values, a, valuestoadd,
 
477
                                                SLAPI_VALUE_FLAG_IGNOREERROR |
 
478
                                                SLAPI_VALUE_FLAG_PRESERVECSNSET, NULL);
 
479
                        valuearray_update_csn (valuestoadd,CSN_TYPE_VALUE_UPDATED,csn);
 
480
                        slapi_valueset_add_attr_valuearray_ext (a, &a->a_present_values, valuestoadd, valuearray_count(valuestoadd), SLAPI_VALUE_FLAG_PASSIN, NULL);
 
481
                        slapi_ch_free ( (void **)&valuestoadd );
 
482
                        /*
 
483
                         * Now delete non-RDN values from a->a_present_values; and
 
484
                         * restore possible RDN values from a->a_deleted_values
 
485
                         */
 
486
                        resolve_attribute_state_single_valued(e, a, attr_state);
 
487
                        retVal= LDAP_SUCCESS;
 
488
                }
 
489
                else
 
490
                {
 
491
                        Slapi_Value **deletedvalues= NULL;
 
492
                        switch(attr_state)
 
493
                        {
 
494
                                case ATTRIBUTE_PRESENT:
 
495
                                        /* The attribute is already on the present list */
 
496
                                        break;
 
497
                                case ATTRIBUTE_DELETED:
 
498
                                        /* Move the deleted attribute onto the present list */
 
499
                                        entry_deleted_attribute_to_present_attribute(e, a);
 
500
                                        break;
 
501
                                case ATTRIBUTE_NOTFOUND:
 
502
                                        /* No-op - attribute was initialized & added to entry above */
 
503
                                        break;
 
504
                        }
 
505
                        /* Check if any of the values to be added are on the deleted list */
 
506
                        valueset_remove_valuearray(&a->a_deleted_values,
 
507
                                        a, valuestoadd,
 
508
                                        SLAPI_VALUE_FLAG_IGNOREERROR|SLAPI_VALUE_FLAG_USENEWVALUE,
 
509
                                        &deletedvalues); /* JCM Check return code */
 
510
                        if(deletedvalues!=NULL && deletedvalues[0]!=NULL)
 
511
                        {
 
512
                                /* Some of the values to be added were on the deleted list */
 
513
                                Slapi_Value **v= NULL;
 
514
                                Slapi_ValueSet vs;
 
515
                                /* Add each deleted value to the present list */
 
516
                                valuearray_update_csn(deletedvalues,CSN_TYPE_VALUE_UPDATED,csn);
 
517
                                slapi_valueset_add_attr_valuearray_ext (a, &a->a_present_values, deletedvalues, valuearray_count(deletedvalues), SLAPI_VALUE_FLAG_PASSIN, NULL);
 
518
                                /* Remove the deleted values from the values to add */
 
519
                                valueset_set_valuearray_passin(&vs,valuestoadd); 
 
520
                                valueset_remove_valuearray(&vs, a, deletedvalues, SLAPI_VALUE_FLAG_IGNOREERROR, &v);
 
521
                                valuestoadd= valueset_get_valuearray(&vs);
 
522
                                valuearray_free(&v);
 
523
                                slapi_ch_free((void **)&deletedvalues);
 
524
                        }
 
525
                        valuearray_update_csn(valuestoadd,CSN_TYPE_VALUE_UPDATED,csn);
 
526
                        retVal= attr_add_valuearray(a, valuestoadd, slapi_entry_get_dn_const(e));
 
527
                }
 
528
                a->a_flags = a_flags_orig;
 
529
        }
 
530
        valuearray_free(&valuestoadd);
 
531
 
 
532
        return(retVal);
 
533
}
 
534
 
 
535
static int
 
536
entry_add_present_values_wsi_multi_valued(Slapi_Entry *e, const char *type, struct berval **bervals, const CSN *csn, int urp, long flags)
 
537
{
 
538
        int retVal= LDAP_SUCCESS;
 
539
        Slapi_Value **valuestoadd = NULL;
 
540
 
 
541
        valuearray_init_bervalarray(bervals,&valuestoadd); /* JCM SLOW FUNCTION */
 
542
        if(!valuearray_isempty(valuestoadd))
 
543
        {
 
544
                Slapi_Attr *a = NULL;
 
545
                long a_flags_orig;
 
546
                int attr_state = entry_attr_find_wsi(e, type, &a);
 
547
 
 
548
                a_flags_orig = a->a_flags;
441
549
                a->a_flags |= flags;
442
550
                /* Check if the type of the to-be-added values has DN syntax or not. */
443
551
                if (slapi_attr_is_dn_syntax_attr(a)) {
462
570
                                                SLAPI_VALUE_FLAG_IGNOREERROR |
463
571
                                                SLAPI_VALUE_FLAG_PRESERVECSNSET, NULL);
464
572
 
465
 
                        /* Append the pending values to a->a_present_values */
 
573
                        /* Now add the values in values to add to present or deleted 
 
574
                         * values, depending on their csnset */
466
575
                        valuearray_update_csn (valuestoadd,CSN_TYPE_VALUE_UPDATED,csn);
467
 
                        valueset_add_valuearray_ext(&a->a_present_values, valuestoadd, SLAPI_VALUE_FLAG_PASSIN);
 
576
 
 
577
                        resolve_attribute_state_to_present_or_deleted(e, a, valuestoadd, attr_state);
 
578
 
468
579
                        slapi_ch_free ( (void **)&valuestoadd );
469
580
 
470
 
                        /*
471
 
                         * Now delete non-RDN values from a->a_present_values; and
472
 
                         * restore possible RDN values from a->a_deleted_values
473
 
                         */
474
 
                        resolve_attribute_state(e, a, attr_state, 0);
475
581
                        retVal= LDAP_SUCCESS;
476
582
                }
477
583
                else
478
584
                {
479
585
                        Slapi_Value **deletedvalues= NULL;
 
586
 
480
587
                        switch(attr_state)
481
588
                        {
482
 
                        case ATTRIBUTE_PRESENT:
483
 
                                /* The attribute is already on the present list */
484
 
                                break;
485
 
                        case ATTRIBUTE_DELETED:
486
 
                                /* Move the deleted attribute onto the present list */
487
 
                                entry_deleted_attribute_to_present_attribute(e, a);
488
 
                                break;
489
 
                        case ATTRIBUTE_NOTFOUND:
490
 
                                /* No-op - attribute was initialized & added to entry above */
491
 
                                break;
 
589
                                case ATTRIBUTE_PRESENT:
 
590
                                        /* The attribute is already on the present list */
 
591
                                        break;
 
592
                                case ATTRIBUTE_DELETED:
 
593
                                        /* Move the deleted attribute onto the present list */
 
594
                                        entry_deleted_attribute_to_present_attribute(e, a);
 
595
                                        break;
 
596
                                case ATTRIBUTE_NOTFOUND:
 
597
                                        /* No-op - attribute was initialized & added to entry above */
 
598
                                        break;
492
599
                        }
493
600
                        /* Check if any of the values to be added are on the deleted list */
494
601
                        valueset_remove_valuearray(&a->a_deleted_values,
502
609
                                Slapi_ValueSet vs;
503
610
                                /* Add each deleted value to the present list */
504
611
                                valuearray_update_csn(deletedvalues,CSN_TYPE_VALUE_UPDATED,csn);
505
 
                                valueset_add_valuearray_ext(&a->a_present_values, deletedvalues, SLAPI_VALUE_FLAG_PASSIN);
 
612
                                slapi_valueset_add_attr_valuearray_ext (a, &a->a_present_values, deletedvalues, valuearray_count(deletedvalues), SLAPI_VALUE_FLAG_PASSIN, NULL);
506
613
                                /* Remove the deleted values from the values to add */
507
614
                                valueset_set_valuearray_passin(&vs,valuestoadd); 
508
615
                                valueset_remove_valuearray(&vs, a, deletedvalues, SLAPI_VALUE_FLAG_IGNOREERROR, &v);
512
619
                        }
513
620
                        valuearray_update_csn(valuestoadd,CSN_TYPE_VALUE_UPDATED,csn);
514
621
                        retVal= attr_add_valuearray(a, valuestoadd, slapi_entry_get_dn_const(e));
515
 
                        valuearray_free(&valuestoadd);
516
622
                }
517
623
                a->a_flags = a_flags_orig;
518
624
        }
 
625
        valuearray_free(&valuestoadd);
 
626
 
519
627
        return(retVal);
520
628
}
521
629
 
526
634
 * returning an LDAP result code.
527
635
 */
528
636
static int
 
637
entry_delete_present_values_wsi_single_valued(Slapi_Entry *e, const char *type, struct berval **vals, const CSN *csn, int urp, int mod_op, struct berval **replacevals);
 
638
static int
 
639
entry_delete_present_values_wsi_multi_valued(Slapi_Entry *e, const char *type, struct berval **vals, const CSN *csn, int urp, int mod_op, struct berval **replacevals);
 
640
static int
529
641
entry_delete_present_values_wsi(Slapi_Entry *e, const char *type, struct berval **vals, const CSN *csn, int urp, int mod_op, struct berval **replacevals)
530
642
{
531
643
        int retVal= LDAP_SUCCESS;
532
644
        Slapi_Attr *a= NULL;
533
645
        int attr_state= entry_attr_find_wsi(e, type, &a);
 
646
        
534
647
        if(attr_state==ATTRIBUTE_PRESENT || (attr_state==ATTRIBUTE_DELETED && urp))
535
648
        {
 
649
                if(slapi_attr_flag_is_set(a,SLAPI_ATTR_FLAG_SINGLE))
 
650
                        retVal = entry_delete_present_values_wsi_single_valued(e, type, vals, csn, urp, mod_op, replacevals);
 
651
                else
 
652
                        retVal = entry_delete_present_values_wsi_multi_valued(e, type, vals, csn, urp, mod_op, replacevals);
 
653
        }
 
654
        else if (attr_state==ATTRIBUTE_DELETED)
 
655
        {
 
656
#if defined(USE_OLD_UNHASHED)
 
657
                if (is_type_forbidden(type)) {
 
658
                        retVal = LDAP_SUCCESS;
 
659
                } else {
 
660
                        retVal= LDAP_NO_SUCH_ATTRIBUTE;
 
661
                }
 
662
#else
 
663
                retVal= LDAP_NO_SUCH_ATTRIBUTE;
 
664
#endif
 
665
        }
 
666
        else if (attr_state==ATTRIBUTE_NOTFOUND)
 
667
        {
 
668
#if defined(USE_OLD_UNHASHED)
 
669
                if (is_type_protected(type) || is_type_forbidden(type))
 
670
#else
 
671
                if (is_type_protected(type))
 
672
#endif
 
673
                {
 
674
                        retVal = LDAP_SUCCESS;
 
675
                } else {
 
676
                        if (!urp) {
 
677
                                LDAPDebug1Arg(LDAP_DEBUG_ARGS, "could not find attribute %s\n",
 
678
                                              type);
 
679
                        }
 
680
                        retVal = LDAP_NO_SUCH_ATTRIBUTE;
 
681
                }
 
682
                if ((LDAP_MOD_REPLACE == mod_op) && replacevals && replacevals[0])
 
683
                {
 
684
                        /* Create a new attribute and set the adcsn */
 
685
                        Slapi_Attr *a = slapi_attr_new();
 
686
                        slapi_attr_init(a, type);
 
687
                        attr_set_deletion_csn(a,csn); 
 
688
                        entry_add_deleted_attribute_wsi(e, a);
 
689
                }
 
690
        }
 
691
        return retVal;
 
692
}
 
693
static int
 
694
entry_delete_present_values_wsi_single_valued(Slapi_Entry *e, const char *type, struct berval **vals, const CSN *csn, int urp, int mod_op, struct berval **replacevals)
 
695
{
 
696
        int retVal= LDAP_SUCCESS;
 
697
        Slapi_Attr *a= NULL;
 
698
        int attr_state= entry_attr_find_wsi(e, type, &a);
 
699
        /* The attribute is on the present list, or the deleted list and we're doing URP */
 
700
        if ( vals == NULL || vals[0] == NULL )
 
701
        {
 
702
                /* delete the entire attribute */
 
703
                LDAPDebug( LDAP_DEBUG_ARGS, "removing entire attribute %s\n", type, 0, 0 );
 
704
                attr_set_deletion_csn(a,csn);
 
705
                if(urp)
 
706
                {
 
707
                        resolve_attribute_state_single_valued(e, a, attr_state);
 
708
                        /* resolve attr state single valued */
 
709
                        /* keep_present = check_attr_single_value_is_distingiuished(&a->a_present_values);
 
710
                        if ( !keep_present) {
 
711
                                slapi_valueset_done(&a->a_present_values);
 
712
                                entry_present_attribute_to_deleted_attribute(e, a);
 
713
                                }
 
714
                         */
 
715
                }
 
716
                else
 
717
                {
 
718
                        slapi_valueset_done(&a->a_present_values);
 
719
                        entry_present_attribute_to_deleted_attribute(e, a);
 
720
                }
 
721
                retVal= LDAP_SUCCESS; /* This Operation always succeeds when the attribute is Present */
 
722
        }
 
723
        else
 
724
        {
 
725
                /* delete some specific values */
 
726
            Slapi_Value **valuestodelete= NULL;
 
727
            valuearray_init_bervalarray(vals,&valuestodelete); /* JCM SLOW FUNCTION */
 
728
                /* Check if the type of the to-be-deleted values has DN syntax 
 
729
                 * or not. */
 
730
                if (slapi_attr_is_dn_syntax_attr(a)) {
 
731
                        valuearray_dn_normalize_value(valuestodelete);
 
732
                        a->a_flags |= SLAPI_ATTR_FLAG_NORMALIZED_CES;
 
733
                }
 
734
                if(urp)
 
735
                {
 
736
                        Slapi_Value **valuesupdated= NULL;
 
737
                        valueset_update_csn_for_valuearray(&a->a_present_values, a, valuestodelete, CSN_TYPE_VALUE_DELETED, csn, &valuesupdated);
 
738
                        if( valuesupdated && *valuesupdated)
 
739
                        {
 
740
                                attr_set_deletion_csn(a,csn);                   
 
741
                        }
 
742
                        /* resolve attr state single valued */
 
743
                        valuearray_free(&valuesupdated);
 
744
                        valueset_update_csn_for_valuearray(&a->a_deleted_values, a, valuestodelete, CSN_TYPE_VALUE_DELETED, csn, &valuesupdated);
 
745
                        valuearray_free(&valuesupdated);
 
746
                        valuearray_update_csn(valuestodelete,CSN_TYPE_VALUE_DELETED,csn);
 
747
                        slapi_valueset_add_attr_valuearray_ext (a, &a->a_deleted_values, valuestodelete, valuearray_count(valuestodelete), SLAPI_VALUE_FLAG_PASSIN, NULL);
 
748
                        slapi_ch_free((void **)&valuestodelete);
 
749
                        resolve_attribute_state_single_valued(e, a, attr_state);
 
750
                        retVal= LDAP_SUCCESS;
 
751
                }
 
752
                else
 
753
                {
 
754
                        Slapi_Value **deletedvalues= NULL;
 
755
                        retVal= valueset_remove_valuearray(&a->a_present_values, a, valuestodelete, 0 /* Do Not Ignore Errors */,&deletedvalues);
 
756
                        if(retVal==LDAP_SUCCESS && deletedvalues != NULL)
 
757
                        {
 
758
                                valuearray_free(&deletedvalues);
 
759
                                /* The attribute is single valued and the value was successful deleted */
 
760
                                /* but there could have been an add in the same operation, so double check */
 
761
                                if (valueset_isempty(&a->a_present_values)) {
 
762
                                        entry_present_attribute_to_deleted_attribute(e, a);
 
763
                                }
 
764
                        }
 
765
                        else if (retVal != LDAP_SUCCESS)
 
766
                        {
 
767
                                /* Failed 
 
768
                                 * - Value not found
 
769
                                 * - Operations error
 
770
                                 */
 
771
                                if ( retVal==LDAP_OPERATIONS_ERROR )
 
772
                                {
 
773
                                        LDAPDebug( LDAP_DEBUG_ANY, "Possible existing duplicate "
 
774
                                                "value for attribute type %s found in "
 
775
                                                "entry %s\n", a->a_type, slapi_entry_get_dn_const(e), 0 );
 
776
                                }
 
777
                        }
 
778
                        valuearray_free(&valuestodelete);
 
779
                }
 
780
        }
 
781
        return( retVal );
 
782
}
 
783
static int
 
784
entry_delete_present_values_wsi_multi_valued(Slapi_Entry *e, const char *type, struct berval **vals, const CSN *csn, int urp, int mod_op, struct berval **replacevals)
 
785
{
 
786
        int retVal= LDAP_SUCCESS;
 
787
        Slapi_Attr *a= NULL;
 
788
        int attr_state = entry_attr_find_wsi(e, type, &a);
536
789
                /* The attribute is on the present list, or the deleted list and we're doing URP */
537
790
                if ( vals == NULL || vals[0] == NULL )
538
791
                {
541
794
                        attr_set_deletion_csn(a,csn);
542
795
                        if(urp)
543
796
                        {
544
 
                                resolve_attribute_state(e, a, attr_state, 1 /* set delete priority */); /* ABSOLVED */
 
797
                                /* there might be values added or specifically deleted later than 
 
798
                                 * the current attr delete operation. These values need to be 
 
799
                                 * preserved, all others can be removed, purging should o the job.
 
800
                                 */
 
801
                                valueset_purge(&a->a_present_values, csn);
 
802
                                valueset_purge(&a->a_deleted_values, csn);
 
803
                                if(attr_state==ATTRIBUTE_PRESENT && valueset_isempty(&a->a_present_values))
 
804
                                        entry_present_attribute_to_deleted_attribute(e, a);
545
805
                        }
546
806
                        else
547
807
                        {
548
 
                                if(!slapi_attr_flag_is_set(a,SLAPI_ATTR_FLAG_SINGLE))
549
 
                                {
550
 
                                        /* We don't maintain a deleted value list for single valued attributes */
551
 
                                        valueset_add_valueset(&a->a_deleted_values, &a->a_present_values); /* JCM Would be better to passin the valuestodelete */
552
 
                                }
553
808
                                slapi_valueset_done(&a->a_present_values);
 
809
                                slapi_valueset_done(&a->a_deleted_values);
554
810
                                entry_present_attribute_to_deleted_attribute(e, a);
555
811
                        }
556
812
                        retVal= LDAP_SUCCESS; /* This Operation always succeeds when the attribute is Present */
558
814
                else
559
815
                {
560
816
                        /* delete some specific values */
561
 
                    Slapi_Value **valuestodelete= NULL;
562
 
                    valuearray_init_bervalarray(vals,&valuestodelete); /* JCM SLOW FUNCTION */
 
817
                        Slapi_Value **valuestodelete= NULL;
 
818
                        valuearray_init_bervalarray(vals,&valuestodelete); /* JCM SLOW FUNCTION */
563
819
                        /* Check if the type of the to-be-deleted values has DN syntax 
564
820
                         * or not. */
565
821
                        if (slapi_attr_is_dn_syntax_attr(a)) {
568
824
                        }
569
825
                        if(urp)
570
826
                        {
 
827
                                /* check if values to delete are in present values
 
828
                                 * if v in present values and VU-csn<csn and v not distinguished move to deleted values
 
829
                                 * if v not in present values, check deleted values and update csn, if distinguisehed at csn
 
830
                                 *      move back to present values
 
831
                                 */ 
 
832
 
 
833
 
571
834
                                Slapi_Value **valuesupdated= NULL;
572
 
                                valueset_update_csn_for_valuearray(&a->a_present_values, a, valuestodelete, CSN_TYPE_VALUE_DELETED, csn, &valuesupdated);
573
 
                                /* if we removed the last value, we need to mark the attribute as deleted
574
 
                                   the resolve_attribute_state() code will "resurrect" the attribute if
575
 
                                   there are present values with a later CSN - otherwise, even though
576
 
                                   the value will be updated with a VDCSN which is later than the VUCSN,
577
 
                                   the attribute will not be deleted */
578
 
                                if(slapi_attr_flag_is_set(a,SLAPI_ATTR_FLAG_SINGLE) && valuesupdated &&
579
 
                                   *valuesupdated)
580
 
                                {
581
 
                                        attr_set_deletion_csn(a,csn);                   
582
 
                                }
583
 
                                valuearray_free(&valuesupdated);
584
 
                                valueset_update_csn_for_valuearray(&a->a_deleted_values, a, valuestodelete, CSN_TYPE_VALUE_DELETED, csn, &valuesupdated);
585
 
                                valuearray_free(&valuesupdated);
 
835
                                valueset_update_csn_for_valuearray_ext(&a->a_present_values, a, valuestodelete, CSN_TYPE_VALUE_DELETED, csn, &valuesupdated, 1);
 
836
                                resolve_attribute_state_present_to_deleted(e, a, valuesupdated); 
 
837
                                valuearray_free(&valuesupdated);
 
838
 
 
839
                                valueset_update_csn_for_valuearray_ext(&a->a_deleted_values, a, valuestodelete, CSN_TYPE_VALUE_DELETED, csn, &valuesupdated, 1);
 
840
                                resolve_attribute_state_deleted_to_present(e, a, valuesupdated);
 
841
                                valuearray_free(&valuesupdated);
 
842
 
586
843
                                valuearray_update_csn(valuestodelete,CSN_TYPE_VALUE_DELETED,csn);
587
 
                                valueset_add_valuearray_ext(&a->a_deleted_values, valuestodelete, SLAPI_VALUE_FLAG_PASSIN);
 
844
                                slapi_valueset_add_attr_valuearray_ext (a, &a->a_deleted_values, valuestodelete, valuearray_count(valuestodelete), SLAPI_VALUE_FLAG_PASSIN, NULL);
 
845
                                if(attr_state==ATTRIBUTE_PRESENT && valueset_isempty(&a->a_present_values))
 
846
                                        entry_present_attribute_to_deleted_attribute(e, a);
588
847
                                /* all the elements in valuestodelete are passed;
589
848
                                 * should free valuestodelete only (don't call valuearray_free)
590
849
                                 * [622023] */
591
850
                                slapi_ch_free((void **)&valuestodelete);
592
 
                                resolve_attribute_state(e, a, attr_state, 0);
593
851
                                retVal= LDAP_SUCCESS;
594
852
                        }
595
853
                        else
596
854
                        {
 
855
                                /* find the values to delete in present values, 
 
856
                                 * update the csns and add to the deleted values
 
857
                                 */  
597
858
                                Slapi_Value **deletedvalues= NULL;
598
859
                                retVal= valueset_remove_valuearray(&a->a_present_values, a, valuestodelete, 0 /* Do Not Ignore Errors */,&deletedvalues);
599
860
                                if(retVal==LDAP_SUCCESS && deletedvalues != NULL)
600
861
                                {
601
 
                                        if(!slapi_attr_flag_is_set(a,SLAPI_ATTR_FLAG_SINGLE))
602
 
                                        {
603
 
                                                /* We don't maintain a deleted value list for single valued attributes */
604
 
                                                /* Add each deleted value to the deleted set */
605
 
                                                valuearray_update_csn(deletedvalues,CSN_TYPE_VALUE_DELETED,csn);
606
 
                                                valueset_add_valuearray_ext(&a->a_deleted_values, deletedvalues, SLAPI_VALUE_FLAG_PASSIN);
607
 
                                                slapi_ch_free((void **)&deletedvalues);
608
 
                                        }
609
 
                                        else {
610
 
                                                valuearray_free(&deletedvalues);
611
 
                                        }
 
862
                                        /* Add each deleted value to the deleted set */
 
863
                                        valuearray_update_csn(deletedvalues,CSN_TYPE_VALUE_DELETED,csn);
 
864
                                        slapi_valueset_add_attr_valuearray_ext (a,
 
865
                                                 &a->a_deleted_values, deletedvalues, valuearray_count(deletedvalues), SLAPI_VALUE_FLAG_PASSIN, NULL);
 
866
                                        slapi_ch_free((void **)&deletedvalues);
612
867
                                        if(valueset_isempty(&a->a_present_values))
613
868
                                        {
614
869
                                                /* There are no present values, so move the
619
874
                                else if (retVal != LDAP_SUCCESS)
620
875
                                {
621
876
                                        /* Failed 
622
 
                                         * - Duplicate value
623
877
                                         * - Value not found
624
878
                                         * - Operations error
625
879
                                         */
626
880
                                        if ( retVal==LDAP_OPERATIONS_ERROR )
627
881
                                        {
628
882
                                                LDAPDebug( LDAP_DEBUG_ANY, "Possible existing duplicate "
629
 
                                                        "value for attribute type %s found in "
630
 
                                                        "entry %s\n", a->a_type, slapi_entry_get_dn_const(e), 0 );
 
883
                                                           "value for attribute type %s found in "
 
884
                                                           "entry %s\n", a->a_type, slapi_entry_get_dn_const(e), 0 );
631
885
                                        }
632
886
                                }
633
887
                                valuearray_free(&valuestodelete);
634
888
                        }
635
889
                }
636
 
        }
637
 
        else if (attr_state==ATTRIBUTE_DELETED)
638
 
        {
639
 
                /* If the type is in the forbidden attr list (e.g., unhashed password),
640
 
                 * we don't return the reason of the failure to the clients. */
641
 
#if defined(USE_OLD_UNHASHED)
642
 
                if (is_type_forbidden(type)) {
643
 
                        retVal = LDAP_SUCCESS;
644
 
                } else {
645
 
                        retVal= LDAP_NO_SUCH_ATTRIBUTE;
646
 
                }
647
 
#else
648
 
                retVal= LDAP_NO_SUCH_ATTRIBUTE;
649
 
#endif
650
 
        }
651
 
        else if (attr_state==ATTRIBUTE_NOTFOUND)
652
 
        {
653
 
                /*
654
 
                 * If type is in the protected_attrs_all list, we could ignore the
655
 
                 * failure, as the attribute could only exist in the entry in the 
656
 
                 * memory when the add/mod operation is done, while the retried entry 
657
 
                 * from the db does not contain the attribute.
658
 
                 * So is in the forbidden_attrs list.  We don't return the reason
659
 
                 * of the failure.
660
 
                 */
661
 
#if defined(USE_OLD_UNHASHED)
662
 
                if (is_type_protected(type) || is_type_forbidden(type))
663
 
#else
664
 
                if (is_type_protected(type))
665
 
#endif
666
 
                {
667
 
                        retVal = LDAP_SUCCESS;
668
 
                } else {
669
 
                        if (!urp) {
670
 
                                /* Only warn if not urping */
671
 
                                LDAPDebug1Arg(LDAP_DEBUG_ARGS, "could not find attribute %s\n",
672
 
                                              type);
673
 
                        }
674
 
                        retVal = LDAP_NO_SUCH_ATTRIBUTE;
675
 
                }
676
 
                /* NOTE: LDAP says that a MOD REPLACE with no vals of a non-existent
677
 
                   attribute is a no-op - MOD REPLACE with some vals will add the attribute */
678
 
                /* if we are doing a replace with actual values, meaning the result
679
 
                   of the mod is that the attribute will have some values, we need to create
680
 
                   a dummy attribute for entry_add_present_values_wsi to use, and set
681
 
                   the deletion csn to the csn of the current operation */
682
 
                /* note that if LDAP_MOD_REPLACE == mod_op then vals is NULL - 
683
 
                   see entry_replace_present_values_wsi */
684
 
                if ((LDAP_MOD_REPLACE == mod_op) && replacevals && replacevals[0])
685
 
                {
686
 
                        /* Create a new attribute and set the adcsn */
687
 
                        Slapi_Attr *a = slapi_attr_new();
688
 
                        slapi_attr_init(a, type);
689
 
                        attr_set_deletion_csn(a,csn); 
690
 
                        /* mark the attribute as deleted - it does not really
691
 
                           exist yet - the code in entry_add_present_values_wsi
692
 
                           will add it back to the present list in the non urp case,
693
 
                           or determine if the attribute needs to be added
694
 
                           or not in the urp case
695
 
                        */
696
 
                        entry_add_deleted_attribute_wsi(e, a);
697
 
                }
698
 
        }
699
890
        return( retVal );
700
891
}
701
892
 
718
909
         * slapi_entry_add_values() returns LDAP_SUCCESS and so the
719
910
         * attribute remains deleted (which is the correct outcome).
720
911
         */
721
 
        return( entry_add_present_values_wsi( e, type, vals, csn, urp, SLAPI_ATTR_FLAG_CMP_BITBYBIT ));
 
912
        return( entry_add_present_values_wsi( e, type, vals, csn, urp, 0));
722
913
}
723
914
 
724
915
/*
767
958
        for (aiep = attrs_in_extension; aiep && aiep->ext_type; aiep++) {
768
959
                if (0 == strcasecmp(mod->mod_type, aiep->ext_type)) {
769
960
                        Slapi_Attr *a;
770
 
                        int rc;
771
 
                        Slapi_Value **ext_vals = NULL;
772
 
                        rc = slapi_pw_get_entry_ext(e, &ext_vals);
773
 
                        if (rc) {
774
 
                                continue; /* skip it. */
775
 
                        }
776
961
 
 
962
                        /* remove the attribute from the attr list */
777
963
                        a = attrlist_remove(&e->e_attrs, mod->mod_type);
778
964
                        if (a && a->a_present_values.va) {
779
965
                                /* a->a_present_values.va is consumed if successful. */
780
 
                                rc = slapi_pw_set_entry_ext(e, a->a_present_values.va,
781
 
                                                            SLAPI_EXT_SET_REPLACE);
 
966
                                int rc = slapi_pw_set_entry_ext(e, a->a_present_values.va,
 
967
                                                                SLAPI_EXT_SET_REPLACE);
782
968
                                if (LDAP_SUCCESS == rc) {
783
969
                                        /* va is set to entry extension; just release the rest */
784
970
                                        a->a_present_values.va = NULL;
785
971
                                }
786
972
                                slapi_attr_free(&a);
787
973
                        } else {
 
974
                                Slapi_Value **ext_vals = NULL;
 
975
                                slapi_pw_get_entry_ext(e, &ext_vals);
788
976
                                if (ext_vals) {
789
977
                                        /* slapi_pw_set_entry_ext frees the stored extension */
790
 
                                        rc = slapi_pw_set_entry_ext(e, NULL, SLAPI_EXT_SET_REPLACE);
 
978
                                        slapi_pw_set_entry_ext(e, NULL, SLAPI_EXT_SET_REPLACE);
791
979
                                        ext_vals = NULL;
792
980
                                }
793
981
                        }
825
1013
                           and the csn doesn't already have a subsequence
826
1014
                           if the csn already has a subsequence, assume it was generated
827
1015
                           on another replica in the correct order */
828
 
                        if (urp && (csn_get_subseqnum(csn) == 0)) {
 
1016
                        if (csn_get_subseqnum(csn) == 0) {
829
1017
                                csn_increment_subsequence(&localcsn);
830
1018
                        }
831
1019
                }
1043
1231
        return r;
1044
1232
}
1045
1233
 
1046
 
static void
1047
 
resolve_attribute_state_multi_valued(Slapi_Entry *e, Slapi_Attr *a, int attribute_state, int delete_priority)
1048
 
{
1049
 
        int i;
1050
 
        const CSN *adcsn= attr_get_deletion_csn(a);
1051
 
        Slapi_ValueSet *vs= valueset_dup(&a->a_present_values); /* JCM This is slow... but otherwise we end up iterating through a changing array */
1052
 
        Slapi_Value *v;
1053
 
 
1054
 
        /* Loop over the present attribute values */
1055
 
        i= slapi_valueset_first_value( vs, &v );
1056
 
        while(v!=NULL)
1057
 
        {
1058
 
                const CSN *vdcsn;
1059
 
                const CSN *vucsn;
1060
 
                const CSN *deletedcsn;
1061
 
            /* This call ensures that the value does not contain a deletion_csn
1062
 
                 * which is before the presence_csn or distinguished_csn of the value.
1063
 
                 */ 
1064
 
            purge_attribute_state_multi_valued(a, v);
1065
 
                vdcsn= value_get_csn(v, CSN_TYPE_VALUE_DELETED);
1066
 
                vucsn= value_get_csn(v, CSN_TYPE_VALUE_UPDATED);
1067
 
                deletedcsn= csn_max(vdcsn, adcsn);
1068
 
 
1069
 
                /* Check if the attribute or value was deleted after the value was
1070
 
                 * last updated.  If the value update CSN and the deleted CSN are
1071
 
                 * the same (meaning they are separate mods from the same exact
1072
 
                 * operation), we should only delete the value if delete priority
1073
 
                 * is set.  Delete priority should only be set when we are deleting
1074
 
                 * all value of an attribute.  This prevents us from leaving a value
1075
 
                 * that was added as a previous mod in the same exact modify
1076
 
                 * operation as the subsequent delete.*/
1077
 
                if((csn_compare(vucsn,deletedcsn)<0) ||
1078
 
                        (delete_priority && (csn_compare(vucsn,deletedcsn) == 0)))
1079
 
                {
1080
 
                if(!value_distinguished_at_csn(e, a, v, deletedcsn))
1081
 
                        {
1082
 
                                entry_present_value_to_deleted_value(a,v);
1083
 
                        }
1084
 
                }
1085
 
                i= slapi_valueset_next_value( vs, i, &v );
1086
 
        }
1087
 
        slapi_valueset_free(vs);
1088
 
 
1089
 
        /* Loop over the deleted attribute values */
1090
 
        vs= valueset_dup(&a->a_deleted_values); /* JCM This is slow... but otherwise we end up iterating through a changing array */
1091
 
        i= slapi_valueset_first_value( vs, &v );
1092
 
        while(v!=NULL)
1093
 
        {
1094
 
                const CSN *vdcsn;
1095
 
                const CSN *vucsn;
1096
 
                const CSN *deletedcsn;
1097
 
            /* This call ensures that the value does not contain a deletion_csn which is before the presence_csn or distinguished_csn of the value. */ 
1098
 
            purge_attribute_state_multi_valued(a, v);
1099
 
                vdcsn= value_get_csn(v, CSN_TYPE_VALUE_DELETED);
1100
 
                vucsn= value_get_csn(v, CSN_TYPE_VALUE_UPDATED);
1101
 
                deletedcsn= csn_max(vdcsn, adcsn);
1102
 
 
1103
 
                /* check if the attribute or value was deleted after the value was last updated */
1104
 
                /* When a replace operation happens, the entry_replace_present_values_wsi() function
1105
 
                 * first calls entry_delete_present_values_wsi with vals == NULL to essentially delete
1106
 
                 * the attribute and set the deletion csn.  If the urp flag is set (urp in this case
1107
 
                 * meaning the operation is a replicated op), entry_delete_present_values_wsi will
1108
 
                 * call this function which will move the present values to the deleted values
1109
 
                 * (see above - delete_priority will be 1) then the below code will move the
1110
 
                 * attribute to the deleted list.
1111
 
                 * next, entry_replace_present_values_wsi will call entry_add_present_values_wsi
1112
 
                 * to add the values provided in the replace operation.  We need to be able to
1113
 
                 * "resurrect" these deleted values and resurrect the deleted attribute.  In the
1114
 
                 * replace case, the deletedcsn will be the same as the vucsn of the values that
1115
 
                 * should be present values.
1116
 
                 */
1117
 
                if((csn_compare(vucsn,deletedcsn)>0) ||
1118
 
                   ((delete_priority == 0) && (csn_compare(vucsn,deletedcsn)==0)) ||
1119
 
                value_distinguished_at_csn(e, a, v, deletedcsn))
1120
 
                {
1121
 
                        entry_deleted_value_to_present_value(a,v);
1122
 
                }
1123
 
                i= slapi_valueset_next_value( vs, i, &v );
1124
 
        }
1125
 
        slapi_valueset_free(vs);
1126
 
 
 
1234
/* This call ensures that the value does not contain a deletion_csn which is before the presence_csn or distinguished_csn of the value. */ 
 
1235
static void
 
1236
resolve_attribute_state_deleted_to_present(Slapi_Entry *e, Slapi_Attr *a, Slapi_Value **valuestoupdate)
 
1237
{
 
1238
        const CSN *vdcsn;
 
1239
        const CSN *vucsn;
 
1240
        const CSN *deletedcsn;
 
1241
        const CSN *adcsn= attr_get_deletion_csn(a);
 
1242
        int i;
 
1243
        if ( valuestoupdate != NULL && valuestoupdate[0] != NULL ) {
 
1244
                for (i=0;valuestoupdate[i]!=NULL;++i) {
 
1245
                        purge_attribute_state_multi_valued(a, valuestoupdate[i]);
 
1246
                        vdcsn= value_get_csn(valuestoupdate[i], CSN_TYPE_VALUE_DELETED);
 
1247
                        vucsn= value_get_csn(valuestoupdate[i], CSN_TYPE_VALUE_UPDATED);
 
1248
                        deletedcsn= csn_max(vdcsn, adcsn);
 
1249
                        if((csn_compare(vucsn,deletedcsn)>=0) ||
 
1250
                                value_distinguished_at_csn(e, a, valuestoupdate[i], deletedcsn))
 
1251
                        {
 
1252
                                entry_deleted_value_to_present_value(a,valuestoupdate[i]);
 
1253
                        }
 
1254
                        valuestoupdate[i]->v_csnset = NULL;
 
1255
                }
 
1256
        }
 
1257
}
 
1258
 
 
1259
static void
 
1260
resolve_attribute_state_to_present_or_deleted(Slapi_Entry *e, Slapi_Attr *a, Slapi_Value **valuestoupdate, int attribute_state)
 
1261
{
 
1262
        const CSN *vdcsn;
 
1263
        const CSN *vucsn;
 
1264
        const CSN *deletedcsn;
 
1265
        const CSN *adcsn= attr_get_deletion_csn(a);
 
1266
        int i;
 
1267
        if ( valuestoupdate != NULL && valuestoupdate[0] != NULL ) {
 
1268
                for (i=0;valuestoupdate[i]!=NULL;++i) {
 
1269
                        purge_attribute_state_multi_valued(a, valuestoupdate[i]);
 
1270
                        vdcsn= value_get_csn(valuestoupdate[i], CSN_TYPE_VALUE_DELETED);
 
1271
                        vucsn= value_get_csn(valuestoupdate[i], CSN_TYPE_VALUE_UPDATED);
 
1272
                        deletedcsn= csn_max(vdcsn, adcsn);
 
1273
                        if((csn_compare(vucsn,deletedcsn)>=0) ||
 
1274
                                value_distinguished_at_csn(e, a, valuestoupdate[i], deletedcsn))
 
1275
                        {
 
1276
                                slapi_valueset_add_value_ext(&a->a_present_values, valuestoupdate[i], SLAPI_VALUE_FLAG_PASSIN);
 
1277
                        } else {
 
1278
                                slapi_valueset_add_value_ext(&a->a_deleted_values, valuestoupdate[i], SLAPI_VALUE_FLAG_PASSIN);
 
1279
                        }
 
1280
                }
 
1281
        }
1127
1282
        if(valueset_isempty(&a->a_present_values))
1128
1283
        {
1129
1284
                if(attribute_state==ATTRIBUTE_PRESENT)
1141
1296
}
1142
1297
 
1143
1298
static void
 
1299
resolve_attribute_state_present_to_deleted(Slapi_Entry *e, Slapi_Attr *a, Slapi_Value **valuestoupdate)
 
1300
{
 
1301
        const CSN *vdcsn;
 
1302
        const CSN *vucsn;
 
1303
        const CSN *deletedcsn;
 
1304
        const CSN *adcsn= attr_get_deletion_csn(a);
 
1305
        int i;
 
1306
        if ( valuestoupdate != NULL && valuestoupdate[0] != NULL ) {
 
1307
        for (i=0;valuestoupdate[i]!=NULL;++i) {
 
1308
        /* This call ensures that the value does not contain a deletion_csn
 
1309
         * which is before the presence_csn or distinguished_csn of the value.
 
1310
         */ 
 
1311
            purge_attribute_state_multi_valued(a, valuestoupdate[i]);
 
1312
                vdcsn= value_get_csn(valuestoupdate[i], CSN_TYPE_VALUE_DELETED);
 
1313
                vucsn= value_get_csn(valuestoupdate[i], CSN_TYPE_VALUE_UPDATED);
 
1314
                deletedcsn= csn_max(vdcsn, adcsn);
 
1315
                        if(csn_compare(vucsn,deletedcsn)<0) 
 
1316
                        {
 
1317
                                if(!value_distinguished_at_csn(e, a, valuestoupdate[i], deletedcsn))
 
1318
                                {
 
1319
                                        entry_present_value_to_deleted_value(a,valuestoupdate[i]);
 
1320
                                }
 
1321
                        }
 
1322
                valuestoupdate[i]->v_csnset = NULL;
 
1323
        }
 
1324
        }
 
1325
}
 
1326
 
 
1327
static void
1144
1328
resolve_attribute_state_single_valued(Slapi_Entry *e, Slapi_Attr *a, int attribute_state)
1145
1329
{
1146
1330
        Slapi_Value *current_value= NULL;
1148
1332
        Slapi_Value *new_value= NULL;
1149
1333
        const CSN *current_value_vucsn;
1150
1334
        const CSN *pending_value_vucsn;
 
1335
        const CSN *pending_value_vdcsn;
1151
1336
        const CSN *adcsn;
1152
1337
        int i;
1153
1338
 
1161
1346
                slapi_attr_next_value(a,i,&new_value);
1162
1347
        }
1163
1348
        attr_first_deleted_value(a,&pending_value);
1164
 
 
1165
1349
        /* purge_attribute_state_single_valued */
1166
1350
        adcsn= attr_get_deletion_csn(a);
1167
1351
        current_value_vucsn= value_get_csn(current_value, CSN_TYPE_VALUE_UPDATED);
1168
1352
        pending_value_vucsn= value_get_csn(pending_value, CSN_TYPE_VALUE_UPDATED);
1169
 
    if((pending_value!=NULL && (csn_compare(adcsn, pending_value_vucsn)<0)) || 
1170
 
        (pending_value==NULL && (csn_compare(adcsn, current_value_vucsn)<0)))
 
1353
        pending_value_vdcsn= value_get_csn(pending_value, CSN_TYPE_VALUE_DELETED);
 
1354
        if((pending_value!=NULL && (csn_compare(adcsn, pending_value_vucsn)<0)) ||
 
1355
           (pending_value==NULL && (csn_compare(adcsn, current_value_vucsn)<0)))
1171
1356
        {
1172
1357
                attr_set_deletion_csn(a,NULL);
1173
1358
                adcsn= NULL;
1174
 
    }
 
1359
        }
1175
1360
 
1176
 
        if(new_value==NULL)
1177
 
        {
1178
 
        /* check if the pending value should become the current value */ 
1179
 
        if(pending_value!=NULL)
 
1361
        /* in the case of the following:
 
1362
         * add: value2
 
1363
         * delete: value1
 
1364
         * we will have current_value with VUCSN CSN1
 
1365
         * and pending_value with VDCSN CSN2
 
1366
         * and new_value == NULL
 
1367
         * current_value != pending_value
 
1368
         * and
 
1369
         * VUCSN == VDCSN (ignoring subseq)
 
1370
         * even though value1.VDCSN > value2.VUCSN
 
1371
         * value2 should still win because the value is _different_
 
1372
         */
 
1373
        if (current_value && pending_value && !new_value && !adcsn &&
 
1374
            (0 != slapi_value_compare(a, current_value, pending_value)) &&
 
1375
            (0 == csn_compare_ext(current_value_vucsn, pending_value_vdcsn, CSN_COMPARE_SKIP_SUBSEQ)))
 
1376
        {
 
1377
                /* just remove the deleted value */
 
1378
                entry_deleted_value_to_zapped_value(a,pending_value);
 
1379
                pending_value = NULL;
 
1380
        }
 
1381
        else if(new_value==NULL)
 
1382
        {
 
1383
                /* check if the pending value should become the current value */
 
1384
                if(pending_value!=NULL)
1180
1385
                {
1181
1386
                        if(!value_distinguished_at_csn(e,a,current_value,pending_value_vucsn))
1182
1387
                        {
1183
 
                    /* attribute.current_value = attribute.pending_value; */
1184
 
                    /* attribute.pending_value = NULL; */
 
1388
                                /* attribute.current_value = attribute.pending_value; */
 
1389
                                /* attribute.pending_value = NULL; */
1185
1390
                                entry_present_value_to_zapped_value(a,current_value);
1186
1391
                                entry_deleted_value_to_present_value(a,pending_value);
1187
1392
                                current_value= pending_value;
1190
1395
                                pending_value_vucsn= NULL;
1191
1396
                        }
1192
1397
                }
1193
 
        /* check if the current value should be deleted */ 
1194
 
        if(current_value!=NULL)
 
1398
                /* check if the current value should be deleted */
 
1399
                if(current_value!=NULL)
1195
1400
                {
1196
1401
                        if(csn_compare(adcsn,current_value_vucsn)>0) /* check if the attribute was deleted after the value was last updated */
1197
1402
                        {
1198
 
                    if(!value_distinguished_at_csn(e,a,current_value,current_value_vucsn))
 
1403
                                if(!value_distinguished_at_csn(e,a,current_value,current_value_vucsn))
1199
1404
                                {
1200
1405
                                        entry_present_value_to_zapped_value(a,current_value);
1201
1406
                                        current_value= NULL;
1207
1412
        else /* addition of a new value */ 
1208
1413
        {
1209
1414
                const CSN *new_value_vucsn= value_get_csn(new_value,CSN_TYPE_VALUE_UPDATED);
1210
 
        if(csn_compare(new_value_vucsn,current_value_vucsn)<0)
 
1415
                if(csn_compare(new_value_vucsn,current_value_vucsn)<0)
1211
1416
                {
1212
 
            /*
1213
 
             * if the new value was distinguished at the time the current value was added 
1214
 
             * then the new value should become current
1215
 
             */ 
1216
 
            if(value_distinguished_at_csn(e,a,new_value,current_value_vucsn))
 
1417
                        /*
 
1418
                         * if the new value was distinguished at the time the current value was added
 
1419
                         * then the new value should become current
 
1420
                         */
 
1421
                        if(value_distinguished_at_csn(e,a,new_value,current_value_vucsn))
1217
1422
                        {
1218
 
                /* attribute.pending_value = attribute.current_value  */
1219
 
                /* attribute.current_value = new_value  */
1220
 
                if(pending_value==NULL)
 
1423
                                /* attribute.pending_value = attribute.current_value  */
 
1424
                                /* attribute.current_value = new_value  */
 
1425
                                if(pending_value==NULL)
1221
1426
                                {
1222
1427
                                        entry_present_value_to_deleted_value(a,current_value);
1223
1428
                                }
1233
1438
                        }
1234
1439
                        else
1235
1440
                        {
1236
 
                /* new_value= NULL */
 
1441
                                /* new_value= NULL */
1237
1442
                                entry_present_value_to_zapped_value(a, new_value);
1238
1443
                                new_value= NULL;
1239
1444
                        }
1240
1445
                }
1241
 
        else    /* new value is after the current value */ 
 
1446
                else    /* new value is after the current value */
1242
1447
                {
1243
 
            if(!value_distinguished_at_csn(e, a, current_value, new_value_vucsn))
 
1448
                        if(!value_distinguished_at_csn(e, a, current_value, new_value_vucsn))
1244
1449
                        {
1245
 
                /* attribute.current_value = new_value */
 
1450
                                /* attribute.current_value = new_value */
1246
1451
                                entry_present_value_to_zapped_value(a, current_value);
1247
1452
                                current_value= new_value;
1248
1453
                                new_value= NULL;
1249
1454
                                current_value_vucsn= new_value_vucsn;
1250
1455
                        }
1251
 
            else /* value is distinguished - check if we should replace the current pending value */ 
 
1456
                        else /* value is distinguished - check if we should replace the current pending value */
1252
1457
                        {
1253
 
                if(csn_compare(new_value_vucsn, pending_value_vucsn)>0)
 
1458
                                if(csn_compare(new_value_vucsn, pending_value_vucsn)>0)
1254
1459
                                {
1255
 
                    /* attribute.pending_value = new_value */
 
1460
                                        /* attribute.pending_value = new_value */
1256
1461
                                        entry_deleted_value_to_zapped_value(a,pending_value);
1257
1462
                                        entry_present_value_to_deleted_value(a,new_value);
1258
1463
                                        pending_value= new_value;
1259
1464
                                        new_value= NULL;
1260
1465
                                        pending_value_vucsn= new_value_vucsn;
1261
 
                } 
1262
 
            } 
1263
 
        } 
1264
 
    } 
 
1466
                                }
 
1467
                        }
 
1468
                }
 
1469
        }
1265
1470
 
1266
 
    /*
1267
 
     * This call ensures that the attribute does not have a pending_value
 
1471
        /*
 
1472
         * This call ensures that the attribute does not have a pending_value
1268
1473
         * or a deletion_csn that is earlier than the current_value.
1269
1474
         */ 
1270
1475
        /* purge_attribute_state_single_valued */
1271
 
    if((pending_value!=NULL && (csn_compare(adcsn, pending_value_vucsn)<0)) || 
1272
 
        (pending_value==NULL && (csn_compare(adcsn, current_value_vucsn)<0)))
 
1476
        if((pending_value!=NULL && (csn_compare(adcsn, pending_value_vucsn)<0)) ||
 
1477
           (pending_value==NULL && (csn_compare(adcsn, current_value_vucsn)<0)))
1273
1478
        {
1274
1479
                attr_set_deletion_csn(a,NULL);
1275
1480
                adcsn= NULL;
1276
 
    } 
 
1481
        }
1277
1482
 
1278
 
    /* set attribute state */ 
1279
 
    if(current_value==NULL)
 
1483
        /* set attribute state */
 
1484
        if(current_value==NULL)
1280
1485
        {
1281
1486
                if(attribute_state==ATTRIBUTE_PRESENT)
1282
1487
                {
1283
1488
                        entry_present_attribute_to_deleted_attribute(e, a);
1284
1489
                }
1285
1490
        }
1286
 
    else 
 
1491
        else
1287
1492
        {
1288
1493
                if(attribute_state==ATTRIBUTE_DELETED)
1289
1494
                {
1290
1495
                        entry_deleted_attribute_to_present_attribute(e, a);
1291
1496
                }
1292
 
    }
 
1497
        }
1293
1498
}
1294
1499
 
1295
 
static void
1296
 
resolve_attribute_state(Slapi_Entry *e, Slapi_Attr *a, int attribute_state, int delete_priority)
1297
 
{
1298
 
        if(slapi_attr_flag_is_set(a,SLAPI_ATTR_FLAG_SINGLE))
1299
 
        {
1300
 
                resolve_attribute_state_single_valued(e,a,attribute_state);
1301
 
        }
1302
 
        else
1303
 
        {
1304
 
                resolve_attribute_state_multi_valued(e,a,attribute_state, delete_priority);
1305
 
        }
1306
 
}