PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LTP GCOV extension - code coverage report
Current view: directory - ldap - ldap.c
Test: PHP Code Coverage
Date: 2009-11-19 Instrumented lines: 804
Code covered: 92.9 % Executed lines: 747
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | PHP Version 5                                                        |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1997-2009 The PHP Group                                |
       6                 :    +----------------------------------------------------------------------+
       7                 :    | This source file is subject to version 3.01 of the PHP license,      |
       8                 :    | that is bundled with this package in the file LICENSE, and is        |
       9                 :    | available through the world-wide-web at the following url:           |
      10                 :    | http://www.php.net/license/3_01.txt                                  |
      11                 :    | If you did not receive a copy of the PHP license and are unable to   |
      12                 :    | obtain it through the world-wide-web, please send a note to          |
      13                 :    | license@php.net so we can mail you a copy immediately.               |
      14                 :    +----------------------------------------------------------------------+
      15                 :    | Authors: Amitay Isaacs  <amitay@w-o-i.com>                           |
      16                 :    |          Eric Warnke    <ericw@albany.edu>                           |
      17                 :    |          Rasmus Lerdorf <rasmus@php.net>                             |
      18                 :    |          Gerrit Thomson <334647@swin.edu.au>                         |
      19                 :    |          Jani Taskinen  <sniper@iki.fi>                              |
      20                 :    |          Stig Venaas    <venaas@uninett.no>                          |
      21                 :    |          Doug Goldstein <cardoe@cardoe.com>                          |
      22                 :    | PHP 4.0 updates:  Zeev Suraski <zeev@zend.com>                       |
      23                 :    +----------------------------------------------------------------------+
      24                 :  */
      25                 :  
      26                 : /* $Id: ldap.c 287936 2009-09-01 08:42:10Z patrickallaert $ */
      27                 : #define IS_EXT_MODULE
      28                 : 
      29                 : #ifdef HAVE_CONFIG_H
      30                 : #include "config.h"
      31                 : #endif
      32                 : 
      33                 : /* Additional headers for NetWare */
      34                 : #if defined(NETWARE) && (NEW_LIBC)
      35                 : #include <sys/select.h>
      36                 : #include <sys/timeval.h>
      37                 : #endif
      38                 : 
      39                 : #include "php.h"
      40                 : #include "php_ini.h"
      41                 : 
      42                 : #include <stddef.h>
      43                 : 
      44                 : #include "ext/standard/dl.h"
      45                 : #include "php_ldap.h"
      46                 : 
      47                 : #ifdef PHP_WIN32
      48                 : #include <string.h>
      49                 : #if HAVE_NSLDAP
      50                 : #include <winsock2.h>
      51                 : #endif
      52                 : #define strdup _strdup
      53                 : #undef WINDOWS
      54                 : #undef strcasecmp
      55                 : #undef strncasecmp
      56                 : #define WINSOCK 1
      57                 : #define __STDC__ 1
      58                 : #endif
      59                 : 
      60                 : #include "ext/standard/php_string.h"
      61                 : #include "ext/standard/info.h"
      62                 : 
      63                 : #ifdef HAVE_LDAP_SASL_H
      64                 : #include <sasl.h>
      65                 : #elif defined(HAVE_LDAP_SASL_SASL_H)
      66                 : #include <sasl/sasl.h>
      67                 : #endif
      68                 : 
      69                 : typedef struct {
      70                 :         LDAP *link;
      71                 : #if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC)
      72                 :         zval *rebindproc;
      73                 : #endif
      74                 : } ldap_linkdata;
      75                 : 
      76                 : typedef struct {
      77                 :         LDAPMessage *data;
      78                 :         BerElement *ber;
      79                 :         int id;
      80                 : } ldap_resultentry;
      81                 : 
      82                 : ZEND_DECLARE_MODULE_GLOBALS(ldap)
      83                 : static PHP_GINIT_FUNCTION(ldap);
      84                 : 
      85                 : static
      86                 :         ZEND_BEGIN_ARG_INFO(arg3to6of6_force_ref, 0)
      87                 :                 ZEND_ARG_PASS_INFO(0)
      88                 :                 ZEND_ARG_PASS_INFO(0)
      89                 :                 ZEND_ARG_PASS_INFO(1)
      90                 :                 ZEND_ARG_PASS_INFO(1)
      91                 :                 ZEND_ARG_PASS_INFO(1)
      92                 :                 ZEND_ARG_PASS_INFO(1)
      93                 :         ZEND_END_ARG_INFO();
      94                 : 
      95                 : static int le_link, le_result, le_result_entry;
      96                 : 
      97                 : /*
      98                 :         This is just a small subset of the functionality provided by the LDAP library. All the 
      99                 :         operations are synchronous. Referrals are not handled automatically.
     100                 : */
     101                 : /* {{{ ldap_functions[]
     102                 :  */
     103                 : zend_function_entry ldap_functions[] = {
     104                 :         PHP_FE(ldap_connect,                                                            NULL)
     105                 :         PHP_FALIAS(ldap_close,          ldap_unbind,                    NULL)
     106                 :         PHP_FE(ldap_bind,                                                                       NULL)
     107                 : #ifdef HAVE_LDAP_SASL
     108                 :         PHP_FE(ldap_sasl_bind,                                                          NULL)
     109                 : #endif
     110                 :         PHP_FE(ldap_unbind,                                                                     NULL)
     111                 :         PHP_FE(ldap_read,                                                                       NULL)
     112                 :         PHP_FE(ldap_list,                                                                       NULL)
     113                 :         PHP_FE(ldap_search,                                                                     NULL)
     114                 :         PHP_FE(ldap_free_result,                                                        NULL)
     115                 :         PHP_FE(ldap_count_entries,                                                      NULL)
     116                 :         PHP_FE(ldap_first_entry,                                                        NULL)
     117                 :         PHP_FE(ldap_next_entry,                                                         NULL)
     118                 :         PHP_FE(ldap_get_entries,                                                        NULL)
     119                 :         PHP_FE(ldap_first_attribute,    third_arg_force_ref)
     120                 :         PHP_FE(ldap_next_attribute,             third_arg_force_ref)
     121                 :         PHP_FE(ldap_get_attributes,                                                     NULL)
     122                 :         PHP_FALIAS(ldap_get_values,     ldap_get_values_len,                            NULL)
     123                 :         PHP_FE(ldap_get_values_len,                                                     NULL)
     124                 :         PHP_FE(ldap_get_dn,                                                                     NULL)
     125                 :         PHP_FE(ldap_explode_dn,                                                         NULL)
     126                 :         PHP_FE(ldap_dn2ufn,                                                                     NULL)
     127                 :         PHP_FE(ldap_add,                                                                        NULL)
     128                 :         PHP_FE(ldap_delete,                                                                     NULL)
     129                 :         PHP_FALIAS(ldap_modify,         ldap_mod_replace,               NULL)
     130                 : 
     131                 : /* additional functions for attribute based modifications, Gerrit Thomson */
     132                 :         PHP_FE(ldap_mod_add,                                                            NULL)
     133                 :         PHP_FE(ldap_mod_replace,                                                        NULL)
     134                 :         PHP_FE(ldap_mod_del,                                                            NULL)
     135                 : /* end gjt mod */
     136                 : 
     137                 :         PHP_FE(ldap_errno,                                                                      NULL)
     138                 :         PHP_FE(ldap_err2str,                                                            NULL)
     139                 :         PHP_FE(ldap_error,                                                                      NULL)
     140                 :         PHP_FE(ldap_compare,                                                            NULL)
     141                 :         PHP_FE(ldap_sort,                                                                       NULL)
     142                 : 
     143                 : #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10
     144                 :         PHP_FE(ldap_rename,                                                                     NULL)
     145                 :         PHP_FE(ldap_get_option,                 third_arg_force_ref)
     146                 :         PHP_FE(ldap_set_option,                                                         NULL)
     147                 :         PHP_FE(ldap_first_reference,                                            NULL)
     148                 :         PHP_FE(ldap_next_reference,                                                     NULL)
     149                 : #ifdef HAVE_LDAP_PARSE_REFERENCE
     150                 :         PHP_FE(ldap_parse_reference,    third_arg_force_ref)
     151                 : #endif
     152                 : #ifdef HAVE_LDAP_PARSE_RESULT
     153                 :         PHP_FE(ldap_parse_result,                       arg3to6of6_force_ref)
     154                 : #endif
     155                 : #ifdef HAVE_LDAP_START_TLS_S
     156                 :         PHP_FE(ldap_start_tls,                                                          NULL)
     157                 : #endif
     158                 : #endif
     159                 : 
     160                 : #if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC)
     161                 :         PHP_FE(ldap_set_rebind_proc,                                            NULL)
     162                 : #endif
     163                 : 
     164                 : #ifdef STR_TRANSLATION
     165                 :         PHP_FE(ldap_t61_to_8859,                                                        NULL)
     166                 :         PHP_FE(ldap_8859_to_t61,                                                        NULL)
     167                 : #endif
     168                 : 
     169                 :         {NULL, NULL, NULL}
     170                 : };
     171                 : /* }}} */
     172                 : 
     173                 : zend_module_entry ldap_module_entry = {
     174                 :         STANDARD_MODULE_HEADER,
     175                 :         "ldap", 
     176                 :         ldap_functions, 
     177                 :         PHP_MINIT(ldap), 
     178                 :         PHP_MSHUTDOWN(ldap), 
     179                 :         NULL, 
     180                 :         NULL,
     181                 :         PHP_MINFO(ldap), 
     182                 :         NO_VERSION_YET,
     183                 :         PHP_MODULE_GLOBALS(ldap),
     184                 :         PHP_GINIT(ldap),
     185                 :         NULL,
     186                 :         NULL,
     187                 :         STANDARD_MODULE_PROPERTIES_EX
     188                 : };
     189                 : 
     190                 : #ifdef COMPILE_DL_LDAP
     191                 : ZEND_GET_MODULE(ldap)
     192                 : # ifdef PHP_WIN32
     193                 : # include "zend_arg_defs.c"
     194                 : # endif
     195                 : #endif
     196                 : 
     197                 : static void _close_ldap_link(zend_rsrc_list_entry *rsrc TSRMLS_DC)
     198             182 : {
     199             182 :         ldap_linkdata *ld = (ldap_linkdata *)rsrc->ptr;
     200                 : 
     201             182 :         ldap_unbind_s(ld->link);
     202                 : #if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC)
     203             182 :         if (ld->rebindproc != NULL) {
     204               1 :                 zval_dtor(ld->rebindproc);
     205               1 :                 FREE_ZVAL(ld->rebindproc);
     206                 :         }
     207                 : #endif
     208             182 :         efree(ld);
     209             182 :         LDAPG(num_links)--;
     210             182 : }
     211                 : 
     212                 : static void _free_ldap_result(zend_rsrc_list_entry *rsrc TSRMLS_DC)
     213              46 : {
     214              46 :         LDAPMessage *result = (LDAPMessage *)rsrc->ptr;
     215              46 :         ldap_msgfree(result);
     216              46 : }
     217                 : 
     218                 : static void _free_ldap_result_entry(zend_rsrc_list_entry *rsrc TSRMLS_DC)
     219              14 : {
     220              14 :         ldap_resultentry *entry = (ldap_resultentry *)rsrc->ptr;
     221                 : 
     222              14 :         if (entry->ber != NULL) {
     223               1 :                 ber_free(entry->ber, 0);
     224               1 :                 entry->ber = NULL;
     225                 :         }
     226              14 :         zend_list_delete(entry->id);
     227              14 :         efree(entry);
     228              14 : } 
     229                 : 
     230                 : /* {{{ PHP_INI_BEGIN
     231                 :  */
     232                 : PHP_INI_BEGIN()
     233                 :         STD_PHP_INI_ENTRY_EX("ldap.max_links", "-1", PHP_INI_SYSTEM, OnUpdateLong, max_links, zend_ldap_globals, ldap_globals, display_link_numbers)
     234                 : PHP_INI_END()
     235                 : /* }}} */
     236                 : 
     237                 : /* {{{ PHP_GINIT_FUNCTION
     238                 :  */
     239                 : static PHP_GINIT_FUNCTION(ldap)
     240           13565 : {
     241           13565 :         ldap_globals->num_links = 0;
     242           13565 : }
     243                 : /* }}} */
     244                 : 
     245                 : /* {{{ PHP_MINIT_FUNCTION
     246                 :  */
     247                 : PHP_MINIT_FUNCTION(ldap)
     248           13565 : {
     249           13565 :         REGISTER_INI_ENTRIES();
     250                 : 
     251                 :         /* Constants to be used with deref-parameter in php_ldap_do_search() */
     252           13565 :         REGISTER_LONG_CONSTANT("LDAP_DEREF_NEVER", LDAP_DEREF_NEVER, CONST_PERSISTENT | CONST_CS);
     253           13565 :         REGISTER_LONG_CONSTANT("LDAP_DEREF_SEARCHING", LDAP_DEREF_SEARCHING, CONST_PERSISTENT | CONST_CS);
     254           13565 :         REGISTER_LONG_CONSTANT("LDAP_DEREF_FINDING", LDAP_DEREF_FINDING, CONST_PERSISTENT | CONST_CS);
     255           13565 :         REGISTER_LONG_CONSTANT("LDAP_DEREF_ALWAYS", LDAP_DEREF_ALWAYS, CONST_PERSISTENT | CONST_CS);
     256                 : 
     257                 : #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10
     258                 :         /* LDAP options */
     259           13565 :         REGISTER_LONG_CONSTANT("LDAP_OPT_DEREF", LDAP_OPT_DEREF, CONST_PERSISTENT | CONST_CS);
     260           13565 :         REGISTER_LONG_CONSTANT("LDAP_OPT_SIZELIMIT", LDAP_OPT_SIZELIMIT, CONST_PERSISTENT | CONST_CS);
     261           13565 :         REGISTER_LONG_CONSTANT("LDAP_OPT_TIMELIMIT", LDAP_OPT_TIMELIMIT, CONST_PERSISTENT | CONST_CS);
     262           13565 :         REGISTER_LONG_CONSTANT("LDAP_OPT_PROTOCOL_VERSION", LDAP_OPT_PROTOCOL_VERSION, CONST_PERSISTENT | CONST_CS);
     263           13565 :         REGISTER_LONG_CONSTANT("LDAP_OPT_ERROR_NUMBER", LDAP_OPT_ERROR_NUMBER, CONST_PERSISTENT | CONST_CS);
     264           13565 :         REGISTER_LONG_CONSTANT("LDAP_OPT_REFERRALS", LDAP_OPT_REFERRALS, CONST_PERSISTENT | CONST_CS);
     265                 : #ifdef LDAP_OPT_RESTART
     266           13565 :         REGISTER_LONG_CONSTANT("LDAP_OPT_RESTART", LDAP_OPT_RESTART, CONST_PERSISTENT | CONST_CS);
     267                 : #endif
     268                 : #ifdef LDAP_OPT_HOST_NAME
     269           13565 :         REGISTER_LONG_CONSTANT("LDAP_OPT_HOST_NAME", LDAP_OPT_HOST_NAME, CONST_PERSISTENT | CONST_CS);
     270                 : #endif
     271           13565 :         REGISTER_LONG_CONSTANT("LDAP_OPT_ERROR_STRING", LDAP_OPT_ERROR_STRING, CONST_PERSISTENT | CONST_CS);
     272                 : #ifdef LDAP_OPT_MATCHED_DN
     273           13565 :         REGISTER_LONG_CONSTANT("LDAP_OPT_MATCHED_DN", LDAP_OPT_MATCHED_DN, CONST_PERSISTENT | CONST_CS);
     274                 : #endif
     275           13565 :         REGISTER_LONG_CONSTANT("LDAP_OPT_SERVER_CONTROLS", LDAP_OPT_SERVER_CONTROLS, CONST_PERSISTENT | CONST_CS);
     276           13565 :         REGISTER_LONG_CONSTANT("LDAP_OPT_CLIENT_CONTROLS", LDAP_OPT_CLIENT_CONTROLS, CONST_PERSISTENT | CONST_CS);
     277                 : #endif
     278                 : #ifdef LDAP_OPT_DEBUG_LEVEL
     279           13565 :         REGISTER_LONG_CONSTANT("LDAP_OPT_DEBUG_LEVEL", LDAP_OPT_DEBUG_LEVEL, CONST_PERSISTENT | CONST_CS);
     280                 : #endif
     281                 : 
     282                 : #ifdef HAVE_LDAP_SASL
     283                 :         REGISTER_LONG_CONSTANT("LDAP_OPT_X_SASL_MECH", LDAP_OPT_X_SASL_MECH, CONST_PERSISTENT | CONST_CS);
     284                 :         REGISTER_LONG_CONSTANT("LDAP_OPT_X_SASL_REALM", LDAP_OPT_X_SASL_REALM, CONST_PERSISTENT | CONST_CS);
     285                 :         REGISTER_LONG_CONSTANT("LDAP_OPT_X_SASL_AUTHCID", LDAP_OPT_X_SASL_AUTHCID, CONST_PERSISTENT | CONST_CS);
     286                 :         REGISTER_LONG_CONSTANT("LDAP_OPT_X_SASL_AUTHZID", LDAP_OPT_X_SASL_AUTHZID, CONST_PERSISTENT | CONST_CS);
     287                 : #endif
     288                 : 
     289                 : #ifdef ORALDAP
     290                 :         REGISTER_LONG_CONSTANT("GSLC_SSL_NO_AUTH", GSLC_SSL_NO_AUTH, CONST_PERSISTENT | CONST_CS);
     291                 :         REGISTER_LONG_CONSTANT("GSLC_SSL_ONEWAY_AUTH", GSLC_SSL_ONEWAY_AUTH, CONST_PERSISTENT | CONST_CS);
     292                 :         REGISTER_LONG_CONSTANT("GSLC_SSL_TWOWAY_AUTH", GSLC_SSL_TWOWAY_AUTH, CONST_PERSISTENT | CONST_CS);
     293                 : #endif
     294                 : 
     295           13565 :         le_link = zend_register_list_destructors_ex(_close_ldap_link, NULL, "ldap link", module_number);
     296           13565 :         le_result = zend_register_list_destructors_ex(_free_ldap_result, NULL, "ldap result", module_number);
     297           13565 :         le_result_entry = zend_register_list_destructors_ex(_free_ldap_result_entry, NULL, "ldap result entry", module_number);
     298                 : 
     299           13565 :         Z_TYPE(ldap_module_entry) = type;
     300                 : 
     301           13565 :         return SUCCESS;
     302                 : }
     303                 : /* }}} */
     304                 : 
     305                 : /* {{{ PHP_MSHUTDOWN_FUNCTION
     306                 :  */
     307                 : PHP_MSHUTDOWN_FUNCTION(ldap)
     308           13597 : {
     309           13597 :         UNREGISTER_INI_ENTRIES();
     310           13597 :         return SUCCESS;
     311                 : }
     312                 : /* }}} */
     313                 : 
     314                 : /* {{{ PHP_MINFO_FUNCTION
     315                 :  */
     316                 : PHP_MINFO_FUNCTION(ldap)
     317               6 : {
     318                 :         char tmp[32];
     319                 : #if HAVE_NSLDAP
     320                 :         LDAPVersion ver;
     321                 :         double SDKVersion;
     322                 : #endif
     323                 : 
     324               6 :         php_info_print_table_start();
     325               6 :         php_info_print_table_row(2, "LDAP Support", "enabled");
     326               6 :         php_info_print_table_row(2, "RCS Version", "$Id: ldap.c 287936 2009-09-01 08:42:10Z patrickallaert $");
     327                 : 
     328               6 :         if (LDAPG(max_links) == -1) {
     329               6 :                 snprintf(tmp, 31, "%ld/unlimited", LDAPG(num_links));
     330                 :         } else {
     331               0 :                 snprintf(tmp, 31, "%ld/%ld", LDAPG(num_links), LDAPG(max_links));
     332                 :         }
     333               6 :         php_info_print_table_row(2, "Total Links", tmp);
     334                 : 
     335                 : #ifdef LDAP_API_VERSION
     336               6 :         snprintf(tmp, 31, "%d", LDAP_API_VERSION);
     337               6 :         php_info_print_table_row(2, "API Version", tmp);
     338                 : #endif
     339                 : 
     340                 : #ifdef LDAP_VENDOR_NAME
     341               6 :         php_info_print_table_row(2, "Vendor Name", LDAP_VENDOR_NAME);
     342                 : #endif
     343                 : 
     344                 : #ifdef LDAP_VENDOR_VERSION
     345               6 :         snprintf(tmp, 31, "%d", LDAP_VENDOR_VERSION);
     346               6 :         php_info_print_table_row(2, "Vendor Version", tmp);
     347                 : #endif
     348                 : 
     349                 : #if HAVE_NSLDAP
     350                 :         SDKVersion = ldap_version(&ver);
     351                 :         snprintf(tmp, 31, "%F", SDKVersion/100.0);
     352                 :         php_info_print_table_row(2, "SDK Version", tmp);
     353                 : 
     354                 :         snprintf(tmp, 31, "%F", ver.protocol_version/100.0);
     355                 :         php_info_print_table_row(2, "Highest LDAP Protocol Supported", tmp);
     356                 : 
     357                 :         snprintf(tmp, 31, "%F", ver.SSL_version/100.0);
     358                 :         php_info_print_table_row(2, "SSL Level Supported", tmp);
     359                 : 
     360                 :         if (ver.security_level != LDAP_SECURITY_NONE) {
     361                 :                 snprintf(tmp, 31, "%d", ver.security_level);
     362                 :         } else {
     363                 :                 strcpy(tmp, "SSL not enabled");
     364                 :         }
     365                 :         php_info_print_table_row(2, "Level of Encryption", tmp);
     366                 : #endif
     367                 : 
     368                 : #ifdef HAVE_LDAP_SASL
     369                 :         php_info_print_table_row(2, "SASL Support", "Enabled");
     370                 : #endif
     371                 : 
     372               6 :         php_info_print_table_end();
     373               6 : }
     374                 : /* }}} */
     375                 : 
     376                 : /* {{{ proto resource ldap_connect([string host [, int port]])
     377                 :    Connect to an LDAP server */
     378                 : PHP_FUNCTION(ldap_connect)
     379             185 : {
     380             185 :         char *host = NULL;
     381                 :         int hostlen;
     382             185 :         long port = 389; /* Default port */
     383                 : #ifdef HAVE_ORALDAP
     384                 :         char *wallet = NULL, *walletpasswd = NULL;
     385                 :         int walletlen = 0, walletpasswdlen = 0;
     386                 :         long authmode = GSLC_SSL_NO_AUTH;
     387                 :         int ssl=0;
     388                 : #endif
     389                 :         ldap_linkdata *ld;
     390                 :         LDAP *ldap;
     391                 : 
     392                 : #ifdef HAVE_ORALDAP
     393                 :         if (ZEND_NUM_ARGS() == 3 || ZEND_NUM_ARGS() == 4) {
     394                 :                 WRONG_PARAM_COUNT;
     395                 :         }
     396                 : 
     397                 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|slssl", &host, &hostlen, &port, &wallet, &walletlen, &walletpasswd, &walletpasswdlen, &authmode) == FAILURE) {
     398                 :                 RETURN_FALSE;
     399                 :         }
     400                 : 
     401                 :         if (ZEND_NUM_ARGS() == 5) {
     402                 :                 ssl = 1;
     403                 :         }
     404                 : #else
     405             185 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sl", &host, &hostlen, &port) == FAILURE) {
     406               1 :                 RETURN_FALSE;
     407                 :         }
     408                 : #endif
     409                 : 
     410             184 :         if (LDAPG(max_links) != -1 && LDAPG(num_links) >= LDAPG(max_links)) {
     411               1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many open links (%ld)", LDAPG(num_links));
     412               1 :                 RETURN_FALSE;
     413                 :         }
     414                 : 
     415             183 :         ld = ecalloc(1, sizeof(ldap_linkdata));
     416                 : 
     417                 : #ifdef LDAP_API_FEATURE_X_OPENLDAP
     418             185 :         if (host != NULL && strchr(host, '/')) {
     419                 :                 int rc;
     420                 :                 
     421               3 :                 rc = ldap_initialize(&ldap, host);
     422               3 :                 if (rc != LDAP_SUCCESS) {
     423               1 :                         efree(ld);
     424               1 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not create session handle: %s", ldap_err2string(rc));
     425               1 :                         RETURN_FALSE;
     426                 :                 }
     427                 :         } else {
     428             180 :                 ldap = ldap_init(host, port);
     429                 :         }
     430                 : #else
     431                 :         ldap = ldap_open(host, port);
     432                 : #endif
     433                 :         
     434             182 :         if (ldap == NULL) {
     435               0 :                 efree(ld);
     436               0 :                 RETURN_FALSE;
     437                 :         } else {
     438                 : #ifdef HAVE_ORALDAP
     439                 :                 if (ssl) {
     440                 :                         if (ldap_init_SSL(&ldap->ld_sb, wallet, walletpasswd, authmode)) {
     441                 :                                 efree(ld);
     442                 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSL init failed");
     443                 :                                 RETURN_FALSE;
     444                 :                         }
     445                 :                 }                       
     446                 : #endif
     447             182 :                 LDAPG(num_links)++;
     448             182 :                 ld->link = ldap;
     449             182 :                 ZEND_REGISTER_RESOURCE(return_value, ld, le_link);
     450                 :         }
     451                 : 
     452                 : }
     453                 : /* }}} */
     454                 : 
     455                 : /* {{{ _get_lderrno
     456                 :  */
     457                 : static int _get_lderrno(LDAP *ldap)
     458              15 : {
     459                 : #if !HAVE_NSLDAP
     460                 : #if LDAP_API_VERSION > 2000 || HAVE_ORALDAP_10
     461                 :         int lderr;
     462                 : 
     463                 :         /* New versions of OpenLDAP do it this way */
     464              15 :         ldap_get_option(ldap, LDAP_OPT_ERROR_NUMBER, &lderr);
     465              15 :         return lderr;
     466                 : #else
     467                 :         return ldap->ld_errno;
     468                 : #endif
     469                 : #else
     470                 :         return ldap_get_lderrno(ldap, NULL, NULL);
     471                 : #endif
     472                 : }
     473                 : /* }}} */
     474                 : 
     475                 : /* {{{ proto bool ldap_bind(resource link [, string dn [, string password]])
     476                 :    Bind to LDAP directory */
     477                 : PHP_FUNCTION(ldap_bind)
     478             152 : {
     479                 :         zval *link;
     480             152 :         char *ldap_bind_dn = NULL, *ldap_bind_pw = NULL;
     481                 :         int ldap_bind_dnlen, ldap_bind_pwlen;
     482                 :         ldap_linkdata *ld;
     483                 :         int rc;
     484                 : 
     485             152 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|ss", &link, &ldap_bind_dn, &ldap_bind_dnlen, &ldap_bind_pw, &ldap_bind_pwlen) == FAILURE) {
     486               1 :                 RETURN_FALSE;
     487                 :         }
     488                 : 
     489             151 :         ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
     490                 : 
     491             151 :         if ((rc = ldap_bind_s(ld->link, ldap_bind_dn, ldap_bind_pw, LDAP_AUTH_SIMPLE)) != LDAP_SUCCESS) {
     492               2 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to bind to server: %s", ldap_err2string(rc));
     493               2 :                 RETURN_FALSE;
     494                 :         } else {
     495             149 :                 RETURN_TRUE;
     496                 :         }
     497                 : }
     498                 : /* }}} */
     499                 : 
     500                 : #ifdef HAVE_LDAP_SASL
     501                 : typedef struct {
     502                 :         char *mech;
     503                 :         char *realm;
     504                 :         char *authcid;
     505                 :         char *passwd;
     506                 :         char *authzid;
     507                 : } php_ldap_bictx;
     508                 : 
     509                 : /* {{{ _php_sasl_setdefs
     510                 :  */
     511                 : static php_ldap_bictx *_php_sasl_setdefs(LDAP *ld, char *sasl_mech, char *sasl_realm, char *sasl_authc_id, char *passwd, char *sasl_authz_id)
     512                 : {
     513                 :         php_ldap_bictx *ctx;
     514                 : 
     515                 :         ctx = ber_memalloc(sizeof(php_ldap_bictx));     
     516                 :         ctx->mech    = (sasl_mech) ? ber_strdup(sasl_mech) : NULL;
     517                 :         ctx->realm   = (sasl_realm) ? ber_strdup(sasl_realm) : NULL;
     518                 :         ctx->authcid = (sasl_authc_id) ? ber_strdup(sasl_authc_id) : NULL;
     519                 :         ctx->passwd  = (passwd) ? ber_strdup(passwd) : NULL;
     520                 :         ctx->authzid = (sasl_authz_id) ? ber_strdup(sasl_authz_id) : NULL;
     521                 : 
     522                 :         if (ctx->mech == NULL) {
     523                 :                 ldap_get_option(ld, LDAP_OPT_X_SASL_MECH, &ctx->mech);
     524                 :         }
     525                 :         if (ctx->realm == NULL) {
     526                 :                 ldap_get_option(ld, LDAP_OPT_X_SASL_REALM, &ctx->realm);
     527                 :         }
     528                 :         if (ctx->authcid == NULL) {
     529                 :                 ldap_get_option(ld, LDAP_OPT_X_SASL_AUTHCID, &ctx->authcid);
     530                 :         }
     531                 :         if (ctx->authzid == NULL) {
     532                 :                 ldap_get_option(ld, LDAP_OPT_X_SASL_AUTHZID, &ctx->authzid);
     533                 :         }
     534                 : 
     535                 :         return ctx;
     536                 : }
     537                 : /* }}} */
     538                 : 
     539                 : /* {{{ _php_sasl_freedefs
     540                 :  */
     541                 : static void _php_sasl_freedefs(php_ldap_bictx *ctx)
     542                 : {
     543                 :         if (ctx->mech) ber_memfree(ctx->mech);
     544                 :         if (ctx->realm) ber_memfree(ctx->realm);
     545                 :         if (ctx->authcid) ber_memfree(ctx->authcid);
     546                 :         if (ctx->passwd) ber_memfree(ctx->passwd);
     547                 :         if (ctx->authzid) ber_memfree(ctx->authzid);
     548                 :         ber_memfree(ctx);
     549                 : }
     550                 : /* }}} */
     551                 : 
     552                 : /* {{{ _php_sasl_interact
     553                 :    Internal interact function for SASL */
     554                 : static int _php_sasl_interact(LDAP *ld, unsigned flags, void *defaults, void *in)
     555                 : {
     556                 :         sasl_interact_t *interact = in;
     557                 :         const char *p;
     558                 :         php_ldap_bictx *ctx = defaults;
     559                 : 
     560                 :         for (;interact->id != SASL_CB_LIST_END;interact++) {
     561                 :                 p = NULL;
     562                 :                 switch(interact->id) {
     563                 :                         case SASL_CB_GETREALM:
     564                 :                                 p = ctx->realm;
     565                 :                                 break;
     566                 :                         case SASL_CB_AUTHNAME:
     567                 :                                 p = ctx->authcid;
     568                 :                                 break;
     569                 :                         case SASL_CB_USER:
     570                 :                                 p = ctx->authzid;
     571                 :                                 break;
     572                 :                         case SASL_CB_PASS:
     573                 :                                 p = ctx->passwd;
     574                 :                                 break;
     575                 :                 }
     576                 :                 if (p) {
     577                 :                         interact->result = p;
     578                 :                         interact->len = strlen(interact->result);
     579                 :                 }
     580                 :         }
     581                 :         return LDAP_SUCCESS;
     582                 : }
     583                 : /* }}} */
     584                 : 
     585                 : /* {{{ proto bool ldap_sasl_bind(resource link [, string binddn [, string password [, string sasl_mech [, string sasl_realm [, string sasl_authc_id [, string sasl_authz_id [, string props]]]]]]])
     586                 :    Bind to LDAP directory using SASL */
     587                 : PHP_FUNCTION(ldap_sasl_bind)
     588                 : {
     589                 :         zval *link;
     590                 :         ldap_linkdata *ld;
     591                 :         char *binddn = NULL;
     592                 :         char *passwd = NULL;
     593                 :         char *sasl_mech = NULL;
     594                 :         char *sasl_realm = NULL;
     595                 :         char *sasl_authz_id = NULL;
     596                 :         char *sasl_authc_id = NULL;
     597                 :         char *props = NULL;
     598                 :         int rc, dn_len, passwd_len, mech_len, realm_len, authc_id_len, authz_id_len, props_len;
     599                 :         php_ldap_bictx *ctx;
     600                 : 
     601                 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|sssssss", &link, &binddn, &dn_len, &passwd, &passwd_len, &sasl_mech, &mech_len, &sasl_realm, &realm_len, &sasl_authc_id, &authc_id_len, &sasl_authz_id, &authz_id_len, &props, &props_len) == FAILURE) {
     602                 :                 RETURN_FALSE;
     603                 :         }
     604                 : 
     605                 :         ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
     606                 : 
     607                 :         ctx = _php_sasl_setdefs(ld->link, sasl_mech, sasl_realm, sasl_authc_id, passwd, sasl_authz_id);
     608                 : 
     609                 :         if (props) {
     610                 :                 ldap_set_option(ld->link, LDAP_OPT_X_SASL_SECPROPS, props);
     611                 :         }
     612                 : 
     613                 :         rc = ldap_sasl_interactive_bind_s(ld->link, binddn, ctx->mech, NULL, NULL, LDAP_SASL_QUIET, _php_sasl_interact, ctx);
     614                 :         if (rc != LDAP_SUCCESS) {
     615                 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to bind to server: %s", ldap_err2string(rc));
     616                 :                 RETVAL_FALSE;
     617                 :         } else {
     618                 :                 RETVAL_TRUE;
     619                 :         }
     620                 :         _php_sasl_freedefs(ctx);
     621                 : }
     622                 : /* }}} */
     623                 : #endif /* HAVE_LDAP_SASL */
     624                 : 
     625                 : /* {{{ proto bool ldap_unbind(resource link)
     626                 :    Unbind from LDAP directory */
     627                 : PHP_FUNCTION(ldap_unbind)
     628              60 : {
     629                 :         zval *link;
     630                 :         ldap_linkdata *ld;
     631                 : 
     632              60 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &link) == FAILURE) {
     633               3 :                 RETURN_FALSE;
     634                 :         }
     635                 : 
     636              57 :         ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
     637                 : 
     638              56 :         zend_list_delete(Z_LVAL_P(link));
     639              56 :         RETURN_TRUE;
     640                 : }
     641                 : /* }}} */
     642                 : 
     643                 : /* {{{ php_set_opts
     644                 :  */
     645                 : static void php_set_opts(LDAP *ldap, int sizelimit, int timelimit, int deref, int *old_sizelimit, int *old_timelimit, int *old_deref)
     646              93 : {
     647                 :         /* sizelimit */
     648              93 :         if (sizelimit > -1) {
     649                 : #if (LDAP_API_VERSION >= 2004) || HAVE_NSLDAP || HAVE_ORALDAP_10
     650              14 :                 ldap_get_option(ldap, LDAP_OPT_SIZELIMIT, old_sizelimit);
     651              14 :                 ldap_set_option(ldap, LDAP_OPT_SIZELIMIT, &sizelimit);
     652                 : #else
     653                 :                 *old_sizelimit = ldap->ld_sizelimit; 
     654                 :                 ldap->ld_sizelimit = sizelimit; 
     655                 : #endif
     656                 :         }
     657                 : 
     658                 :         /* timelimit */
     659              93 :         if (timelimit > -1) {
     660                 : #if (LDAP_API_VERSION >= 2004) || HAVE_NSLDAP || HAVE_ORALDAP_10
     661              10 :                 ldap_get_option(ldap, LDAP_OPT_SIZELIMIT, old_timelimit);
     662              10 :                 ldap_set_option(ldap, LDAP_OPT_TIMELIMIT, &timelimit);
     663                 : #else
     664                 :                 *old_timelimit = ldap->ld_timelimit; 
     665                 :                 ldap->ld_timelimit = timelimit; 
     666                 : #endif
     667                 :         }
     668                 : 
     669                 :         /* deref */
     670              93 :         if (deref > -1) {
     671                 : #if (LDAP_API_VERSION >= 2004) || HAVE_NSLDAP || HAVE_ORALDAP_10
     672               8 :                 ldap_get_option(ldap, LDAP_OPT_SIZELIMIT, old_deref);
     673               8 :                 ldap_set_option(ldap, LDAP_OPT_DEREF, &deref);
     674                 : #else
     675                 :                 *old_deref = ldap->ld_deref; 
     676                 :                 ldap->ld_deref = deref; 
     677                 : #endif
     678                 :         }
     679              93 : }
     680                 : /* }}} */
     681                 : 
     682                 : /* {{{ php_ldap_do_search
     683                 :  */
     684                 : static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope)
     685              60 : {
     686                 :         zval **link, **base_dn, **filter, **attrs, **attr, **attrsonly, **sizelimit, **timelimit, **deref;
     687              60 :         char *ldap_base_dn = NULL;
     688              60 :         char *ldap_filter = NULL;
     689              60 :         char **ldap_attrs = NULL; 
     690              60 :         ldap_linkdata *ld = NULL;
     691                 :         LDAPMessage *ldap_res;
     692              60 :         int ldap_attrsonly = 0;
     693              60 :         int ldap_sizelimit = -1; 
     694              60 :         int ldap_timelimit = -1; 
     695              60 :         int ldap_deref = -1;     
     696              60 :         int old_ldap_sizelimit = -1; 
     697              60 :         int old_ldap_timelimit = -1; 
     698              60 :         int old_ldap_deref = -1;         
     699              60 :         int num_attribs = 0;
     700                 :         int i, errno;
     701              60 :         int myargcount = ZEND_NUM_ARGS();
     702              60 :         int ret = 1;
     703                 : 
     704              60 :         if (myargcount < 3 || myargcount > 8 || zend_get_parameters_ex(myargcount, &link, &base_dn, &filter, &attrs, &attrsonly, &sizelimit, &timelimit, &deref) == FAILURE) {
     705               9 :                 WRONG_PARAM_COUNT;
     706                 :         }
     707                 : 
     708                 :         /* Reverse -> fall through */
     709              51 :         switch (myargcount) {
     710                 :                 case 8 :
     711               4 :                         convert_to_long_ex(deref);
     712               4 :                         ldap_deref = Z_LVAL_PP(deref);
     713                 : 
     714                 :                 case 7 :
     715               5 :                         convert_to_long_ex(timelimit);
     716               5 :                         ldap_timelimit = Z_LVAL_PP(timelimit);
     717                 : 
     718                 :                 case 6 :
     719               7 :                         convert_to_long_ex(sizelimit);
     720               7 :                         ldap_sizelimit = Z_LVAL_PP(sizelimit);
     721                 : 
     722                 :                 case 5 :
     723               8 :                         convert_to_long_ex(attrsonly);
     724               8 :                         ldap_attrsonly = Z_LVAL_PP(attrsonly);
     725                 : 
     726                 :                 case 4 : 
     727              21 :                         if (Z_TYPE_PP(attrs) != IS_ARRAY) {
     728               1 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expected Array as last element");
     729               1 :                                 ret = 0;
     730               1 :                                 goto cleanup;
     731                 :                         }
     732                 : 
     733              20 :                         num_attribs = zend_hash_num_elements(Z_ARRVAL_PP(attrs));
     734              20 :                         ldap_attrs = safe_emalloc((num_attribs+1), sizeof(char *), 0);
     735                 : 
     736              43 :                         for (i = 0; i<num_attribs; i++) {
     737              24 :                                 if (zend_hash_index_find(Z_ARRVAL_PP(attrs), i, (void **) &attr) == FAILURE) {
     738               1 :                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Array initialization wrong");
     739               1 :                                         ret = 0;
     740               1 :                                         goto cleanup;
     741                 :                                 }
     742                 : 
     743              23 :                                 SEPARATE_ZVAL(attr);
     744              23 :                                 convert_to_string_ex(attr);
     745              23 :                                 ldap_attrs[i] = Z_STRVAL_PP(attr);
     746                 :                         }
     747              19 :                         ldap_attrs[num_attribs] = NULL;
     748                 :                 
     749                 :                 case 3 :
     750                 :                 
     751                 :                 break;
     752                 : 
     753                 :                 default:
     754               0 :                         WRONG_PARAM_COUNT;
     755                 :                 break;
     756                 :         }
     757                 : 
     758                 :         /* parallel search? */
     759              49 :         if (Z_TYPE_PP(link) == IS_ARRAY) {
     760                 :                 int i, nlinks, nbases, nfilters, *rcs;
     761                 :                 ldap_linkdata **lds;
     762                 :                 zval **entry, *resource;
     763                 :                 
     764               6 :                 nlinks = zend_hash_num_elements(Z_ARRVAL_PP(link));
     765               6 :                 if (nlinks == 0) {
     766               1 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "No links in link array");
     767               1 :                         ret = 0;
     768               1 :                         goto cleanup;
     769                 :                 }
     770                 : 
     771               5 :                 if (Z_TYPE_PP(base_dn) == IS_ARRAY) {
     772               1 :                         nbases = zend_hash_num_elements(Z_ARRVAL_PP(base_dn));
     773               1 :                         if (nbases != nlinks) {
     774               1 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Base must either be a string, or an array with the same number of elements as the links array");
     775               1 :                                 ret = 0;
     776               1 :                                 goto cleanup;
     777                 :                         }
     778               0 :                         zend_hash_internal_pointer_reset(Z_ARRVAL_PP(base_dn));
     779                 :                 } else {
     780               4 :                         nbases = 0; /* this means string, not array */
     781                 :                         /* If anything else than string is passed, ldap_base_dn = NULL */
     782               4 :                         if (Z_TYPE_PP(base_dn) == IS_STRING) {
     783               2 :                                 ldap_base_dn = Z_STRVAL_PP(base_dn);
     784                 :                         } else {
     785               2 :                                 ldap_base_dn = NULL;
     786                 :                         }
     787                 :                 }
     788                 : 
     789               4 :                 if (Z_TYPE_PP(filter) == IS_ARRAY) {
     790               2 :                         nfilters = zend_hash_num_elements(Z_ARRVAL_PP(filter));
     791               2 :                         if (nfilters != nlinks) {
     792               1 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Filter must either be a string, or an array with the same number of elements as the links array");
     793               1 :                                 ret = 0;
     794               1 :                                 goto cleanup;
     795                 :                         }
     796               1 :                         zend_hash_internal_pointer_reset(Z_ARRVAL_PP(filter));
     797                 :                 } else {
     798               2 :                         nfilters = 0; /* this means string, not array */
     799               2 :                         convert_to_string_ex(filter);
     800               2 :                         ldap_filter = Z_STRVAL_PP(filter);
     801                 :                 }
     802                 : 
     803               3 :                 lds = safe_emalloc(nlinks, sizeof(ldap_linkdata), 0);
     804               3 :                 rcs = safe_emalloc(nlinks, sizeof(*rcs), 0);
     805                 :                 
     806               3 :                 zend_hash_internal_pointer_reset(Z_ARRVAL_PP(link));
     807               9 :                 for (i=0; i<nlinks; i++) {
     808               6 :                         zend_hash_get_current_data(Z_ARRVAL_PP(link), (void **)&entry);
     809                 : 
     810               6 :                         ld = (ldap_linkdata *) zend_fetch_resource(entry TSRMLS_CC, -1, "ldap link", NULL, 1, le_link);
     811               6 :                         if (ld == NULL) {
     812               0 :                                 ret = 0;
     813               0 :                                 goto cleanup_parallel;
     814                 :                         }
     815               6 :                         if (nbases != 0) { /* base_dn an array? */
     816               0 :                                 zend_hash_get_current_data(Z_ARRVAL_PP(base_dn), (void **)&entry);
     817               0 :                                 zend_hash_move_forward(Z_ARRVAL_PP(base_dn));
     818                 : 
     819                 :                                 /* If anything else than string is passed, ldap_base_dn = NULL */
     820               0 :                                 if (Z_TYPE_PP(entry) == IS_STRING) {
     821               0 :                                         ldap_base_dn = Z_STRVAL_PP(entry);
     822                 :                                 } else {
     823               0 :                                         ldap_base_dn = NULL;
     824                 :                                 }
     825                 :                         }
     826               6 :                         if (nfilters != 0) { /* filter an array? */
     827               2 :                                 zend_hash_get_current_data(Z_ARRVAL_PP(filter), (void **)&entry);
     828               2 :                                 zend_hash_move_forward(Z_ARRVAL_PP(filter));
     829               2 :                                 convert_to_string_ex(entry);
     830               2 :                                 ldap_filter = Z_STRVAL_PP(entry);
     831                 :                         }
     832                 : 
     833               6 :                         php_set_opts(ld->link, ldap_sizelimit, ldap_timelimit, ldap_deref, &old_ldap_sizelimit, &old_ldap_timelimit, &old_ldap_deref);
     834                 : 
     835                 :                         /* Run the actual search */     
     836               6 :                         rcs[i] = ldap_search(ld->link, ldap_base_dn, scope, ldap_filter, ldap_attrs, ldap_attrsonly);
     837               6 :                         lds[i] = ld;
     838               6 :                         zend_hash_move_forward(Z_ARRVAL_PP(link));
     839                 :                 }
     840                 :                 
     841               3 :                 array_init(return_value);
     842                 : 
     843                 :                 /* Collect results from the searches */
     844               9 :                 for (i=0; i<nlinks; i++) {
     845               6 :                         MAKE_STD_ZVAL(resource);
     846               6 :                         if (rcs[i] != -1) {
     847               6 :                                 rcs[i] = ldap_result(lds[i]->link, LDAP_RES_ANY, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res);
     848                 :                         }
     849               6 :                         if (rcs[i] != -1) {
     850               6 :                                 ZEND_REGISTER_RESOURCE(resource, ldap_res, le_result);
     851               6 :                                 add_next_index_zval(return_value, resource);
     852                 :                         } else {
     853               0 :                                 add_next_index_bool(return_value, 0);
     854                 :                         }
     855                 :                 }
     856                 : 
     857               3 : cleanup_parallel:
     858               3 :                 efree(lds);
     859               3 :                 efree(rcs);
     860                 :         } else {
     861              43 :                 convert_to_string_ex(filter);
     862              43 :                 ldap_filter = Z_STRVAL_PP(filter);
     863                 : 
     864                 :                 /* If anything else than string is passed, ldap_base_dn = NULL */
     865              43 :                 if (Z_TYPE_PP(base_dn) == IS_STRING) {
     866              42 :                         ldap_base_dn = Z_STRVAL_PP(base_dn);
     867                 :                 }
     868                 : 
     869              43 :                 ld = (ldap_linkdata *) zend_fetch_resource(link TSRMLS_CC, -1, "ldap link", NULL, 1, le_link);
     870              43 :                 if (ld == NULL) {
     871               1 :                         ret = 0;
     872               1 :                         goto cleanup;
     873                 :                 }
     874                 : 
     875              42 :                 php_set_opts(ld->link, ldap_sizelimit, ldap_timelimit, ldap_deref, &old_ldap_sizelimit, &old_ldap_timelimit, &old_ldap_deref);
     876                 : 
     877                 :                 /* Run the actual search */     
     878              42 :                 errno = ldap_search_s(ld->link, ldap_base_dn, scope, ldap_filter, ldap_attrs, ldap_attrsonly, &ldap_res);
     879                 :         
     880              44 :                 if (errno != LDAP_SUCCESS
     881                 :                         && errno != LDAP_SIZELIMIT_EXCEEDED
     882                 : #ifdef LDAP_ADMINLIMIT_EXCEEDED
     883                 :                         && errno != LDAP_ADMINLIMIT_EXCEEDED
     884                 : #endif
     885                 : #ifdef LDAP_REFERRAL
     886                 :                         && errno != LDAP_REFERRAL
     887                 : #endif
     888                 :                 ) {
     889               2 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Search: %s", ldap_err2string(errno));
     890               2 :                         ret = 0;
     891                 :                 } else {
     892              40 :                         if (errno == LDAP_SIZELIMIT_EXCEEDED) {
     893               6 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Partial search results returned: Sizelimit exceeded");
     894                 :                         }
     895                 : #ifdef LDAP_ADMINLIMIT_EXCEEDED
     896              34 :                         else if (errno == LDAP_ADMINLIMIT_EXCEEDED) {
     897               0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Partial search results returned: Adminlimit exceeded");
     898                 :                         }
     899                 : #endif
     900                 :                         
     901              40 :                         ZEND_REGISTER_RESOURCE(return_value, ldap_res, le_result);
     902                 :                 }
     903                 :         }
     904                 : 
     905              51 : cleanup:
     906              51 :         if (ld) {
     907                 :                 /* Restoring previous options */        
     908              45 :                 php_set_opts(ld->link, old_ldap_sizelimit, old_ldap_timelimit, old_ldap_deref, &ldap_sizelimit, &ldap_timelimit, &ldap_deref);
     909                 :         }
     910              51 :         if (ldap_attrs != NULL) {
     911              20 :                 efree(ldap_attrs);
     912                 :         }
     913              51 :         if (!ret) {
     914               8 :                 RETVAL_BOOL(ret);
     915                 :         }
     916                 : }
     917                 : /* }}} */
     918                 : 
     919                 : /* {{{ proto resource ldap_read(resource link, string base_dn, string filter [, array attrs [, int attrsonly [, int sizelimit [, int timelimit [, int deref]]]]])
     920                 :    Read an entry */
     921                 : PHP_FUNCTION(ldap_read)
     922               6 : {
     923               6 :         php_ldap_do_search(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_SCOPE_BASE);
     924               6 : }
     925                 : /* }}} */
     926                 : 
     927                 : /* {{{ proto resource ldap_list(resource link, string base_dn, string filter [, array attrs [, int attrsonly [, int sizelimit [, int timelimit [, int deref]]]]])
     928                 :    Single-level search */
     929                 : PHP_FUNCTION(ldap_list)
     930               6 : {
     931               6 :         php_ldap_do_search(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_SCOPE_ONELEVEL);
     932               6 : }
     933                 : /* }}} */
     934                 : 
     935                 : /* {{{ proto resource ldap_search(resource link, string base_dn, string filter [, array attrs [, int attrsonly [, int sizelimit [, int timelimit [, int deref]]]]])
     936                 :    Search LDAP tree under base_dn */
     937                 : PHP_FUNCTION(ldap_search)
     938              48 : {
     939              48 :         php_ldap_do_search(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_SCOPE_SUBTREE);
     940              48 : }
     941                 : /* }}} */
     942                 : 
     943                 : /* {{{ proto bool ldap_free_result(resource result)
     944                 :    Free result memory */
     945                 : PHP_FUNCTION(ldap_free_result)
     946               3 : {
     947                 :         zval **result;
     948                 :         LDAPMessage *ldap_result;
     949                 : 
     950               3 :         if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &result) == FAILURE) {
     951               1 :                 WRONG_PARAM_COUNT;
     952                 :         }
     953                 : 
     954               2 :         ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, result, -1, "ldap result", le_result);
     955                 : 
     956               1 :         zend_list_delete(Z_LVAL_PP(result));  /* Delete list entry and call registered destructor function */
     957               1 :         RETVAL_TRUE;
     958                 : }
     959                 : /* }}} */
     960                 : 
     961                 : /* {{{ proto int ldap_count_entries(resource link, resource result)
     962                 :    Count the number of entries in a search result */
     963                 : PHP_FUNCTION(ldap_count_entries)
     964               3 : {
     965                 :         zval **link, **result;
     966                 :         ldap_linkdata *ld;
     967                 :         LDAPMessage *ldap_result;
     968                 : 
     969               3 :         if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &link, &result) == FAILURE) {
     970               1 :                 WRONG_PARAM_COUNT;
     971                 :         }
     972                 : 
     973               2 :         ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
     974               2 :         ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, result, -1, "ldap result", le_result);
     975                 : 
     976               1 :         RETURN_LONG(ldap_count_entries(ld->link, ldap_result));
     977                 : }
     978                 : /* }}} */
     979                 : 
     980                 : /* {{{ proto resource ldap_first_entry(resource link, resource result)
     981                 :    Return first result id */
     982                 : PHP_FUNCTION(ldap_first_entry)
     983              12 : {
     984                 :         zval **link, **result;
     985                 :         ldap_linkdata *ld;      
     986                 :         ldap_resultentry *resultentry;
     987                 :         LDAPMessage *ldap_result, *entry;
     988                 : 
     989              12 :         if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &link, &result) == FAILURE) {
     990               2 :                 WRONG_PARAM_COUNT;
     991                 :         }
     992                 : 
     993              10 :         ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
     994              10 :         ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, result, -1, "ldap result", le_result);
     995                 : 
     996               9 :         if ((entry = ldap_first_entry(ld->link, ldap_result)) == NULL) {
     997               0 :                 RETVAL_FALSE;
     998                 :         } else {
     999               9 :                 resultentry = emalloc(sizeof(ldap_resultentry));
    1000               9 :                 ZEND_REGISTER_RESOURCE(return_value, resultentry, le_result_entry);
    1001               9 :                 resultentry->id = Z_LVAL_PP(result);
    1002               9 :                 zend_list_addref(resultentry->id);
    1003               9 :                 resultentry->data = entry;
    1004               9 :                 resultentry->ber = NULL;
    1005                 :         }
    1006                 : }
    1007                 : /* }}} */
    1008                 : 
    1009                 : /* {{{ proto resource ldap_next_entry(resource link, resource result_entry)
    1010                 :    Get next result entry */
    1011                 : PHP_FUNCTION(ldap_next_entry)
    1012               5 : {
    1013                 :         zval **link, **result_entry;
    1014                 :         ldap_linkdata *ld;
    1015                 :         ldap_resultentry *resultentry, *resultentry_next;
    1016                 :         LDAPMessage *entry_next;
    1017                 : 
    1018               5 :         if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &link, &result_entry) == FAILURE) {
    1019               2 :                 WRONG_PARAM_COUNT;
    1020                 :         }
    1021                 : 
    1022               3 :         ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
    1023               3 :         ZEND_FETCH_RESOURCE(resultentry, ldap_resultentry *, result_entry, -1, "ldap result entry", le_result_entry);
    1024                 : 
    1025               2 :         if ((entry_next = ldap_next_entry(ld->link, resultentry->data)) == NULL) {
    1026               1 :                 RETVAL_FALSE;
    1027                 :         } else {
    1028               1 :                 resultentry_next = emalloc(sizeof(ldap_resultentry));
    1029               1 :                 ZEND_REGISTER_RESOURCE(return_value, resultentry_next, le_result_entry);
    1030               1 :                 resultentry_next->id = resultentry->id;
    1031               1 :                 zend_list_addref(resultentry->id);
    1032               1 :                 resultentry_next->data = entry_next;
    1033               1 :                 resultentry_next->ber = NULL;
    1034                 :         }
    1035                 : }
    1036                 : /* }}} */
    1037                 : 
    1038                 : /* {{{ proto array ldap_get_entries(resource link, resource result)
    1039                 :    Get all result entries */
    1040                 : PHP_FUNCTION(ldap_get_entries)
    1041              33 : {
    1042                 :         zval **link, **result;
    1043                 :         LDAPMessage *ldap_result, *ldap_result_entry;
    1044                 :         zval *tmp1, *tmp2;
    1045                 :         ldap_linkdata *ld;
    1046                 :         LDAP *ldap;
    1047                 :         int num_entries, num_attrib, num_values, i;
    1048                 :         BerElement *ber;
    1049                 :         char *attribute;
    1050                 :         size_t attr_len;
    1051                 :         struct berval **ldap_value;
    1052                 :         char *dn;
    1053                 : 
    1054              33 :         if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &link, &result) == FAILURE) {
    1055               2 :                 WRONG_PARAM_COUNT;
    1056                 :         }
    1057                 : 
    1058              31 :         ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
    1059              31 :         ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, result, -1, "ldap result", le_result);
    1060                 : 
    1061              30 :         ldap = ld->link;
    1062              30 :         num_entries = ldap_count_entries(ldap, ldap_result);
    1063                 : 
    1064              30 :         if (num_entries == 0) return;
    1065              24 :         num_entries = 0;
    1066                 :         
    1067              24 :         ldap_result_entry = ldap_first_entry(ldap, ldap_result);
    1068              24 :         if (ldap_result_entry == NULL) RETURN_FALSE;
    1069                 : 
    1070              24 :         array_init(return_value);
    1071              24 :         add_assoc_long(return_value, "count", num_entries);
    1072                 : 
    1073              97 :         while (ldap_result_entry != NULL) {
    1074                 : 
    1075              49 :                 MAKE_STD_ZVAL(tmp1);
    1076              49 :                 array_init(tmp1);
    1077                 : 
    1078              49 :                 num_attrib = 0;
    1079              49 :                 attribute = ldap_first_attribute(ldap, ldap_result_entry, &ber);
    1080                 : 
    1081             215 :                 while (attribute != NULL) {
    1082             117 :                         ldap_value = ldap_get_values_len(ldap, ldap_result_entry, attribute);
    1083             117 :                         num_values = ldap_count_values_len(ldap_value);
    1084                 : 
    1085             117 :                         MAKE_STD_ZVAL(tmp2);
    1086             117 :                         array_init(tmp2);
    1087             117 :                         add_assoc_long(tmp2, "count", num_values);
    1088             232 :                         for (i = 0; i < num_values; i++) {
    1089             115 :                                 add_index_stringl(tmp2, i, ldap_value[i]->bv_val, ldap_value[i]->bv_len, 1);
    1090                 :                         }       
    1091             117 :                         ldap_value_free_len(ldap_value);
    1092                 : 
    1093             117 :                         attr_len = strlen(attribute);
    1094             117 :                         zend_hash_update(Z_ARRVAL_P(tmp1), php_strtolower(attribute, attr_len), attr_len+1, (void *) &tmp2, sizeof(zval *), NULL);
    1095             117 :                         add_index_string(tmp1, num_attrib, attribute, 1);
    1096                 : 
    1097             117 :                         num_attrib++;
    1098                 : #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS
    1099             117 :                         ldap_memfree(attribute);
    1100                 : #endif
    1101             117 :                         attribute = ldap_next_attribute(ldap, ldap_result_entry, ber);
    1102                 :                 }
    1103                 : #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS
    1104              49 :                 if (ber != NULL) {
    1105              49 :                         ber_free(ber, 0);
    1106                 :                 }
    1107                 : #endif
    1108                 : 
    1109              49 :                 add_assoc_long(tmp1, "count", num_attrib);
    1110              49 :                 dn = ldap_get_dn(ldap, ldap_result_entry);
    1111              49 :                 add_assoc_string(tmp1, "dn", dn, 1);
    1112                 : #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS
    1113              49 :                 ldap_memfree(dn);
    1114                 : #else
    1115                 :                 free(dn);
    1116                 : #endif
    1117                 : 
    1118              49 :                 zend_hash_index_update(Z_ARRVAL_P(return_value), num_entries, (void *) &tmp1, sizeof(zval *), NULL);
    1119                 :                 
    1120              49 :                 num_entries++;
    1121              49 :                 ldap_result_entry = ldap_next_entry(ldap, ldap_result_entry);
    1122                 :         }
    1123                 : 
    1124              24 :         add_assoc_long(return_value, "count", num_entries);
    1125                 : 
    1126                 : }
    1127                 : /* }}} */
    1128                 : 
    1129                 : /* {{{ proto string ldap_first_attribute(resource link, resource result_entry)
    1130                 :    Return first attribute */
    1131                 : PHP_FUNCTION(ldap_first_attribute)
    1132               4 : {
    1133                 :         zval **link, **result_entry;
    1134                 :         ldap_linkdata *ld;
    1135                 :         ldap_resultentry *resultentry;
    1136                 :         char *attribute;
    1137               4 :         int argc = ZEND_NUM_ARGS();
    1138                 : 
    1139               4 :         if ((argc < 2 || argc > 3) || zend_get_parameters_ex(2, &link, &result_entry) == FAILURE) {
    1140               1 :                 WRONG_PARAM_COUNT;
    1141                 :         }
    1142                 : 
    1143               3 :         ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
    1144               3 :         ZEND_FETCH_RESOURCE(resultentry, ldap_resultentry *, result_entry, -1, "ldap result entry", le_result_entry);
    1145                 : 
    1146               2 :         if ((attribute = ldap_first_attribute(ld->link, resultentry->data, &resultentry->ber)) == NULL) {
    1147               0 :                 RETURN_FALSE;
    1148                 :         } else {
    1149               2 :                 RETVAL_STRING(attribute, 1);
    1150                 : #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS
    1151               2 :                 ldap_memfree(attribute);
    1152                 : #endif
    1153                 :         }
    1154                 : }
    1155                 : /* }}} */
    1156                 : 
    1157                 : /* {{{ proto string ldap_next_attribute(resource link, resource result_entry)
    1158                 :    Get the next attribute in result */
    1159                 : PHP_FUNCTION(ldap_next_attribute)
    1160               6 : {
    1161                 :         zval **link, **result_entry;
    1162                 :         ldap_linkdata *ld;
    1163                 :         ldap_resultentry *resultentry;
    1164                 :         char *attribute;
    1165               6 :         int argc = ZEND_NUM_ARGS();
    1166                 : 
    1167               6 :         if ((argc < 2 || argc > 3) || zend_get_parameters_ex(2, &link, &result_entry) == FAILURE) {
    1168               1 :                 WRONG_PARAM_COUNT;
    1169                 :         }
    1170                 : 
    1171               5 :         ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
    1172               5 :         ZEND_FETCH_RESOURCE(resultentry, ldap_resultentry *, result_entry, -1, "ldap result entry", le_result_entry);
    1173                 : 
    1174               4 :         if (resultentry->ber == NULL) {
    1175               1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "called before calling ldap_first_attribute() or no attributes found in result entry");
    1176               1 :                 RETURN_FALSE;
    1177                 :         }
    1178                 : 
    1179               3 :         if ((attribute = ldap_next_attribute(ld->link, resultentry->data, resultentry->ber)) == NULL) {
    1180                 : #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS
    1181               1 :                 if (resultentry->ber != NULL) {
    1182               1 :                         ber_free(resultentry->ber, 0);
    1183               1 :                         resultentry->ber = NULL;
    1184                 :                 }
    1185                 : #endif
    1186               1 :                 RETURN_FALSE;
    1187                 :         } else {
    1188               2 :                 RETVAL_STRING(attribute, 1);
    1189                 : #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS
    1190               2 :                 ldap_memfree(attribute);
    1191                 : #endif
    1192                 :         }
    1193                 : }
    1194                 : /* }}} */
    1195                 : 
    1196                 : /* {{{ proto array ldap_get_attributes(resource link, resource result_entry)
    1197                 :    Get attributes from a search result entry */
    1198                 : PHP_FUNCTION(ldap_get_attributes)
    1199               3 : {
    1200                 :         zval **link, **result_entry;
    1201                 :         zval *tmp;
    1202                 :         ldap_linkdata *ld;
    1203                 :         ldap_resultentry *resultentry;
    1204                 :         char *attribute;
    1205                 :         struct berval **ldap_value;
    1206                 :         int i, num_values, num_attrib;
    1207                 :         BerElement *ber;
    1208                 : 
    1209               3 :         if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &link, &result_entry) == FAILURE) {
    1210               1 :                 WRONG_PARAM_COUNT;
    1211                 :         }
    1212                 : 
    1213               2 :         ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
    1214               2 :         ZEND_FETCH_RESOURCE(resultentry, ldap_resultentry *, result_entry, -1, "ldap result entry", le_result_entry);
    1215                 : 
    1216               1 :         array_init(return_value);
    1217               1 :         num_attrib = 0;
    1218                 :         
    1219               1 :         attribute = ldap_first_attribute(ld->link, resultentry->data, &ber);
    1220               5 :         while (attribute != NULL) {
    1221               3 :                 ldap_value = ldap_get_values_len(ld->link, resultentry->data, attribute);
    1222               3 :                 num_values = ldap_count_values_len(ldap_value);
    1223                 : 
    1224               3 :                 MAKE_STD_ZVAL(tmp);
    1225               3 :                 array_init(tmp);
    1226               3 :                 add_assoc_long(tmp, "count", num_values);
    1227               8 :                 for (i = 0; i < num_values; i++) {
    1228               5 :                         add_index_stringl(tmp, i, ldap_value[i]->bv_val, ldap_value[i]->bv_len, 1);
    1229                 :                 }
    1230               3 :                 ldap_value_free_len(ldap_value);
    1231                 : 
    1232               3 :                 zend_hash_update(Z_ARRVAL_P(return_value), attribute, strlen(attribute)+1, (void *) &tmp, sizeof(zval *), NULL);
    1233               3 :                 add_index_string(return_value, num_attrib, attribute, 1);
    1234                 : 
    1235               3 :                 num_attrib++;
    1236                 : #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS
    1237               3 :                 ldap_memfree(attribute);
    1238                 : #endif
    1239               3 :                 attribute = ldap_next_attribute(ld->link, resultentry->data, ber);
    1240                 :         }
    1241                 : #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS
    1242               1 :         if (ber != NULL) {
    1243               1 :                 ber_free(ber, 0);
    1244                 :         }
    1245                 : #endif
    1246                 :         
    1247               1 :         add_assoc_long(return_value, "count", num_attrib);
    1248                 : }
    1249                 : /* }}} */
    1250                 : 
    1251                 : /* {{{ proto array ldap_get_values_len(resource link, resource result_entry, string attribute)
    1252                 :    Get all values with lengths from a result entry */
    1253                 : PHP_FUNCTION(ldap_get_values_len)
    1254               7 : {
    1255                 :         zval **link, **result_entry, **attr;
    1256                 :         ldap_linkdata *ld;
    1257                 :         ldap_resultentry *resultentry;
    1258                 :         char* attribute;
    1259                 :         struct berval **ldap_value_len;
    1260                 :         int i, num_values;
    1261                 :         
    1262               7 :         if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &link, &result_entry, &attr) == FAILURE) {
    1263               3 :                 WRONG_PARAM_COUNT;
    1264                 :         }
    1265                 :         
    1266               4 :         ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
    1267               4 :         ZEND_FETCH_RESOURCE(resultentry, ldap_resultentry *, result_entry, -1, "ldap result entry", le_result_entry);
    1268                 : 
    1269               4 :         convert_to_string_ex(attr);
    1270               4 :         attribute = Z_STRVAL_PP(attr);
    1271                 :         
    1272               4 :         if ((ldap_value_len = ldap_get_values_len(ld->link, resultentry->data, attribute)) == NULL) {
    1273               1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot get the value(s) of attribute %s", ldap_err2string(_get_lderrno(ld->link)));
    1274               1 :                 RETURN_FALSE;
    1275                 :         }
    1276                 :         
    1277               3 :         num_values = ldap_count_values_len(ldap_value_len);
    1278               3 :         array_init(return_value);
    1279                 :         
    1280               6 :         for (i=0; i<num_values; i++) {
    1281               3 :                 add_next_index_stringl(return_value, ldap_value_len[i]->bv_val, ldap_value_len[i]->bv_len, 1);
    1282                 :         }
    1283                 :         
    1284               3 :         add_assoc_long(return_value, "count", num_values);
    1285               3 :         ldap_value_free_len(ldap_value_len);
    1286                 : 
    1287                 : }
    1288                 : /* }}} */
    1289                 : 
    1290                 : /* {{{ proto string ldap_get_dn(resource link, resource result_entry)
    1291                 :    Get the DN of a result entry */
    1292                 : PHP_FUNCTION(ldap_get_dn) 
    1293               3 : {
    1294                 :         zval **link, **result_entry;
    1295                 :         ldap_linkdata *ld;
    1296                 :         ldap_resultentry *resultentry;
    1297                 :         char *text;
    1298                 : 
    1299               3 :         if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &link, &result_entry) == FAILURE) {
    1300               1 :                 WRONG_PARAM_COUNT;
    1301                 :         }
    1302                 :         
    1303               2 :         ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
    1304               2 :         ZEND_FETCH_RESOURCE(resultentry, ldap_resultentry *, result_entry, -1, "ldap result entry", le_result_entry);
    1305                 : 
    1306               1 :         text = ldap_get_dn(ld->link, resultentry->data);
    1307               1 :         if (text != NULL) {
    1308               1 :                 RETVAL_STRING(text, 1);
    1309                 : #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS
    1310               1 :                 ldap_memfree(text);
    1311                 : #else
    1312                 :                 free(text);
    1313                 : #endif
    1314                 :         } else {
    1315               0 :                 RETURN_FALSE;
    1316                 :         }
    1317                 : }
    1318                 : /* }}} */
    1319                 : 
    1320                 : /* {{{ proto array ldap_explode_dn(string dn, int with_attrib)
    1321                 :    Splits DN into its component parts */
    1322                 : PHP_FUNCTION(ldap_explode_dn)
    1323              10 : {
    1324                 :         zval **dn, **with_attrib;
    1325                 :         char **ldap_value;
    1326                 :         int i, count;
    1327                 : 
    1328              10 :         if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &dn, &with_attrib) == FAILURE) {
    1329               2 :                 WRONG_PARAM_COUNT;
    1330                 :         }
    1331                 : 
    1332               8 :         convert_to_string_ex(dn);
    1333               8 :         convert_to_long_ex(with_attrib);
    1334                 : 
    1335               8 :         if (!(ldap_value = ldap_explode_dn(Z_STRVAL_PP(dn), Z_LVAL_PP(with_attrib)))) {
    1336                 :                 /* Invalid parameters were passed to ldap_explode_dn */
    1337               4 :                 RETURN_FALSE;
    1338                 :         }
    1339                 : 
    1340               4 :         i=0;
    1341               4 :         while (ldap_value[i] != NULL) i++;
    1342               4 :         count = i;
    1343                 : 
    1344               4 :         array_init(return_value);
    1345                 : 
    1346               4 :         add_assoc_long(return_value, "count", count);
    1347              18 :         for (i = 0; i<count; i++) {
    1348              14 :                 add_index_string(return_value, i, ldap_value[i], 1);
    1349                 :         }
    1350                 : 
    1351               4 :         ldap_value_free(ldap_value);
    1352                 : }
    1353                 : /* }}} */
    1354                 : 
    1355                 : /* {{{ proto string ldap_dn2ufn(string dn)
    1356                 :    Convert DN to User Friendly Naming format */
    1357                 : PHP_FUNCTION(ldap_dn2ufn)
    1358               5 : {
    1359                 :         zval **dn;
    1360                 :         char *ufn;
    1361                 : 
    1362               5 :         if (ZEND_NUM_ARGS() !=1 || zend_get_parameters_ex(1, &dn)==FAILURE) {
    1363               1 :                 WRONG_PARAM_COUNT;
    1364                 :         }
    1365                 :         
    1366               4 :         convert_to_string_ex(dn);
    1367                 :         
    1368               4 :         ufn = ldap_dn2ufn(Z_STRVAL_PP(dn));
    1369                 :         
    1370               4 :         if (ufn !=NULL) {
    1371               2 :                 RETVAL_STRING(ufn, 1);
    1372                 : #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS
    1373               2 :                 ldap_memfree(ufn);
    1374                 : #endif
    1375                 :         } else {
    1376               2 :                 RETURN_FALSE;
    1377                 :         }
    1378                 : }
    1379                 : /* }}} */
    1380                 : 
    1381                 : 
    1382                 : /* added to fix use of ldap_modify_add for doing an ldap_add, gerrit thomson. */
    1383                 : #define PHP_LD_FULL_ADD 0xff
    1384                 : /* {{{ php_ldap_do_modify
    1385                 :  */
    1386                 : static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper)
    1387             206 : {
    1388                 :         zval **link, **dn, **entry, **value, **ivalue;
    1389                 :         ldap_linkdata *ld;
    1390                 :         char *ldap_dn;
    1391                 :         LDAPMod **ldap_mods;
    1392                 :         int i, j, num_attribs, num_values;
    1393                 :         int *num_berval;
    1394                 :         char *attribute;
    1395                 :         ulong index;
    1396             206 :         int is_full_add=0; /* flag for full add operation so ldap_mod_add can be put back into oper, gerrit THomson */
    1397                 :  
    1398             206 :         if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &link, &dn, &entry) == FAILURE) {
    1399              20 :                 WRONG_PARAM_COUNT;
    1400                 :         }       
    1401                 : 
    1402             186 :         if (Z_TYPE_PP(entry) != IS_ARRAY) {
    1403               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expected Array as the last element");
    1404               0 :                 RETURN_FALSE;
    1405                 :         }
    1406                 : 
    1407             186 :         ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
    1408                 : 
    1409             186 :         convert_to_string_ex(dn);
    1410             186 :         ldap_dn = Z_STRVAL_PP(dn);
    1411                 : 
    1412             186 :         num_attribs = zend_hash_num_elements(Z_ARRVAL_PP(entry));
    1413             186 :         ldap_mods = safe_emalloc((num_attribs+1), sizeof(LDAPMod *), 0);
    1414             186 :         num_berval = safe_emalloc(num_attribs, sizeof(int), 0);
    1415             186 :         zend_hash_internal_pointer_reset(Z_ARRVAL_PP(entry));
    1416                 : 
    1417                 :         /* added by gerrit thomson to fix ldap_add using ldap_mod_add */
    1418             186 :         if (oper == PHP_LD_FULL_ADD) {
    1419             168 :                 oper = LDAP_MOD_ADD;
    1420             168 :                 is_full_add = 1;
    1421                 :         }
    1422                 :         /* end additional , gerrit thomson */
    1423                 : 
    1424             929 :         for (i = 0; i < num_attribs; i++) {
    1425             747 :                 ldap_mods[i] = emalloc(sizeof(LDAPMod));
    1426             747 :                 ldap_mods[i]->mod_op = oper | LDAP_MOD_BVALUES;
    1427                 : 
    1428             747 :                 if (zend_hash_get_current_key(Z_ARRVAL_PP(entry), &attribute, &index, 0) == HASH_KEY_IS_STRING) {
    1429             744 :                         ldap_mods[i]->mod_type = estrdup(attribute);
    1430                 :                 } else {
    1431               3 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown attribute in the data");
    1432                 :                         /* Free allocated memory */
    1433               9 :                         while (i >= 0) {
    1434               3 :                                 efree(ldap_mods[i--]);
    1435                 :                         }
    1436               3 :                         efree(num_berval);
    1437               3 :                         efree(ldap_mods);       
    1438               3 :                         RETURN_FALSE;
    1439                 :                 }
    1440                 : 
    1441             744 :                 zend_hash_get_current_data(Z_ARRVAL_PP(entry), (void **)&value);
    1442                 : 
    1443             744 :                 if (Z_TYPE_PP(value) != IS_ARRAY) {
    1444             688 :                         num_values = 1;
    1445                 :                 } else {
    1446              56 :                         num_values = zend_hash_num_elements(Z_ARRVAL_PP(value));
    1447                 :                 }
    1448                 :                 
    1449             744 :                 num_berval[i] = num_values;
    1450             744 :                 ldap_mods[i]->mod_bvalues = safe_emalloc((num_values + 1), sizeof(struct berval *), 0);
    1451                 : 
    1452                 : /* allow for arrays with one element, no allowance for arrays with none but probably not required, gerrit thomson. */
    1453            1432 :                 if ((num_values == 1) && (Z_TYPE_PP(value) != IS_ARRAY)) {
    1454             688 :                         convert_to_string_ex(value);
    1455             688 :                         ldap_mods[i]->mod_bvalues[0] = (struct berval *) emalloc (sizeof(struct berval));
    1456             688 :                         ldap_mods[i]->mod_bvalues[0]->bv_len = Z_STRLEN_PP(value);
    1457             688 :                         ldap_mods[i]->mod_bvalues[0]->bv_val = Z_STRVAL_PP(value);
    1458                 :                 } else {        
    1459             217 :                         for (j = 0; j < num_values; j++) {
    1460             162 :                                 if (zend_hash_index_find(Z_ARRVAL_PP(value), j, (void **) &ivalue) == FAILURE) {
    1461               1 :                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Value array must have consecutive indices 0, 1, ...");
    1462               1 :                                         num_berval[i] = j;
    1463               1 :                                         num_attribs = i + 1;
    1464               1 :                                         RETVAL_FALSE;
    1465               1 :                                         goto errexit;
    1466                 :                                 }
    1467             161 :                                 convert_to_string_ex(ivalue);
    1468             161 :                                 ldap_mods[i]->mod_bvalues[j] = (struct berval *) emalloc (sizeof(struct berval));
    1469             161 :                                 ldap_mods[i]->mod_bvalues[j]->bv_len = Z_STRLEN_PP(ivalue);
    1470             161 :                                 ldap_mods[i]->mod_bvalues[j]->bv_val = Z_STRVAL_PP(ivalue);
    1471                 :                         }
    1472                 :                 }
    1473             743 :                 ldap_mods[i]->mod_bvalues[num_values] = NULL;
    1474             743 :                 zend_hash_move_forward(Z_ARRVAL_PP(entry));
    1475                 :         }
    1476             182 :         ldap_mods[num_attribs] = NULL;
    1477                 : 
    1478                 : /* check flag to see if do_mod was called to perform full add , gerrit thomson */
    1479             182 :         if (is_full_add == 1) {
    1480             166 :                 if ((i = ldap_add_s(ld->link, ldap_dn, ldap_mods)) != LDAP_SUCCESS) {
    1481               6 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Add: %s", ldap_err2string(i));
    1482               6 :                         RETVAL_FALSE;
    1483             160 :                 } else RETVAL_TRUE;
    1484                 :         } else {
    1485              16 :                 if ((i = ldap_modify_s(ld->link, ldap_dn, ldap_mods)) != LDAP_SUCCESS) {
    1486              12 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Modify: %s", ldap_err2string(i));
    1487              12 :                         RETVAL_FALSE;
    1488               4 :                 } else RETVAL_TRUE;     
    1489                 :         }
    1490                 : 
    1491             183 : errexit:
    1492             927 :         for (i = 0; i < num_attribs; i++) {
    1493             744 :                 efree(ldap_mods[i]->mod_type);
    1494            1593 :                 for (j = 0; j < num_berval[i]; j++) {
    1495             849 :                         efree(ldap_mods[i]->mod_bvalues[j]);
    1496                 :                 }
    1497             744 :                 efree(ldap_mods[i]->mod_bvalues);
    1498             744 :                 efree(ldap_mods[i]);
    1499                 :         }
    1500             183 :         efree(num_berval);
    1501             183 :         efree(ldap_mods);       
    1502                 : 
    1503             183 :         return;
    1504                 : }
    1505                 : /* }}} */
    1506                 : 
    1507                 : /* {{{ proto bool ldap_add(resource link, string dn, array entry)
    1508                 :    Add entries to LDAP directory */
    1509                 : PHP_FUNCTION(ldap_add)
    1510             172 : {
    1511                 :         /* use a newly define parameter into the do_modify so ldap_mod_add can be used the way it is supposed to be used , Gerrit THomson */
    1512             172 :         php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_LD_FULL_ADD);
    1513             172 : }
    1514                 : /* }}} */
    1515                 : 
    1516                 : /* three functions for attribute base modifications, gerrit Thomson */
    1517                 : 
    1518                 : /* {{{ proto bool ldap_mod_replace(resource link, string dn, array entry)
    1519                 :    Replace attribute values with new ones */
    1520                 : PHP_FUNCTION(ldap_mod_replace)
    1521              17 : {
    1522              17 :         php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_REPLACE);
    1523              17 : }
    1524                 : /* }}} */
    1525                 : 
    1526                 : /* {{{ proto bool ldap_mod_add(resource link, string dn, array entry)
    1527                 :    Add attribute values to current */
    1528                 : PHP_FUNCTION(ldap_mod_add)
    1529               9 : {
    1530               9 :         php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_ADD);
    1531               9 : }
    1532                 : /* }}} */
    1533                 : 
    1534                 : /* {{{ proto bool ldap_mod_del(resource link, string dn, array entry)
    1535                 :    Delete attribute values */
    1536                 : PHP_FUNCTION(ldap_mod_del)
    1537               8 : {
    1538               8 :         php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_DELETE);
    1539               8 : }
    1540                 : /* }}} */
    1541                 : 
    1542                 : /* {{{ proto bool ldap_delete(resource link, string dn)
    1543                 :    Delete an entry from a directory */
    1544                 : PHP_FUNCTION(ldap_delete)
    1545             168 : {
    1546                 :         zval **link, **dn;
    1547                 :         ldap_linkdata *ld;
    1548                 :         char *ldap_dn;
    1549                 :         int rc;
    1550                 : 
    1551             168 :         if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &link, &dn) == FAILURE) {
    1552               3 :                 WRONG_PARAM_COUNT;
    1553                 :         }
    1554                 : 
    1555             165 :         ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
    1556                 : 
    1557             165 :         convert_to_string_ex(dn);
    1558             165 :         ldap_dn = Z_STRVAL_PP(dn);
    1559                 : 
    1560             165 :         if ((rc = ldap_delete_s(ld->link, ldap_dn)) != LDAP_SUCCESS) {
    1561               5 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Delete: %s", ldap_err2string(rc));
    1562               5 :                 RETURN_FALSE;
    1563                 :         }
    1564                 : 
    1565             160 :         RETURN_TRUE;
    1566                 : }
    1567                 : /* }}} */
    1568                 : 
    1569                 : /* {{{ proto int ldap_errno(resource link)
    1570                 :    Get the current ldap error number */
    1571                 : PHP_FUNCTION(ldap_errno)
    1572               9 : {
    1573                 :         zval **link;
    1574                 :         ldap_linkdata *ld;
    1575                 : 
    1576               9 :         if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(ht, &link) == FAILURE) {
    1577               2 :                 WRONG_PARAM_COUNT;
    1578                 :         }
    1579                 : 
    1580               7 :         ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
    1581                 : 
    1582               7 :         RETURN_LONG(_get_lderrno(ld->link));
    1583                 : }
    1584                 : /* }}} */
    1585                 : 
    1586                 : /* {{{ proto string ldap_err2str(int errno)
    1587                 :    Convert error number to error string */
    1588                 : PHP_FUNCTION(ldap_err2str)
    1589               3 : {
    1590                 :         zval **perrno;
    1591                 : 
    1592               3 :         if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(ht, &perrno) == FAILURE) {
    1593               2 :                 WRONG_PARAM_COUNT;
    1594                 :         }
    1595                 : 
    1596               1 :         convert_to_long_ex(perrno);
    1597               1 :         RETURN_STRING(ldap_err2string(Z_LVAL_PP(perrno)), 1);
    1598                 : }
    1599                 : /* }}} */
    1600                 : 
    1601                 : /* {{{ proto string ldap_error(resource link)
    1602                 :    Get the current ldap error string */
    1603                 : PHP_FUNCTION(ldap_error) 
    1604               9 : {
    1605                 :         zval **link;
    1606                 :         ldap_linkdata *ld;
    1607                 :         int ld_errno;
    1608                 : 
    1609               9 :         if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(ht, &link) == FAILURE) {
    1610               2 :                 WRONG_PARAM_COUNT;
    1611                 :         }
    1612                 : 
    1613               7 :         ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
    1614                 : 
    1615               7 :         ld_errno = _get_lderrno(ld->link);
    1616                 : 
    1617               7 :         RETURN_STRING(ldap_err2string(ld_errno), 1);
    1618                 : }
    1619                 : /* }}} */
    1620                 : 
    1621                 : /* {{{ proto bool ldap_compare(resource link, string dn, string attr, string value)
    1622                 :    Determine if an entry has a specific value for one of its attributes */
    1623                 : PHP_FUNCTION(ldap_compare) 
    1624               7 : {
    1625                 :         zval **link, **dn, **attr, **value;
    1626                 :         char *ldap_dn, *ldap_attr, *ldap_value;
    1627                 :         ldap_linkdata *ld;
    1628                 :         int errno;
    1629                 : 
    1630               7 :         if (ZEND_NUM_ARGS() != 4 || zend_get_parameters_ex(4, &link, &dn, &attr, &value) == FAILURE) {
    1631               4 :                 WRONG_PARAM_COUNT;
    1632                 :         }
    1633                 : 
    1634               3 :         ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
    1635                 : 
    1636               3 :         convert_to_string_ex(dn);
    1637               3 :         convert_to_string_ex(attr);
    1638               3 :         convert_to_string_ex(value);
    1639                 : 
    1640               3 :         ldap_dn = Z_STRVAL_PP(dn);
    1641               3 :         ldap_attr = Z_STRVAL_PP(attr);
    1642               3 :         ldap_value = Z_STRVAL_PP(value);
    1643                 : 
    1644               3 :         errno = ldap_compare_s(ld->link, ldap_dn, ldap_attr, ldap_value);
    1645                 : 
    1646               3 :         switch (errno) {
    1647                 :                 case LDAP_COMPARE_TRUE:
    1648               1 :                         RETURN_TRUE;
    1649                 :                         break;
    1650                 : 
    1651                 :                 case LDAP_COMPARE_FALSE:
    1652               1 :                         RETURN_FALSE;
    1653                 :                         break;
    1654                 :         }
    1655                 :         
    1656               1 :         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Compare: %s", ldap_err2string(errno));
    1657               1 :         RETURN_LONG(-1);
    1658                 : 
    1659                 : }
    1660                 : /* }}} */
    1661                 : 
    1662                 : /* {{{ proto bool ldap_sort(resource link, resource result, string sortfilter)
    1663                 :    Sort LDAP result entries */
    1664                 : PHP_FUNCTION(ldap_sort)
    1665               7 : {
    1666                 :         zval *link, *result;
    1667                 :         ldap_linkdata *ld;
    1668                 :         char *sortfilter;
    1669                 :         int sflen;
    1670                 :         zend_rsrc_list_entry *le;
    1671                 : 
    1672               7 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rrs", &link, &result, &sortfilter, &sflen) == FAILURE) {
    1673               4 :                 RETURN_FALSE;
    1674                 :         }
    1675                 : 
    1676               3 :         ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
    1677                 : 
    1678               3 :         if (zend_hash_index_find(&EG(regular_list), Z_LVAL_P(result), (void **) &le) == FAILURE || le->type != le_result) {
    1679               1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Supplied resource is not a valid ldap result resource");
    1680               1 :                 RETURN_FALSE;
    1681                 :         }
    1682                 : 
    1683               2 :         if (ldap_sort_entries(ld->link, (LDAPMessage **) &le->ptr, sflen ? sortfilter : NULL, strcmp) != LDAP_SUCCESS) {
    1684               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ldap_err2string(errno));
    1685               0 :                 RETURN_FALSE;
    1686                 :         }
    1687                 : 
    1688               2 :         RETURN_TRUE;
    1689                 : }
    1690                 : /* }}} */
    1691                 : 
    1692                 : #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10
    1693                 : /* {{{ proto bool ldap_get_option(resource link, int option, mixed retval)
    1694                 :    Get the current value of various session-wide parameters */
    1695                 : PHP_FUNCTION(ldap_get_option) 
    1696              21 : {
    1697                 :         zval **link, **option, **retval;
    1698                 :         ldap_linkdata *ld;
    1699                 :         int opt;
    1700                 :         
    1701              21 :         if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &link, &option, &retval) == FAILURE) {
    1702               4 :                 WRONG_PARAM_COUNT;
    1703                 :         }
    1704                 : 
    1705              17 :         ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
    1706                 : 
    1707              17 :         convert_to_long_ex(option);
    1708              17 :         opt = Z_LVAL_PP(option);
    1709                 : 
    1710              17 :         switch (opt) {
    1711                 :         /* options with int value */
    1712                 :         case LDAP_OPT_DEREF:
    1713                 :         case LDAP_OPT_SIZELIMIT:
    1714                 :         case LDAP_OPT_TIMELIMIT:
    1715                 :         case LDAP_OPT_PROTOCOL_VERSION:
    1716                 :         case LDAP_OPT_ERROR_NUMBER:
    1717                 :         case LDAP_OPT_REFERRALS:
    1718                 : #ifdef LDAP_OPT_RESTART
    1719                 :         case LDAP_OPT_RESTART:
    1720                 : #endif
    1721                 :                 {
    1722                 :                         int val;
    1723              12 :                         if (ldap_get_option(ld->link, opt, &val)) {
    1724               0 :                                 RETURN_FALSE;
    1725                 :                         }
    1726              12 :                         zval_dtor(*retval);
    1727              12 :                         ZVAL_LONG(*retval, val);
    1728              12 :                 } break;
    1729                 :         /* options with string value */
    1730                 :         case LDAP_OPT_ERROR_STRING:
    1731                 : #ifdef LDAP_OPT_HOST_NAME
    1732                 :         case LDAP_OPT_HOST_NAME:
    1733                 : #endif
    1734                 : #ifdef HAVE_LDAP_SASL
    1735                 :         case LDAP_OPT_X_SASL_MECH:   
    1736                 :         case LDAP_OPT_X_SASL_REALM:
    1737                 :         case LDAP_OPT_X_SASL_AUTHCID:
    1738                 :         case LDAP_OPT_X_SASL_AUTHZID:
    1739                 : #endif
    1740                 : #ifdef LDAP_OPT_MATCHED_DN
    1741                 :         case LDAP_OPT_MATCHED_DN:
    1742                 : #endif
    1743                 :                 {
    1744               1 :                         char *val = NULL;
    1745                 : 
    1746               1 :                         if (ldap_get_option(ld->link, opt, &val) || val == NULL || *val == '\0') {
    1747               0 :                                 if (val) {
    1748               0 :                                         ldap_memfree(val);
    1749                 :                                 }
    1750               0 :                                 RETURN_FALSE;
    1751                 :                         }
    1752               1 :                         zval_dtor(*retval);
    1753               1 :                         ZVAL_STRING(*retval, val, 1);
    1754               1 :                         ldap_memfree(val);
    1755               1 :                 } break;
    1756                 : /* options not implemented
    1757                 :         case LDAP_OPT_SERVER_CONTROLS:
    1758                 :         case LDAP_OPT_CLIENT_CONTROLS:
    1759                 :         case LDAP_OPT_API_INFO:
    1760                 :         case LDAP_OPT_API_FEATURE_INFO:
    1761                 : */
    1762                 :         default:
    1763               4 :                 RETURN_FALSE;
    1764                 :         }
    1765              13 :         RETURN_TRUE;
    1766                 : }
    1767                 : /* }}} */
    1768                 : 
    1769                 : /* {{{ proto bool ldap_set_option(resource link, int option, mixed newval)
    1770                 :    Set the value of various session-wide parameters */
    1771                 : PHP_FUNCTION(ldap_set_option) 
    1772             185 : {
    1773                 :         zval **link, **option, **newval;
    1774                 :         ldap_linkdata *ld;
    1775                 :         LDAP *ldap;
    1776                 :         int opt;
    1777                 :         
    1778             185 :         if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &link, &option, &newval) == FAILURE) {
    1779               4 :                 WRONG_PARAM_COUNT;
    1780                 :         }
    1781                 : 
    1782             181 :         if (Z_TYPE_PP(link) == IS_NULL) {
    1783               0 :                 ldap = NULL;
    1784                 :         } else {
    1785             181 :                 ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
    1786             181 :                 ldap = ld->link;
    1787                 :         }
    1788                 : 
    1789             181 :         convert_to_long_ex(option);
    1790             181 :         opt = Z_LVAL_PP(option);
    1791                 : 
    1792             181 :         switch (opt) {
    1793                 :         /* options with int value */
    1794                 :         case LDAP_OPT_DEREF:
    1795                 :         case LDAP_OPT_SIZELIMIT:
    1796                 :         case LDAP_OPT_TIMELIMIT:
    1797                 :         case LDAP_OPT_PROTOCOL_VERSION:
    1798                 :         case LDAP_OPT_ERROR_NUMBER:
    1799                 : #ifdef LDAP_OPT_DEBUG_LEVEL
    1800                 :         case LDAP_OPT_DEBUG_LEVEL:
    1801                 : #endif
    1802                 :                 {
    1803                 :                         int val;
    1804             164 :                         convert_to_long_ex(newval);
    1805             164 :                         val = Z_LVAL_PP(newval);
    1806             164 :                         if (ldap_set_option(ldap, opt, &val)) {
    1807               1 :                                 RETURN_FALSE;
    1808                 :                         }
    1809             163 :                 } break;
    1810                 :                 /* options with string value */
    1811                 :         case LDAP_OPT_ERROR_STRING:
    1812                 : #ifdef LDAP_OPT_HOST_NAME
    1813                 :         case LDAP_OPT_HOST_NAME:
    1814                 : #endif
    1815                 : #ifdef HAVE_LDAP_SASL
    1816                 :         case LDAP_OPT_X_SASL_MECH:   
    1817                 :         case LDAP_OPT_X_SASL_REALM:
    1818                 :         case LDAP_OPT_X_SASL_AUTHCID:
    1819                 :         case LDAP_OPT_X_SASL_AUTHZID:
    1820                 : #endif
    1821                 : #ifdef LDAP_OPT_MATCHED_DN
    1822                 :         case LDAP_OPT_MATCHED_DN:
    1823                 : #endif
    1824                 :                 {
    1825                 :                         char *val;
    1826               1 :                         convert_to_string_ex(newval);
    1827               1 :                         val = Z_STRVAL_PP(newval);
    1828               1 :                         if (ldap_set_option(ldap, opt, val)) {
    1829               0 :                                 RETURN_FALSE;
    1830                 :                         }
    1831               1 :                 } break;
    1832                 :                 /* options with boolean value */
    1833                 :         case LDAP_OPT_REFERRALS:
    1834                 : #ifdef LDAP_OPT_RESTART
    1835                 :         case LDAP_OPT_RESTART:
    1836                 : #endif
    1837                 :                 {
    1838                 :                         void *val;
    1839               4 :                         convert_to_boolean_ex(newval);
    1840               4 :                         val = Z_LVAL_PP(newval)
    1841                 :                                 ? LDAP_OPT_ON : LDAP_OPT_OFF;
    1842               4 :                         if (ldap_set_option(ldap, opt, val)) {
    1843               0 :                                 RETURN_FALSE;
    1844                 :                         }
    1845               4 :                 } break;
    1846                 :                 /* options with control list value */
    1847                 :         case LDAP_OPT_SERVER_CONTROLS:
    1848                 :         case LDAP_OPT_CLIENT_CONTROLS:
    1849                 :                 {
    1850                 :                         LDAPControl *ctrl, **ctrls, **ctrlp;
    1851                 :                         zval **ctrlval, **val;
    1852                 :                         int ncontrols;
    1853              11 :                         char error=0;
    1854                 : 
    1855              11 :                         if ((Z_TYPE_PP(newval) != IS_ARRAY) || !(ncontrols = zend_hash_num_elements(Z_ARRVAL_PP(newval)))) {
    1856               1 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expected non-empty array value for this option");
    1857               1 :                                 RETURN_FALSE;
    1858                 :                         }
    1859              10 :                         ctrls = safe_emalloc((1 + ncontrols), sizeof(*ctrls), 0);
    1860              10 :                         *ctrls = NULL;
    1861              10 :                         ctrlp = ctrls;
    1862              10 :                         zend_hash_internal_pointer_reset(Z_ARRVAL_PP(newval));
    1863              34 :                         while (zend_hash_get_current_data(Z_ARRVAL_PP(newval), (void**)&ctrlval) == SUCCESS) {
    1864              16 :                                 if (Z_TYPE_PP(ctrlval) != IS_ARRAY) {
    1865               1 :                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "The array value must contain only arrays, where each array is a control");
    1866               1 :                                         error = 1;
    1867               1 :                                         break;
    1868                 :                                 }
    1869              15 :                                 if (zend_hash_find(Z_ARRVAL_PP(ctrlval), "oid", sizeof("oid"), (void **) &val) == FAILURE) {
    1870               1 :                                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "Control must have an oid key");
    1871               1 :                                         error = 1;
    1872               1 :                                         break;
    1873                 :                                 }
    1874              14 :                                 ctrl = *ctrlp = emalloc(sizeof(**ctrlp));
    1875              14 :                                 convert_to_string_ex(val);
    1876              14 :                                 ctrl->ldctl_oid = Z_STRVAL_PP(val);
    1877              14 :                                 if (zend_hash_find(Z_ARRVAL_PP(ctrlval), "value", sizeof("value"), (void **) &val) == SUCCESS) {
    1878               5 :                                         convert_to_string_ex(val);
    1879               5 :                                         ctrl->ldctl_value.bv_val = Z_STRVAL_PP(val);
    1880               5 :                                         ctrl->ldctl_value.bv_len = Z_STRLEN_PP(val);
    1881                 :                                 } else {
    1882               9 :                                         ctrl->ldctl_value.bv_val = NULL;
    1883               9 :                                         ctrl->ldctl_value.bv_len = 0;
    1884                 :                                 }
    1885              14 :                                 if (zend_hash_find(Z_ARRVAL_PP(ctrlval), "iscritical", sizeof("iscritical"), (void **) &val) == SUCCESS) {
    1886               5 :                                         convert_to_boolean_ex(val);
    1887               5 :                                         ctrl->ldctl_iscritical = Z_BVAL_PP(val);
    1888                 :                                 } else {
    1889               9 :                                         ctrl->ldctl_iscritical = 0;
    1890                 :                                 }
    1891                 :                                 
    1892              14 :                                 ++ctrlp;
    1893              14 :                                 *ctrlp = NULL;
    1894              14 :                                 zend_hash_move_forward(Z_ARRVAL_PP(newval));
    1895                 :                         }
    1896              10 :                         if (!error) {
    1897               8 :                                 error = ldap_set_option(ldap, opt, ctrls);
    1898                 :                         }
    1899              10 :                         ctrlp = ctrls;
    1900              34 :                         while (*ctrlp) {
    1901              14 :                                 efree(*ctrlp);
    1902              14 :                                 ctrlp++;
    1903                 :                         }
    1904              10 :                         efree(ctrls);
    1905              10 :                         if (error) {
    1906               2 :                                 RETURN_FALSE;
    1907                 :                         }
    1908               8 :                 } break;
    1909                 :         default:
    1910               1 :                 RETURN_FALSE;
    1911                 :         }
    1912             176 :         RETURN_TRUE;
    1913                 : }
    1914                 : /* }}} */
    1915                 : 
    1916                 : #ifdef HAVE_LDAP_PARSE_RESULT
    1917                 : /* {{{ proto bool ldap_parse_result(resource link, resource result, int errcode, string matcheddn, string errmsg, array referrals)
    1918                 :    Extract information from result */
    1919                 : PHP_FUNCTION(ldap_parse_result) 
    1920               2 : {
    1921                 :         zval **link, **result, **errcode, **matcheddn, **errmsg, **referrals;
    1922                 :         ldap_linkdata *ld;
    1923                 :         LDAPMessage *ldap_result;
    1924                 :         char **lreferrals, **refp;
    1925                 :         char *lmatcheddn, *lerrmsg;
    1926               2 :         int rc, lerrcode, myargcount = ZEND_NUM_ARGS();
    1927                 : 
    1928               2 :         if (myargcount < 3 || myargcount > 6 || zend_get_parameters_ex(myargcount, &link, &result, &errcode, &matcheddn, &errmsg, &referrals) == FAILURE) {
    1929               1 :                 WRONG_PARAM_COUNT;
    1930                 :         }
    1931                 : 
    1932               1 :         ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
    1933               1 :         ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, result, -1, "ldap result", le_result);
    1934                 : 
    1935               1 :         rc = ldap_parse_result(ld->link, ldap_result, &lerrcode,
    1936                 :                                 myargcount > 3 ? &lmatcheddn : NULL,
    1937                 :                                 myargcount > 4 ? &lerrmsg : NULL,
    1938                 :                                 myargcount > 5 ? &lreferrals : NULL,
    1939                 :                                 NULL /* &serverctrls */,
    1940                 :                                 0);
    1941               1 :         if (rc != LDAP_SUCCESS) {
    1942               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to parse result: %s", ldap_err2string(rc));
    1943               0 :                 RETURN_FALSE;
    1944                 :         }
    1945                 : 
    1946               1 :         zval_dtor(*errcode);
    1947               1 :         ZVAL_LONG(*errcode, lerrcode);
    1948                 : 
    1949                 :         /* Reverse -> fall through */
    1950               1 :         switch (myargcount) {
    1951                 :                 case 6:
    1952               1 :                         zval_dtor(*referrals);
    1953               1 :                         array_init(*referrals);
    1954               1 :                         if (lreferrals != NULL) {
    1955               1 :                                 refp = lreferrals;
    1956               3 :                                 while (*refp) {
    1957               1 :                                         add_next_index_string(*referrals, *refp, 1);
    1958               1 :                                         refp++;
    1959                 :                                 }
    1960               1 :                                 ldap_value_free(lreferrals);
    1961                 :                         }
    1962                 :                 case 5:
    1963               1 :                         zval_dtor(*errmsg);
    1964               1 :                         if (lerrmsg == NULL) {
    1965               0 :                                 ZVAL_EMPTY_STRING(*errmsg);
    1966                 :                         } else {
    1967               1 :                                 ZVAL_STRING(*errmsg, lerrmsg, 1);
    1968               1 :                                 ldap_memfree(lerrmsg);
    1969                 :                         }
    1970                 :                 case 4: 
    1971               1 :                         zval_dtor(*matcheddn);
    1972               1 :                         if (lmatcheddn == NULL) {
    1973               0 :                                 ZVAL_EMPTY_STRING(*matcheddn);
    1974                 :                         } else {
    1975               1 :                                 ZVAL_STRING(*matcheddn, lmatcheddn, 1);
    1976               1 :                                 ldap_memfree(lmatcheddn);
    1977                 :                         }
    1978                 :         }
    1979               1 :         RETURN_TRUE;
    1980                 : }
    1981                 : /* }}} */
    1982                 : #endif
    1983                 : 
    1984                 : /* {{{ proto resource ldap_first_reference(resource link, resource result)
    1985                 :    Return first reference */
    1986                 : PHP_FUNCTION(ldap_first_reference)
    1987               6 : {
    1988                 :         zval **link, **result;
    1989                 :         ldap_linkdata *ld;
    1990                 :         ldap_resultentry *resultentry;
    1991                 :         LDAPMessage *ldap_result, *entry;
    1992                 : 
    1993               6 :         if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &link, &result) == FAILURE) {
    1994               2 :                 WRONG_PARAM_COUNT;
    1995                 :         }
    1996                 : 
    1997               4 :         ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
    1998               4 :         ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, result, -1, "ldap result", le_result);
    1999                 : 
    2000               3 :         if ((entry = ldap_first_reference(ld->link, ldap_result)) == NULL) {
    2001               0 :                 RETVAL_FALSE;
    2002                 :         } else {
    2003               3 :                 resultentry = emalloc(sizeof(ldap_resultentry));
    2004               3 :                 ZEND_REGISTER_RESOURCE(return_value, resultentry, le_result_entry);
    2005               3 :                 resultentry->id = Z_LVAL_PP(result);
    2006               3 :                 zend_list_addref(resultentry->id);
    2007               3 :                 resultentry->data = entry;
    2008                 :         }
    2009                 : }
    2010                 : /* }}} */
    2011                 : 
    2012                 : /* {{{ proto resource ldap_next_reference(resource link, resource reference_entry)
    2013                 :    Get next reference */
    2014                 : PHP_FUNCTION(ldap_next_reference)
    2015               4 : {
    2016                 :         zval **link, **result_entry;
    2017                 :         ldap_linkdata *ld;
    2018                 :         ldap_resultentry *resultentry, *resultentry_next;
    2019                 :         LDAPMessage *entry_next;
    2020                 : 
    2021               4 :         if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &link, &result_entry) == FAILURE) {
    2022               2 :                 WRONG_PARAM_COUNT;
    2023                 :         }
    2024                 : 
    2025               2 :         ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
    2026               2 :         ZEND_FETCH_RESOURCE(resultentry, ldap_resultentry *, result_entry, -1, "ldap result entry", le_result_entry);
    2027                 : 
    2028               1 :         if ((entry_next = ldap_next_reference(ld->link, resultentry->data)) == NULL) {
    2029               0 :                 RETVAL_FALSE;
    2030                 :         } else {
    2031               1 :                 resultentry_next = emalloc(sizeof(ldap_resultentry));
    2032               1 :                 ZEND_REGISTER_RESOURCE(return_value, resultentry_next, le_result_entry);
    2033               1 :                 resultentry_next->id = resultentry->id;
    2034               1 :                 zend_list_addref(resultentry->id);
    2035               1 :                 resultentry_next->data = entry_next;
    2036                 :         }
    2037                 : }
    2038                 : /* }}} */
    2039                 : 
    2040                 : #ifdef HAVE_LDAP_PARSE_REFERENCE
    2041                 : /* {{{ proto bool ldap_parse_reference(resource link, resource reference_entry, array referrals)
    2042                 :    Extract information from reference entry */
    2043                 : PHP_FUNCTION(ldap_parse_reference)
    2044               6 : {
    2045                 :         zval **link, **result_entry, **referrals;
    2046                 :         ldap_linkdata *ld;
    2047                 :         ldap_resultentry *resultentry;
    2048                 :         char **lreferrals, **refp;
    2049                 : 
    2050               6 :         if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &link, &result_entry, &referrals) == FAILURE) {
    2051               2 :                 WRONG_PARAM_COUNT;
    2052                 :         }
    2053                 : 
    2054               4 :         ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
    2055               4 :         ZEND_FETCH_RESOURCE(resultentry, ldap_resultentry *, result_entry, -1, "ldap result entry", le_result_entry);
    2056                 : 
    2057               3 :         if (ldap_parse_reference(ld->link, resultentry->data, &lreferrals, NULL /* &serverctrls */, 0) != LDAP_SUCCESS) {
    2058               0 :                 RETURN_FALSE;
    2059                 :         }
    2060                 : 
    2061               3 :         zval_dtor(*referrals);
    2062               3 :         array_init(*referrals);
    2063               3 :         if (lreferrals != NULL) {
    2064               3 :                 refp = lreferrals;
    2065               9 :                 while (*refp) {
    2066               3 :                         add_next_index_string(*referrals, *refp, 1);
    2067               3 :                         refp++;
    2068                 :                 }
    2069               3 :                 ldap_value_free(lreferrals);
    2070                 :         }
    2071               3 :         RETURN_TRUE;
    2072                 : }
    2073                 : /* }}} */
    2074                 : #endif
    2075                 : 
    2076                 : /* {{{ proto bool ldap_rename(resource link, string dn, string newrdn, string newparent, bool deleteoldrdn);
    2077                 :    Modify the name of an entry */
    2078                 : PHP_FUNCTION(ldap_rename)
    2079               4 : {
    2080                 :         zval **link, **dn, **newrdn, **newparent, **deleteoldrdn;
    2081                 :         ldap_linkdata *ld;
    2082                 :         int rc;
    2083               4 :         char *newp = NULL;
    2084                 :         
    2085               4 :         if (ZEND_NUM_ARGS() != 5 || zend_get_parameters_ex(5, &link, &dn, &newrdn, &newparent, &deleteoldrdn) == FAILURE) {
    2086               1 :                 WRONG_PARAM_COUNT;
    2087                 :         }
    2088                 : 
    2089               3 :         ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
    2090                 : 
    2091               3 :         convert_to_string_ex(dn);
    2092               3 :         convert_to_string_ex(newrdn);
    2093               3 :         convert_to_string_ex(newparent);
    2094               3 :         convert_to_boolean_ex(deleteoldrdn);
    2095                 : 
    2096               3 :         newp = (Z_STRLEN_PP(newparent) > 0) ?  Z_STRVAL_PP(newparent) : NULL;
    2097                 : 
    2098                 : #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10
    2099               3 :         rc = ldap_rename_s(ld->link, Z_STRVAL_PP(dn), Z_STRVAL_PP(newrdn), newp, Z_BVAL_PP(deleteoldrdn), NULL, NULL);
    2100                 : #else
    2101                 :         if (newp != NULL) {
    2102                 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "You are using old LDAP API, newparent must be the empty string, can only modify RDN");
    2103                 :                 RETURN_FALSE;
    2104                 :         }
    2105                 : /* could support old APIs but need check for ldap_modrdn2()/ldap_modrdn() */
    2106                 :         rc = ldap_modrdn2_s(ld->link, Z_STRVAL_PP(dn), Z_STRVAL_PP(newrdn), Z_BVAL_PP(deleteoldrdn));
    2107                 : #endif
    2108                 : 
    2109               3 :         if (rc == LDAP_SUCCESS) {
    2110               2 :                 RETURN_TRUE;
    2111                 :         }
    2112               1 :         RETURN_FALSE;
    2113                 : }
    2114                 : /* }}} */
    2115                 : 
    2116                 : #ifdef HAVE_LDAP_START_TLS_S
    2117                 : /* {{{ proto bool ldap_start_tls(resource link)
    2118                 :    Start TLS */
    2119                 : PHP_FUNCTION(ldap_start_tls)
    2120               3 : {
    2121                 :         zval **link;
    2122                 :         ldap_linkdata *ld;
    2123               3 :         int rc, protocol = LDAP_VERSION3;
    2124                 : 
    2125               3 :         if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &link) == FAILURE) {
    2126               2 :                 WRONG_PARAM_COUNT;
    2127                 :         }
    2128                 : 
    2129               1 :         ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
    2130                 : 
    2131               1 :         if (((rc = ldap_set_option(ld->link, LDAP_OPT_PROTOCOL_VERSION, &protocol)) != LDAP_SUCCESS) ||
    2132                 :                 ((rc = ldap_start_tls_s(ld->link, NULL, NULL)) != LDAP_SUCCESS)
    2133                 :         ) {
    2134               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING,"Unable to start TLS: %s", ldap_err2string(rc));
    2135               0 :                 RETURN_FALSE;
    2136                 :         } else {
    2137               1 :                 RETURN_TRUE;
    2138                 :         }
    2139                 : }
    2140                 : /* }}} */
    2141                 : #endif
    2142                 : #endif /* (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 */
    2143                 : 
    2144                 : #if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC)
    2145                 : /* {{{ _ldap_rebind_proc()
    2146                 : */
    2147                 : int _ldap_rebind_proc(LDAP *ldap, const char *url, ber_tag_t req, ber_int_t msgid, void *params)
    2148               0 : {
    2149                 :         ldap_linkdata *ld;
    2150                 :         int retval;
    2151                 :         zval *cb_url;
    2152                 :         zval **cb_args[2];
    2153                 :         zval *cb_retval;
    2154               0 :         zval *cb_link = (zval *) params;
    2155                 :         TSRMLS_FETCH();
    2156                 : 
    2157               0 :         ld = (ldap_linkdata *) zend_fetch_resource(&cb_link TSRMLS_CC, -1, "ldap link", NULL, 1, le_link);
    2158                 : 
    2159                 :         /* link exists and callback set? */
    2160               0 :         if (ld == NULL || ld->rebindproc == NULL) {
    2161               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Link not found or no callback set");
    2162               0 :                 return LDAP_OTHER;
    2163                 :         }
    2164                 : 
    2165                 :         /* callback */
    2166               0 :         MAKE_STD_ZVAL(cb_url);
    2167               0 :         ZVAL_STRING(cb_url, estrdup(url), 0);
    2168               0 :         cb_args[0] = &cb_link;
    2169               0 :         cb_args[1] = &cb_url;
    2170               0 :         if (call_user_function_ex(EG(function_table), NULL, ld->rebindproc, &cb_retval, 2, cb_args, 0, NULL TSRMLS_CC) == SUCCESS && cb_retval) {
    2171               0 :                 convert_to_long_ex(&cb_retval);
    2172               0 :                 retval = Z_LVAL_P(cb_retval);
    2173               0 :                 zval_ptr_dtor(&cb_retval);
    2174                 :         } else {
    2175               0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "rebind_proc PHP callback failed");
    2176               0 :                 retval = LDAP_OTHER;
    2177                 :         }
    2178               0 :         zval_dtor(cb_url);
    2179               0 :         FREE_ZVAL(cb_url);
    2180               0 :         return retval;
    2181                 : }
    2182                 : /* }}} */
    2183                 : 
    2184                 : /* {{{ proto bool ldap_set_rebind_proc(resource link, string callback)
    2185                 :    Set a callback function to do re-binds on referral chasing. */
    2186                 : PHP_FUNCTION(ldap_set_rebind_proc)
    2187               6 : {
    2188                 :         zval *link, *callback;
    2189                 :         ldap_linkdata *ld;
    2190                 :         char *callback_name;
    2191                 : 
    2192               6 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz", &link, &callback) == FAILURE) {
    2193               2 :                 RETURN_FALSE;
    2194                 :         }
    2195                 : 
    2196               4 :         ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
    2197                 : 
    2198               4 :         if (Z_TYPE_P(callback) == IS_STRING && Z_STRLEN_P(callback) == 0) {
    2199                 :                 /* unregister rebind procedure */
    2200               1 :                 if (ld->rebindproc != NULL) {
    2201               1 :                         zval_dtor(ld->rebindproc);
    2202               1 :                         ld->rebindproc = NULL;
    2203               1 :                         ldap_set_rebind_proc(ld->link, NULL, NULL);
    2204                 :                 }
    2205               1 :                 RETURN_TRUE;
    2206                 :         }
    2207                 : 
    2208                 :         /* callable? */
    2209               3 :         if (!zend_is_callable(callback, 0, &callback_name)) {
    2210               1 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Two arguments expected for '%s' to be a valid callback", callback_name);
    2211               1 :                 efree(callback_name);
    2212               1 :                 RETURN_FALSE;
    2213                 :         }
    2214               2 :         efree(callback_name);
    2215                 : 
    2216                 :         /* register rebind procedure */
    2217               2 :         if (ld->rebindproc == NULL) {
    2218               2 :                 ldap_set_rebind_proc(ld->link, _ldap_rebind_proc, (void *) link);
    2219                 :         } else {
    2220               0 :                 zval_dtor(ld->rebindproc);
    2221                 :         }
    2222                 : 
    2223               2 :         ALLOC_ZVAL(ld->rebindproc);
    2224               2 :         *ld->rebindproc = *callback;
    2225               2 :         zval_copy_ctor(ld->rebindproc);
    2226               2 :         RETURN_TRUE;
    2227                 : }
    2228                 : /* }}} */
    2229                 : #endif
    2230                 : 
    2231                 : #ifdef STR_TRANSLATION
    2232                 : /* {{{ php_ldap_do_translate
    2233                 :  */
    2234                 : static void php_ldap_do_translate(INTERNAL_FUNCTION_PARAMETERS, int way) 
    2235                 : {
    2236                 :         zval **value;
    2237                 :         char *ldap_buf;
    2238                 :         unsigned long ldap_len;
    2239                 :         int result;
    2240                 :                 
    2241                 :         if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &value) == FAILURE) {
    2242                 :                 WRONG_PARAM_COUNT;
    2243                 :         }
    2244                 : 
    2245                 :         convert_to_string_ex(value);
    2246                 :         ldap_buf = Z_STRVAL_PP(value);
    2247                 :         ldap_len = Z_STRLEN_PP(value);
    2248                 : 
    2249                 :         if (ldap_len == 0) {
    2250                 :                 RETURN_FALSE;
    2251                 :         }
    2252                 : 
    2253                 :         if (way == 1) {
    2254                 :                 result = ldap_8859_to_t61(&ldap_buf, &ldap_len, 0);
    2255                 :         } else {
    2256                 :                 result = ldap_t61_to_8859(&ldap_buf, &ldap_len, 0);
    2257                 :         }
    2258                 : 
    2259                 :         if (result == LDAP_SUCCESS) {
    2260                 :                 RETVAL_STRINGL(ldap_buf, ldap_len, 1);
    2261                 :                 free(ldap_buf);
    2262                 :         } else {
    2263                 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Conversion from iso-8859-1 to t61 failed: %s", ldap_err2string(result));
    2264                 :                 RETVAL_FALSE;
    2265                 :         }
    2266                 : 
    2267                 :         return;
    2268                 : }
    2269                 : /* }}} */
    2270                 : 
    2271                 : /* {{{ proto string ldap_t61_to_8859(string value)
    2272                 :    Translate t61 characters to 8859 characters */
    2273                 : PHP_FUNCTION(ldap_t61_to_8859)
    2274                 : {
    2275                 :         php_ldap_do_translate(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
    2276                 : }
    2277                 : /* }}} */
    2278                 : 
    2279                 : /* {{{ proto string ldap_8859_to_t61(string value)
    2280                 :    Translate 8859 characters to t61 characters */
    2281                 : PHP_FUNCTION(ldap_8859_to_t61)
    2282                 : {
    2283                 :         php_ldap_do_translate(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
    2284                 : }
    2285                 : /* }}} */
    2286                 : #endif
    2287                 : 
    2288                 : /*
    2289                 :  * Local variables:
    2290                 :  * tab-width: 4
    2291                 :  * c-basic-offset: 4
    2292                 :  * End:
    2293                 :  * vim600: sw=4 ts=4 fdm=marker
    2294                 :  * vim<600: sw=4 ts=4
    2295                 :  */

Generated by: LTP GCOV extension version 1.5

Generated at Thu, 19 Nov 2009 08:20:10 +0000 (5 days ago)

Copyright © 2005-2009 The PHP Group
All rights reserved.