#include <stdlib.h>
#include <string.h>
#include <NetInfo/dsrecord.h>
#include <NetInfo/dsx500.h>
#include <NetInfo/dsutil.h>
#include <NetInfo/utf-8.h>
static char **explode_name(char *name, u_int32_t notypes, u_int32_t is_type);
#define INQUOTE 1
#define OUTQUOTE 2
#define NAME_TYPE_X500_RDN 0
#define NAME_TYPE_X500_DN 1
#define NAME_TYPE_NETINFO_PATH 2
char **
dsx500_explode_dn(char *dn, u_int32_t notypes)
{
return explode_name(dn, notypes, NAME_TYPE_X500_DN);
}
char **
dsx500_explode_rdn(char *rdn, u_int32_t notypes)
{
return explode_name(rdn, notypes, NAME_TYPE_X500_RDN);
}
char *
dsx500_dn_to_netinfo_string_path (char *dn)
{
char *dce, *q, **rdns, **p, *c;
int len = 0;
rdns = explode_name(dn, 0, NAME_TYPE_X500_DN);
if (rdns == NULL)
{
return NULL;
}
for (p = rdns; *p != NULL; p++)
{
for (c = *p; *c != '\0'; c++)
{
if (*c == '/') len++;
len++;
}
len++;
}
q = dce = malloc(len + 1);
if (dce == NULL)
{
return NULL;
}
p--;
for (; p >= rdns; p--)
{
*q++ = '/';
for (c = *p; *c != '\0'; c++)
{
if (*c == '/')
*q++ = '\\';
*q++ = *c;
}
}
*q = '\0';
return dce;
}
char *
dsx500_netinfo_string_path_to_dn (char *netinfo_name)
{
char *dn, *q, **rdns, **p, *c;
int len = 0;
if (*netinfo_name == '/')
netinfo_name++;
rdns = explode_name(netinfo_name, 0, NAME_TYPE_NETINFO_PATH);
if (rdns == NULL)
{
return NULL;
}
for (p = rdns; *p != NULL; p++)
{
for (c = *p; *c != '\0'; c++)
{
if (NeedEscapeRDN(*c)) len++;
len++;
}
len++;
}
q = dn = malloc(len);
if (dn == NULL)
{
return NULL;
}
p--;
for (; p >= rdns; p--)
{
for (c = *p; *c != '\0'; c++)
{
if (NeedEscapeRDN(*c))
*q++ = '\\';
*q++ = *c;
}
*q++ = ',';
}
*--q = '\0';
return dn;
}
static char **
explode_name(char *name, u_int32_t notypes, u_int32_t is_type)
{
const char *p, *q, *rdn;
char **parts = NULL;
int offset, state, have_equals, count = 0, endquote,
len;
if (name == NULL)
name = "";
while (dsutil_utf8_isspace(name))
{
DSUTIL_UTF8_INCR(name);
}
p = rdn = name;
offset = 0;
state = OUTQUOTE;
have_equals = 0;
do
{
p += offset;
offset = 1;
switch (*p)
{
case '\\':
if (p[1] != '\0')
{
offset = DSUTIL_UTF8_OFFSET(++p);
}
break;
case '"':
if (state == INQUOTE)
state = OUTQUOTE;
else
state = INQUOTE;
break;
case '=':
if (state == OUTQUOTE)
have_equals++;
break;
case '+':
if (is_type == NAME_TYPE_X500_RDN)
goto end_part;
break;
case '/':
if (is_type == NAME_TYPE_NETINFO_PATH)
goto end_part;
break;
case ';':
case ',':
if (is_type == NAME_TYPE_X500_DN)
goto end_part;
break;
case '\0':
end_part:
if (state == OUTQUOTE)
{
int need_ni_name = 0;
++count;
if ((is_type == NAME_TYPE_NETINFO_PATH) && (have_equals == 0))
need_ni_name = 1;
have_equals = 0;
if (parts == NULL)
{
if ((parts = (char **) malloc(8
* sizeof(char *))) == NULL)
return (NULL);
}
else if (count >= 8)
{
if ((parts = (char **) realloc(parts,
(count + 1) * sizeof(char *)))
== NULL)
return (NULL);
}
parts[count] = NULL;
endquote = 0;
if (notypes)
{
for (q = rdn; q < p && *q != '='; ++q)
{
;
}
if (q < p)
{
rdn = ++q;
}
if (*rdn == '"')
{
++rdn;
}
if (p[-1] == '"')
{
endquote = 1;
--p;
}
}
len = p - rdn;
if (need_ni_name)
len += sizeof("name=") - 1;
if ((parts[count - 1] = (char *) calloc(1,
len + 1)) != NULL)
{
char *r = parts[count - 1];
if (need_ni_name)
{
memmove(r, "name=", len);
r += sizeof("name=") - 1;
}
memmove(r, rdn, len);
if (!endquote)
{
while (len > 0 && dsutil_utf8_isspace(
&parts[count - 1][len - 1]))
{
--len;
}
}
parts[count - 1][len] = '\0';
}
if (endquote == 1)
p++;
rdn = *p ? &p[1] : p;
while (dsutil_utf8_isspace(rdn))
++rdn;
} break;
}
} while (*p);
return (parts);
}
static char *
get_next_substring(const char *s, char d)
{
char *str, *r;
r = str = malloc(strlen(s) + 1);
if (r == NULL)
{
return NULL;
}
while (*s && dsutil_utf8_isspace(s))
{
s++;
}
while (*s && (*s != d))
{
*str++ = *s++;
}
*str = '\0';
return r;
}
char *
dsx500_rdn_attr_type(char *s)
{
return get_next_substring(s, '=');
}
char *
dsx500_rdn_attr_value(char *rdn)
{
const char *str;
if ((str = strchr(rdn, '=')) != NULL)
{
return get_next_substring(++str, '\0');
}
return NULL;
}
u_int32_t
dsx500_validate_rdn(char *rdn)
{
return strchr(rdn, '=') != NULL;
}
char *
dsx500_make_dn(char *p_dn, char *newrdn)
{
char *new_dn;
if (p_dn == NULL || p_dn[0] == '\0')
{
return copyString(newrdn);
}
new_dn = (char *) malloc(strlen(p_dn) + strlen(newrdn) + 3);
if (new_dn == NULL)
{
return NULL;
}
strcpy(new_dn, newrdn);
strcat(new_dn, ",");
strcat(new_dn, p_dn);
return new_dn;
}