diff options
Diffstat (limited to 'ext/ldap/ldap.c')
| -rw-r--r-- | ext/ldap/ldap.c | 1275 |
1 files changed, 1275 insertions, 0 deletions
diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c new file mode 100644 index 0000000000..b4bc182982 --- /dev/null +++ b/ext/ldap/ldap.c @@ -0,0 +1,1275 @@ +/* + +----------------------------------------------------------------------+ + | PHP HTML Embedded Scripting Language Version 3.0 | + +----------------------------------------------------------------------+ + | Copyright (c) 1997,1998 PHP Development Team (See Credits file) | + +----------------------------------------------------------------------+ + | This program is free software; you can redistribute it and/or modify | + | it under the terms of one of the following licenses: | + | | + | A) the GNU General Public License as published by the Free Software | + | Foundation; either version 2 of the License, or (at your option) | + | any later version. | + | | + | B) the PHP License as published by the PHP Development Team and | + | included in the distribution in the file: LICENSE | + | | + | This program is distributed in the hope that it will be useful, | + | but WITHOUT ANY WARRANTY; without even the implied warranty of | + | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | + | GNU General Public License for more details. | + | | + | You should have received a copy of both licenses referred to here. | + | If you did not, or have any questions about PHP licensing, please | + | contact core@php.net. | + +----------------------------------------------------------------------+ + | Authors: Amitay Isaacs <amitay@w-o-i.com> | + | Eric Warnke <ericw@albany.edu> | + | Rasmus Lerdorf <rasmus@lerdorf.on.ca> | + +----------------------------------------------------------------------+ + */ + + +/* $Id$ */ +#define IS_EXT_MODULE +#if !PHP_31 && defined(THREAD_SAFE) +#undef THREAD_SAFE +#endif +#ifdef THREAD_SAFE +#include "tls.h" +DWORD ldapTLS; +static int numthreads=0; +void *ldap_mutex; +#endif + +#if !(WIN32|WINNT) +#include "config.h" +#endif +#include "php.h" + +#if HAVE_LDAP + +#if COMPILE_DL +#if PHP_31 +#include "ext/phpdl.h" +#include "ext/standard/dl.h" +#else +#include "dl/phpdl.h" +#include "functions/dl.h" +#endif +#endif +#include "php3_ldap.h" + +#if WIN32|WINNT +#include <string.h> +#if HAVE_NSLDAP +#include <winsock.h> +#endif +#define strdup _strdup +#undef WINDOWS +#undef strcasecmp +#undef strncasecmp +#define WINSOCK 1 +#define __STDC__ 1 +#endif + +#if PHP_31 +#include "ext/standard/php3_string.h" +#else +#include "functions/php3_string.h" +#endif + + +#if THREAD_SAFE & HAVE_NSLDAP +#include "php3_threads.h" +/* Structure for LDAP error values */ +#define LDAP_TLS_VARS ldap_module *PHP3_TLS_GET(ldapTLS,php3_ldap_module) +#define LDAP_GLOBAL(a) php3_ldap_module->a +#else +#define LDAP_TLS_VARS +#define LDAP_GLOBAL(a) php3_ldap_module.a +ldap_module php3_ldap_module; +#endif + + + +/* + This is just a small subset of the functionality provided by the LDAP library. All the + operations are synchronous. Referrals are not handled automatically. +*/ + +function_entry ldap_functions[] = { + {"ldap_connect", php3_ldap_connect, NULL}, + {"ldap_close", php3_ldap_unbind, NULL}, + {"ldap_bind", php3_ldap_bind, NULL}, + {"ldap_unbind", php3_ldap_unbind, NULL}, + {"ldap_read", php3_ldap_read, NULL}, + {"ldap_list", php3_ldap_list, NULL}, + {"ldap_search", php3_ldap_search, NULL}, + {"ldap_free_result", php3_ldap_free_result, NULL}, + {"ldap_count_entries", php3_ldap_count_entries, NULL}, + {"ldap_first_entry", php3_ldap_first_entry, NULL}, + {"ldap_next_entry", php3_ldap_next_entry, NULL}, + {"ldap_get_entries", php3_ldap_get_entries, NULL}, + {"ldap_first_attribute", php3_ldap_first_attribute, NULL}, + {"ldap_next_attribute", php3_ldap_next_attribute, NULL}, + {"ldap_get_attributes", php3_ldap_get_attributes, NULL}, + {"ldap_get_values", php3_ldap_get_values, NULL}, + {"ldap_get_dn", php3_ldap_get_dn, NULL}, + {"ldap_explode_dn", php3_ldap_explode_dn, NULL}, + {"ldap_dn2ufn", php3_ldap_dn2ufn, NULL}, + {"ldap_add", php3_ldap_add, NULL}, + {"ldap_delete", php3_ldap_delete, NULL}, + {"ldap_modify", php3_ldap_modify, NULL}, + {NULL, NULL, NULL} +}; + + +php3_module_entry ldap_module_entry = { + "LDAP", ldap_functions, php3_minit_ldap, php3_mshutdown_ldap, NULL, NULL, php3_info_ldap, STANDARD_MODULE_PROPERTIES +}; + + + +#if COMPILE_DL +DLEXPORT php3_module_entry *get_module(void ) { return &ldap_module_entry; } +#endif + + +#if 0 /* see my note in php3_ldap.h. smc */ +/* Function for setting thread-specific LDAP error values */ +static void php3_ldap_set_ld_error( int err, char *matched, char *errmsg, void *dummy ) +{ + LDAP_TLS_VARS; + + /* Set the error code returned by the LDAP operation */ + LDAP_GLOBAL(le_errno) = err; + /* Specify the components of the DN that matched (if + an "NO_SUCH_OBJECT" error occurred */ + if ( LDAP_GLOBAL(le_matched) != NULL ) { + ldap_memfree( LDAP_GLOBAL(le_matched) ); + } + LDAP_GLOBAL(le_matched) = matched; + /* Specify the error message corresponding to the error code */ + if ( LDAP_GLOBAL(le_errmsg) != NULL ) { + ldap_memfree( LDAP_GLOBAL(le_errmsg) ); + } + LDAP_GLOBAL(le_errmsg) = errmsg; +} + +/* Function for getting the thread-specific LDAP error values */ +static int php3_ldap_get_ld_error( char **matched, char **errmsg, void *dummy ) +{ + LDAP_TLS_VARS; + /* Retrieve the error values */ + if ( matched != NULL ) { + *matched = LDAP_GLOBAL(le_matched); + } + if ( errmsg != NULL ) { + *errmsg = LDAP_GLOBAL(le_errmsg); + } + return( LDAP_GLOBAL(le_errno) ); +} + +/* Function for setting the value of the errno variable */ +static void php3_ldap_set_errno( int err ) +{ + errno = err; +} + +/* Function for getting the value of the errno variable */ +static int php3_ldap_get_errno( void ) +{ + return( errno ); +} +#endif /* THREAD_SAFE && NSLDAP */ + +static void _close_ldap_link(LDAP *ld) +{ + LDAP_TLS_VARS; + ldap_unbind_s(ld); + /* php3_printf("Freeing ldap connection");*/ + LDAP_GLOBAL(num_links)--; +} + + +static void _free_ldap_result(LDAPMessage *result) +{ + ldap_msgfree(result); +} + +int php3_minit_ldap(INIT_FUNC_ARGS) +{ +#if defined(THREAD_SAFE) + ldap_module *php3_ldap_module; + PHP3_MUTEX_ALLOC(ldap_mutex); + PHP3_MUTEX_LOCK(ldap_mutex); + numthreads++; + if (numthreads==1){ + if (!PHP3_TLS_PROC_STARTUP(ldapTLS)){ + PHP3_MUTEX_UNLOCK(ldap_mutex); + PHP3_MUTEX_FREE(ldap_mutex); + return 0; + } + } + PHP3_MUTEX_UNLOCK(ldap_mutex); + if(!PHP3_TLS_THREAD_INIT(ldapTLS,php3_ldap_module,ldap_module)) + return 0; +#if 0 /*HAVE_NSLDAP*/ + /* Set up the ldap_thread_fns structure with pointers + to the functions that you want called */ + memset( &LDAP_GLOBAL(tfns), '\0', sizeof(struct ldap_thread_fns) ); + /* Specify the functions that you want called */ + /* Call the my_mutex_alloc() function whenever mutexes + need to be allocated */ + LDAP_GLOBAL(tfns).ltf_mutex_alloc = (void *(*)(void)) php3_mutex_alloc; + /* Call the my_mutex_free() function whenever mutexes + need to be destroyed */ + LDAP_GLOBAL(tfns).ltf_mutex_free = (void (*)(void *)) php3_mutex_free; + /* Call the pthread_mutex_lock() function whenever a + thread needs to lock a mutex. */ + LDAP_GLOBAL(tfns).ltf_mutex_lock = (int (*)(void *)) php3_mutex_lock; + /* Call the pthread_mutex_unlock() function whenever a + thread needs to unlock a mutex. */ + LDAP_GLOBAL(tfns).ltf_mutex_unlock = (int (*)(void *)) php3_mutex_unlock; + /* Call the get_errno() function to get the value of errno */ + LDAP_GLOBAL(tfns).ltf_get_errno = php3_ldap_get_errno; + /* Call the set_errno() function to set the value of errno */ + LDAP_GLOBAL(tfns).ltf_set_errno = php3_ldap_set_errno; + /* Call the get_ld_error() function to get error values from + calls to functions in the libldap library */ + LDAP_GLOBAL(tfns).ltf_get_lderrno = php3_ldap_get_ld_error; + /* Call the set_ld_error() function to set error values for + calls to functions in the libldap library */ + LDAP_GLOBAL(tfns).ltf_set_lderrno = php3_ldap_set_ld_error; + /* Don't pass any extra parameter to the functions for + getting and setting libldap function call errors */ + LDAP_GLOBAL(tfns).ltf_lderrno_arg = NULL; +/* Set the session option that specifies the functions to call for multi-threaded clients */ + if (ldap_set_option( ld, LDAP_OPT_THREAD_FN_PTRS, (void *) &LDAP_GLOBAL(tfns))!= 0) { + ldap_perror( ld, "ldap_set_option: thread pointers" ); + } +#endif +#endif + if (cfg_get_long("ldap.max_links", &LDAP_GLOBAL(max_links)) == FAILURE) { + LDAP_GLOBAL(max_links) = -1; + } + + if (cfg_get_string("ldap.base_dn", &LDAP_GLOBAL(base_dn)) == FAILURE) { + LDAP_GLOBAL(base_dn) = NULL; + } + + LDAP_GLOBAL(le_result) = register_list_destructors(_free_ldap_result, NULL); + LDAP_GLOBAL(le_link) = register_list_destructors(_close_ldap_link, NULL); + + /*FIXME is this safe in threaded environment? if so, please comment*/ + ldap_module_entry.type = type; + + return SUCCESS; +} + +int php3_mshutdown_ldap(void){ +#ifdef THREAD_SAFE + LDAP_TLS_VARS; + PHP3_TLS_THREAD_FREE(php3_ldap_module); + PHP3_MUTEX_LOCK(ldap_mutex); + numthreads--; + if (!numthreads) { + PHP3_TLS_PROC_SHUTDOWN(ldapTLS); + } + PHP3_MUTEX_UNLOCK(ldap_mutex); + PHP3_MUTEX_FREE(ldap_mutex); +#endif + return SUCCESS; +} + +void php3_info_ldap(void) +{ + char maxl[16]; +#if HAVE_NSLDAP + LDAPVersion ver; + double SDKVersion; + /* Print version information */ + SDKVersion = ldap_version( &ver ); +#endif + LDAP_TLS_VARS; + + if (LDAP_GLOBAL(max_links) == -1) { + strcpy(maxl, "Unlimited"); + } else { + snprintf(maxl, 15, "%ld", LDAP_GLOBAL(max_links)); + maxl[15] = 0; + } + + php3_printf("<table>" + "<tr><td>Total links:</td><td>%d/%s</td></tr>\n" + "<tr><td>RCS Version:</td><td>$Id$</td></tr>\n" +#if HAVE_NSLDAP + "<tr><td>SDK Version:</td><td>%f</td></tr>" + "<tr><td>Highest LDAP Protocol Supported:</td><td>%f</td></tr>" + "<tr><td>SSL Level Supported:</td><td>%f</td></tr>" +#endif + ,LDAP_GLOBAL(num_links),maxl +#if HAVE_NSLDAP + ,SDKVersion/100.0,ver.protocol_version/100.0,ver.SSL_version/100.0 +#endif + ); +#if HAVE_NSLDAP + if ( ver.security_level != LDAP_SECURITY_NONE ) { + php3_printf( "<tr><td>Level of encryption:</td><td>%d bits</td></tr>\n", ver.security_level ); + } else { + php3_printf( "<tr><td>SSL not enabled.</td><td></td></tr>\n" ); + } +#endif + php3_printf("</table>\n"); + +} + +/* {{{ proto int ldap_connect([string host [, int port]]) + Connect to an LDAP server */ +void php3_ldap_connect(INTERNAL_FUNCTION_PARAMETERS) +{ + char *host; + int port; + /* char *hashed_details; + int hashed_details_length;*/ + LDAP *ldap; + LDAP_TLS_VARS; + + switch(ARG_COUNT(ht)) { + case 0: + host = NULL; + port = 0; + /* hashed_details = estrndup("ldap_", 5); + hashed_details_length = 4+1; */ + break; + + case 1: { + pval *yyhost; + + if (getParameters(ht, 1, &yyhost) == FAILURE) { + RETURN_FALSE; + } + + convert_to_string(yyhost); + host = yyhost->value.str.val; + port = 389; /* Default port */ + + /* hashed_details_length = yyhost->value.str.len+4+1; + hashed_details = emalloc(hashed_details_length+1); + sprintf(hashed_details, "ldap_%s", yyhost->value.str.val);*/ + } + break; + + case 2: { + pval *yyhost, *yyport; + + if (getParameters(ht, 2, &yyhost, &yyport) == FAILURE) { + RETURN_FALSE; + } + + convert_to_string(yyhost); + host = yyhost->value.str.val; + convert_to_long(yyport); + port = yyport->value.lval; + + /* Do we need to take care of hosts running multiple LDAP servers ? */ + /* hashed_details_length = yyhost->value.str.len+4+1; + hashed_details = emalloc(hashed_details_length+1); + sprintf(hashed_details, "ldap_%s", yyhost->value.str.val);*/ + } + break; + + default: + WRONG_PARAM_COUNT; + break; + } + + if (LDAP_GLOBAL(max_links)!=-1 && LDAP_GLOBAL(num_links)>=LDAP_GLOBAL(max_links)) { + php3_error(E_WARNING, "LDAP: Too many open links (%d)", LDAP_GLOBAL(num_links)); + RETURN_FALSE; + } + + ldap = ldap_open(host,port); + if ( ldap == NULL ) { + RETURN_FALSE; + } else { + RETURN_LONG(php3_list_insert((void*)ldap,LDAP_GLOBAL(le_link))); + } + +} +/* }}} */ + + +static LDAP * _get_ldap_link(pval *link, HashTable *list) +{ + LDAP *ldap; + int type; + LDAP_TLS_VARS; + + convert_to_long(link); + ldap = (LDAP *) php3_list_find(link->value.lval, &type); + + if (!ldap || !(type == LDAP_GLOBAL(le_link))) { + php3_error(E_WARNING, "%d is not a LDAP link index", link->value.lval); + return NULL; + } + return ldap; +} + + +static LDAPMessage * _get_ldap_result(pval *result, HashTable *list) +{ + LDAPMessage *ldap_result; + int type; + LDAP_TLS_VARS; + + convert_to_long(result); + ldap_result = (LDAPMessage *) php3_list_find(result->value.lval, &type); + + if (!ldap_result || type != LDAP_GLOBAL(le_result)) { + php3_error(E_WARNING, "%d is not a LDAP result index", result->value.lval); + return NULL; + } + + return ldap_result; +} + + +static LDAPMessage * _get_ldap_result_entry(pval *result, HashTable *list) +{ + LDAPMessage *ldap_result_entry; + int type; + LDAP_TLS_VARS; + + convert_to_long(result); + ldap_result_entry = (LDAPMessage *) php3_list_find(result->value.lval, &type); + + if (!ldap_result_entry || type != LDAP_GLOBAL(le_result_entry)) { + php3_error(E_WARNING, "%d is not a LDAP result entry index", result->value.lval); + return NULL; + } + + return ldap_result_entry; +} + + +static BerElement * _get_ber_entry(pval *berp, HashTable *list) +{ + BerElement *ber; + int type; + LDAP_TLS_VARS; + + convert_to_long(berp); + ber = (BerElement *) php3_list_find(berp->value.lval, &type); + + if ( type != LDAP_GLOBAL(le_ber_entry)) { + php3_error(E_WARNING, "%d is not a BerElement index", berp->value.lval); + return NULL; + } + + return ber; +} + +#if 0 +void php3_ber_free(INTERNAL_FUNCTION_PARAMETERS) +{ + pval *berp; + + if ( getParameters(ht,1,&berp) == FAILURE ) RETURN_FALSE; + + php3_list_delete(berp->value.lval); + RETURN_TRUE; +} +#endif + +/* {{{ proto int ldap_bind(int link [, string dn, string password]) + Bind to LDAP directory */ +void php3_ldap_bind(INTERNAL_FUNCTION_PARAMETERS) +{ +pval *link, *bind_rdn, *bind_pw; +char *ldap_bind_rdn, *ldap_bind_pw; +LDAP *ldap; + + switch(ARG_COUNT(ht)) { + case 1: /* Anonymous Bind */ + if (getParameters(ht, 1, &link) == FAILURE) { + RETURN_FALSE; + } + + ldap_bind_rdn = NULL; + ldap_bind_pw = NULL; + + break; + + case 3 : + if (getParameters(ht, 3, &link, &bind_rdn, &bind_pw) == FAILURE) { + RETURN_FALSE; + } + + convert_to_string(bind_rdn); + convert_to_string(bind_pw); + + ldap_bind_rdn = bind_rdn->value.str.val; + ldap_bind_pw = bind_pw->value.str.val; + + break; + + default: + WRONG_PARAM_COUNT; + break; + } + + ldap = _get_ldap_link(link, list); + if (ldap == NULL) RETURN_FALSE; + + if (ldap_bind_s(ldap, ldap_bind_rdn, ldap_bind_pw, LDAP_AUTH_SIMPLE) != LDAP_SUCCESS) { +#if !HAVE_NSLDAP +#if LDAP_API_VERSION > 2000 + /* New versions of OpenLDAP do it this way */ + php3_error(E_WARNING,"LDAP: Unable to bind to server: %s",ldap_err2string(ldap_get_lderrno(ldap,NULL,NULL))); +#else + php3_error(E_WARNING,"LDAP: Unable to bind to server: %s",ldap_err2string(ldap->ld_errno)); +#endif +#endif + RETURN_FALSE; + } else { + RETURN_TRUE; + } +} +/* }}} */ + +/* {{{ proto int ldap_unbind(int link) + Unbind from LDAP directory */ +void php3_ldap_unbind(INTERNAL_FUNCTION_PARAMETERS) +{ +pval *link; +LDAP *ldap; + + if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &link) == FAILURE) { + WRONG_PARAM_COUNT; + } + + convert_to_long(link); + + ldap = _get_ldap_link(link, list); + if (ldap == NULL) RETURN_FALSE; + + php3_list_delete(link->value.lval); + RETURN_TRUE; +} +/* }}} */ + + +static void php3_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope) +{ + pval *link, *base_dn, *filter, *attrs, *attr; + char *ldap_base_dn, *ldap_filter; + LDAP *ldap; + char **ldap_attrs = NULL; + int attrsonly; + LDAPMessage *ldap_result; + int num_attribs=0, i; + LDAP_TLS_VARS; + + switch(ARG_COUNT(ht)) { + case 3 : + if (getParameters(ht, 3, &link, &base_dn, &filter) == FAILURE) { + RETURN_FALSE; + } + + convert_to_string(base_dn); + convert_to_string(filter); + + ldap_base_dn = base_dn->value.str.val; + ldap_filter = filter->value.str.val; + + break; + + case 4 : + if (getParameters(ht, 4, &link, &base_dn, &filter, &attrs) == FAILURE) { + RETURN_FALSE; + } + + if (attrs->type != IS_ARRAY) { + php3_error(E_WARNING, "LDAP: Expected Array as last element"); + RETURN_FALSE; + } + + convert_to_string(base_dn); + convert_to_string(filter); + + ldap_base_dn = base_dn->value.str.val; + ldap_filter = filter->value.str.val; + + num_attribs = _php3_hash_num_elements(attrs->value.ht); + if ((ldap_attrs = emalloc((num_attribs+1) * sizeof(char *))) == NULL) { + php3_error(E_WARNING, "LDAP: Could not allocate memory"); + RETURN_FALSE; + return; + } + + for(i=0; i<num_attribs; i++) { + if (_php3_hash_index_find(attrs->value.ht, i, (void **) &attr) == FAILURE) { + php3_error(E_WARNING, "LDAP: Array initialization wrong"); + RETURN_FALSE; + return; + } + convert_to_string(attr); + ldap_attrs[i] = attr->value.str.val; + } + ldap_attrs[num_attribs] = NULL; + + break; + + default: + WRONG_PARAM_COUNT; + break; + } + + /* fix to make null base_dn's work */ + if ( strlen(ldap_base_dn) < 1 ) { + ldap_base_dn = NULL; + } + + ldap = _get_ldap_link(link, list); + if (ldap == NULL) RETURN_FALSE; + + /* Is it useful to only get the attributes ? */ + attrsonly = 0; + + /* We can possibly add the timeout value also */ + + if (ldap_search_s(ldap, ldap_base_dn, scope, ldap_filter, ldap_attrs, attrsonly, &ldap_result) != LDAP_SUCCESS) { +#if !HAVE_NSLDAP +#if LDAP_API_VERSION > 2000 + php3_error(E_WARNING,"LDAP: Unable to perform the search: %s",ldap_err2string(ldap_get_lderrno(ldap,NULL,NULL))); +#else + php3_error(E_WARNING, "LDAP: Unable to perform the search: %s", ldap_err2string(ldap->ld_errno)); +#endif +#endif + RETVAL_FALSE; + } else { + RETVAL_LONG(php3_list_insert(ldap_result, LDAP_GLOBAL(le_result))); + } + + if (ldap_attrs != NULL) { + /* for(i=0; i<num_attribs; i++) efree(ldap_attrs[i]); */ + efree(ldap_attrs); + } + return; +} + +/* {{{ proto int ldap_read(int link, string base_dn, string filter [, string attributes]) + Read an entry */ +void php3_ldap_read(INTERNAL_FUNCTION_PARAMETERS) +{ + php3_ldap_do_search(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_SCOPE_BASE); +} +/* }}} */ + +/* {{{ proto int ldap_list(int link, string base_dn, string filter [, string attributes]) + Single-level search */ +void php3_ldap_list(INTERNAL_FUNCTION_PARAMETERS) +{ + php3_ldap_do_search(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_SCOPE_ONELEVEL); +} +/* }}} */ + + +/* {{{ proto int ldap_search(int link, string base_dn, string filter [, string attributes]) + Search LDAP tree under base_dn */ +void php3_ldap_search(INTERNAL_FUNCTION_PARAMETERS) +{ + php3_ldap_do_search(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_SCOPE_SUBTREE); +} +/* }}} */ + +/* {{{ proto int ldap_free_result(int result) + Free result memory */ +void php3_ldap_free_result(INTERNAL_FUNCTION_PARAMETERS) +{ +pval *result; +LDAPMessage *ldap_result; + + if (ARG_COUNT(ht) != 1 || getParameters(ht, 1, &result) == FAILURE) { + WRONG_PARAM_COUNT; + } + + ldap_result = _get_ldap_result(result, list); + if (ldap_result == NULL) { + RETVAL_FALSE; + } else { + php3_list_delete(result->value.lval); /* Delete list entry and call registered destructor function */ + RETVAL_TRUE; + } + return; +} +/* }}} */ + +/* {{{ proto int ldap_count_entries(int link, int result) + Count the number of entries in a search result */ +void php3_ldap_count_entries(INTERNAL_FUNCTION_PARAMETERS) +{ +pval *result, *link; +LDAP *ldap; +LDAPMessage *ldap_result; + + if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &link, &result) == FAILURE) { + WRONG_PARAM_COUNT; + } + + ldap = _get_ldap_link(link, list); + if (ldap == NULL) RETURN_FALSE; + + ldap_result = _get_ldap_result(result, list); + if (ldap_result == NULL) RETURN_FALSE; + + RETURN_LONG(ldap_count_entries(ldap, ldap_result)); +} +/* }}} */ + +/* {{{ proto int ldap_first_entry(int link, int result) + Return first result id */ +void php3_ldap_first_entry(INTERNAL_FUNCTION_PARAMETERS) +{ + pval *result, *link; + LDAP *ldap; + LDAPMessage *ldap_result; + LDAPMessage *ldap_result_entry; + LDAP_TLS_VARS; + + if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &link, &result) == FAILURE) { + WRONG_PARAM_COUNT; + } + + ldap = _get_ldap_link(link, list); + if (ldap == NULL) RETURN_FALSE; + + ldap_result = _get_ldap_result(result, list); + if (ldap_result == NULL) RETURN_FALSE; + + if ((ldap_result_entry = ldap_first_entry(ldap, ldap_result)) == NULL) { + RETURN_FALSE; + } else { + RETURN_LONG(php3_list_insert(ldap_result_entry, LDAP_GLOBAL(le_result_entry))); + } +} +/* }}} */ + +/* {{{ proto int ldap_next_entry(int link, int entry) + Get next result entry */ +void php3_ldap_next_entry(INTERNAL_FUNCTION_PARAMETERS) +{ + pval *result_entry, *link; + LDAP *ldap; + LDAPMessage *ldap_result_entry, *ldap_result_entry_next; + LDAP_TLS_VARS; + + if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &link, &result_entry) == FAILURE) { + WRONG_PARAM_COUNT; + } + + ldap = _get_ldap_link(link, list); + if (ldap == NULL) RETURN_FALSE; + + ldap_result_entry = _get_ldap_result_entry(result_entry, list); + if (ldap_result_entry == NULL) RETURN_FALSE; + + if ((ldap_result_entry_next = ldap_next_entry(ldap, ldap_result_entry)) == NULL) { + RETURN_FALSE; + } else { + RETURN_LONG(php3_list_insert(ldap_result_entry_next, LDAP_GLOBAL(le_result_entry))); + } +} +/* }}} */ + +/* {{{ proto array ldap_get_entries(int link, int result) + Get all result entries */ +void php3_ldap_get_entries(INTERNAL_FUNCTION_PARAMETERS) +{ +pval *link, *result; +LDAPMessage *ldap_result, *ldap_result_entry; +pval tmp1, tmp2; +LDAP *ldap; +int num_entries, num_attrib, num_values, i; +int attr_count, entry_count; +BerElement *ber; +char *attribute; +char **ldap_value; +char *dn; + + if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &link, &result) == FAILURE) { + WRONG_PARAM_COUNT; + } + + ldap = _get_ldap_link(link, list); + if (ldap == NULL) RETURN_FALSE; + + ldap_result = _get_ldap_result(result, list); + if (ldap_result == NULL) RETURN_FALSE; + + num_entries = ldap_count_entries(ldap, ldap_result); + + array_init(return_value); + add_assoc_long(return_value, "count", num_entries); + + if (num_entries == 0) return; + + ldap_result_entry = ldap_first_entry(ldap, ldap_result); + if (ldap_result_entry == NULL) RETURN_FALSE; + + entry_count = 0; + + while(ldap_result_entry != NULL) { + + num_attrib = 0; + attribute = ldap_first_attribute(ldap, ldap_result_entry, &ber); + if (attribute == NULL) RETURN_FALSE; + while (attribute != NULL) { + num_attrib++; + attribute = ldap_next_attribute(ldap, ldap_result_entry, ber); + } + + array_init(&tmp1); + + attr_count = 0; + attribute = ldap_first_attribute(ldap, ldap_result_entry, &ber); + while (attribute != NULL) { + ldap_value = ldap_get_values(ldap, ldap_result_entry, attribute); + num_values = ldap_count_values(ldap_value); + + array_init(&tmp2); + add_assoc_long(&tmp2, "count", num_values); + for(i=0; i<num_values; i++) { + add_index_string(&tmp2, i, ldap_value[i], 1); + } + ldap_value_free(ldap_value); + + _php3_hash_update(tmp1.value.ht, _php3_strtolower(attribute), strlen(attribute)+1, (void *) &tmp2, sizeof(pval), NULL); + add_index_string(&tmp1, attr_count, attribute, 1); + + attr_count++; + attribute = ldap_next_attribute(ldap, ldap_result_entry, ber); + } + + add_assoc_long(&tmp1, "count", num_attrib); + dn = ldap_get_dn(ldap, ldap_result_entry); + add_assoc_string(&tmp1, "dn", dn, 1); + + _php3_hash_index_update(return_value->value.ht, entry_count, (void *) &tmp1, sizeof(pval), NULL); + + entry_count++; + ldap_result_entry = ldap_next_entry(ldap, ldap_result_entry); + } + + add_assoc_long(return_value, "count", num_entries); +} +/* }}} */ + +/* {{{ proto string ldap_first_attribute(int link, int result, int ber) + Return first attribute */ +void php3_ldap_first_attribute(INTERNAL_FUNCTION_PARAMETERS) +{ + pval *result,*link,*berp; + LDAP *ldap; + LDAPMessage *ldap_result_entry; + BerElement *ber; + char *attribute; + LDAP_TLS_VARS; + + if (ARG_COUNT(ht) != 3 || getParameters(ht, 3, &link, &result,&berp) == FAILURE || ParameterPassedByReference(ht,3)==0 ) { + WRONG_PARAM_COUNT; + } + + ldap = _get_ldap_link(link,list); + if (ldap == NULL) RETURN_FALSE; + + ldap_result_entry = _get_ldap_result_entry(result,list); + if (ldap_result_entry == NULL) RETURN_FALSE; + + if ((attribute = ldap_first_attribute(ldap, ldap_result_entry, &ber)) == NULL) { + RETURN_FALSE; + } else { + /* brep is passed by ref so we do not have to account for memory */ + berp->type=IS_LONG; + berp->value.lval=php3_list_insert(ber, LDAP_GLOBAL(le_ber_entry)); + + RETVAL_STRING(attribute,1); +#ifdef WINDOWS + ldap_memfree(attribute); +#endif + } +} +/* }}} */ + +/* {{{ proto string ldap_next_attribute(int link, int result, int ber) + Get the next attribute in result */ +void php3_ldap_next_attribute(INTERNAL_FUNCTION_PARAMETERS) +{ +pval *result,*link,*berp; +LDAP *ldap; +LDAPMessage *ldap_result_entry; +BerElement *ber; +char *attribute; + + if (ARG_COUNT(ht) != 3 || getParameters(ht, 3, &link, &result,&berp) == FAILURE ) { + WRONG_PARAM_COUNT; + } + + ldap = _get_ldap_link(link,list); + if (ldap == NULL) RETURN_FALSE; + + ldap_result_entry = _get_ldap_result_entry(result,list); + if (ldap_result_entry == NULL) RETURN_FALSE; + + ber = _get_ber_entry(berp,list); + + if ((attribute = ldap_next_attribute(ldap, ldap_result_entry, ber)) == NULL) { + RETURN_FALSE; + } else { + RETVAL_STRING(attribute,1); +#ifdef WINDOWS + ldap_memfree(attribute); +#endif + } +} +/* }}} */ + +/* {{{ proto array ldap_get_attributes(int link, int result) + Get attributes from a search result entry */ +void php3_ldap_get_attributes(INTERNAL_FUNCTION_PARAMETERS) +{ +pval *link, *result_entry; +pval tmp; +LDAP *ldap; +LDAPMessage *ldap_result_entry; +char *attribute; +char **ldap_value; +int i, count, num_values, num_attrib; +BerElement *ber; + + if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &link, &result_entry) == FAILURE) { + WRONG_PARAM_COUNT; + } + + ldap = _get_ldap_link(link, list); + if (ldap == NULL) RETURN_FALSE; + + ldap_result_entry = _get_ldap_result_entry(result_entry, list); + if (ldap_result_entry == NULL) RETURN_FALSE; + + num_attrib = 0; + attribute = ldap_first_attribute(ldap, ldap_result_entry, &ber); + if (attribute == NULL) RETURN_FALSE; + while (attribute != NULL) { + num_attrib++; + attribute = ldap_next_attribute(ldap, ldap_result_entry, ber); + } + + array_init(return_value); + + count=0; + attribute = ldap_first_attribute(ldap, ldap_result_entry, &ber); + while (attribute != NULL) { + ldap_value = ldap_get_values(ldap, ldap_result_entry, attribute); + num_values = ldap_count_values(ldap_value); + + array_init(&tmp); + add_assoc_long(&tmp, "count", num_values); + for(i=0; i<num_values; i++) { + add_index_string(&tmp, i, ldap_value[i], 1); + } + ldap_value_free(ldap_value); + + _php3_hash_update(return_value->value.ht, attribute, strlen(attribute)+1, (void *) &tmp, sizeof(pval), NULL); + add_index_string(return_value, count, attribute, 1); + + count++; + attribute = ldap_next_attribute(ldap, ldap_result_entry, ber); + } + + add_assoc_long(return_value, "count", num_attrib); +} +/* }}} */ + +/* {{{ proto array ldap_get_values(int link, int result, string attribute) + Get all values from a result entry */ +void php3_ldap_get_values(INTERNAL_FUNCTION_PARAMETERS) +{ +pval *link, *result_entry, *attr; +LDAP *ldap; +LDAPMessage *ldap_result_entry; +char *attribute; +char **ldap_value; +int i, num_values; + + if (ARG_COUNT(ht) != 3 || getParameters(ht, 3, &link, &result_entry, &attr) == FAILURE) { + WRONG_PARAM_COUNT; + } + + ldap = _get_ldap_link(link, list); + if (ldap == NULL) RETURN_FALSE; + + ldap_result_entry = _get_ldap_result_entry(result_entry, list); + if (ldap_result_entry == NULL) RETURN_FALSE; + + convert_to_string(attr); + attribute = attr->value.str.val; + + if ((ldap_value = ldap_get_values(ldap, ldap_result_entry, attribute)) == NULL) { +#if !HAVE_NSLDAP +#if LDAP_API_VERSION > 2000 + php3_error(E_WARNING, "LDAP: Cannot get the value(s) of attribute %s", ldap_err2string(ldap_get_lderrno(ldap,NULL,NULL))); +#else + php3_error(E_WARNING, "LDAP: Cannot get the value(s) of attribute %s", ldap_err2string(ldap->ld_errno)); +#endif +#endif + RETURN_FALSE; + } + + num_values = ldap_count_values(ldap_value); + + if (array_init(return_value) == FAILURE) { + RETURN_FALSE; + } + + for(i=0; i<num_values; i++) { + add_next_index_string(return_value, ldap_value[i], 1); + } + + add_assoc_long(return_value, "count", num_values); + + ldap_value_free(ldap_value); +} +/* }}} */ + +/* {{{ proto string ldap_get_dn(int link, int result) + Get the DN of a result entry */ +void php3_ldap_get_dn(INTERNAL_FUNCTION_PARAMETERS) +{ + pval *link,*entryp; + LDAP *ld; + LDAPMessage *entry; + char *text; + + if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &link, &entryp) == FAILURE) { + WRONG_PARAM_COUNT; + } + + ld = _get_ldap_link(link, list); + if (ld == NULL) RETURN_FALSE; + + entry = _get_ldap_result_entry(entryp, list); + if (entry == NULL) RETURN_FALSE; + + text = ldap_get_dn(ld, entry); + if ( text != NULL ) { + RETVAL_STRING(text,1); +#ifdef WINDOWS + ldap_memfree(text); +#endif + } else { + RETURN_FALSE; + } +} +/* }}} */ + +/* {{{ proto array ldap_explode_dn(string dn, int with_attrib) + Splits DN into its component parts */ +void php3_ldap_explode_dn(INTERNAL_FUNCTION_PARAMETERS) +{ +pval *dn, *with_attrib; +char **ldap_value; +int i, count; + + if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &dn, &with_attrib)== FAILURE) { + WRONG_PARAM_COUNT; + } + + convert_to_string(dn); + convert_to_long(with_attrib); + + ldap_value = ldap_explode_dn(dn->value.str.val, with_attrib->value.lval); + + i=0; + while(ldap_value[i] != NULL) i++; + count = i; + + if (array_init(return_value) == FAILURE) { + RETURN_FALSE; + } + + add_assoc_long(return_value, "count", count); + for(i=0; i<count; i++) { + add_index_string(return_value, i, ldap_value[i], 1); + } + + ldap_value_free(ldap_value); +} +/* }}} */ + +/* {{{ proto string ldap_dn2ufn(string dn) + Convert DN to User Friendly Naming format */ +void php3_ldap_dn2ufn(INTERNAL_FUNCTION_PARAMETERS) +{ + pval *dn; + char *ufn; + + if (ARG_COUNT(ht) !=1 || getParameters(ht,1,&dn)==FAILURE) { + WRONG_PARAM_COUNT; + } + + convert_to_string(dn); + + ufn = ldap_dn2ufn(dn->value.str.val); + + if (ufn !=NULL) { + RETVAL_STRING(ufn,1); +#ifdef WINDOWS + ldap_memfree(ufn); +#endif + } else { + RETURN_FALSE; + } +} +/* }}} */ + + +static void php3_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper) +{ +pval *link, *dn, *entry, *value, *ivalue; +LDAP *ldap; +char *ldap_dn; +LDAPMod **ldap_mods; +int i, j, num_attribs, num_values; +char *attribute; +ulong index; + + if (ARG_COUNT(ht) != 3 || getParameters(ht, 3, &link, &dn, &entry) == FAILURE) { + WRONG_PARAM_COUNT; + } + + if (entry->type != IS_ARRAY) { + php3_error(E_WARNING, "LDAP: Expected Array as the last element"); + RETURN_FALSE; + } + + ldap = _get_ldap_link(link, list); + if (ldap == NULL) RETURN_FALSE; + + convert_to_string(dn); + ldap_dn = dn->value.str.val; + + num_attribs = _php3_hash_num_elements(entry->value.ht); + + ldap_mods = emalloc((num_attribs+1) * sizeof(LDAPMod *)); + + _php3_hash_internal_pointer_reset(entry->value.ht); + + for(i=0; i<num_attribs; i++) { + ldap_mods[i] = emalloc(sizeof(LDAPMod)); + + ldap_mods[i]->mod_op = oper; + + if (_php3_hash_get_current_key(entry->value.ht, &attribute, &index) == HASH_KEY_IS_STRING) { + ldap_mods[i]->mod_type = estrdup(attribute); + efree(attribute); + } else { + php3_error(E_WARNING, "LDAP: Unknown Attribute in the data"); + } + + _php3_hash_get_current_data(entry->value.ht, (void **) &value); + + if (value->type != IS_ARRAY) { + num_values = 1; + } else { + num_values = _php3_hash_num_elements(value->value.ht); + } + + ldap_mods[i]->mod_values = emalloc((num_values+1) * sizeof(char *)); + + if (num_values == 1) { + convert_to_string(value); + ldap_mods[i]->mod_values[0] = value->value.str.val; + } else { + for(j=0; j<num_values; j++) { + _php3_hash_index_find(value->value.ht, j, (void **) &ivalue); + convert_to_string(ivalue); + ldap_mods[i]->mod_values[j] = ivalue->value.str.val; + } + } + ldap_mods[i]->mod_values[num_values] = NULL; + + _php3_hash_move_forward(entry->value.ht); + } + ldap_mods[num_attribs] = NULL; + + if (oper == LDAP_MOD_ADD) { + if (ldap_add_s(ldap, ldap_dn, ldap_mods) != LDAP_SUCCESS) { + ldap_perror(ldap, "LDAP"); + php3_error(E_WARNING, "LDAP: add operation could not be completed."); + RETVAL_FALSE; + } else RETVAL_TRUE; + } else { + if (ldap_modify_s(ldap, ldap_dn, ldap_mods) != LDAP_SUCCESS) { + php3_error(E_WARNING, "LDAP: modify operation could not be completed."); + RETVAL_FALSE; + } else RETVAL_TRUE; + } + + for(i=0; i<num_attribs; i++) { + efree(ldap_mods[i]->mod_type); + efree(ldap_mods[i]->mod_values); + efree(ldap_mods[i]); + } + efree(ldap_mods); + + return; +} + +/* {{{ proto int ldap_add(int link, string dn, array entry) + Add entries to LDAP directory */ +void php3_ldap_add(INTERNAL_FUNCTION_PARAMETERS) +{ + php3_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_ADD); +} +/* }}} */ + + +/* {{{ proto int ldap_modify(int link, string dn, array entry) + Modify an LDAP entry */ +void php3_ldap_modify(INTERNAL_FUNCTION_PARAMETERS) +{ + php3_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_REPLACE); +} +/* }}} */ + +/* {{{ proto int ldap_delete(int link, string dn) + Delete an entry from a directory */ +void php3_ldap_delete(INTERNAL_FUNCTION_PARAMETERS) +{ +pval *link, *dn; +LDAP *ldap; +char *ldap_dn; + + if (ARG_COUNT(ht) != 2 || getParameters(ht, 2, &link, &dn) == FAILURE) { + WRONG_PARAM_COUNT; + } + + ldap = _get_ldap_link(link, list); + if (ldap == NULL) RETURN_FALSE; + + convert_to_string(dn); + ldap_dn = dn->value.str.val; + + if (ldap_delete_s(ldap, ldap_dn) != LDAP_SUCCESS) { + ldap_perror(ldap, "LDAP"); + RETURN_FALSE; + } + + RETURN_TRUE; +} +/* }}} */ + +#endif |
