summaryrefslogtreecommitdiffstats
path: root/ldap/servers/slapd/rdn.c
diff options
context:
space:
mode:
Diffstat (limited to 'ldap/servers/slapd/rdn.c')
-rw-r--r--ldap/servers/slapd/rdn.c574
1 files changed, 563 insertions, 11 deletions
diff --git a/ldap/servers/slapd/rdn.c b/ldap/servers/slapd/rdn.c
index 97b0719f..1ef2b836 100644
--- a/ldap/servers/slapd/rdn.c
+++ b/ldap/servers/slapd/rdn.c
@@ -43,8 +43,6 @@
#include "slap.h"
-#define FLAG_RDNS 0
-
Slapi_RDN *
slapi_rdn_new()
{
@@ -62,6 +60,14 @@ slapi_rdn_new_dn(const char *dn)
}
Slapi_RDN *
+slapi_rdn_new_all_dn(const char *dn)
+{
+ Slapi_RDN *rdn= slapi_rdn_new();
+ slapi_rdn_init_all_dn(rdn,dn);
+ return rdn;
+}
+
+Slapi_RDN *
slapi_rdn_new_sdn(const Slapi_DN *sdn)
{
Slapi_RDN *rdn= slapi_rdn_new();
@@ -82,7 +88,10 @@ slapi_rdn_init(Slapi_RDN *rdn)
{
rdn->flag= 0;
rdn->rdn= NULL;
+ rdn->nrdn= NULL;
rdn->rdns= NULL;
+ rdn->all_rdns = NULL;
+ rdn->all_nrdns = NULL;
rdn->butcheredupto= -1; /* Means we haven't started converting '=' to '\0' in rdns */
}
@@ -96,9 +105,166 @@ slapi_rdn_init_dn(Slapi_RDN *rdn,const char *dn)
if(dns!=NULL)
{
rdn->rdn= slapi_ch_strdup(dns[0]);
- slapi_ldap_value_free(dns);
+ slapi_ldap_value_free(dns);
+ }
+ }
+}
+
+/*
+ * This function sets dn to Slapi_RDN.
+ * Note: This function checks if the DN is in the root or sub suffix
+ * the server owns. If it is, the root or sub suffix is treated as one
+ * "rdn" (e.g., "dc=sub,dc=example,dc=com") and 0 is returned.
+ * If it is not, the DN is separated by ',' and each string is set to RDN
+ * array. (e.g., input: "uid=A,ou=does_not_exist" ==> "uid=A", "ou=
+ * does_not_exist") and 1 is returned.
+ *
+ * Return Value: 0 -- Success
+ * -1 -- Error (invalid input: NULL DN or RDN, empty RDN ",,")
+ * 1 -- "dn" does not belong to the database; could be "rdn"
+ */
+static int
+_slapi_rdn_init_all_dn_ext(Slapi_RDN *rdn, const Slapi_DN *sdn)
+{
+ const char *dn = NULL;
+ const char *ndn= NULL;
+ const Slapi_DN *suffix = NULL;
+ char **dns = NULL;
+ int rc = 1;
+
+ if (NULL == rdn || NULL == sdn)
+ {
+ return -1;
+ }
+
+ dn = slapi_sdn_get_dn(sdn);
+ for (; isspace(*dn) ; dn++) ;
+
+ /* Suffix is a part of mapping tree. We should not free it */
+ suffix = slapi_get_suffix_by_dn(sdn);
+ if (suffix) {
+ char *p;
+ ndn = slapi_sdn_get_ndn(sdn);
+ p = PL_strcaserstr(ndn, slapi_sdn_get_ndn(suffix));
+ if (p) {
+ if (p == ndn) { /* dn is suffix */
+ charray_add(&dns, slapi_ch_strdup(dn));
+ rc = 0; /* success */
+ } else {
+ int commas = 0;
+ int len = strlen(dn);
+ char *endp = NULL;
+ /* count ',' in suffix */
+ char *q = (char *)slapi_sdn_get_ndn(suffix);
+ while (NULL != (q = PL_strchr(q, ','))) {
+ commas++;
+ q++;
+ }
+ /* found out the previous ',' (++commas-th) to suffix in dn */
+ ++commas;
+ q = endp = (char *)dn + len;
+ while (commas > 0 && q) {
+ q = PL_strnrchr(dn, ',', len);
+ commas--;
+ if (q) {
+ len -= endp - q;
+ endp = q;
+ }
+ }
+ if (q) {
+ char bakup = *q;
+ *q = '\0';
+ dns = ldap_explode_dn(dn, 0);
+ if (NULL == dns) { /* if dn contains NULL RDN (e.g., ",,"),
+ ldap_explode_dn returns NULL */
+ *q = bakup;
+ return -1;
+ }
+ /* add the suffix */
+ charray_add(&dns,
+ slapi_ch_strdup(slapi_sdn_get_dn(suffix)));
+ *q = bakup;
+ rc = 0; /* success */
+ } else {
+ /* Given dn does not belong to this server. Just set it. */
+ dns = ldap_explode_dn(dn, 0);
+ }
+ }
+ } else {
+ /* Given dn does not belong to this server. Just set it. */
+ dns = ldap_explode_dn(dn, 0);
}
+ } else {
+ /* Given dn does not belong to this server. Just set it. */
+ dns = ldap_explode_dn(dn, 0);
+ }
+
+ /* Get the last matched position */
+ if(dns)
+ {
+ rdn->rdn = slapi_ch_strdup(dns[0]);
+ rdn->all_rdns = dns;
+ slapi_setbit_uchar(rdn->flag,FLAG_ALL_RDNS);
+ }
+
+ return rc;
+}
+
+/*
+ * This function sets dn to Slapi_RDN.
+ * Note: The underlying function _slapi_rdn_init_all_dn_ext checks if the DN
+ * is in the root or sub suffix the server owns. If it is, the root or sub
+ * suffix is treated as one "rdn" (e.g., "dc=sub,dc=example,dc=com") and 0 is
+ * returned. If it is not, the DN is separated by ',' and each string is set
+ * to RDN array. (e.g., input: "uid=A,ou=does_not_exist" ==> "uid=A", "ou=
+ * does_not_exist") and 1 is returned.
+ *
+ * Return Value: 0 -- Success
+ * -1 -- Error
+ * 1 -- dn does not belong to the database
+ */
+int
+slapi_rdn_init_all_dn(Slapi_RDN *rdn, const char *dn)
+{
+ int rc = 0; /* success */
+ Slapi_DN sdn = {0};
+
+ if (NULL == rdn || NULL == dn)
+ {
+ return -1;
+ }
+ slapi_rdn_init(rdn);
+ slapi_sdn_set_dn_byval(&sdn, dn);
+ rc = _slapi_rdn_init_all_dn_ext(rdn, (const Slapi_DN *)&sdn);
+ slapi_sdn_done(&sdn);
+ return rc;
+}
+
+/*
+ * This function sets DN from sdn to Slapi_RDN.
+ * Note: The underlying function _slapi_rdn_init_all_dn_ext checks if the DN
+ * is in the root or sub suffix the server owns. If it is, the root or sub
+ * suffix is treated as one "rdn" (e.g., "dc=sub,dc=example,dc=com") and 0 is
+ * returned. If it is not, the DN is separated by ',' and each string is set
+ * to RDN array. (e.g., input: "uid=A,ou=does_not_exist" ==> "uid=A", "ou=
+ * does_not_exist") and 1 is returned.
+ *
+ * Return Value: 0 -- Success
+ * -1 -- Error
+ * 1 -- dn does not belong to the database
+ */
+int
+slapi_rdn_init_all_sdn(Slapi_RDN *rdn, const Slapi_DN *sdn)
+{
+ int rc = 0; /* success */
+
+ if (NULL == rdn || NULL == sdn)
+ {
+ return -1;
}
+ slapi_rdn_init(rdn);
+ rc = _slapi_rdn_init_all_dn_ext(rdn, sdn);
+ return rc;
}
void
@@ -129,6 +295,13 @@ slapi_rdn_set_dn(Slapi_RDN *rdn,const char *dn)
}
void
+slapi_rdn_set_all_dn(Slapi_RDN *rdn,const char *dn)
+{
+ slapi_rdn_done(rdn);
+ slapi_rdn_init_all_dn(rdn, dn);
+}
+
+void
slapi_rdn_set_sdn(Slapi_RDN *rdn,const Slapi_DN *sdn)
{
slapi_rdn_done(rdn);
@@ -181,8 +354,11 @@ slapi_rdn_done(Slapi_RDN *rdn)
{
if(rdn!=NULL)
{
- slapi_ch_free((void**)&(rdn->rdn));
+ slapi_ch_free_string(&(rdn->rdn));
+ slapi_ch_free_string(&(rdn->nrdn));
slapi_ldap_value_free(rdn->rdns);
+ slapi_ldap_value_free(rdn->all_rdns);
+ slapi_ldap_value_free(rdn->all_nrdns);
slapi_rdn_init(rdn);
}
}
@@ -220,7 +396,7 @@ slapi_rdn_get_next(Slapi_RDN *rdn, int index, char **type, char **value)
}
else
{
- *type= strchr(rdn->rdns[index],'=');
+ *type= PL_strchr(rdn->rdns[index],'=');
if(*type==NULL)
{
/* This just shouldn't happen... */
@@ -433,15 +609,391 @@ slapi_rdn_compare(Slapi_RDN *rdn1, Slapi_RDN *rdn2)
}
const char *
-slapi_rdn_get_rdn(const Slapi_RDN *rdn)
+slapi_rdn_get_rdn(const Slapi_RDN *srdn)
{
- return rdn->rdn;
+ return srdn->rdn;
}
+/* srdn is updated in the function, it cannot be const */
const char *
-slapi_rdn_get_nrdn(const Slapi_RDN *rdn)
+slapi_rdn_get_nrdn(Slapi_RDN *srdn)
+{
+ if (NULL == srdn || NULL == srdn->rdn)
+ {
+ return NULL;
+ }
+ if (NULL == srdn->nrdn)
+ {
+ srdn->nrdn = slapi_ch_strdup(srdn->rdn);
+ slapi_dn_normalize_case(srdn->nrdn);
+ }
+ return (const char *)srdn->nrdn;
+}
+
+/*
+ * Get the leaf (first) rdn from rdns or nrdns array depending on the flag
+ *
+ * flag: FLAG_ALL_RDNS -- raw (not normalized)
+ * : FLAG_ALL_NRDNS -- normalized
+ *
+ * Output: first rdn
+ *
+ * Return value: the index of the first rdn.
+ * : -1, if failed
+ */
+int
+slapi_rdn_get_first_ext(Slapi_RDN *srdn, const char **firstrdn, int flag)
+{
+ char **ptr = NULL;
+ int idx = -1;
+
+ if (NULL == firstrdn)
+ {
+ return idx;
+ }
+ *firstrdn = NULL;
+ if (NULL == srdn)
+ {
+ return idx;
+ }
+
+ if (FLAG_ALL_RDNS == flag)
+ {
+ ptr = srdn->all_rdns;
+ }
+ else if (FLAG_ALL_NRDNS == flag)
+ {
+ if (NULL == srdn->all_nrdns)
+ {
+ srdn->all_nrdns = charray_dup(srdn->all_rdns);
+ for (ptr = srdn->all_nrdns; ptr && *ptr; ptr++)
+ {
+ slapi_dn_normalize_case(*ptr);
+ }
+ }
+ ptr = srdn->all_nrdns;
+ }
+ if (ptr)
+ {
+ *firstrdn = *ptr;
+ idx = 0;
+ }
+
+ return idx;
+}
+
+/*
+ * Get the top (last) rdn from rdns or nrdns array depending on the flag
+ *
+ * flag: FLAG_ALL_RDNS -- raw (not normalized)
+ * : FLAG_ALL_NRDNS -- normalized
+ *
+ * Output: last rdn
+ *
+ * Return value: the index of the last rdn.
+ * : -1, if failed
+ */
+int
+slapi_rdn_get_last_ext(Slapi_RDN *srdn, const char **lastrdn, int flag)
+{
+ char **ptr = NULL;
+ int idx = -1;
+
+ if (NULL == lastrdn)
+ {
+ return idx;
+ }
+ *lastrdn = NULL;
+ if (NULL == srdn)
+ {
+ return idx;
+ }
+
+ if (FLAG_ALL_RDNS == flag)
+ {
+ ptr = srdn->all_rdns;
+ }
+ else if (FLAG_ALL_NRDNS == flag)
+ {
+ if (NULL == srdn->all_nrdns)
+ {
+ srdn->all_nrdns = charray_dup(srdn->all_rdns);
+ for (ptr = srdn->all_nrdns; ptr && *ptr; ptr++)
+ {
+ slapi_dn_normalize_case(*ptr);
+ }
+ }
+ ptr = srdn->all_nrdns;
+ }
+ if (ptr)
+ {
+ for ( ; ptr && *ptr; ptr++) idx++;
+ ptr--;
+ }
+ if (ptr)
+ {
+ *lastrdn = *ptr;
+ }
+
+ return idx;
+}
+
+/*
+ * Get the previous rdn of the given index (idx) from rdns or nrdns array
+ * depending on the flag -> rdn
+ *
+ * flag: FLAG_ALL_RDNS -- raw (not normalized)
+ * : FLAG_ALL_NRDNS -- normalized
+ *
+ * Output: prevrdn
+ *
+ * Return value: the index of the returned rdn.
+ * : -1, if failed or done
+ */
+int
+slapi_rdn_get_prev_ext(Slapi_RDN *srdn, int idx, const char **prevrdn, int flag)
+{
+ int rc = -1;
+
+ if (NULL == prevrdn)
+ {
+ return rc;
+ }
+ *prevrdn = NULL;
+ if (NULL == srdn || idx <= 0)
+ {
+ return rc;
+ }
+
+ if (FLAG_ALL_RDNS == flag)
+ {
+ *prevrdn = srdn->all_rdns[idx-1];
+ rc = idx - 1;
+ }
+ else if (FLAG_ALL_NRDNS == flag)
+ {
+ *prevrdn = srdn->all_nrdns[idx-1];
+ rc = idx - 1;
+ }
+
+ return rc;
+}
+
+/*
+ * Get the next rdn of the given index (idx) from rdns or nrdns array
+ * depending on the flag -> rdn
+ *
+ * flag: FLAG_ALL_RDNS -- raw (not normalized)
+ * : FLAG_ALL_NRDNS -- normalized
+ *
+ * Output: nextrdn
+ *
+ * Return value: the index of the returned rdn.
+ * : -1, if failed or done
+ */
+int
+slapi_rdn_get_next_ext(Slapi_RDN *srdn, int idx, const char **nextrdn, int flag)
+{
+ int rc = -1;
+
+ if (NULL == nextrdn)
+ {
+ return rc;
+ }
+ *nextrdn = NULL;
+ if (NULL == srdn || idx < 0)
+ {
+ return rc;
+ }
+
+ if (FLAG_ALL_RDNS == flag)
+ {
+ *nextrdn = srdn->all_rdns[idx+1];
+ rc = idx + 1;
+ }
+ else if (FLAG_ALL_NRDNS == flag)
+ {
+ *nextrdn = srdn->all_nrdns[idx+1];
+ rc = idx + 1;
+ }
+
+ return rc;
+}
+
+/*
+ * addrdn is going to be freed when rdn is freed if byref is 0
+ * if byref is non 0, the caller should not free it.
+ */
+int
+slapi_rdn_add_rdn_to_all_rdns(Slapi_RDN *srdn, char *addrdn, int byref)
+{
+ if (NULL == srdn || NULL == addrdn || '\0' == *addrdn)
+ {
+ return -1;
+ }
+ charray_add(&(srdn->all_rdns), byref?addrdn:slapi_ch_strdup(addrdn));
+ return 0;
+}
+
+int
+slapi_rdn_add_srdn_to_all_rdns(Slapi_RDN *srdn, Slapi_RDN *addsrdn)
+{
+ if (NULL == srdn || NULL == addsrdn)
+ {
+ return -1;
+ }
+ if (NULL == srdn->rdn)
+ {
+ srdn->rdn = slapi_ch_strdup(addsrdn->rdn);
+ }
+ charray_merge(&(srdn->all_rdns), addsrdn->all_rdns, 1 /* copy */);
+ return 0;
+}
+
+/*
+ * Get estimated DN length from all_rdns
+ * If srdn is NULL or srdn does not have all_rdns, it returns -1;
+ */
+int
+slapi_rdn_get_dn_len(Slapi_RDN *srdn)
{
- /* JCM - Normalised RDN? */
- PR_ASSERT(0);
- return NULL;
+ size_t len = -1;
+ char **rdnp = NULL;
+
+ if (NULL == srdn || NULL == srdn->all_rdns)
+ {
+ return len;
+ }
+ len = 0;
+ for (rdnp = srdn->all_rdns; rdnp && *rdnp; rdnp++) {
+ len += strlen(*rdnp) + 1; /* 1 for ',' */
+ }
+ len += 1;
+
+ return len;
+}
+
+/*
+ * Generate DN string from all_rdns
+ * If srdn is NULL or srdn does not have all_rdns, it returns -1;
+ */
+int
+slapi_rdn_get_dn(Slapi_RDN *srdn, char **dn)
+{
+ size_t len = 0;
+ char **rdnp = NULL;
+ char *ptr = NULL;
+ char *enddn = NULL;
+
+ if (NULL == srdn || NULL == srdn->all_rdns || NULL == dn)
+ {
+ return -1;
+ }
+ for (rdnp = srdn->all_rdns; rdnp && *rdnp; rdnp++) {
+ len += strlen(*rdnp) + 1; /* 1 for ',' */
+ }
+ len += 1;
+ len = slapi_rdn_get_dn_len(srdn);
+ *dn = (char *)slapi_ch_malloc(len);
+ enddn = *dn + len - 1;
+ ptr = *dn;
+ for (rdnp = srdn->all_rdns; rdnp && *rdnp; rdnp++) {
+ size_t mylen = strlen(*rdnp) + 1;
+ if (ptr + mylen > enddn) {
+ slapi_ch_free_string(dn);
+ *dn = NULL;
+ return -1;
+ }
+ PR_snprintf(ptr, len, "%s,", *rdnp);
+ len -= mylen;
+ ptr += mylen;
+ }
+ ptr = strrchr(*dn, ',');
+ if (ptr) {
+ *ptr = '\0';
+ return 0;
+ } else {
+ slapi_ch_free_string(dn);
+ *dn = NULL;
+ return -1;
+ }
+}
+
+int
+slapi_srdn_copy(const Slapi_RDN *from, Slapi_RDN *to)
+{
+ if (NULL == from || NULL == to)
+ {
+ return -1;
+ }
+ slapi_rdn_done(to);
+ to->rdn = slapi_ch_strdup(from->rdn);
+ to->rdns = charray_dup(from->rdns);
+ to->all_rdns = charray_dup(from->all_rdns);
+ to->all_nrdns = charray_dup(from->all_nrdns);
+ return 0;
+}
+
+int
+slapi_rdn_replace_rdn(Slapi_RDN *srdn, char *new_rdn)
+{
+ if (NULL == srdn)
+ {
+ return -1;
+ }
+
+ slapi_ch_free_string(&(srdn->rdn));
+ slapi_ch_free_string(&(srdn->nrdn));
+ srdn->rdn = slapi_ch_strdup(new_rdn);
+ srdn->nrdn = slapi_ch_strdup(srdn->rdn);
+ slapi_dn_normalize_case(srdn->nrdn);
+
+ if (srdn->all_rdns)
+ {
+ slapi_ch_free_string(&(srdn->all_rdns[0]));
+ srdn->all_rdns[0] = slapi_ch_strdup(srdn->rdn);
+ }
+ if (srdn->all_nrdns)
+ {
+ slapi_ch_free_string(&(srdn->all_nrdns[0]));
+ srdn->all_nrdns[0] = slapi_ch_strdup(srdn->nrdn);
+ }
+
+ return 0;
+}
+
+int
+slapi_rdn_partial_dup(Slapi_RDN *from, Slapi_RDN **to, int rdnidx)
+{
+ char **ptr = NULL;
+ int lastidx = -1;
+
+ if (NULL == from || NULL == to || rdnidx < 0)
+ {
+ return -1;
+ }
+ *to = NULL;
+
+ for (ptr = from->all_rdns; ptr && *ptr; ptr++) lastidx++;
+ if (rdnidx > lastidx)
+ {
+ return -1;
+ }
+
+ if (NULL == from->all_nrdns)
+ {
+ from->all_nrdns = charray_dup(from->all_rdns);
+ for (ptr = from->all_nrdns; ptr && *ptr; ptr++)
+ {
+ slapi_dn_normalize_case(*ptr);
+ }
+ }
+
+ *to = slapi_rdn_new();
+
+ (*to)->rdn = slapi_ch_strdup(from->all_rdns[rdnidx]);
+ (*to)->nrdn = slapi_ch_strdup(from->all_nrdns[rdnidx]);
+ (*to)->all_rdns = charray_dup(&(from->all_rdns[rdnidx]));
+ (*to)->all_nrdns = charray_dup(&(from->all_nrdns[rdnidx]));
+ return 0;
}