encode_read_entry(Slapi_PBlock *pb, Slapi_Entry *e, char **attrs, int alluserattrs, int attr_count)
{
    Slapi_Operation *op = NULL;
    Connection *conn = NULL;
    LDAPControl **ctrlp = NULL;
    struct berval *bv = NULL;
    BerElement *ber = NULL;
    int real_attrs_only = 0;
    int rc = 0;

    if ((ber = der_alloc()) == NULL) {
        rc = -1;
        goto cleanup;
    }

    slapi_pblock_get(pb, SLAPI_OPERATION, &op);
    slapi_pblock_get(pb, SLAPI_CONNECTION, &conn);

    if (conn == NULL || op == NULL) {
        slapi_log_err(SLAPI_LOG_ERR, "encode_read_entry",
                      "NULL param error: conn (0x%p) op (0x%p)\n", conn, op);
        rc = -1;
        goto cleanup;
    }

    /* Start the ber encoding with the DN */
    rc = ber_printf(ber, "t{s{", LDAP_RES_SEARCH_ENTRY, slapi_entry_get_dn_const(e));
    if (rc == -1) {
        rc = -1;
        goto cleanup;
    }

    /* determine whether we are to return virtual attributes */
    slapi_pblock_get(pb, SLAPI_REQCONTROLS, &ctrlp);
    if (slapi_control_present(ctrlp, LDAP_CONTROL_REAL_ATTRS_ONLY, NULL, NULL)) {
        real_attrs_only = SLAPI_SEND_VATTR_FLAG_REALONLY;
    }
    if (slapi_control_present(ctrlp, LDAP_CONTROL_VIRT_ATTRS_ONLY, NULL, NULL)) {
        if (real_attrs_only != SLAPI_SEND_VATTR_FLAG_REALONLY) {
            real_attrs_only = SLAPI_SEND_VATTR_FLAG_VIRTUALONLY;
        } else {
            /* we cannot service a request for virtual only and real only */
            slapi_log_err(SLAPI_LOG_ERR, "encode_read_entry",
                          "Both real and virtual attributes only controls requested.\n");
            rc = -1;
            goto cleanup;
        }
    }

    /*
     * We maintain a flag array so that we can remove requests
     * for duplicate attributes.  We also need to set o_searchattrs
     * for the attribute processing, as modify op's don't have search attrs.
     */
    op->o_searchattrs = attrs;

    /* Send all the attributes */
    if (alluserattrs) {
        rc = send_all_attrs(e, attrs, op, pb, ber, 0, conn->c_ldapversion,
                            real_attrs_only, attr_count, 0, 1);
        if (rc) {
            goto cleanup;
        }
    }

    /* Send a specified list of attributes */
    if (attrs != NULL) {
        rc = send_specific_attrs(e, attrs, op, pb, ber, 0, conn->c_ldapversion, real_attrs_only);
        if (rc) {
            goto cleanup;
        }
    }

    /* wrap up the ber encoding */
    rc = ber_printf(ber, "}}");
    if (rc != -1) {
        /* generate our string encoded value */
        rc = ber_flatten(ber, &bv);
    }

cleanup:

    ber_free(ber, 1);
    if (rc != 0) {
        return NULL;
    } else {
        return bv;
    }
}
encode_read_entry(Slapi_PBlock *pb, Slapi_Entry *e, char **attrs, int alluserattrs, int attr_count)
{
    Slapi_Operation *op = NULL;
    Connection *conn = NULL;
    LDAPControl **ctrlp = NULL;
    struct berval *bv = NULL;
    BerElement *ber = NULL;
    int real_attrs_only = 0;
    int rc = 0;

    if ((ber = der_alloc()) == NULL) {
        rc = -1;
        goto cleanup;
    }

    slapi_pblock_get(pb, SLAPI_OPERATION, &op);
    slapi_pblock_get(pb, SLAPI_CONNECTION, &conn);

    if (conn == NULL || op == NULL) {
        slapi_log_err(SLAPI_LOG_ERR, "encode_read_entry",
                      "NULL param error: conn (0x%p) op (0x%p)\n", conn, op);
        rc = -1;
        goto cleanup;
    }

     
    rc = ber_printf(ber, "t{s{", LDAP_RES_SEARCH_ENTRY, slapi_entry_get_dn_const(e));
    if (rc == -1) {
        rc = -1;
        goto cleanup;
    }

     
    slapi_pblock_get(pb, SLAPI_REQCONTROLS, &ctrlp);
    if (slapi_control_present(ctrlp, LDAP_CONTROL_REAL_ATTRS_ONLY, NULL, NULL)) {
        real_attrs_only = SLAPI_SEND_VATTR_FLAG_REALONLY;
    }
    if (slapi_control_present(ctrlp, LDAP_CONTROL_VIRT_ATTRS_ONLY, NULL, NULL)) {
        if (real_attrs_only != SLAPI_SEND_VATTR_FLAG_REALONLY) {
            real_attrs_only = SLAPI_SEND_VATTR_FLAG_VIRTUALONLY;
        } else {
             
            slapi_log_err(SLAPI_LOG_ERR, "encode_read_entry",
                          "Both real and virtual attributes only controls requested.\n");
            rc = -1;
            goto cleanup;
        }
    }

     
    op->o_searchattrs = attrs;

     
    if (alluserattrs) {
        rc = send_all_attrs(e, attrs, op, pb, ber, 0, conn->c_ldapversion,
                            real_attrs_only, attr_count, 0, 1);
        if (rc) {
            goto cleanup;
        }
    }

     
    if (attrs != NULL) {
        rc = send_specific_attrs(e, attrs, op, pb, ber, 0, conn->c_ldapversion, real_attrs_only);
        if (rc) {
            goto cleanup;
        }
    }

     
    rc = ber_printf(ber, "}}");
    if (rc != -1) {
         
        rc = ber_flatten(ber, &bv);
    }

cleanup:

    ber_free(ber, 1);
    if (rc != 0) {
        return NULL;
    } else {
        return bv;
    }
}