[SR-Dev] git:janakj/ldap: - parse and check the result message

Jan Janak jan at iptel.org
Fri Feb 13 00:57:02 CET 2009


Module: sip-router
Branch: janakj/ldap
Commit: 09e32928839c2be69caa0ad96a25b725b268482f
URL:    http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=09e32928839c2be69caa0ad96a25b725b268482f

Author: Jan Janak <jan at iptel.org>
Committer: Jan Janak <jan at iptel.org>
Date:   Mon May 12 15:01:17 2008 +0000

- parse and check the result message
- support for binary values
- better support for integers
- support for bitmap fields

---

 modules/db_ldap/ld_cmd.c |   99 ++++++++++++++++++++++++++-------------------
 modules/db_ldap/ld_fld.c |   77 +++++++++++++++++++++++++++--------
 modules/db_ldap/ld_fld.h |    2 +-
 modules/db_ldap/todo.txt |    2 -
 4 files changed, 117 insertions(+), 63 deletions(-)

diff --git a/modules/db_ldap/ld_cmd.c b/modules/db_ldap/ld_cmd.c
index 8444bed..209db1e 100644
--- a/modules/db_ldap/ld_cmd.c
+++ b/modules/db_ldap/ld_cmd.c
@@ -251,27 +251,18 @@ int ld_cmd(db_cmd_t* cmd)
 
 	switch(cmd->type) {
 	case DB_PUT:
-		ERR("ldap: DB_PUT not supported\n");
-		goto error;
-		break;
-		
 	case DB_DEL:
-		ERR("ldap: DB_DEL not supported\n");
+	case DB_UPD:
+		ERR("ldap: The driver does not support directory modifications yet.\n");
 		goto error;
 		break;
-
+		
 	case DB_GET:		
 		break;
 
-	case DB_UPD:
-		ERR("ldap: DB_UPD not supported\n");
-		goto error;
-		break;
-		
 	case DB_SQL:
-		ERR("ldap: DB_SQL not supported\n");
+		ERR("ldap: The driver does not support raw queries yet.\n");
 		goto error;
-        break;
 	}
 
 	cfg = ld_find_config(&cmd->table);
@@ -293,7 +284,6 @@ int ld_cmd(db_cmd_t* cmd)
 	if (ld_resolve_fld(cmd->result, cfg) < 0) goto error;
 
 	if (build_result_array(&lcmd->result, cmd) < 0) goto error;
-
 	DB_SET_PAYLOAD(cmd, lcmd);
 	return 0;
 
@@ -314,10 +304,14 @@ int ld_cmd_exec(db_res_t* res, db_cmd_t* cmd)
 	struct ld_res* lres;
 	struct ld_cmd* lcmd;
 	struct ld_con* lcon;
-	char* filter;
-	int ret;
+	char* filter, *err_desc;
+	int ret, err;
 	LDAPMessage* msg;
 
+	filter = NULL;
+	err_desc = NULL;
+	msg = NULL;
+
 	/* First things first: retrieve connection info from the currently active
 	 * connection and also mysql payload from the database command
 	 */
@@ -327,57 +321,72 @@ int ld_cmd_exec(db_res_t* res, db_cmd_t* cmd)
 
 	if (build_search_filter(&filter, cmd->match, &lcmd->filter) < 0) {
 		ERR("ldap: Error while building LDAP search filter\n");
-		return -1;
+		goto error;
 	}
 
 	ret = ldap_search_ext_s(lcon->con, lcmd->base, lcmd->scope, filter,
 							lcmd->result, 0, NULL, NULL, NULL, 0, &msg);
-	if (filter) pkg_free(filter);
 
 	if (ret != LDAP_SUCCESS) {
 		ERR("ldap: Error in ldap_search: %s\n", ldap_err2string(ret));
-		return -1;
+		goto error;
+	}
+
+	ret = ldap_parse_result(lcon->con, msg, &err, NULL, &err_desc, NULL, NULL, 0);
+	if (ret != LDAP_SUCCESS) {
+		ERR("ldap: Error while reading result status: %s\n", 
+			ldap_err2string(ret));
+		goto error;
 	}
 
+	if (err != LDAP_SUCCESS) {
+		ERR("ldap: LDAP server reports error: %s\n", ldap_err2string(err));
+		goto error;
+	}
+			
 	if (res) {
 		lres = DB_GET_PAYLOAD(res);
-		if (lres->msg) ldap_msgfree(lres->msg);
 		lres->msg = msg;
 	} else {
 		ldap_msgfree(msg);
 	}
 
+	if (filter) pkg_free(filter);
+	if (err_desc) ldap_memfree(err_desc);
 	return 0;
+	
+ error:
+	if (filter) pkg_free(filter);
+	if (msg) ldap_msgfree(msg);
+	if (err_desc) ldap_memfree(err_desc);
+	return -1;
 }
 
 
-int ld_cmd_first(db_res_t* res)
+/* Iterate to the next search result in the linked list
+ * of messages returned by the LDAP server and convert
+ * the field values.
+ */
+static int next_search_entry(db_res_t* res, LDAP* con)
 {
-	db_con_t* con;
 	struct ld_res* lres;
-	struct ld_con* lcon;
 
 	lres = DB_GET_PAYLOAD(res);
-	/* FIXME */
-	con = res->cmd->ctx->con[db_payload_idx];
-	lcon = DB_GET_PAYLOAD(con);
-
-	lres->current = ldap_first_message(lcon->con, lres->msg);
 	while(lres->current) {
 		if (ldap_msgtype(lres->current) == LDAP_RES_SEARCH_ENTRY) {
 			break;
 		}
-		lres->current = ldap_next_message(lcon->con, lres->msg);
+		lres->current = ldap_next_message(con, lres->current);
 	}
 	if (lres->current == NULL) return 1;
 
-	if (ld_ldap2fld(res->cmd->result, lcon->con, lres->current) < 0) return -1;
+	if (ld_ldap2fld(res->cmd->result, con, lres->current) < 0) return -1;
 	res->cur_rec->fld = res->cmd->result;
 	return 0;
 }
 
 
-int ld_cmd_next(db_res_t* res)
+int ld_cmd_first(db_res_t* res)
 {
 	db_con_t* con;
 	struct ld_res* lres;
@@ -388,19 +397,25 @@ int ld_cmd_next(db_res_t* res)
 	con = res->cmd->ctx->con[db_payload_idx];
 	lcon = DB_GET_PAYLOAD(con);
 
-	if (lres->current == NULL) return 1;
+	lres->current = ldap_first_message(lcon->con, lres->msg);
+	return next_search_entry(res, lcon->con);
+}
+
+
+int ld_cmd_next(db_res_t* res)
+{
+	db_con_t* con;
+	struct ld_res* lres;
+	struct ld_con* lcon;
+
+	lres = DB_GET_PAYLOAD(res);
+	/* FIXME */
+	con = res->cmd->ctx->con[db_payload_idx];
+	lcon = DB_GET_PAYLOAD(con);
 
 	lres->current = ldap_next_message(lcon->con, lres->current);
-	while(lres->current) {
-		if (ldap_msgtype(lres->current) == LDAP_RES_SEARCH_ENTRY) {
-			break;
-		}
-		lres->current = ldap_next_message(lcon->con, lres->current);
-	}
-	if (lres->current == NULL) return 1;
-	if (ld_ldap2fld(res->cmd->result, lcon->con, lres->current) < 0) return -1;
-	res->cur_rec->fld = res->cmd->result;
-	return 0;
+	return next_search_entry(res, lcon->con);
 }
 
+
 /** @} */
diff --git a/modules/db_ldap/ld_fld.c b/modules/db_ldap/ld_fld.c
index 2c06727..b886d85 100644
--- a/modules/db_ldap/ld_fld.c
+++ b/modules/db_ldap/ld_fld.c
@@ -41,6 +41,7 @@
 #include "../../db/db_drv.h"
 #include "../../mem/mem.h"
 #include "../../dprint.h"
+#include "../../ut.h"
 
 #include <stdint.h>
 #include <string.h>
@@ -53,7 +54,7 @@
 static void ld_fld_free(db_fld_t* fld, struct ld_fld* payload)
 {
 	db_drv_free(&payload->gen);
-	if (payload->values) ldap_value_free(payload->values);
+	if (payload->values) ldap_value_free_len(payload->values);
 	payload->values = NULL;
 	pkg_free(payload);
 }
@@ -97,48 +98,88 @@ int ld_resolve_fld(db_fld_t* fld, struct ld_config* cfg)
 }
 
 
+static inline int ldap_int2db_int(int* dst, str* src)
+{
+	if (str2sint(src, dst) != 0) {
+		ERR("ldap: Error while converting value '%.*s' to integer\n",
+			src->len, ZSW(src->s));
+		return -1;
+	}
+	return 0;
+}
+
+
+static inline int ldap_bit2db_int(int* dst, str* src)
+{
+	int i, v;
+
+	if (src->len > 32) {
+		WARN("ldap: bitString '%.*s'B is longer than 32 bits, truncating\n",
+			 src->len, ZSW(src->s));
+	}
+	v = 0;
+	for(i = 0; i < src->len; i++) {
+		v <<= 1;
+		v += src->s[i] - '0';
+	}
+	*dst = v;
+	return 0;
+}
+
+
 int ld_ldap2fld(db_fld_t* fld, LDAP* ldap, LDAPMessage* msg)
 {
 	int i;
 	struct ld_fld* lfld;
+	str tmp;
 
 	if (fld == NULL || msg == NULL) return 0;
 	for(i = 0; !DB_FLD_EMPTY(fld) && !DB_FLD_LAST(fld[i]); i++) {	
 		lfld = DB_GET_PAYLOAD(fld + i);
 
-		if (lfld->values) ldap_value_free(lfld->values);
-		lfld->values = ldap_get_values(ldap, msg, lfld->attr.s);
+		if (lfld->values) ldap_value_free_len(lfld->values);
+		lfld->values = ldap_get_values_len(ldap, msg, lfld->attr.s);
 
-		if (lfld->values == NULL) {
-			/* FIXME: Test for errno value here */
-			ERR("ldap: Error in ldap_get_values\n");
-			return -1;
-		}
-
-		if (lfld->values[0] == NULL) {
+		if (lfld->values == NULL || lfld->values[0] == NULL) {
 			fld[i].flags |= DB_NULL;
 			continue;
 		}
 
 		if (lfld->values[1] != NULL) {
-			ERR("ldap: Multivalue attributes not yet supported\n");
+			ERR("ldap: Multivalue attributes not yet supported: %.*s\n", 
+				lfld->attr.len, lfld->attr.s);
 			return -1;
 		}
 
 		switch(fld[i].type) {
-		case DB_STR:
-			fld[i].v.cstr = lfld->values[0];
+		case DB_CSTR:
+			fld[i].v.cstr = lfld->values[0]->bv_val;
 			break;
 
-		case DB_CSTR:
-			fld[i].v.lstr.s = lfld->values[0];
-			fld[i].v.lstr.len = strlen(lfld->values[0]);
+		case DB_STR:
+		case DB_BLOB:
+			fld[i].v.lstr.s = lfld->values[0]->bv_val;
+			fld[i].v.lstr.len = lfld->values[0]->bv_len;
 			break;
 
 		case DB_INT:
-			fld[i].v.int4 = 33;
-			break;
+		case DB_BITMAP:
+			tmp.s = lfld->values[0]->bv_val;
+			tmp.len = lfld->values[0]->bv_len;
 
+
+			if (tmp.s[0] == '\'' && 
+				tmp.s[tmp.len - 1] == 'B' &&
+				tmp.s[tmp.len - 2] == '\'') {
+
+				tmp.s++;
+				tmp.len -= 3;
+				return ldap_bit2db_int(&fld[i].v.int4, &tmp);
+			} else {
+				return ldap_int2db_int(&fld[i].v.int4, &tmp);
+			}
+			break;
+			
 		default:
 			ERR("ldap: Unsupported field type: %d\n", fld[i].type);
 			return -1;
diff --git a/modules/db_ldap/ld_fld.h b/modules/db_ldap/ld_fld.h
index 404f501..6994ace 100644
--- a/modules/db_ldap/ld_fld.h
+++ b/modules/db_ldap/ld_fld.h
@@ -48,7 +48,7 @@
 struct ld_fld {
 	db_drv_t gen;
 	str attr;  /**< Name of corresponding LDAP attribute */
-	char** values; /**< Values retrieved from the LDAP result */
+	struct berval** values; /**< Values retrieved from the LDAP result */
 };
 
 
diff --git a/modules/db_ldap/todo.txt b/modules/db_ldap/todo.txt
index 6c75a58..7e9c544 100644
--- a/modules/db_ldap/todo.txt
+++ b/modules/db_ldap/todo.txt
@@ -8,6 +8,4 @@
 * Proper handling of NULL values
 * use the asynchronous functions of the api instead of synchronous
 * Support for multi-value attributes (they should be broken up into rows)
-* Handle the value in LDAP_RES_SEARCH_RESULT somehow intelligently (it
-  may indicate a failure)
 




More information about the sr-dev mailing list