summaryrefslogtreecommitdiffstats
path: root/lib/ldaputil/dbconf.c
diff options
context:
space:
mode:
authorcvsadm <cvsadm>2005-01-21 00:44:34 +0000
committercvsadm <cvsadm>2005-01-21 00:44:34 +0000
commitb2093e3016027d6b5cf06b3f91f30769bfc099e2 (patch)
treecf58939393a9032182c4fbc4441164a9456e82f8 /lib/ldaputil/dbconf.c
downloadds-ldapserver7x.tar.gz
ds-ldapserver7x.tar.xz
ds-ldapserver7x.zip
Moving NSCP Directory Server from DirectoryBranch to TRUNK, initial drop. (foxworth)ldapserver7x
Diffstat (limited to 'lib/ldaputil/dbconf.c')
-rw-r--r--lib/ldaputil/dbconf.c704
1 files changed, 704 insertions, 0 deletions
diff --git a/lib/ldaputil/dbconf.c b/lib/ldaputil/dbconf.c
new file mode 100644
index 00000000..684d62df
--- /dev/null
+++ b/lib/ldaputil/dbconf.c
@@ -0,0 +1,704 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+
+#include <string.h>
+#include <malloc.h>
+#include <ctype.h>
+
+#include <ldaputil/errors.h>
+#include <ldaputil/certmap.h>
+#include <ldaputil/encode.h>
+#include <ldaputil/dbconf.h>
+
+#define BIG_LINE 1024
+
+static const char *DB_DIRECTIVE = "directory";
+static const int DB_DIRECTIVE_LEN = 9; /* strlen("DB_DIRECTIVE") */
+
+static const char *ENCODED = "encoded";
+
+static void insert_dbinfo_propval(DBConfDBInfo_t *db_info,
+ DBPropVal_t *propval)
+{
+ if (db_info->lastprop) {
+ db_info->lastprop->next = propval;
+ }
+ else {
+ db_info->firstprop = propval;
+ }
+
+ db_info->lastprop = propval;
+}
+
+static void insert_dbconf_dbinfo(DBConfInfo_t *conf_info,
+ DBConfDBInfo_t *db_info)
+{
+ if (conf_info->lastdb) {
+ conf_info->lastdb->next = db_info;
+ }
+ else {
+ conf_info->firstdb = db_info;
+ }
+
+ conf_info->lastdb = db_info;
+}
+
+void dbconf_free_propval (DBPropVal_t *propval)
+{
+ if (propval) {
+ if (propval->prop) free(propval->prop);
+ if (propval->val) free(propval->val);
+ memset((void *)propval, 0, sizeof(DBPropVal_t));
+ free(propval);
+ }
+}
+
+NSAPI_PUBLIC void dbconf_free_dbinfo (DBConfDBInfo_t *db_info)
+{
+ if (db_info) {
+ DBPropVal_t *next;
+ DBPropVal_t *cur;
+
+ if (db_info->dbname) free(db_info->dbname);
+ if (db_info->url) free(db_info->url);
+
+ cur = db_info->firstprop;
+
+ while(cur) {
+ next = cur->next;
+ dbconf_free_propval(cur);
+ cur = next;
+ }
+
+ memset((void *)db_info, 0, sizeof(DBConfDBInfo_t));
+ free(db_info);
+ }
+}
+
+NSAPI_PUBLIC void dbconf_free_confinfo (DBConfInfo_t *conf_info)
+{
+ DBConfDBInfo_t *next;
+ DBConfDBInfo_t *cur;
+
+ if (conf_info) {
+ cur = conf_info->firstdb;
+
+ while (cur) {
+ next = cur->next;
+ dbconf_free_dbinfo(cur);
+ cur = next;
+ }
+
+ memset((void *)conf_info, 0, sizeof(DBConfInfo_t));
+ free(conf_info);
+ }
+}
+
+static int skip_blank_lines_and_spaces(FILE *fp, char *buf, char **ptr_out,
+ int *eof)
+{
+ char *ptr = buf;
+ char *end;
+
+ while(buf && (*buf || fgets(buf, BIG_LINE, fp))) {
+ ptr = buf;
+
+ /* skip leading whitespace */
+ while(*ptr && isspace(*ptr)) ++ptr;
+
+ /* skip blank line or comment */
+ if (!*ptr || *ptr == '#') {
+ *buf = 0; /* to force reading of next line */
+ continue;
+ }
+
+ /* Non-blank line found */
+ break;
+ }
+
+ *ptr_out = ptr;
+ if (!*ptr) {
+ *eof = 1;
+ }
+ else {
+ /* skip trailing whitespace */
+ end = ptr + strlen(ptr) - 1;
+ while(isspace(*end)) *end-- = 0;
+ }
+
+ return LDAPU_SUCCESS;
+}
+
+static int dbconf_parse_propval (char *buf, char *ptr,
+ DBConfDBInfo_t *db_info)
+{
+ char *dbname = db_info->dbname;
+ int dbname_len = strlen(dbname);
+ char *prop;
+ char *val;
+ DBPropVal_t *propval;
+ char *delimeter_chars = " \t";
+ char *lastchar;
+ int end_of_prop;
+ char *encval = 0; /* encoded value */
+ char *origprop = 0;
+
+ if ((ptr - buf + dbname_len > BIG_LINE) ||
+ strncmp(ptr, dbname, dbname_len) ||
+ !(ptr[dbname_len] == ':' || isspace(ptr[dbname_len])))
+ {
+ /* Not a prop-val for the current db but not an error */
+ return LDAPU_ERR_NOT_PROPVAL;
+ }
+
+ /* remove the last char if it is newline */
+ lastchar = strrchr(buf, '\n');
+ if (lastchar) *lastchar = '\0';
+
+ prop = ptr + dbname_len + 1;
+
+ while(*prop && (isspace(*prop) || *prop == ':')) ++prop;
+
+ if (!*prop) {
+ return LDAPU_ERR_PROP_IS_MISSING;
+ }
+
+ end_of_prop = strcspn(prop, delimeter_chars);
+
+ if (prop[end_of_prop] != '\0') {
+ /* buf doesn't end here -- val is present */
+ prop[end_of_prop] = '\0';
+ val = &prop[end_of_prop + 1];
+
+ while(*val && isspace(*val)) ++val;
+ if (*val == '\0') val = 0;
+ }
+ else {
+ val = 0;
+ }
+
+ /*
+ * The prop-val line could be one of the following:
+ * "<dbname>:prop val" OR "<dbname>:encoded prop encval"
+ * If (prop == "encoded") then the val has "prop encval".
+ * Get the actual prop from val and get encval (i.e. encoded value)
+ * and decode it. If it is encoded then the val part must be non-NULL.
+ */
+ if (val && *val && !strcmp(prop, ENCODED)) {
+ /* val has the actual prop followed by the encoded value */
+ origprop = prop;
+ prop = val;
+ while(*prop && (isspace(*prop) || *prop == ':')) ++prop;
+
+ if (!*prop) {
+ return LDAPU_ERR_PROP_IS_MISSING;
+ }
+
+ end_of_prop = strcspn(prop, delimeter_chars);
+
+ if (prop[end_of_prop] != '\0') {
+ /* buf doesn't end here -- encval is present */
+ prop[end_of_prop] = '\0';
+ encval = &prop[end_of_prop + 1];
+
+ while(*encval && isspace(*encval)) ++encval;
+ if (*encval == '\0') encval = 0;
+ }
+ else {
+ encval = 0;
+ }
+
+ if (!encval) {
+ /* special case - if encval is null, "encoded" itself is a
+ * property and what we have in prop now is the value. */
+ val = prop;
+ prop = origprop;
+ }
+ else {
+ /* decode the value */
+ val = dbconf_decodeval(encval);
+ }
+ }
+
+ /* Success - we have prop & val */
+ propval = (DBPropVal_t *)malloc(sizeof(DBPropVal_t));
+
+ if (!propval) return LDAPU_ERR_OUT_OF_MEMORY;
+ memset((void *)propval, 0, sizeof(DBPropVal_t));
+ propval->prop = strdup(prop);
+ propval->val = val ? strdup(val) : 0;
+
+ if (!propval->prop || (val && !propval->val)) {
+ dbconf_free_propval(propval);
+ return LDAPU_ERR_OUT_OF_MEMORY;
+ }
+
+ if (encval) free(val); /* val was allocated by dbconf_decodeval */
+
+ insert_dbinfo_propval(db_info, propval);
+ return LDAPU_SUCCESS;
+}
+
+static int dbconf_read_propval (FILE *fp, char *buf, DBConfDBInfo_t *db_info,
+ int *eof)
+{
+ int rv;
+ char *ptr = buf;
+
+ while(buf && (*buf || fgets(buf, BIG_LINE, fp))) {
+ ptr = buf;
+
+ rv = skip_blank_lines_and_spaces(fp, buf, &ptr, eof);
+
+ if (rv != LDAPU_SUCCESS || *eof) return rv;
+
+ /* We have a non-blank line which could be prop-val pair for the
+ * dbname in the db_info. parse the prop-val pair and continue.
+ */
+ rv = dbconf_parse_propval(buf, ptr, db_info);
+
+ if (rv == LDAPU_ERR_NOT_PROPVAL) return LDAPU_SUCCESS;
+ if (rv != LDAPU_SUCCESS) return rv;
+
+ *buf = 0; /* to force reading of next line */
+ }
+
+ if (!*buf) *eof = 1;
+
+ return LDAPU_SUCCESS;
+}
+
+static int parse_directive(char *buf, const char *directive,
+ const int directive_len,
+ DBConfDBInfo_t **db_info_out)
+{
+ DBConfDBInfo_t *db_info;
+ char *dbname;
+ char *url;
+ int end_of_dbname;
+ char *delimeter_chars = " \t";
+ char *lastchar;
+
+ /* remove the last char if it is newline */
+ lastchar = strrchr(buf, '\n');
+ if (lastchar) *lastchar = '\0';
+
+ if (strncmp(buf, directive, directive_len) ||
+ !isspace(buf[directive_len]))
+ {
+ return LDAPU_ERR_DIRECTIVE_IS_MISSING;
+ }
+
+ dbname = buf + directive_len + 1;
+
+ while(*dbname && isspace(*dbname)) ++dbname;
+
+ if (!*dbname) {
+ return LDAPU_ERR_DBNAME_IS_MISSING;
+ }
+
+ end_of_dbname = strcspn(dbname, delimeter_chars);
+
+ if (dbname[end_of_dbname] != '\0') {
+ /* buf doesn't end here -- url is present */
+ dbname[end_of_dbname] = '\0';
+ url = &dbname[end_of_dbname + 1];
+
+ while(*url && isspace(*url)) ++url;
+
+ if (*url == '\0') url = 0;
+ }
+ else {
+ url = 0;
+ }
+
+ /* Success - we have dbname & url */
+ db_info = (DBConfDBInfo_t *)malloc(sizeof(DBConfDBInfo_t));
+
+ if (!db_info) return LDAPU_ERR_OUT_OF_MEMORY;
+ memset((void *)db_info, 0, sizeof(DBConfDBInfo_t));
+ db_info->dbname = strdup(dbname);
+ db_info->url = url ? strdup(url) : 0;
+
+ if (!db_info->dbname || (url && !db_info->url)) {
+ dbconf_free_dbinfo(db_info);
+ return LDAPU_ERR_OUT_OF_MEMORY;
+ }
+
+ *db_info_out = db_info;
+ return LDAPU_SUCCESS;
+}
+
+/* Read the next database info from the file and put it in db_info_out. The
+ * buf may contain first line of the database info. When this function
+ * finishes, the buf may contain unprocessed information (which should be
+ * passed to the next call to read_db_info).
+ */
+static int read_db_info (FILE *fp, char *buf, DBConfDBInfo_t **db_info_out,
+ const char *directive, const int directive_len,
+ int *eof)
+{
+ char *ptr;
+ int found_directive = 0;
+ DBConfDBInfo_t *db_info;
+ int rv;
+
+ *db_info_out = 0;
+
+ rv = skip_blank_lines_and_spaces(fp, buf, &ptr, eof);
+
+ if (rv != LDAPU_SUCCESS || *eof) return rv;
+
+ /* We possibly have a directive of the form "directory <name> <url>" */
+ rv = parse_directive(ptr, directive, directive_len, &db_info);
+ if (rv != LDAPU_SUCCESS) return rv;
+
+ /* We have parsed the directive successfully -- lets look for additional
+ * property-value pairs for the database.
+ */
+ if (!fgets(buf, BIG_LINE, fp)) {
+ *eof = 1;
+ rv = LDAPU_SUCCESS;
+ }
+ else {
+ rv = dbconf_read_propval(fp, buf, db_info, eof);
+ }
+
+ if (rv != LDAPU_SUCCESS) {
+ dbconf_free_dbinfo(db_info);
+ *db_info_out = 0;
+ }
+ else {
+ *db_info_out = db_info;
+ }
+
+ return rv;
+}
+
+int dbconf_read_config_file_sub (const char *file,
+ const char *directive,
+ const int directive_len,
+ DBConfInfo_t **conf_info_out)
+{
+ FILE *fp;
+ DBConfInfo_t *conf_info;
+ DBConfDBInfo_t *db_info;
+ char buf[BIG_LINE];
+ int rv;
+ int eof;
+
+ buf[0] = 0;
+
+#ifdef XP_WIN32
+ if ((fp = fopen(file, "rt")) == NULL)
+#else
+ if ((fp = fopen(file, "r")) == NULL)
+#endif
+ {
+ return LDAPU_ERR_CANNOT_OPEN_FILE;
+ }
+
+ /* Allocate DBConfInfo_t */
+ conf_info = (DBConfInfo_t *)malloc(sizeof(DBConfInfo_t));
+
+ if (!conf_info) {
+ fclose(fp);
+ return LDAPU_ERR_OUT_OF_MEMORY;
+ }
+
+ memset((void *)conf_info, 0, sizeof(DBConfInfo_t));
+
+ /* Read each db info */
+ eof = 0;
+ while(!eof &&
+ ((rv = read_db_info(fp, buf, &db_info, directive, directive_len, &eof)) == LDAPU_SUCCESS))
+ {
+ insert_dbconf_dbinfo(conf_info, db_info);
+ }
+
+ if (rv != LDAPU_SUCCESS) {
+ dbconf_free_confinfo(conf_info);
+ *conf_info_out = 0;
+ }
+ else {
+ *conf_info_out = conf_info;
+ }
+
+ fclose(fp);
+ return rv;
+}
+
+NSAPI_PUBLIC int dbconf_read_config_file (const char *file, DBConfInfo_t **conf_info_out)
+{
+ return dbconf_read_config_file_sub(file, DB_DIRECTIVE, DB_DIRECTIVE_LEN,
+ conf_info_out);
+}
+
+int dbconf_read_default_dbinfo_sub (const char *file,
+ const char *directive,
+ const int directive_len,
+ DBConfDBInfo_t **db_info_out)
+{
+ FILE *fp;
+ DBConfDBInfo_t *db_info;
+ char buf[BIG_LINE];
+ int rv;
+ int eof;
+
+ buf[0] = 0;
+
+#ifdef XP_WIN32
+ if ((fp = fopen(file, "rt")) == NULL)
+#else
+ if ((fp = fopen(file, "r")) == NULL)
+#endif
+ {
+ return LDAPU_ERR_CANNOT_OPEN_FILE;
+ }
+
+ /* Read each db info until eof or dbname == default*/
+ eof = 0;
+
+ while(!eof &&
+ ((rv = read_db_info(fp, buf, &db_info, directive, directive_len, &eof)) == LDAPU_SUCCESS))
+ {
+ if (!strcmp(db_info->dbname, DBCONF_DEFAULT_DBNAME)) break;
+ dbconf_free_dbinfo(db_info);
+ }
+
+ if (rv != LDAPU_SUCCESS) {
+ *db_info_out = 0;
+ }
+ else {
+ *db_info_out = db_info;
+ }
+
+ fclose(fp);
+ return rv;
+}
+
+
+NSAPI_PUBLIC int dbconf_read_default_dbinfo (const char *file,
+ DBConfDBInfo_t **db_info_out)
+{
+ return dbconf_read_default_dbinfo_sub(file, DB_DIRECTIVE, DB_DIRECTIVE_LEN,
+ db_info_out);
+}
+
+/*
+ * ldapu_strncasecmp - is like strncasecmp on UNIX but also accepts null strings.
+ */
+/* Not tested */
+static int ldapu_strncasecmp (const char *s1, const char *s2, size_t len)
+{
+ int ls1, ls2; /* tolower values of chars in s1 & s2 resp. */
+
+ if (0 == len) return 0;
+ else if (!s1) return !s2 ? 0 : 0-tolower(*s2);
+ else if (!s2) return tolower(*s1);
+
+#ifdef XP_WIN32
+ while(len > 0 && *s1 && *s2 &&
+ (ls1 = tolower(*s1)) == (ls2 = tolower(*s2)))
+ {
+ s1++; s2++; len--;
+ }
+
+ if (0 == len)
+ return 0;
+ else if (!*s1)
+ return *s2 ? 0-tolower(*s2) : 0;
+ else if (!*s2)
+ return tolower(*s1);
+ else
+ return ls1 - ls2;
+#else
+ return strncasecmp(s1, s2, len);
+#endif
+}
+
+
+/*
+ * ldapu_strcasecmp - is like strcasecmp on UNIX but also accepts null strings.
+ */
+int ldapu_strcasecmp (const char *s1, const char *s2)
+{
+ int ls1, ls2; /* tolower values of chars in s1 & s2 resp. */
+
+ if (!s1) return !s2 ? 0 : 0-tolower(*s2);
+ else if (!s2) return tolower(*s1);
+
+#ifdef XP_WIN32
+ while(*s1 && *s2 && (ls1 = tolower(*s1)) == (ls2 = tolower(*s2))) { s1++; s2++; }
+
+ if (!*s1)
+ return *s2 ? 0-tolower(*s2) : 0;
+ else if (!*s2)
+ return tolower(*s1);
+ else
+ return ls1 - ls2;
+#else
+ return strcasecmp(s1, s2);
+#endif
+}
+
+NSAPI_PUBLIC int ldapu_dbinfo_attrval (DBConfDBInfo_t *db_info,
+ const char *attr, char **val)
+{
+ /* Look for given attr in the db_info and return its value */
+ int rv = LDAPU_ATTR_NOT_FOUND;
+ DBPropVal_t *next;
+
+ *val = 0;
+
+ if (db_info) {
+ next = db_info->firstprop;
+ while (next) {
+ rv = ldapu_strcasecmp(attr, next->prop);
+ if (!rv) {
+ /* Found the property */
+ *val = next->val ? strdup(next->val) : 0;
+
+ if (next->val && !*val) {
+ rv = LDAPU_ERR_OUT_OF_MEMORY;
+ }
+ else {
+ rv = LDAPU_SUCCESS;
+ }
+ break;
+ }
+ next = next->next;
+ }
+ }
+
+ return rv;
+}
+
+void dbconf_print_propval (DBPropVal_t *propval)
+{
+ if (propval) {
+ fprintf(stderr, "\tprop: \"%s\"\tval: \"%s\"\n", propval->prop,
+ propval->val ? propval->val : "");
+ }
+ else {
+ fprintf(stderr, "Null propval\n");
+ }
+}
+
+void dbconf_print_dbinfo (DBConfDBInfo_t *db_info)
+{
+ DBPropVal_t *next;
+
+ if (db_info) {
+ fprintf(stderr, "dbname: \"%s\"\n", db_info->dbname);
+ fprintf(stderr, "url: \t\"%s\"\n", db_info->url ? db_info->url : "");
+ next = db_info->firstprop;
+ while (next) {
+ dbconf_print_propval(next);
+ next = next->next;
+ }
+ }
+ else {
+ fprintf(stderr, "Null db_info\n");
+ }
+}
+
+void dbconf_print_confinfo (DBConfInfo_t *conf_info)
+{
+ DBConfDBInfo_t *next;
+
+ if (conf_info) {
+ next = conf_info->firstdb;
+ while (next) {
+ dbconf_print_dbinfo(next);
+ next = next->next;
+ }
+ }
+ else {
+ fprintf(stderr, "Null conf_info\n");
+ }
+}
+
+
+
+NSAPI_PUBLIC int dbconf_output_db_directive (FILE *fp, const char *dbname,
+ const char *url)
+{
+ fprintf(fp, "%s %s %s\n", DB_DIRECTIVE, dbname, url);
+ return LDAPU_SUCCESS;
+}
+
+NSAPI_PUBLIC int dbconf_output_propval (FILE *fp, const char *dbname,
+ const char *prop, const char *val, const int encoded)
+{
+ if (encoded && val && *val) {
+ char *new_val = dbconf_encodeval(val);
+
+ if (!new_val) return LDAPU_ERR_OUT_OF_MEMORY;
+ fprintf(fp, "%s:%s %s %s\n", dbname, ENCODED,
+ prop, new_val);
+ free(new_val);
+ }
+ else {
+ fprintf(fp, "%s:%s %s\n", dbname, prop, val ? val : "");
+ }
+
+ return LDAPU_SUCCESS;
+}
+
+
+
+NSAPI_PUBLIC int dbconf_get_dbnames (const char *dbmap, char ***dbnames_out, int *cnt_out)
+{
+ DBConfInfo_t *conf_info = 0;
+ DBConfDBInfo_t *db = 0;
+ int cnt = 0;
+ char **dbnames = 0;
+ char *heap = 0;
+ int rv;
+
+ *dbnames_out = 0;
+ *cnt_out = 0;
+
+ rv = dbconf_read_config_file(dbmap, &conf_info);
+
+ if (rv != LDAPU_SUCCESS) return rv;
+
+ db = conf_info->firstdb;
+
+
+ dbnames = (char **)malloc(32*1024);
+ heap = (char *)dbnames + 2*1024;
+
+ if (!dbnames) {
+ dbconf_free_confinfo(conf_info);
+ return LDAPU_ERR_OUT_OF_MEMORY;
+ }
+
+ *dbnames_out = dbnames;
+
+ while(db) {
+ *dbnames++ = heap;
+ strcpy(heap, db->dbname);
+ heap += strlen(db->dbname)+1;
+ db = db->next;
+ cnt++;
+ }
+
+ *dbnames = NULL;
+ *cnt_out = cnt;
+ dbconf_free_confinfo(conf_info);
+
+ return LDAPU_SUCCESS;
+}
+
+NSAPI_PUBLIC int dbconf_free_dbnames (char **dbnames)
+{
+ if (dbnames)
+ free(dbnames);
+
+ return LDAPU_SUCCESS;
+}