diff options
author | Tomas Guisasola <tomas@luaforge.net> | 2003-06-16 16:41:15 +0000 |
---|---|---|
committer | Tomas Guisasola <tomas@luaforge.net> | 2003-06-16 16:41:15 +0000 |
commit | bf486bd844df001e0bd515e4c244f9fb5ef3e901 (patch) | |
tree | 1a629a39e72b10caa72eb0b45a6eab4960985ce4 /lualdap/src | |
parent | Remocao de comentarios. (diff) | |
download | lualdap-bf486bd844df001e0bd515e4c244f9fb5ef3e901.tar.xz lualdap-bf486bd844df001e0bd515e4c244f9fb5ef3e901.zip |
Acrescimo da operacao de adicao.
Diffstat (limited to 'lualdap/src')
-rwxr-xr-x | lualdap/src/lualdap.c | 432 |
1 files changed, 297 insertions, 135 deletions
diff --git a/lualdap/src/lualdap.c b/lualdap/src/lualdap.c index 41b1a90..1f9079e 100755 --- a/lualdap/src/lualdap.c +++ b/lualdap/src/lualdap.c @@ -1,6 +1,6 @@ /* ** LuaLDAP -** $Id: lualdap.c,v 1.3 2003-06-16 10:36:01 tomas Exp $ +** $Id: lualdap.c,v 1.4 2003-06-16 16:41:15 tomas Exp $ */ #include <stdlib.h> @@ -49,26 +49,45 @@ static conn_data *getconnection (lua_State *L) { /* +** Copy a Lua string to a C string optionally indicating length. +*/ +static char *luastrcpy (lua_State *L, int index, size_t *length) { + size_t len = lua_strlen (L, index); + char *str = malloc (len * sizeof(char)); + memcpy (str, lua_tostring (L, index), len); + if (length) + *length = len; + return str; +} + + +/* ** Create a NULL-terminated array of C-strings from a Lua table. -** @param tab stack index of the table. +** It also works for one string (instead of a table with a unique value). +** @param tab stack index of the table (or string). ** @return NULL-terminated array of C-strings. */ static char **table2strarray (lua_State *L, int tab) { char **array; int i; - int n = luaL_getn (L, tab); - array = malloc ((n+1) * sizeof(char *)); - for (i = 0; i < n; i++) { - lua_rawgeti (L, tab, i+1); /* get table element */ - if (lua_isstring (L, -1)) { - int len = lua_strlen (L, -1); - array[i] = malloc (len * sizeof(char)); - memcpy (array[i], lua_tostring (L, -1), len); - } else { + int n; + if (lua_istable (L, tab)) { + n = luaL_getn (L, tab); + array = malloc ((n+1) * sizeof(char *)); + for (i = 0; i < n; i++) { + lua_rawgeti (L, tab, i+1); /* push table element */ + if (lua_isstring (L, -1)) + array[i] = luastrcpy (L, -1, NULL); + else { + luaL_error (L, LUALDAP_PREFIX"invalid value"); + } } + lua_pop (L, n); + } else if (lua_isstring (L, tab)) { + array = malloc (2 * sizeof(char *)); + array[0] = luastrcpy (L, -1, NULL); } array[n] = NULL; - lua_pop (L, n); return array; } @@ -87,6 +106,55 @@ static void free_strarray (char **array) { /* +** Create a NULL-terminated array of berval strings from a Lua table. +** It also works for one string (instead of a table with a unique value). +** @param tab stack index of the table (or string). +** @return NULL-terminated array of berval strings. +*/ +static BerValue **table2bervalarray (lua_State *L, int tab) { + BerValue **array; + int i; + int n; + if (lua_istable (L, tab)) { + n = luaL_getn (L, tab); + array = malloc ((n+1) * sizeof(BerValue *)); + for (i = 0; i < n; i++) { + lua_rawgeti (L, tab, i+1); /* push table element */ + if (lua_isstring (L, -1)) { + array[i] = (BerValue *)malloc (sizeof (BerValue)); + array[i]->bv_val = luastrcpy (L, -1, &(array[i]->bv_len)); + } else { + luaL_error (L, LUALDAP_PREFIX"invalid value"); + } + } + lua_pop (L, n); + } else if (lua_isstring (L, tab)) { + n = 1; + array = (BerValue **)malloc (2 * sizeof(BerValue *)); + array[0] = (BerValue *)malloc (sizeof (BerValue)); + array[0]->bv_val = luastrcpy (L, -1, &(array[0]->bv_len)); + } + array[n] = NULL; + return array; +} + + +/* +** Free a NULL-terminated array of bervalstrings. +*/ +static void free_bervalarray (BerValue **array) { + if (array) { + int i; + for (i = 0; array[i] != NULL; i++) { + free (array[i]->bv_val); + free (array[i]); + } + free (array); + } +} + + +/* ** Unbind from the directory. ** @param #1 LDAP connection. ** @return 1 in case of success; nothing when already closed. @@ -106,160 +174,95 @@ static int lualdap_close (lua_State *L) { /* -** Push an attribute value (or a table of values) on top of the stack. -** @param entry Current entry. -** @param attr Name of entry's attribute to get values from. -** @return 1 in case of success. +** Counts the number of string keys of a given table. */ -static int pushvalues (lua_State *L, LDAP *ld, LDAPMessage *entry, char *attr) { - int i, n; - BerValue **vals = ldap_get_values_len (ld, entry, attr); - if ((n = ldap_count_values_len (vals)) == 1) - lua_pushlstring (L, vals[0]->bv_val, vals[0]->bv_len); - else { /* Multiple values */ - lua_newtable (L); - for (i = 0; i < n; i++) { - lua_pushlstring (L, vals[i]->bv_val, vals[i]->bv_len); - lua_rawseti (L, -2, i); - } +static size_t nstrkeys (lua_State *L, int tab) { + int n = 0; + lua_pushnil (L); + while (lua_next(L, tab) != 0) { + lua_pop (L, 1); + if (lua_isstring (L, -1)) + n++; } - ldap_value_free_len (vals); - return 1; + return n; } /* -** Store entry's distinguished name at the given table. -** @param entry Current entry. -** @param tab Absolute stack index of the table. +** Convert a pair (string, value) into a LDAPMod structure. +** Assume that string is at index -2 and value at -1. */ -static void setdn (lua_State *L, LDAP *ld, LDAPMessage *entry, int tab) { - char *dn = ldap_get_dn (ld, entry); - lua_pushstring (L, "dn"); - lua_pushstring (L, dn); - lua_rawset (L, tab); - ldap_memfree (dn); +static LDAPMod *attr2mod (lua_State *L, int op) { + LDAPMod *mod = (LDAPMod *)malloc (sizeof (LDAPMod)); + mod->mod_op = op; + mod->mod_type = luastrcpy (L, -2, NULL); + mod->mod_bvalues = table2bervalarray (L, lua_gettop(L)); + return mod; } /* -** Store entry's attributes and values at the given table. -** @param entry Current entry. -** @param tab Absolute stack index of the table. +** Free an LDAPMod structure. */ -static void setattribs (lua_State *L, LDAP *ld, LDAPMessage *entry, int tab) { - char *attr; - BerElement *ber = NULL; - for (attr = ldap_first_attribute (ld, entry, &ber); - attr != NULL; - attr = ldap_next_attribute (ld, entry, ber)) - { - lua_pushstring (L, attr); - pushvalues (L, ld, entry, attr); - lua_rawset (L, tab); /* tab[attr] = vals */ - ldap_memfree (attr); - } - if (ber) - ber_free (ber, 0); +static void free_mod (LDAPMod *mod) { + if (mod->mod_type) + free (mod->mod_type); + free_bervalarray (mod->mod_bvalues); + free (mod); } /* -** Retrieve the next message and all of its attributes and values. -** @param #1 LDAP connection. -** @param #2 previous entry (or nil if first call). -** @return #1 current entry (or nil if no more entries). -** @return #2 table with entry's attributes and values. +** Convert a Lua table into an array of attributes. +** An array of attributes is a NULL-terminated array of LDAPMod's. */ -static int search_entries (lua_State *L) { - conn_data *conn = (conn_data *)lua_touserdata (L, 1); - LDAPMessage *entry; - - /* get next (or first) entry */ - if (lua_isnil (L, 2)) /* first call */ - entry = ldap_first_entry (conn->ld, - (LDAPMessage *)lua_topointer (L, lua_upvalueindex (1))); - else /* get next message */ - entry = ldap_next_entry (conn->ld, (LDAPMessage *)lua_topointer(L,2)); - - if (entry == NULL) { /* no more messages */ - ldap_msgfree ((LDAPMessage *)lua_topointer (L, lua_upvalueindex(1))); - lua_pushnil (L); - return 1; - } else { /* build table of attributes and its values */ - int tab; - lua_pushlightuserdata (L, entry); /* push current entry */ - lua_newtable (L); - tab = lua_gettop (L); - setdn (L, conn->ld, entry, tab); - setattribs (L, conn->ld, entry, tab); - return 2; +static LDAPMod **table2attrarray (lua_State *L, int tab) { + LDAPMod **array; + size_t n = nstrkeys (L, tab); + array = (LDAPMod **)malloc ((n+1) * sizeof (LDAPMod *)); + array[n] = NULL; + n = 0; + lua_pushnil (L); + while (lua_next (L, tab) != 0) { + if (lua_isstring (L, -1)) { + array[n] = attr2mod (L, LDAP_MOD_ADD); + n++; + } + lua_pop (L, 1); } + return array; } /* -** Convert a string to one of the possible scopes of the search. +** Free an LDAPMod array. */ -static int string2scope (const char *s) { - switch (*s) { - case 'b': - return LDAP_SCOPE_BASE; - case 'o': - return LDAP_SCOPE_ONELEVEL; - case 's': - return LDAP_SCOPE_SUBTREE; - default: - return LDAP_SCOPE_DEFAULT; - } +static void free_attrarray (LDAPMod **array) { + int i; + for (i = 0; array[i] != NULL; i++) + free_mod (array[i]); + free (array); } /* -** Perform a search operation. +** Add a new entry to the directory. ** @param #1 LDAP connection. -** @param #2 String with base entry's DN. -** @param #3 String with search scope. -** @param #4 String with search filter. -** @param #5 Table with names of attributes to retrieve. -** @return #1 Function to iterate over the result entries. -** @return #2 LDAP connection. -** @return #3 nil as first entry. -** The search result is defined as an upvalue of the iterator. +** @param #2 String with new entry's DN. +** @param #3 Table with new entry's attributes and values. +** @return ?? */ -static int lualdap_search_attribs (lua_State *L) { +static int lualdap_add (lua_State *L) { conn_data *conn = (conn_data *)getconnection (L); - const char *base = luaL_check_string (L, 2); - int scope = string2scope (luaL_check_string (L, 3)); - const char *filter = luaL_check_string (L, 4); - char **attrs = NULL; - int attrsonly = 0; /* types and values. parameter? */ - int msgid; - int rc; - LDAPMessage *res; - struct timeval *timeout = NULL; /* ??? function parameter ??? */ - int sizelimit = LDAP_NO_LIMIT; /* ??? function parameter ??? */ - - if (lua_istable (L, 5)) - attrs = table2strarray (L, 5); - rc = ldap_search_ext (conn->ld, base, scope, filter, attrs, attrsonly, - NULL, NULL, timeout, sizelimit, &msgid); - free_strarray (attrs); - if (rc != LDAP_SUCCESS) + const char *dn = luaL_check_string (L, 2); + LDAPMod **attrs = table2attrarray (L, 3); + int rc = ldap_add_ext_s (conn->ld, dn, attrs, NULL, NULL); + free_attrarray (attrs); + if (rc == LDAP_SUCCESS) { + lua_pushboolean (L, 1); + return 1; + } else return faildirect (L, ldap_err2string (rc)); - - rc = ldap_result (conn->ld, LDAP_RES_ANY, LDAP_MSG_ALL, timeout, &res); - if (rc == 0) - return faildirect (L, LUALDAP_PREFIX"result timeout expired"); - else if (rc == -1) - return faildirect (L, LUALDAP_PREFIX"result error"); - - lua_pushlightuserdata (L, res); /* push result as upvalue for iterator */ - lua_pushcclosure (L, search_entries, 1); /* push iterator function */ - lua_pushvalue (L, 1); /* push connection as "state" to iterator */ - lua_pushnil (L); /* push nil as "initial value" for iterator */ - - return 3; } @@ -453,6 +456,164 @@ static int lualdap_modify (lua_State *L) { /* +** Push an attribute value (or a table of values) on top of the stack. +** @param entry Current entry. +** @param attr Name of entry's attribute to get values from. +** @return 1 in case of success. +*/ +static int pushvalues (lua_State *L, LDAP *ld, LDAPMessage *entry, char *attr) { + int i, n; + BerValue **vals = ldap_get_values_len (ld, entry, attr); + if ((n = ldap_count_values_len (vals)) == 1) + lua_pushlstring (L, vals[0]->bv_val, vals[0]->bv_len); + else { /* Multiple values */ + lua_newtable (L); + for (i = 0; i < n; i++) { + lua_pushlstring (L, vals[i]->bv_val, vals[i]->bv_len); + lua_rawseti (L, -2, i); + } + } + ldap_value_free_len (vals); + return 1; +} + + +/* +** Store entry's distinguished name at the given table. +** @param entry Current entry. +** @param tab Absolute stack index of the table. +*/ +static void setdn (lua_State *L, LDAP *ld, LDAPMessage *entry, int tab) { + char *dn = ldap_get_dn (ld, entry); + lua_pushstring (L, "dn"); + lua_pushstring (L, dn); + lua_rawset (L, tab); + ldap_memfree (dn); +} + + +/* +** Store entry's attributes and values at the given table. +** @param entry Current entry. +** @param tab Absolute stack index of the table. +*/ +static void setattribs (lua_State *L, LDAP *ld, LDAPMessage *entry, int tab) { + char *attr; + BerElement *ber = NULL; + for (attr = ldap_first_attribute (ld, entry, &ber); + attr != NULL; + attr = ldap_next_attribute (ld, entry, ber)) + { + lua_pushstring (L, attr); + pushvalues (L, ld, entry, attr); + lua_rawset (L, tab); /* tab[attr] = vals */ + ldap_memfree (attr); + } + if (ber) + ber_free (ber, 0); +} + + +/* +** Retrieve the next message and all of its attributes and values. +** @param #1 LDAP connection. +** @param #2 previous entry (or nil if first call). +** @return #1 current entry (or nil if no more entries). +** @return #2 table with entry's attributes and values. +*/ +static int search_entries (lua_State *L) { + conn_data *conn = (conn_data *)lua_touserdata (L, 1); + LDAPMessage *entry; + + /* get next (or first) entry */ + if (lua_isnil (L, 2)) /* first call */ + entry = ldap_first_entry (conn->ld, + (LDAPMessage *)lua_topointer (L, lua_upvalueindex (1))); + else /* get next message */ + entry = ldap_next_entry (conn->ld, (LDAPMessage *)lua_topointer(L,2)); + + if (entry == NULL) { /* no more messages */ + ldap_msgfree ((LDAPMessage *)lua_topointer (L, lua_upvalueindex(1))); + lua_pushnil (L); + return 1; + } else { /* build table of attributes and its values */ + int tab; + lua_pushlightuserdata (L, entry); /* push current entry */ + lua_newtable (L); + tab = lua_gettop (L); + setdn (L, conn->ld, entry, tab); + setattribs (L, conn->ld, entry, tab); + return 2; + } +} + + +/* +** Convert a string to one of the possible scopes of the search. +*/ +static int string2scope (const char *s) { + switch (*s) { + case 'b': + return LDAP_SCOPE_BASE; + case 'o': + return LDAP_SCOPE_ONELEVEL; + case 's': + return LDAP_SCOPE_SUBTREE; + default: + return LDAP_SCOPE_DEFAULT; + } +} + + +/* +** Perform a search operation. +** @param #1 LDAP connection. +** @param #2 String with base entry's DN. +** @param #3 String with search scope. +** @param #4 String with search filter. +** @param #5 Table with names of attributes to retrieve. +** @return #1 Function to iterate over the result entries. +** @return #2 LDAP connection. +** @return #3 nil as first entry. +** The search result is defined as an upvalue of the iterator. +*/ +static int lualdap_search_attribs (lua_State *L) { + conn_data *conn = (conn_data *)getconnection (L); + const char *base = luaL_check_string (L, 2); + int scope = string2scope (luaL_check_string (L, 3)); + const char *filter = luaL_check_string (L, 4); + char **attrs = NULL; + int attrsonly = 0; /* types and values. parameter? */ + int msgid; + int rc; + LDAPMessage *res; + struct timeval *timeout = NULL; /* ??? function parameter ??? */ + int sizelimit = LDAP_NO_LIMIT; /* ??? function parameter ??? */ + + if (lua_istable (L, 5)) + attrs = table2strarray (L, 5); + rc = ldap_search_ext (conn->ld, base, scope, filter, attrs, attrsonly, + NULL, NULL, timeout, sizelimit, &msgid); + free_strarray (attrs); + if (rc != LDAP_SUCCESS) + return faildirect (L, ldap_err2string (rc)); + + rc = ldap_result (conn->ld, LDAP_RES_ANY, LDAP_MSG_ALL, timeout, &res); + if (rc == 0) + return faildirect (L, LUALDAP_PREFIX"result timeout expired"); + else if (rc == -1) + return faildirect (L, LUALDAP_PREFIX"result error"); + + lua_pushlightuserdata (L, res); /* push result as upvalue for iterator */ + lua_pushcclosure (L, search_entries, 1); /* push iterator function */ + lua_pushvalue (L, 1); /* push connection as "state" to iterator */ + lua_pushnil (L); /* push nil as "initial value" for iterator */ + + return 3; +} + + +/* ** Set metatable of userdata on top of the stack. */ static void lualdap_setmeta (lua_State *L) { @@ -467,6 +628,7 @@ static void lualdap_setmeta (lua_State *L) { static int lualdap_createmeta (lua_State *L) { const luaL_reg methods[] = { {"close", lualdap_close}, + {"add", lualdap_add}, {"compare", lualdap_compare}, {"delete", lualdap_delete}, {"modify", lualdap_modify}, |