send_all_attrs(Slapi_Entry *e, char **attrs, Slapi_Operation *op, Slapi_PBlock *pb, BerElement *ber, int attrsonly, int ldapversion, int real_attrs_only, int some_named_attrs, int alloperationalattrs, int alluserattrs)
{
    int i = 0;
    int rc = 0;

    int typelist_flags = 0;
    vattr_type_thang *typelist = NULL;
    vattr_type_thang *current_type = NULL;
    char *current_type_name = NULL;
    int rewrite_rfc1274 = 0;
    int vattr_flags = 0;
    const char *dn = NULL;
    char **default_attrs = NULL;

    if (real_attrs_only == SLAPI_SEND_VATTR_FLAG_REALONLY)
        vattr_flags = SLAPI_REALATTRS_ONLY;
    else {
        vattr_flags = SLAPI_VIRTUALATTRS_REQUEST_POINTERS;
        if (real_attrs_only == SLAPI_SEND_VATTR_FLAG_VIRTUALONLY)
            vattr_flags |= SLAPI_VIRTUALATTRS_ONLY;
    }

    if (some_named_attrs || alloperationalattrs) {
        /*
         * If the client listed some attribute types by name, one or
         * more of the requested types MAY be operational.  Inform the
         * virtual attributes subsystem (certain optimizations are done
         * by the vattrs code and vattr service providers if operational
         * attributes are NOT requested).
         */
        vattr_flags |= SLAPI_VIRTUALATTRS_LIST_OPERATIONAL_ATTRS;
    }

    rc = slapi_vattr_list_attrs(e, &typelist, vattr_flags, &typelist_flags);
    if (0 != rc) {
        goto exit;
    }

    if (typelist_flags & SLAPI_VIRTUALATTRS_REALATTRS_ONLY) {
        /*
         * There is no point in consulting the vattr service providers
                 * for every attr if they didn't contribute to the attr list.
         */
        vattr_flags |= SLAPI_REALATTRS_ONLY;
    }

    rewrite_rfc1274 = config_get_rewrite_rfc1274();

    dn = slapi_entry_get_dn_const(e);
    if (dn == NULL || *dn == '\0') {
        default_attrs = slapi_entry_attr_get_charray(e, CONFIG_RETURN_DEFAULT_OPATTR);
    }
    /* Send the attrs back to the client */
    for (current_type = vattr_typethang_first(typelist); current_type; current_type = vattr_typethang_next(current_type)) {

        Slapi_ValueSet **values = NULL;
        int attr_free_flags = 0;
        unsigned long current_type_flags = 0;
        int sendit = 0;
        char *name_to_return = NULL;
        int *type_name_disposition = 0;
        char **actual_type_name = NULL;
        const char *v2name = NULL;

        current_type_name = vattr_typethang_get_name(current_type);
        current_type_flags = vattr_typethang_get_flags(current_type);

        name_to_return = current_type_name;
        /* We only return operational attributes if the client is LDAPv2 and the attribute is one of a special set,
           OR if all operational attrs are requested, OR if the client also requested the attribute by name.
           If it did, we use the specified name rather than the base name.
         */
        if (current_type_flags & SLAPI_ATTR_FLAG_OPATTR) {
            if ((LDAP_VERSION2 == ldapversion && LASTMODATTR(current_type_name)) || alloperationalattrs) {
                sendit = 1;
            } else {
                for (i = 0; attrs != NULL && attrs[i] != NULL; i++) {
                    if (slapi_attr_type_cmp(attrs[i], current_type_name, SLAPI_TYPE_CMP_SUBTYPE) == 0) {
                        sendit = 1;
                        name_to_return = op->o_searchattrs[i];
                        break;
                    }
                }
                if (!sendit && default_attrs) {
                    for (i = 0; default_attrs != NULL && default_attrs[i] != NULL; i++) {
                        if (slapi_attr_type_cmp(default_attrs[i], current_type_name, SLAPI_TYPE_CMP_SUBTYPE) == 0) {
                            sendit = 1;
                            break;
                        }
                    }
                }
            }
            /*
         * it's a user attribute. send it.
         */
        } else if (alluserattrs) {
            sendit = 1;
        }
        /* Now send to the client */
        if (sendit) {
            /**********************************************/
            int item_count = 0;
            int iter = 0;
            Slapi_DN *namespace_dn;
            Slapi_Backend *be = 0;
            vattr_context *ctx;

            /* get the namespace dn */
            slapi_pblock_get(pb, SLAPI_BACKEND, (void *)&be);
            namespace_dn = (Slapi_DN *)slapi_be_getsuffix(be, 0);

            /* Get the attribute value from the vattr service */
            /* ctx will be freed by attr_context_ungrok() */
            ctx = vattr_context_new(pb);
            rc = slapi_vattr_namespace_values_get_sp(
                ctx,
                e,
                namespace_dn,
                current_type_name,
                &values,
                &type_name_disposition,
                &actual_type_name,
                vattr_flags | SLAPI_VIRTUALATTRS_SUPPRESS_SUBTYPES,
                &attr_free_flags,
                &item_count);
            if ((0 == rc) && (item_count > 0)) {

                for (iter = 0; iter < item_count; iter++) {
                    int skipit;
                    if (rc != 0) {
                        /* we hit an error - we need to free all of the stuff allocated by
                           slapi_vattr_namespace_values_get_sp */
                        slapi_vattr_values_free(&(values[iter]), &(actual_type_name[iter]), attr_free_flags);
                        continue;
                    }

                    if (SLAPI_VIRTUALATTRS_TYPE_NAME_MATCHED_SUBTYPE == type_name_disposition[iter]) {
                        name_to_return = actual_type_name[iter];
                    }

                    /* If current_type_name is in attrs, we could rely on send_specific_attrs. */
                    skipit = 0;
                    for (i = 0; attrs && attrs[i]; i++) {
                        if (slapi_attr_type_cmp(current_type_name, attrs[i], SLAPI_TYPE_CMP_SUBTYPE) == 0) {
                            skipit = 1;
                            break;
                        }
                    }

                    if (!skipit) {
                        rc = encode_attr_2(pb, ber, e, values[iter], attrsonly,
                                           current_type_name, name_to_return);

                        if (rewrite_rfc1274 != 0) {
                            v2name = idds_map_attrt_v3(current_type_name);
                            if (v2name != NULL) {
                                /* also return values with RFC1274 attr name */
                                rc = encode_attr_2(pb, ber, e, values[iter],
                                                   attrsonly,
                                                   current_type_name,
                                                   v2name);
                            }
                        }
                    }

                    slapi_vattr_values_free(&(values[iter]), &(actual_type_name[iter]), attr_free_flags);
                }

                slapi_ch_free((void **)&actual_type_name);
                slapi_ch_free((void **)&type_name_disposition);
                slapi_ch_free((void **)&values);
                if (rc != 0) {
                    goto exit;
                }

            } else {
                /* if we got here, then either values is NULL or values contains no elements
                   either way we can free it */
                slapi_ch_free((void **)&values);
                slapi_ch_free((void **)&actual_type_name);
                slapi_ch_free((void **)&type_name_disposition);
                rc = 0;
            }
        }
    }
exit:
    if (NULL != typelist) {
        slapi_vattr_attrs_free(&typelist, typelist_flags);
    }
    if (NULL != default_attrs) {
        slapi_ch_free((void **)&default_attrs);
    }
    return rc;
}
send_all_attrs(Slapi_Entry *e, char **attrs, Slapi_Operation *op, Slapi_PBlock *pb, BerElement *ber, int attrsonly, int ldapversion, int real_attrs_only, int some_named_attrs, int alloperationalattrs, int alluserattrs)
{
    int i = 0;
    int rc = 0;

    int typelist_flags = 0;
    vattr_type_thang *typelist = NULL;
    vattr_type_thang *current_type = NULL;
    char *current_type_name = NULL;
    int rewrite_rfc1274 = 0;
    int vattr_flags = 0;
    const char *dn = NULL;
    char **default_attrs = NULL;

    if (real_attrs_only == SLAPI_SEND_VATTR_FLAG_REALONLY)
        vattr_flags = SLAPI_REALATTRS_ONLY;
    else {
        vattr_flags = SLAPI_VIRTUALATTRS_REQUEST_POINTERS;
        if (real_attrs_only == SLAPI_SEND_VATTR_FLAG_VIRTUALONLY)
            vattr_flags |= SLAPI_VIRTUALATTRS_ONLY;
    }

    if (some_named_attrs || alloperationalattrs) {
         
        vattr_flags |= SLAPI_VIRTUALATTRS_LIST_OPERATIONAL_ATTRS;
    }

    rc = slapi_vattr_list_attrs(e, &typelist, vattr_flags, &typelist_flags);
    if (0 != rc) {
        goto exit;
    }

    if (typelist_flags & SLAPI_VIRTUALATTRS_REALATTRS_ONLY) {
         
        vattr_flags |= SLAPI_REALATTRS_ONLY;
    }

    rewrite_rfc1274 = config_get_rewrite_rfc1274();

    dn = slapi_entry_get_dn_const(e);
    if (dn == NULL || *dn == '\0') {
        default_attrs = slapi_entry_attr_get_charray(e, CONFIG_RETURN_DEFAULT_OPATTR);
    }
     
    for (current_type = vattr_typethang_first(typelist); current_type; current_type = vattr_typethang_next(current_type)) {

        Slapi_ValueSet **values = NULL;
        int attr_free_flags = 0;
        unsigned long current_type_flags = 0;
        int sendit = 0;
        char *name_to_return = NULL;
        int *type_name_disposition = 0;
        char **actual_type_name = NULL;
        const char *v2name = NULL;

        current_type_name = vattr_typethang_get_name(current_type);
        current_type_flags = vattr_typethang_get_flags(current_type);

        name_to_return = current_type_name;
         
        if (current_type_flags & SLAPI_ATTR_FLAG_OPATTR) {
            if ((LDAP_VERSION2 == ldapversion && LASTMODATTR(current_type_name)) || alloperationalattrs) {
                sendit = 1;
            } else {
                for (i = 0; attrs != NULL && attrs[i] != NULL; i++) {
                    if (slapi_attr_type_cmp(attrs[i], current_type_name, SLAPI_TYPE_CMP_SUBTYPE) == 0) {
                        sendit = 1;
                        name_to_return = op->o_searchattrs[i];
                        break;
                    }
                }
                if (!sendit && default_attrs) {
                    for (i = 0; default_attrs != NULL && default_attrs[i] != NULL; i++) {
                        if (slapi_attr_type_cmp(default_attrs[i], current_type_name, SLAPI_TYPE_CMP_SUBTYPE) == 0) {
                            sendit = 1;
                            break;
                        }
                    }
                }
            }
             
        } else if (alluserattrs) {
            sendit = 1;
        }
         
        if (sendit) {
             
            int item_count = 0;
            int iter = 0;
            Slapi_DN *namespace_dn;
            Slapi_Backend *be = 0;
            vattr_context *ctx;

             
            slapi_pblock_get(pb, SLAPI_BACKEND, (void *)&be);
            namespace_dn = (Slapi_DN *)slapi_be_getsuffix(be, 0);

             
             
            ctx = vattr_context_new(pb);
            rc = slapi_vattr_namespace_values_get_sp(
                ctx,
                e,
                namespace_dn,
                current_type_name,
                &values,
                &type_name_disposition,
                &actual_type_name,
                vattr_flags | SLAPI_VIRTUALATTRS_SUPPRESS_SUBTYPES,
                &attr_free_flags,
                &item_count);
            if ((0 == rc) && (item_count > 0)) {

                for (iter = 0; iter < item_count; iter++) {
                    int skipit;
                    if (rc != 0) {
                         
                        slapi_vattr_values_free(&(values[iter]), &(actual_type_name[iter]), attr_free_flags);
                        continue;
                    }

                    if (SLAPI_VIRTUALATTRS_TYPE_NAME_MATCHED_SUBTYPE == type_name_disposition[iter]) {
                        name_to_return = actual_type_name[iter];
                    }

                     
                    skipit = 0;
                    for (i = 0; attrs && attrs[i]; i++) {
                        if (slapi_attr_type_cmp(current_type_name, attrs[i], SLAPI_TYPE_CMP_SUBTYPE) == 0) {
                            skipit = 1;
                            break;
                        }
                    }

                    if (!skipit) {
                        rc = encode_attr_2(pb, ber, e, values[iter], attrsonly,
                                           current_type_name, name_to_return);

                        if (rewrite_rfc1274 != 0) {
                            v2name = idds_map_attrt_v3(current_type_name);
                            if (v2name != NULL) {
                                 
                                rc = encode_attr_2(pb, ber, e, values[iter],
                                                   attrsonly,
                                                   current_type_name,
                                                   v2name);
                            }
                        }
                    }

                    slapi_vattr_values_free(&(values[iter]), &(actual_type_name[iter]), attr_free_flags);
                }

                slapi_ch_free((void **)&actual_type_name);
                slapi_ch_free((void **)&type_name_disposition);
                slapi_ch_free((void **)&values);
                if (rc != 0) {
                    goto exit;
                }

            } else {
                 
                slapi_ch_free((void **)&values);
                slapi_ch_free((void **)&actual_type_name);
                slapi_ch_free((void **)&type_name_disposition);
                rc = 0;
            }
        }
    }
exit:
    if (NULL != typelist) {
        slapi_vattr_attrs_free(&typelist, typelist_flags);
    }
    if (NULL != default_attrs) {
        slapi_ch_free((void **)&default_attrs);
    }
    return rc;
}