diff options
-rw-r--r-- | databases/php-ldap/files/ldap-ctrl-exop54.patch | 2260 | ||||
-rw-r--r--[-rwxr-xr-x] | databases/php-ldap/files/ldap-ctrl-exop55.patch (renamed from databases/php-ldap/files/ldap-ctrl-exop.patch) | 222 | ||||
-rw-r--r-- | databases/php-ldap/files/ldap-ctrl-exop56.patch | 2263 | ||||
-rw-r--r-- | databases/php-ldap/options.mk | 4 |
4 files changed, 4636 insertions, 113 deletions
diff --git a/databases/php-ldap/files/ldap-ctrl-exop54.patch b/databases/php-ldap/files/ldap-ctrl-exop54.patch new file mode 100644 index 00000000000..ca351702540 --- /dev/null +++ b/databases/php-ldap/files/ldap-ctrl-exop54.patch @@ -0,0 +1,2260 @@ +--- ext/ldap/ldap.c.orig 2015-03-18 06:33:59.000000000 +0100 ++++ ext/ldap/ldap.c 2015-04-13 05:57:02.000000000 +0200 +@@ -66,8 +66,13 @@ + #elif defined(HAVE_LDAP_SASL_SASL_H) + #include <sasl/sasl.h> + #endif + ++/* XXX Not detected by configure... */ ++#ifdef LDAP_EXOP_REFRESH ++#define HAVE_LDAP_REFRESH 1 ++#endif ++ + typedef struct { + LDAP *link; + #if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC) + zval *rebindproc; +@@ -88,31 +93,46 @@ + #ifdef COMPILE_DL_LDAP + ZEND_GET_MODULE(ldap) + #endif + ++ ++/* {{{ proto void _close_ldap_link() ++ close a connection and free LDAP resources */ + static void _close_ldap_link(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */ + { + ldap_linkdata *ld = (ldap_linkdata *)rsrc->ptr; + +- ldap_unbind_s(ld->link); +-#if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC) ++ /* ldap_unbind_s() is deprecated; ++ * the distinction between ldap_unbind() and ldap_unbind_s() is moot */ ++#ifdef LDAP_API_FEATURE_X_OPENLDAP ++ ldap_unbind_ext(ld->link, NULL, NULL); ++#ifdef HAVE_3ARG_SETREBINDPROC ++ + if (ld->rebindproc != NULL) { + zval_dtor(ld->rebindproc); + FREE_ZVAL(ld->rebindproc); + } + #endif ++#else /* ! LDAP_API_FEATURE_X_OPENLDAP */ ++ ldap_unbind_s(ld->link); ++#endif /* ! LDAP_API_FEATURE_X_OPENLDAP */ ++ + efree(ld); + LDAPG(num_links)--; + } + /* }}} */ + ++/* {{{ proto void _free_ldap_result() ++ free the result of an LDAP operation */ + static void _free_ldap_result(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */ + { + LDAPMessage *result = (LDAPMessage *)rsrc->ptr; + ldap_msgfree(result); + } + /* }}} */ + ++/* {{{ proto void _free_ldap_result_entry() ++ free an entry resulting from an LDAP search operation */ + static void _free_ldap_result_entry(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */ + { + ldap_resultentry *entry = (ldap_resultentry *)rsrc->ptr; + +@@ -203,8 +223,21 @@ + REGISTER_LONG_CONSTANT("GSLC_SSL_ONEWAY_AUTH", GSLC_SSL_ONEWAY_AUTH, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("GSLC_SSL_TWOWAY_AUTH", GSLC_SSL_TWOWAY_AUTH, CONST_PERSISTENT | CONST_CS); + #endif + ++#ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST ++ REGISTER_LONG_CONSTANT("PP_passwordExpired", PP_passwordExpired, CONST_PERSISTENT | CONST_CS); ++ REGISTER_LONG_CONSTANT("PP_accountLocked", PP_accountLocked, CONST_PERSISTENT | CONST_CS); ++ REGISTER_LONG_CONSTANT("PP_changeAfterReset", PP_changeAfterReset, CONST_PERSISTENT | CONST_CS); ++ REGISTER_LONG_CONSTANT("PP_passwordModNotAllowed", PP_passwordModNotAllowed, CONST_PERSISTENT | CONST_CS); ++ REGISTER_LONG_CONSTANT("PP_mustSupplyOldPassword", PP_mustSupplyOldPassword, CONST_PERSISTENT | CONST_CS); ++ REGISTER_LONG_CONSTANT("PP_insufficientPasswordQuality", PP_insufficientPasswordQuality, CONST_PERSISTENT | CONST_CS); ++ REGISTER_LONG_CONSTANT("PP_passwordTooShort", PP_passwordTooShort, CONST_PERSISTENT | CONST_CS); ++ REGISTER_LONG_CONSTANT("PP_passwordTooYoung", PP_passwordTooYoung, CONST_PERSISTENT | CONST_CS); ++ REGISTER_LONG_CONSTANT("PP_passwordInHistory", PP_passwordInHistory, CONST_PERSISTENT | CONST_CS); ++ REGISTER_LONG_CONSTANT("PP_noError", PP_noError, CONST_PERSISTENT | CONST_CS); ++#endif /* LDAP_CONTROL_PASSWORDPOLICYREQUEST */ ++ + le_link = zend_register_list_destructors_ex(_close_ldap_link, NULL, "ldap link", module_number); + le_result = zend_register_list_destructors_ex(_free_ldap_result, NULL, "ldap result", module_number); + le_result_entry = zend_register_list_destructors_ex(_free_ldap_result_entry, NULL, "ldap result entry", module_number); + +@@ -285,15 +318,176 @@ + DISPLAY_INI_ENTRIES(); + } + /* }}} */ + ++ ++/* {{{ proto int _php_parse_referrals_resp() ++ parse an array of LDAP referrals into a zval array */ ++static int _php_parse_referrals_resp(char ***lreferralsp, zval **referrals) ++{ ++ int num_referrals = 0; ++ ++ if (*lreferralsp != NULL) { ++ char **refp = *lreferralsp; ++ ++ while (*refp) { ++ add_next_index_string(*referrals, *refp, 1); ++ refp++; ++ num_referrals++; ++ } ++#ifdef LDAP_API_FEATURE_X_OPENLDAP ++ ber_memvfree((void **)*lreferralsp); ++#else ++ ldap_value_free(*lreferralsp); ++#endif ++ *lreferralsp = NULL; ++ } ++ ++ return num_referrals; ++} ++/* }}} */ ++ ++/* {{{ proto int _php_parse_controls() ++ parse an array of zvals into an array of LDAP controls */ ++static int _php_parse_controls(zval **ctrls, LDAPControl ***lctrlsp) ++{ ++ LDAPControl *lctrl, **lctrls, **lctrlp; ++ zval **ctrlval, **val; ++ int ncontrols; ++ char error = 0; ++ ++ ++ if ((Z_TYPE_PP(ctrls) != IS_ARRAY) || !(ncontrols = zend_hash_num_elements(Z_ARRVAL_PP(ctrls)))) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expected non-empty array value"); ++ return 0; ++ } ++ ++ lctrls = safe_emalloc((1 + ncontrols), sizeof(*lctrls), 0); ++ *lctrls = NULL; ++ lctrlp = lctrls; ++ zend_hash_internal_pointer_reset(Z_ARRVAL_PP(ctrls)); ++ while (zend_hash_get_current_data(Z_ARRVAL_PP(ctrls), (void**)&ctrlval) == SUCCESS) { ++ if (Z_TYPE_PP(ctrlval) != IS_ARRAY) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "The array value must contain only arrays, where each array is a control"); ++ error = 1; ++ break; ++ } ++ if (zend_hash_find(Z_ARRVAL_PP(ctrlval), "oid", sizeof("oid"), (void **) &val) == FAILURE) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Control must have an oid key"); ++ error = 1; ++ break; ++ } ++ lctrl = *lctrlp = emalloc(sizeof(**lctrlp)); ++ convert_to_string_ex(val); ++ lctrl->ldctl_oid = Z_STRVAL_PP(val); ++ if (zend_hash_find(Z_ARRVAL_PP(ctrlval), "value", sizeof("value"), (void **) &val) == SUCCESS) { ++ convert_to_string_ex(val); ++ lctrl->ldctl_value.bv_val = Z_STRVAL_PP(val); ++ lctrl->ldctl_value.bv_len = Z_STRLEN_PP(val); ++ } else { ++ lctrl->ldctl_value.bv_val = NULL; ++ lctrl->ldctl_value.bv_len = 0; ++ } ++ if (zend_hash_find(Z_ARRVAL_PP(ctrlval), "iscritical", sizeof("iscritical"), (void **) &val) == SUCCESS) { ++ convert_to_boolean_ex(val); ++ lctrl->ldctl_iscritical = Z_BVAL_PP(val); ++ } else { ++ lctrl->ldctl_iscritical = 0; ++ } ++ ++ ++lctrlp; ++ *lctrlp = NULL; ++ zend_hash_move_forward(Z_ARRVAL_PP(ctrls)); ++ } ++ if (!error) { ++ *lctrlsp = lctrls; ++ } ++ return ncontrols; ++} ++/* }}} */ ++ ++/* {{{ proto void _php_free_controls() ++ frees an array of LDAP controls as parsed (and malloc'ed) by _php_parse_controls */ ++static void _php_free_controls(LDAPControl ***lctrlsp) ++{ ++ LDAPControl **lctrlp; ++ ++ for (lctrlp = *lctrlsp; *lctrlp; lctrlp++) { ++ efree(*lctrlp); ++ } ++ efree(*lctrlsp); ++ *lctrlsp = NULL; ++} ++/* }}} */ ++ ++/* {{{ proto void _php_parse_controls_resp() ++ parse an array of LDAP controls into a zval array */ ++static int _php_parse_controls_resp(LDAPControl ***lctrlsp, zval **ctrls) ++{ ++ int num_ctrls = 0; ++ ++ if (*lctrlsp != NULL) { ++ int error = 0; ++ LDAPControl **ctrlp = *lctrlsp; ++ ++ while (*ctrlp) { ++ zval *ctrlval = NULL; ++ ++ if ( (*ctrlp)->ldctl_oid == NULL ) { ++ error = 1; ++ break; ++ } ++ ++ MAKE_STD_ZVAL(ctrlval); ++ array_init(ctrlval); ++ ++ add_assoc_string(ctrlval, "oid", (*ctrlp)->ldctl_oid, 1); ++ if ( (*ctrlp)->ldctl_value.bv_len ) { ++ add_assoc_stringl(ctrlval, "value", (*ctrlp)->ldctl_value.bv_val, (*ctrlp)->ldctl_value.bv_len, 1); ++ } ++ ++ /* As per <draft-ietf-ldapbis-protocol>: ++ * ++ * 4.1.11 ++ ++ The criticality field only has meaning in controls attached to ++ request messages (except UnbindRequest). For controls attached to ++ response messages and the UnbindRequest, the criticality field SHOULD ++ be FALSE, and MUST be ignored by the receiving protocol peer. ++ ++ */ ++ ++ add_next_index_zval(*ctrls, ctrlval); ++ ++ num_ctrls++; ++ ctrlp++; ++ } ++ ldap_controls_free(*lctrlsp); ++ *lctrlsp = NULL; ++ ++ if (error) { ++ /* ... */ ++ return -1; ++ } ++ } ++ ++ return num_ctrls; ++} ++/* }}} */ ++ + /* {{{ proto resource ldap_connect([string host [, int port [, string wallet [, string wallet_passwd [, int authmode]]]]]) + Connect to an LDAP server */ + PHP_FUNCTION(ldap_connect) + { + char *host = NULL; + int hostlen; +- long port = 389; /* Default port */ ++ int port = ++#ifdef LDAP_API_FEATURE_X_OPENLDAP ++ LDAP_PORT ++#else /* ! LDAP_API_FEATURE_X_OPENLDAP */ ++ 389 /* Default port */ ++#endif /* ! LDAP_API_FEATURE_X_OPENLDAP */ ++ ; + #ifdef HAVE_ORALDAP + char *wallet = NULL, *walletpasswd = NULL; + int walletlen = 0, walletpasswdlen = 0; + long authmode = GSLC_SSL_NO_AUTH; +@@ -327,23 +521,41 @@ + + ld = ecalloc(1, sizeof(ldap_linkdata)); + + #ifdef LDAP_API_FEATURE_X_OPENLDAP +- if (host != NULL && strchr(host, '/')) { +- int rc; ++ /* OpenLDAP provides a specific call to detect valid LDAP URIs; ++ * ldap_init()/ldap_open() is deprecated, use ldap_initialize() instead. ++ */ ++ { ++ int rc; ++ char *url = host; ++ ++ if (!ldap_is_ldap_url(url)) { ++ int urllen = hostlen + sizeof( "ldap://:65535" ); ++ ++ if (port <= 0 || port > 65535) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid port number: %ld", port); ++ RETURN_FALSE; ++ } ++ ++ url = emalloc(urllen); ++ snprintf( url, urllen, "ldap://%s:%d", host ? host : "", port ); ++ } + +- rc = ldap_initialize(&ldap, host); ++ rc = ldap_initialize(&ldap, url); + if (rc != LDAP_SUCCESS) { + efree(ld); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not create session handle: %s", ldap_err2string(rc)); + RETURN_FALSE; + } +- } else { +- ldap = ldap_init(host, port); ++ ++ if (url != host) { ++ efree(url); ++ } + } +-#else ++#else /* ! LDAP_API_FEATURE_X_OPENLDAP */ + ldap = ldap_open(host, port); +-#endif ++#endif /* ! LDAP_API_FEATURE_X_OPENLDAP */ + + if (ldap == NULL) { + efree(ld); + RETURN_FALSE; +@@ -429,17 +641,33 @@ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Password contains a null byte"); + RETURN_FALSE; + } + +- if ((rc = ldap_bind_s(ld->link, ldap_bind_dn, ldap_bind_pw, LDAP_AUTH_SIMPLE)) != LDAP_SUCCESS) { ++#ifdef LDAP_API_FEATURE_X_OPENLDAP ++ { ++ struct berval cred; ++ ++ /* ldap_bind_s() is deprecated; use ldap_sasl_bind_s() instead */ ++ cred.bv_val = ldap_bind_pw; ++ cred.bv_len = ldap_bind_pw ? ldap_bind_pwlen : 0; ++ rc = ldap_sasl_bind_s(ld->link, ldap_bind_dn, LDAP_SASL_SIMPLE, &cred, ++ NULL, NULL, /* no controls right now */ ++ NULL); /* we don't care about the server's credentials */ ++ } ++#else ++ rc = ldap_bind_s(ld->link, ldap_bind_dn, ldap_bind_pw, LDAP_AUTH_SIMPLE); ++#endif ++ if ( rc != LDAP_SUCCESS) { ++ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to bind to server: %s", ldap_err2string(rc)); + RETURN_FALSE; + } else { + RETURN_TRUE; + } + } + /* }}} */ + ++/* {{{ SASL bind stuff */ + #ifdef HAVE_LDAP_SASL + typedef struct { + char *mech; + char *realm; +@@ -562,8 +790,9 @@ + _php_sasl_freedefs(ctx); + } + /* }}} */ + #endif /* HAVE_LDAP_SASL */ ++/* }}} */ + + /* {{{ proto bool ldap_unbind(resource link) + Unbind from LDAP directory */ + PHP_FUNCTION(ldap_unbind) +@@ -1259,9 +1488,14 @@ + for (i = 0; i<count; i++) { + add_index_string(return_value, i, ldap_value[i], 1); + } + ++#ifdef LDAP_API_FEATURE_X_OPENLDAP ++ /* ldap_value_free() is deprecated */ ++ ber_memvfree((void **)ldap_value); ++#else /* ! LDAP_API_FEATURE_X_OPENLDAP */ + ldap_value_free(ldap_value); ++#endif /* ! LDAP_API_FEATURE_X_OPENLDAP */ + } + /* }}} */ + + /* {{{ proto string ldap_dn2ufn(string dn) +@@ -1292,38 +1526,67 @@ + /* added to fix use of ldap_modify_add for doing an ldap_add, gerrit thomson. */ + #define PHP_LD_FULL_ADD 0xff + /* {{{ php_ldap_do_modify + */ +-static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper) ++static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper, int ext) + { +- zval *link, *entry, **value, **ivalue; ++ zval *link, *entry, **value, **ivalue, **sctrls, **cctrls; + ldap_linkdata *ld; + char *dn; + LDAPMod **ldap_mods; + int i, j, num_attribs, num_values, dn_len; + int *num_berval; + char *attribute; + ulong index; + int is_full_add=0; /* flag for full add operation so ldap_mod_add can be put back into oper, gerrit THomson */ ++ int rc, msgid, myargcount = ZEND_NUM_ARGS(); ++ LDAPMessage *ldap_res; ++ LDAPControl **lsctrls = NULL, **lcctrls = NULL; ++ if (ext) { ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsaZZ", &link, &dn, &dn_len, &entry, &sctrls, &cctrls) != SUCCESS) ++ WRONG_PARAM_COUNT; ++ } else { ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsa", &link, &dn, &dn_len, &entry) != SUCCESS) ++ WRONG_PARAM_COUNT; ++ } + +- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsa", &link, &dn, &dn_len, &entry) != SUCCESS) { +- return; +- } ++ if (Z_TYPE_PP(&entry) != IS_ARRAY) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expected Array as the last element"); ++ RETURN_FALSE; ++ } + +- ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link); + +- num_attribs = zend_hash_num_elements(Z_ARRVAL_P(entry)); +- ldap_mods = safe_emalloc((num_attribs+1), sizeof(LDAPMod *), 0); +- num_berval = safe_emalloc(num_attribs, sizeof(int), 0); +- zend_hash_internal_pointer_reset(Z_ARRVAL_P(entry)); + + /* added by gerrit thomson to fix ldap_add using ldap_mod_add */ + if (oper == PHP_LD_FULL_ADD) { + oper = LDAP_MOD_ADD; + is_full_add = 1; + } + /* end additional , gerrit thomson */ + ++ if (myargcount > 3) { ++ if (is_full_add) { ++#ifndef HAVE_LDAP_ADD_EXT_S ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "ldap_add_ext not available"); ++ RETURN_FALSE; ++#endif /* ! HAVE_LDAP_ADD_EXT_S */ ++ ++ } else { ++#ifndef HAVE_LDAP_MODIFY_EXT_S ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "ldap_modify_ext not available"); ++ RETURN_FALSE; ++#endif /* ! HAVE_LDAP_MODIFY_EXT_S */ ++ } ++ } ++ ++ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link); ++ ++ num_attribs = zend_hash_num_elements(Z_ARRVAL_P(entry)); ++ ldap_mods = safe_emalloc((num_attribs+1), sizeof(LDAPMod *), 0); ++ num_berval = safe_emalloc(num_attribs, sizeof(int), 0); ++ zend_hash_internal_pointer_reset(Z_ARRVAL_P(entry)); ++ ++ + for (i = 0; i < num_attribs; i++) { + ldap_mods[i] = emalloc(sizeof(LDAPMod)); + ldap_mods[i]->mod_op = oper | LDAP_MOD_BVALUES; + ldap_mods[i]->mod_type = NULL; +@@ -1381,19 +1644,78 @@ + zend_hash_move_forward(Z_ARRVAL_P(entry)); + } + ldap_mods[num_attribs] = NULL; + ++ if (ext) { ++ switch (myargcount) { ++ case 5: ++ if (_php_parse_controls(cctrls, &lcctrls) == 0) { ++ RETVAL_FALSE; ++ goto errexit; ++ } ++ ++ case 4: ++ if (_php_parse_controls(sctrls, &lsctrls) == 0) { ++ RETVAL_FALSE; ++ goto errexit; ++ } ++ } ++ } ++ + /* check flag to see if do_mod was called to perform full add , gerrit thomson */ + if (is_full_add == 1) { +- if ((i = ldap_add_s(ld->link, dn, ldap_mods)) != LDAP_SUCCESS) { +- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Add: %s", ldap_err2string(i)); +- RETVAL_FALSE; +- } else RETVAL_TRUE; ++#ifdef HAVE_LDAP_ADD_EXT_S ++ if (ext) { ++ rc = ldap_add_ext(ld->link, dn, ldap_mods, lsctrls, lcctrls, &msgid); ++ ++ } else { ++ rc = ldap_add_ext_s(ld->link, dn, ldap_mods, NULL, NULL); ++ } ++#else /* ! HAVE_LDAP_ADD_EXT_S */ ++ rc = ldap_add_s(ld->link, dn, ldap_mods); ++#endif /* ! HAVE_LDAP_ADD_EXT_S */ ++ + } else { +- if ((i = ldap_modify_ext_s(ld->link, dn, ldap_mods, NULL, NULL)) != LDAP_SUCCESS) { +- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Modify: %s", ldap_err2string(i)); +- RETVAL_FALSE; +- } else RETVAL_TRUE; ++#ifdef HAVE_LDAP_MODIFY_EXT_S ++ if (ext) { ++ rc = ldap_modify_ext(ld->link, dn, ldap_mods, lsctrls, lcctrls, &msgid); ++ ++ } else { ++ rc = ldap_modify_ext_s(ld->link, dn, ldap_mods, NULL, NULL); ++ } ++#else /* ! HAVE_LDAP_MODIFY_EXT_S */ ++ rc = ldap_modify_s(ld->link, dn, ldap_mods); ++#endif /* ! HAVE_LDAP_MODIFY_EXT_S */ ++ } ++ ++ if (rc != LDAP_SUCCESS) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s: %s", is_full_add ? "Add" : "Modify", ldap_err2string(i)); ++ RETVAL_FALSE; ++ ++ } else { ++ if (ext) { ++ rc = ldap_result(ld->link, msgid, LDAP_MSG_ALL, NULL, &ldap_res); ++ if ((is_full_add && rc != LDAP_RES_ADD) || (!is_full_add && rc != LDAP_RES_MODIFY)) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s: unable to collect result", is_full_add ? "Add" : "Modify"); ++ RETVAL_FALSE; ++ ++ } else { ++ int lerr; ++ ++ ZEND_REGISTER_RESOURCE(return_value, ldap_res, le_result); ++ rc = ldap_parse_result(ld->link, ldap_res, &lerr, NULL, NULL, NULL, NULL, 0); ++ if (rc == LDAP_SUCCESS) { ++ rc = lerr; ++ } ++ ++ if (rc != LDAP_SUCCESS) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s failed: %s", is_full_add ? "Add" : "Modify", ldap_err2string(rc)); ++ } ++ } ++ ++ } else { ++ RETVAL_TRUE; ++ } + } + + errexit: + for (i = 0; i < num_attribs; i++) { +@@ -1406,46 +1728,57 @@ + } + efree(num_berval); + efree(ldap_mods); + ++ if (ext) { ++ if (lsctrls) { ++ _php_free_controls(&lsctrls); ++ } ++ if (lcctrls) { ++ _php_free_controls(&lcctrls); ++ } ++ } ++ + return; + } + /* }}} */ + + /* {{{ proto bool ldap_add(resource link, string dn, array entry) + Add entries to LDAP directory */ + PHP_FUNCTION(ldap_add) + { +- /* 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 */ +- php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_LD_FULL_ADD); ++ /* 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 */ ++ php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_LD_FULL_ADD, 0); + } + /* }}} */ + +-/* three functions for attribute base modifications, gerrit Thomson */ ++/* {{{ Three functions for attribute base modifications, gerrit Thomson */ + + /* {{{ proto bool ldap_mod_replace(resource link, string dn, array entry) + Replace attribute values with new ones */ + PHP_FUNCTION(ldap_mod_replace) + { +- php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_REPLACE); ++ php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_REPLACE, 0); + } + /* }}} */ + + /* {{{ proto bool ldap_mod_add(resource link, string dn, array entry) + Add attribute values to current */ + PHP_FUNCTION(ldap_mod_add) + { +- php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_ADD); ++ php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_ADD, 0); + } + /* }}} */ + + /* {{{ proto bool ldap_mod_del(resource link, string dn, array entry) ++ + Delete attribute values */ + PHP_FUNCTION(ldap_mod_del) + { +- php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_DELETE); ++ php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_DELETE, 0); + } + /* }}} */ ++/* }}} */ + + /* {{{ proto bool ldap_delete(resource link, string dn) + Delete an entry from a directory */ + PHP_FUNCTION(ldap_delete) +@@ -1869,38 +2202,109 @@ + RETURN_STRING(ldap_err2string(ld_errno), 1); + } + /* }}} */ + +-/* {{{ proto bool ldap_compare(resource link, string dn, string attr, string value) +- Determine if an entry has a specific value for one of its attributes */ +-PHP_FUNCTION(ldap_compare) ++/* {{{ proto void php_ldap_do_compare */ ++void php_ldap_do_compare(INTERNAL_FUNCTION_PARAMETERS, int ext) + { +- zval *link; +- char *dn, *attr, *value; ++ zval *link, *dn, *attr, *value, **sctrls, **cctrls; ++ char *ldap_dn, *ldap_attr; + int dn_len, attr_len, value_len; + ldap_linkdata *ld; +- int errno; ++ int rc, msgid, lerr, myargcount = ZEND_NUM_ARGS(); ++ LDAPMessage *ldap_res; ++ LDAPControl **lsctrls = NULL, **lcctrls = NULL; + +- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsss", &link, &dn, &dn_len, &attr, &attr_len, &value, &value_len) != SUCCESS) { +- return; ++ if (ext) { ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsss|ZZ", &link, &dn, &dn_len, &attr, &attr_len, &value, &value_len, &sctrls, &cctrls) != SUCCESS) { ++ WRONG_PARAM_COUNT; ++ } ++ } else { ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsss", &link, &dn, &dn_len, &attr, &attr_len, &value, &value_len) != SUCCESS) { ++ WRONG_PARAM_COUNT; ++ } + } + + ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link); + +- errno = ldap_compare_s(ld->link, dn, attr, value); +- +- switch (errno) { +- case LDAP_COMPARE_TRUE: +- RETURN_TRUE; +- break; ++ if (ext) { ++ struct berval ldap_bvalue; ++ switch (myargcount) { ++ case 6: ++ _php_parse_controls(cctrls, &lcctrls); ++ case 5: ++ _php_parse_controls(sctrls, &lsctrls); ++ } + +- case LDAP_COMPARE_FALSE: ++ ldap_bvalue.bv_val = Z_STRVAL_PP(&value); ++ ldap_bvalue.bv_len = Z_STRLEN_PP(&value); ++ rc = ldap_compare_ext(ld->link, ldap_dn, ldap_attr, &ldap_bvalue, lsctrls, lcctrls, &msgid); ++ if (lsctrls) { ++ _php_free_controls(&lsctrls); ++ } ++ if (lcctrls) { ++ _php_free_controls(&lcctrls); ++ } ++ if (rc != LDAP_SUCCESS) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Compare: %s", ldap_err2string(rc)); + RETURN_FALSE; +- break; ++ } ++ ++ rc = ldap_result(ld->link, msgid, LDAP_MSG_ALL, NULL, &ldap_res); ++ if (rc != LDAP_RES_COMPARE) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Compare: unable to get result"); ++ RETURN_FALSE; ++ } ++ ++ ZEND_REGISTER_RESOURCE(return_value, ldap_res, le_result); ++ rc = ldap_parse_result(ld->link, ldap_res, &lerr, NULL, NULL, NULL, NULL, 0); ++ if (rc == LDAP_SUCCESS) { ++ rc = lerr; ++ } ++ ++ switch (rc) { ++ case LDAP_COMPARE_TRUE: ++ case LDAP_COMPARE_FALSE: ++ break; ++ ++ default: ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Compare failed: %s", ldap_err2string(rc)); ++ break; ++ } ++ ++ } else { ++#ifdef HAVE_LDAP_COMPARE_EXT_S ++ struct berval ldap_bvalue; ++ ++ ldap_bvalue.bv_val = Z_STRVAL_PP(&value); ++ ldap_bvalue.bv_len = Z_STRLEN_PP(&value); ++ rc = ldap_compare_ext_s(ld->link, ldap_dn, ldap_attr, &ldap_bvalue, NULL, NULL); ++#else /* ! HAVE_LDAP_COMPARE_EXT_S */ ++ char *ldap_value; ++ ++ ldap_value = Z_STRVAL_PP(&value); ++ rc = ldap_compare_s(ld->link, ldap_dn, ldap_attr, ldap_value); ++#endif /* ! HAVE_LDAP_COMPARE_EXT_S */ ++ ++ switch (rc) { ++ case LDAP_COMPARE_TRUE: ++ RETURN_TRUE; ++ break; ++ ++ case LDAP_COMPARE_FALSE: ++ RETURN_FALSE; ++ break; ++ } ++ ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Compare: %s", ldap_err2string(rc)); ++ RETURN_LONG(-1); + } +- +- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Compare: %s", ldap_err2string(errno)); +- RETURN_LONG(-1); ++} ++/* {{{ proto bool ldap_compare(resource link, string dn, string attr, string valu) ++ Determine if an entry has a specific value for one of its attributes */ ++PHP_FUNCTION(ldap_compare) ++{ ++ php_ldap_do_compare(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); + } + /* }}} */ + + /* {{{ proto bool ldap_sort(resource link, resource result, string sortfilter) +@@ -1932,59 +2336,233 @@ + RETURN_TRUE; + } + /* }}} */ + +-#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 +-/* {{{ proto bool ldap_get_option(resource link, int option, mixed retval) +- Get the current value of various session-wide parameters */ +-PHP_FUNCTION(ldap_get_option) ++/* {{{ Extended API that returns result instead of just bool ++ * to allow further manipulation by the ldap_parse_*() funcs, ++ * Pierangelo Masarati */ ++ ++/* {{{ proto result ldap_bind_ext(resource link [, string dn, string password]) ++ Bind to LDAP directory */ ++PHP_FUNCTION(ldap_bind_ext) + { +- zval *link, *retval; ++ zval *link; ++ char *ldap_bind_dn = NULL, *ldap_bind_pw = NULL; ++ int ldap_bind_dnlen, ldap_bind_pwlen; + ldap_linkdata *ld; +- long option; +- +- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rlz", &link, &option, &retval) != SUCCESS) { +- return; ++ int rc, msgid, lerr; ++ LDAPMessage *ldap_res; ++ ++ 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) { ++ ++ RETURN_FALSE; + } + + ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link); + +- switch (option) { +- /* options with int value */ +- case LDAP_OPT_DEREF: +- case LDAP_OPT_SIZELIMIT: +- case LDAP_OPT_TIMELIMIT: +- case LDAP_OPT_PROTOCOL_VERSION: +- case LDAP_OPT_ERROR_NUMBER: +- case LDAP_OPT_REFERRALS: +-#ifdef LDAP_OPT_RESTART +- case LDAP_OPT_RESTART: ++#ifdef LDAP_API_FEATURE_X_OPENLDAP ++ { ++ struct berval cred; ++ ++ /* ldap_bind() is deprecated; use ldap_sasl_bind() instead */ ++ cred.bv_val = ldap_bind_pw; ++ cred.bv_len = ldap_bind_pw ? ldap_bind_pwlen : 0; ++ ++ rc = ldap_sasl_bind(ld->link, ldap_bind_dn, LDAP_SASL_SIMPLE, &cred, ++ NULL, NULL, /* no controls right now */ ++ &msgid); ++ if (rc != LDAP_SUCCESS) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to bind: %s", ldap_err2string(rc)); ++ RETURN_FALSE; ++ } ++ } ++#else ++ msgid = ldap_bind(ld->link, ldap_bind_dn, ldap_bind_pw, LDAP_AUTH_SIMPLE); ++ if (msgid == -1) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to bind"); ++ RETURN_FALSE; ++ } + #endif +- { +- int val; + +- if (ldap_get_option(ld->link, option, &val)) { +- RETURN_FALSE; +- } +- zval_dtor(retval); +- ZVAL_LONG(retval, val); +- } break; +-#ifdef LDAP_OPT_NETWORK_TIMEOUT +- case LDAP_OPT_NETWORK_TIMEOUT: +- { +- struct timeval *timeout = NULL; ++ rc = ldap_result(ld->link, msgid, LDAP_MSG_ALL, NULL, &ldap_res); ++ if (rc != LDAP_RES_BIND) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to get bind result: %s", ldap_err2string(rc)); ++ RETURN_FALSE; ++ } + +- if (ldap_get_option(ld->link, LDAP_OPT_NETWORK_TIMEOUT, (void *) &timeout)) { +- if (timeout) { +- ldap_memfree(timeout); +- } +- RETURN_FALSE; +- } +- if (!timeout) { +- RETURN_FALSE; +- } +- zval_dtor(retval); +- ZVAL_LONG(retval, timeout->tv_sec); ++ ZEND_REGISTER_RESOURCE(return_value, ldap_res, le_result); ++ rc = ldap_parse_result(ld->link, ldap_res, &lerr, NULL, NULL, NULL, NULL, 0); ++ if (rc == LDAP_SUCCESS) { ++ rc = lerr; ++ } ++ ++ ++ if (rc != LDAP_SUCCESS) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to bind to server: %s", ldap_err2string(rc)); ++ } ++} ++/* }}} */ ++ ++/* {{{ proto result ldap_add_ext(resource link, string dn, array entry) ++ Add entries to LDAP directory; returns result */ ++PHP_FUNCTION(ldap_add_ext) ++{ ++ php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_LD_FULL_ADD, 1); ++} ++/* }}} */ ++ ++/* {{{ proto result ldap_mod_replace_ext(resource link, string dn, array entry) ++ Replace attribute values with new ones */ ++PHP_FUNCTION(ldap_mod_replace_ext) ++{ ++ php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_REPLACE, 1); ++} ++/* }}} */ ++ ++ ++/* {{{ proto result ldap_mod_add_ext(resource link, string dn, array entry) ++ Add attribute values to current */ ++PHP_FUNCTION(ldap_mod_add_ext) ++{ ++ php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_ADD, 1); ++} ++/* }}} */ ++ ++/* {{{ proto result ldap_mod_del_ext(resource link, string dn, array entry) ++ Delete attribute values */ ++PHP_FUNCTION(ldap_mod_del_ext) ++{ ++ php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_DELETE, 1); ++} ++/* }}} */ ++ ++/* {{{ proto result ldap_delete_ext(resource link, string dn) ++ Delete an entry from a directory */ ++PHP_FUNCTION(ldap_delete_ext) ++{ ++ zval **link, **dn, **sctrls, **cctrls; ++ ldap_linkdata *ld; ++ char *ldap_dn; ++ int rc, dn_len, msgid, lerr, myargcount = ZEND_NUM_ARGS(); ++ LDAPMessage *ldap_res; ++ LDAPControl **lsctrls = NULL, **lcctrls = NULL; ++ ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|ZZ", &link, &dn, &dn_len, &sctrls, &cctrls) == FAILURE) { ++ WRONG_PARAM_COUNT; ++ } ++ ++ switch (myargcount) { ++ case 4: ++ _php_parse_controls(cctrls, &lcctrls); ++ ++ case 3: ++ _php_parse_controls(sctrls, &lsctrls); ++ } ++ ++ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link); ++ ++ convert_to_string_ex(dn); ++ ldap_dn = Z_STRVAL_PP(dn); ++ ++#ifdef HAVE_LDAP_DELETE_EXT_S ++ rc = ldap_delete_ext_s(ld->link, ldap_dn, NULL, NULL); ++#else /* ! HAVE_LDAP_DELETE_EXT_S */ ++ rc = ldap_delete_s(ld->link, ldap_dn); ++#endif /* ! HAVE_LDAP_DELETE_EXT_S */ ++ if (lsctrls) { ++ _php_free_controls(&lsctrls); ++ } ++ if (lcctrls) { ++ _php_free_controls(&lcctrls); ++ } ++ if (rc != LDAP_SUCCESS) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Delete: %s", ldap_err2string(rc)); ++ RETURN_FALSE; ++ } ++ ++ rc = ldap_result(ld->link, msgid, LDAP_MSG_ALL, NULL, &ldap_res); ++ if (rc != LDAP_RES_DELETE) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Delete: unable to get result"); ++ RETURN_FALSE; ++ } ++ ++ ZEND_REGISTER_RESOURCE(return_value, ldap_res, le_result); ++ rc = ldap_parse_result(ld->link, ldap_res, &lerr, NULL, NULL, NULL, NULL, 0); ++ if (rc == LDAP_SUCCESS) { ++ rc = lerr; ++ } ++ ++ if (rc != LDAP_SUCCESS) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Delete failed: %s", ldap_err2string(rc)); ++ } ++} ++/* }}} */ ++ ++/* }}} End of extended API, Pierangelo Masarati */ ++ ++ ++/* {{{ proto result ldap_compare_ext(resource link, string dn, string attr, string value) ++ Determine if an entry has a specific value for one of its attributes */ ++PHP_FUNCTION(ldap_compare_ext) ++{ ++ php_ldap_do_compare(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); ++} ++/* }}} */ ++ ++/* }}} End of extended API, Pierangelo Masarati */ ++ ++ ++#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 ++/* {{{ proto bool ldap_get_option(resource link, int option, mixed retval) ++ Get the current value of various session-wide parameters */ ++PHP_FUNCTION(ldap_get_option) ++{ ++ zval *link, *retval; ++ ldap_linkdata *ld; ++ long option; ++ ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rlz", &link, &option, &retval) != SUCCESS) { ++ return; ++ } ++ ++ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link); ++ ++ switch (option) { ++ /* options with int value */ ++ case LDAP_OPT_DEREF: ++ case LDAP_OPT_SIZELIMIT: ++ case LDAP_OPT_TIMELIMIT: ++ case LDAP_OPT_PROTOCOL_VERSION: ++ case LDAP_OPT_ERROR_NUMBER: ++ case LDAP_OPT_REFERRALS: ++#ifdef LDAP_OPT_RESTART ++ case LDAP_OPT_RESTART: ++#endif ++ { ++ int val; ++ ++ if (ldap_get_option(ld->link, option, &val)) { ++ RETURN_FALSE; ++ } ++ zval_dtor(retval); ++ ZVAL_LONG(retval, val); ++ } break; ++#ifdef LDAP_OPT_NETWORK_TIMEOUT ++ case LDAP_OPT_NETWORK_TIMEOUT: ++ { ++ struct timeval *timeout = NULL; ++ ++ if (ldap_get_option(ld->link, LDAP_OPT_NETWORK_TIMEOUT, (void *) &timeout)) { ++ if (timeout) { ++ ldap_memfree(timeout); ++ } ++ RETURN_FALSE; ++ } ++ if (!timeout) { ++ RETURN_FALSE; ++ } ++ zval_dtor(retval); ++ ZVAL_LONG(retval, timeout->tv_sec); + ldap_memfree(timeout); + } break; + #elif defined(LDAP_X_OPT_CONNECT_TIMEOUT) + case LDAP_X_OPT_CONNECT_TIMEOUT: +@@ -2207,21 +2785,23 @@ + } + /* }}} */ + + #ifdef HAVE_LDAP_PARSE_RESULT +-/* {{{ proto bool ldap_parse_result(resource link, resource result, int errcode, string matcheddn, string errmsg, array referrals) ++/* {{{ proto bool ldap_parse_result(resource link, resource result, int errcode [, string matcheddn [, string errmsg [, array referrals [, array serverctrls]]]]) + Extract information from result */ + PHP_FUNCTION(ldap_parse_result) + { +- zval *link, *result, *errcode, *matcheddn, *errmsg, *referrals; ++ zval *link, *result, *errcode, *matcheddn, *errmsg, *referrals, *serverctrls; + ldap_linkdata *ld; + LDAPMessage *ldap_result; +- char **lreferrals, **refp; ++ LDAPControl **lserverctrls; ++ char **lreferrals; + char *lmatcheddn, *lerrmsg; + int rc, lerrcode, myargcount = ZEND_NUM_ARGS(); ++ /* int matcheddn_len, errmsg_len; */ + +- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rrz|zzz", &link, &result, &errcode, &matcheddn, &errmsg, &referrals) != SUCCESS) { +- return; ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rrz|zzzz", &link, &result, &errcode, &matcheddn, &errmsg, &referrals, &serverctrls) != SUCCESS) { ++ WRONG_PARAM_COUNT; + } + + ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link); + ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, &result, -1, "ldap result", le_result); +@@ -2229,9 +2809,9 @@ + rc = ldap_parse_result(ld->link, ldap_result, &lerrcode, + myargcount > 3 ? &lmatcheddn : NULL, + myargcount > 4 ? &lerrmsg : NULL, + myargcount > 5 ? &lreferrals : NULL, +- NULL /* &serverctrls */, ++ myargcount > 6 ? &lserverctrls : NULL, + 0); + if (rc != LDAP_SUCCESS) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to parse result: %s", ldap_err2string(rc)); + RETURN_FALSE; +@@ -2241,19 +2821,15 @@ + ZVAL_LONG(errcode, lerrcode); + + /* Reverse -> fall through */ + switch (myargcount) { ++ case 7: ++ /* use arg #7 as the array of controls returned by the server */ ++ zval_dtor(serverctrls); ++ array_init(serverctrls); ++ _php_parse_controls_resp(&lserverctrls, &serverctrls); + case 6: +- zval_dtor(referrals); +- array_init(referrals); +- if (lreferrals != NULL) { +- refp = lreferrals; +- while (*refp) { +- add_next_index_string(referrals, *refp, 1); +- refp++; +- } +- ldap_value_free(lreferrals); +- } ++ _php_parse_referrals_resp(&lreferrals, &referrals); + case 5: + zval_dtor(errmsg); + if (lerrmsg == NULL) { + ZVAL_EMPTY_STRING(errmsg); +@@ -2274,8 +2850,142 @@ + } + /* }}} */ + #endif + ++/* {{{ Extended operation response parsing, Pierangelo Masarati */ ++#ifdef HAVE_LDAP_PARSE_EXTENDED_RESULT ++/* {{{ proto bool ldap_parse_exop(resource link, resource result [, string retoid [, string retdata]]) ++ Extract information from extended operation result */ ++PHP_FUNCTION(ldap_parse_exop) ++{ ++ zval *link, *result, *retoid, *retdata; ++ ldap_linkdata *ld; ++ LDAPMessage *ldap_result; ++ char *lretoid; ++ struct berval *lretdata; ++ int rc, myargcount = ZEND_NUM_ARGS(); ++ ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr|zz", &link, &result, &retoid, &retdata) == SUCCESS) { ++ WRONG_PARAM_COUNT; ++ } ++ ++ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link); ++ ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, &result, -1, "ldap result", le_result); ++ ++ rc = ldap_parse_extended_result(ld->link, ldap_result, ++ myargcount > 2 ? &lretoid: NULL, ++ myargcount > 3 ? &lretdata: NULL, ++ 0); ++ if (rc != LDAP_SUCCESS) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to parse extended operation result: %s", ldap_err2string(rc)); ++ RETURN_FALSE; ++ } ++ ++ /* Reverse -> fall through */ ++ switch (myargcount) { ++ case 4: ++ /* use arg #4 as the data returned by the server */ ++ zval_dtor(retdata); ++ if (lretdata == NULL) { ++ ZVAL_EMPTY_STRING(retdata); ++ } else { ++ ZVAL_STRINGL(retdata, lretdata->bv_val, lretdata->bv_len, 1); ++ ldap_memfree(lretdata->bv_val); ++ ldap_memfree(lretdata); ++ } ++ case 3: ++ zval_dtor(retoid); ++ if (lretoid == NULL) { ++ ZVAL_EMPTY_STRING(retoid); ++ } else { ++ ZVAL_STRING(retoid, lretoid, 1); ++ ldap_memfree(lretoid); ++ } ++ } ++ RETURN_TRUE; ++} ++/* }}} */ ++ ++#ifdef HAVE_LDAP_PARSE_PASSWD ++/* {{{ proto bool ldap_parse_exop_passwd(resource link, resource result, string newpasswd) ++ Extract information from RFC 3062 password modify extended operation result */ ++PHP_FUNCTION(ldap_parse_exop_passwd) ++{ ++ zval **link, **result, **newpasswd; ++ ldap_linkdata *ld; ++ LDAPMessage *ldap_result; ++ struct berval lnewpasswd; ++ int rc, myargcount = ZEND_NUM_ARGS(); ++ ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZZ", &link, &result, &newpasswd) != SUCCESS) { ++ WRONG_PARAM_COUNT; ++ } ++ ++ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link); ++ ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, result, -1, "ldap result", le_result); ++ ++ rc = ldap_parse_passwd(ld->link, ldap_result, &lnewpasswd); ++ if (rc != LDAP_SUCCESS) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to parse passwd modify extended operation result: %s", ldap_err2string(rc)); ++ RETURN_FALSE; ++ } ++ ++ zval_dtor(*newpasswd); ++ if (lnewpasswd.bv_len == 0) { ++ ZVAL_EMPTY_STRING(*newpasswd); ++ } else { ++ ZVAL_STRINGL(*newpasswd, lnewpasswd.bv_val, lnewpasswd.bv_len, 1); ++ ldap_memfree(lnewpasswd.bv_val); ++ } ++ ++ RETURN_TRUE; ++} ++#else ++/* TODO: implement based on ldap_parse_exop() */ ++/* }}} */ ++#endif ++ ++#ifdef HAVE_LDAP_PARSE_WHOAMI ++/* {{{ proto bool ldap_parse_exop_whoami(resource link, resource result, string authzid) ++ Extract information from <draft-zeilenga-ldap-authzid> whoami extended operation result (a Work in Progress) */ ++PHP_FUNCTION(ldap_parse_exop_whoami) ++{ ++ zval **link, **result, **authzid; ++ ldap_linkdata *ld; ++ LDAPMessage *ldap_result; ++ struct berval *lauthzid; ++ int rc, myargcount = ZEND_NUM_ARGS(); ++ ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZZ", &link, &result, &authzid) != SUCCESS) { ++ WRONG_PARAM_COUNT; ++ } ++ ++ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link); ++ ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, result, -1, "ldap result", le_result); ++ ++ rc = ldap_parse_whoami(ld->link, ldap_result, &lauthzid ); ++ if (rc != LDAP_SUCCESS) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to parse whoami extended operation result: %s", ldap_err2string(rc)); ++ RETURN_FALSE; ++ } ++ ++ zval_dtor(*authzid); ++ if (lauthzid == NULL) { ++ ZVAL_EMPTY_STRING(*authzid); ++ } else { ++ ZVAL_STRINGL(*authzid, lauthzid->bv_val, lauthzid->bv_len, 1); ++ ldap_memfree(lauthzid->bv_val); ++ ldap_memfree(lauthzid); ++ } ++ RETURN_TRUE; ++} ++#else ++/* TODO: implement based on ldap_parse_extended_result() */ ++/* }}} */ ++#endif ++/* }}} */ ++#endif ++ + /* {{{ proto resource ldap_first_reference(resource link, resource result) + Return first reference */ + PHP_FUNCTION(ldap_first_reference) + { +@@ -2758,51 +3468,733 @@ + } + /* }}} */ + #endif + +-/* {{{ arginfo */ +-ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_connect, 0, 0, 0) +- ZEND_ARG_INFO(0, hostname) +- ZEND_ARG_INFO(0, port) +-#ifdef HAVE_ORALDAP +- ZEND_ARG_INFO(0, wallet) +- ZEND_ARG_INFO(0, wallet_passwd) +- ZEND_ARG_INFO(0, authmode) +-#endif +-ZEND_END_ARG_INFO() ++/* {{{ Extended operations, Pierangelo Masarati */ ++#ifdef HAVE_LDAP_EXTENDED_OPERATION_S ++/* {{{ proto ? ldap_exop(resource link, string reqoid [, string reqdata [, string retoid [, string retdata]]]) ++ Extended operation */ ++PHP_FUNCTION(ldap_exop) ++{ ++ zval **link, **reqoid, **reqdata, **retoid, **retdata; ++ char *lreqoid, *lretoid = NULL; ++ struct berval lreqdata, *lretdata = NULL; ++ ldap_linkdata *ld; ++ LDAP *ldap; ++ LDAPMessage *ldap_res; ++ int rc, msgid, myargcount = ZEND_NUM_ARGS(); ++ /* int reqoid_len, reqdata_len, retdata_len, retoid_len, retdat_len; */ + +-ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_resource, 0, 0, 1) +- ZEND_ARG_INFO(0, link_identifier) +-ZEND_END_ARG_INFO() ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ|ZZZ", &link, &reqoid, &reqdata, &retoid, &retdata) != SUCCESS) { ++ WRONG_PARAM_COUNT; ++ } + +-ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_bind, 0, 0, 1) +- ZEND_ARG_INFO(0, link_identifier) +- ZEND_ARG_INFO(0, bind_rdn) +- ZEND_ARG_INFO(0, bind_password) +-ZEND_END_ARG_INFO() ++ if (Z_TYPE_PP(link) == IS_NULL) { ++ ldap = NULL; ++ } else { ++ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link); ++ ldap = ld->link; ++ } + +-#ifdef HAVE_LDAP_SASL +-ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_sasl_bind, 0, 0, 1) +- ZEND_ARG_INFO(0, link) +- ZEND_ARG_INFO(0, binddn) +- ZEND_ARG_INFO(0, password) +- ZEND_ARG_INFO(0, sasl_mech) +- ZEND_ARG_INFO(0, sasl_realm) +- ZEND_ARG_INFO(0, sasl_authz_id) +- ZEND_ARG_INFO(0, props) +-ZEND_END_ARG_INFO() +-#endif ++ switch (myargcount) { ++ case 5: ++ case 4: ++ case 3: ++ convert_to_string_ex(reqdata); ++ lreqdata.bv_val = Z_STRVAL_PP(reqdata); ++ lreqdata.bv_len = Z_STRLEN_PP(reqdata); ++ /* fallthru */ ++ case 2: ++ convert_to_string_ex(reqoid); ++ lreqoid = Z_STRVAL_PP(reqoid); ++ } ++ ++ if (myargcount > 3) { ++ /* synchronous call */ ++ rc = ldap_extended_operation_s(ld->link, lreqoid, ++ lreqdata.bv_len > 0 ? &lreqdata: NULL, ++ NULL, ++ NULL, ++ &lretoid, ++ myargcount > 4 ? &lretdata : NULL ); ++ if (rc != LDAP_SUCCESS ) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Extended operation %s failed: %s (%d)", lreqoid, ldap_err2string(rc), rc); ++ RETURN_FALSE; ++ } + +-ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_read, 0, 0, 3) +- ZEND_ARG_INFO(0, link_identifier) +- ZEND_ARG_INFO(0, base_dn) +- ZEND_ARG_INFO(0, filter) +- ZEND_ARG_INFO(0, attributes) +- ZEND_ARG_INFO(0, attrsonly) +- ZEND_ARG_INFO(0, sizelimit) +- ZEND_ARG_INFO(0, timelimit) +- ZEND_ARG_INFO(0, deref) +-ZEND_END_ARG_INFO() ++ /* Reverse -> fall through */ ++ switch (myargcount) { ++ case 5: ++ /* use arg #4 as the data returned by the server */ ++ zval_dtor(*retdata); ++ if (lretdata == NULL) { ++ ZVAL_EMPTY_STRING(*retdata); ++ } else { ++ ZVAL_STRINGL(*retdata, lretdata->bv_val, lretdata->bv_len, 1); ++ ldap_memfree(lretdata->bv_val); ++ ldap_memfree(lretdata); ++ } ++ case 4: ++ zval_dtor(*retoid); ++ if (lretoid == NULL) { ++ ZVAL_EMPTY_STRING(*retoid); ++ } else { ++ ZVAL_STRING(*retoid, lretoid, 1); ++ ldap_memfree(lretoid); ++ } ++ } ++ ++ RETURN_TRUE; ++ } ++ ++ /* asynchronous call */ ++ rc = ldap_extended_operation(ld->link, lreqoid, ++ lreqdata.bv_len > 0 ? &lreqdata: NULL, ++ NULL, NULL, &msgid); ++ if (rc != LDAP_SUCCESS ) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Extended operation %s failed: %s (%d)", lreqoid, ldap_err2string(rc), rc); ++ RETURN_FALSE; ++ } ++ ++ rc = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res); ++ if (rc == -1) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Extended operation %s failed", lreqoid); ++ RETURN_FALSE; ++ } ++ ++ /* return a PHP control object */ ++ array_init(return_value); ++ ++ ZEND_REGISTER_RESOURCE(return_value, ldap_res, le_result); ++} ++/* }}} */ ++ ++#ifdef HAVE_LDAP_PASSWD_S ++/* {{{ proto ? ldap_exop_passwd(resource link [, string user [, string oldpw [, string newpw [, string newpasswd ]]]]) ++ Passwd modify extended operation */ ++PHP_FUNCTION(ldap_exop_passwd) ++{ ++ zval **link, **user, **newpw, **oldpw, **newpasswd; ++ struct berval luser, loldpw, lnewpw, lnewpasswd; ++ ldap_linkdata *ld; ++ LDAP *ldap; ++ LDAPMessage *ldap_res; ++ int rc, msgid, myargcount = ZEND_NUM_ARGS(); ++ ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|ZZZZ", &link, &user, &oldpw, &newpw, &newpasswd) == FAILURE) { ++ WRONG_PARAM_COUNT; ++ } ++ ++ if (Z_TYPE_PP(link) == IS_NULL) { ++ ldap = NULL; ++ } else { ++ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link); ++ ldap = ld->link; ++ } ++ ++ luser.bv_len = 0; ++ loldpw.bv_len = 0; ++ lnewpw.bv_len = 0; ++ ++ switch (myargcount) { ++ case 5: ++ case 4: ++ convert_to_string_ex(newpw); ++ lnewpw.bv_val = Z_STRVAL_PP(newpw); ++ lnewpw.bv_len = Z_STRLEN_PP(newpw); ++ ++ case 3: ++ convert_to_string_ex(oldpw); ++ loldpw.bv_val = Z_STRVAL_PP(oldpw); ++ loldpw.bv_len = Z_STRLEN_PP(oldpw); ++ ++ case 2: ++ convert_to_string_ex(user); ++ luser.bv_val = Z_STRVAL_PP(user); ++ luser.bv_len = Z_STRLEN_PP(user); ++ } ++ ++ if (myargcount > 4 || lnewpw.bv_len > 0) { ++ /* synchronous call */ ++ rc = ldap_passwd_s(ld->link, &luser, ++ loldpw.bv_len > 0 ? &loldpw : NULL, ++ /* loldpw.bv_len > 0 ? &loldpw : NULL, */ ++ lnewpw.bv_len > 0 ? &lnewpw : NULL, ++ &lnewpasswd, NULL, NULL); ++ if (rc != LDAP_SUCCESS ) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Passwd modify extended operation failed: %s (%d)", ldap_err2string(rc), rc); ++ RETURN_FALSE; ++ } ++ ++ if (myargcount > 4) { ++ zval_dtor(*newpasswd); ++ if (lnewpasswd.bv_len == 0) { ++ ZVAL_EMPTY_STRING(*newpasswd); ++ } else { ++ ZVAL_STRINGL(*newpasswd, lnewpasswd.bv_val, lnewpasswd.bv_len, 1); ++ } ++ } ++ ++ ldap_memfree(lnewpasswd.bv_val); ++ ++ RETURN_TRUE; ++ } ++ ++ /* asynchronous call */ ++ rc = ldap_passwd(ld->link, &luser, ++ loldpw.bv_len > 0 ? &loldpw : NULL, ++ lnewpw.bv_len > 0 ? &lnewpw : NULL, ++ NULL, NULL, &msgid); ++ if (rc != LDAP_SUCCESS ) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Passwd modify extended operation failed: %s (%d)", ldap_err2string(rc), rc); ++ RETURN_FALSE; ++ } ++ ++ rc = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res); ++ if (rc == -1) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Passwd modify extended operation failed"); ++ RETURN_FALSE; ++ } ++ ++ /* return a PHP control object */ ++ array_init(return_value); ++ ++ ZEND_REGISTER_RESOURCE(return_value, ldap_res, le_result); ++} ++#else ++/* TODO: implement based on ldap_extended_operation_s() */ ++/* }}} */ ++#endif ++ ++#ifdef HAVE_LDAP_WHOAMI_S ++/* {{{ proto bool ldap_exop_whoami(resource link [, string authzid]) ++ Whoami extended operation */ ++PHP_FUNCTION(ldap_exop_whoami) ++{ ++ zval **link, **authzid; ++ struct berval *lauthzid; ++ ldap_linkdata *ld; ++ LDAP *ldap; ++ LDAPMessage *ldap_res; ++ int rc, msgid, myargcount = ZEND_NUM_ARGS(); ++ ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|Z", &link, &authzid) == FAILURE) { ++ WRONG_PARAM_COUNT; ++ } ++ ++ if (Z_TYPE_PP(link) == IS_NULL) { ++ ldap = NULL; ++ } else { ++ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link); ++ ldap = ld->link; ++ } ++ ++ if (myargcount == 2) { ++ /* synchronous call */ ++ rc = ldap_whoami_s(ld->link, &lauthzid, NULL, NULL); ++ if (rc != LDAP_SUCCESS ) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Whoami extended operation failed: %s (%d)", ldap_err2string(rc), rc); ++ RETURN_FALSE; ++ } ++ ++ zval_dtor(*authzid); ++ if (lauthzid == NULL) { ++ ZVAL_EMPTY_STRING(*authzid); ++ } else { ++ ZVAL_STRINGL(*authzid, lauthzid->bv_val, lauthzid->bv_len, 1); ++ ldap_memfree(lauthzid->bv_val); ++ ldap_memfree(lauthzid); ++ } ++ ++ RETURN_TRUE; ++ } ++ ++ /* asynchronous call */ ++ rc = ldap_whoami(ld->link, NULL, NULL, &msgid); ++ if (rc != LDAP_SUCCESS ) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Whoami extended operation failed: %s (%d)", ldap_err2string(rc), rc); ++ RETURN_FALSE; ++ } ++ ++ rc = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res); ++ if (rc == -1) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Whoami extended operation failed"); ++ RETURN_FALSE; ++ } ++ ++ /* return a PHP control object */ ++ array_init(return_value); ++ ++ ZEND_REGISTER_RESOURCE(return_value, ldap_res, le_result); ++} ++#else ++/* TODO: implement based on ldap_extended_operation_s() */ ++#endif ++/* }}} */ ++#endif ++/* }}} */ ++ ++/* {{{ LDAP controls encoding/decoding, Pierangelo Masarati */ ++/* {{{ php_set_no_value_server_ctrl ++ */ ++void php_set_no_value_server_ctrl(INTERNAL_FUNCTION_PARAMETERS, const char *oid, const char *msg) ++{ ++ zval **link, **iscritical; ++ ldap_linkdata *ld; ++ LDAP *ldap; ++ LDAPControl ctrl = { 0 }, *ctrlsp[2]; ++ int rc, myargcount = ZEND_NUM_ARGS(); ++ ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|Z", &link, &iscritical) != SUCCESS) { ++ WRONG_PARAM_COUNT; ++ } ++ ++ if (Z_TYPE_PP(link) == IS_NULL) { ++ ldap = NULL; ++ ++ } else { ++ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link); ++ ldap = ld->link; ++ } ++ ++ if (myargcount == 2) { ++ convert_to_boolean_ex(iscritical); ++ ctrl.ldctl_iscritical = Z_BVAL_PP(iscritical); ++ } ++ ++ ctrl.ldctl_oid = (char *)oid; ++ ++ if (ldap) { ++ /* directly set the option */ ++ ctrlsp[0] = &ctrl; ++ ctrlsp[1] = NULL; ++ ++ rc = ldap_set_option(ldap, LDAP_OPT_SERVER_CONTROLS, ctrlsp); ++ if (rc != LDAP_SUCCESS) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set %s control: %s (%d)", msg, ldap_err2string(rc), rc); ++ RETURN_FALSE; ++ } ++ ++ } else { ++ /* return a PHP control object */ ++ array_init(return_value); ++ ++ add_assoc_string(return_value, "oid", ctrl.ldctl_oid, 1); ++ if (ctrl.ldctl_iscritical) { ++ add_assoc_bool(return_value, "iscritical", ctrl.ldctl_iscritical); ++ } ++ } ++ ++ RETURN_TRUE; ++} ++/* }}} */ ++ ++#ifdef LDAP_CONTROL_MANAGEDSAIT ++/* {{{ proto bool ldap_ctrl_manageDSAit(resource link [, bool iscritical]) ++ Inject manageDSAit control */ ++PHP_FUNCTION(ldap_ctrl_manageDSAit) ++{ ++ php_set_no_value_server_ctrl(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_CONTROL_MANAGEDSAIT, "manageDSAit"); ++} ++/* }}} */ ++#endif ++ ++#ifdef LDAP_CONTROL_PAGEDRESULTS ++/* {{{ proto bool ldap_ctrl_paged_results(resource link, int pagesize [, bool iscritical [, string cookie]]) ++ Inject paged results control*/ ++PHP_FUNCTION(ldap_ctrl_paged_results) ++{ ++ zval **link, **pagesize, **iscritical, **cookie; ++ int lpagesize = 0; ++ struct berval lcookie = { 0, NULL }; ++ ldap_linkdata *ld; ++ LDAP *ldap; ++ BerElement *ber = NULL; ++ LDAPControl ctrl, *ctrlsp[2]; ++ int rc, myargcount = ZEND_NUM_ARGS(); ++ ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ|ZZ", &link, &pagesize, &iscritical, &cookie) != SUCCESS) { ++ WRONG_PARAM_COUNT; ++ } ++ ++ if (Z_TYPE_PP(link) == IS_NULL) { ++ ldap = NULL; ++ } else { ++ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link); ++ ldap = ld->link; ++ } ++ ++ ber = ber_alloc_t(LBER_USE_DER); ++ if (ber == NULL) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to alloc BER encoding resources for paged results control"); ++ RETURN_FALSE; ++ } ++ ++ ctrl.ldctl_iscritical = 0; ++ ++ switch (myargcount) { ++ case 4: ++ convert_to_string_ex(cookie); ++ lcookie.bv_val = Z_STRVAL_PP(cookie); ++ lcookie.bv_len = Z_STRLEN_PP(cookie); ++ /* fallthru */ ++ case 3: ++ convert_to_boolean_ex(iscritical); ++ ctrl.ldctl_iscritical = Z_BVAL_PP(iscritical); ++ /* fallthru */ ++ } ++ convert_to_long_ex(pagesize); ++ lpagesize = Z_LVAL_PP(pagesize); ++ ++ ber_printf(ber, "{iO}", lpagesize, &lcookie ); ++ rc = ber_flatten2( ber, &ctrl.ldctl_value, 0 ); ++ if ( rc == -1 ) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to BER encode paged results control"); ++ RETURN_FALSE; ++ } ++ ++ ctrl.ldctl_oid = LDAP_CONTROL_PAGEDRESULTS; ++ ++ if (ldap) { ++ /* directly set the option */ ++ ctrlsp[0] = &ctrl; ++ ctrlsp[1] = NULL; ++ ++ rc = ldap_set_option(ldap, LDAP_OPT_SERVER_CONTROLS, ctrlsp); ++ if (rc != LDAP_SUCCESS) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set paged results control: %s (%d)", ldap_err2string(rc), rc); ++ RETURN_FALSE; ++ } ++ ++ } else { ++ /* return a PHP control object */ ++ array_init(return_value); ++ ++ add_assoc_string(return_value, "oid", ctrl.ldctl_oid, 1); ++ if ( ctrl.ldctl_value.bv_len ) { ++ add_assoc_stringl(return_value, "value", ctrl.ldctl_value.bv_val, ctrl.ldctl_value.bv_len, 1); ++ } ++ if (ctrl.ldctl_iscritical) { ++ add_assoc_bool(return_value, "iscritical", ctrl.ldctl_iscritical); ++ } ++ } ++ ++ if (ber != NULL) { ++ ber_free(ber, 1); ++ } ++} ++/* }}} */ ++ ++/* {{{ proto bool ldap_ctrl_paged_results_resp(resource link, resource result [, string cookie [, int estimated]]) ++ Extract paged results control response */ ++PHP_FUNCTION(ldap_ctrl_paged_results_resp) ++{ ++ zval **link, **result, **cookie, **estimated; ++ struct berval lcookie; ++ int lestimated; ++ ldap_linkdata *ld; ++ LDAPMessage *ldap_result; ++ LDAPControl **lserverctrls, *lctrl; ++ BerElement *ber; ++ ber_tag_t tag; ++ int rc, lerrcode, myargcount = ZEND_NUM_ARGS(); ++ ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ|ZZ", &link, &result, &cookie, &estimated) != SUCCESS) { ++ WRONG_PARAM_COUNT; ++ } ++ ++ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link); ++ ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, result, -1, "ldap result", le_result); ++ ++ rc = ldap_parse_result(ld->link, ++ ldap_result, ++ &lerrcode, ++ NULL, /* matcheddn */ ++ NULL, /* errmsg */ ++ NULL, /* referrals */ ++ &lserverctrls, ++ 0); ++ ++ if (rc != LDAP_SUCCESS) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to parse result: %s (%d)", ldap_err2string(rc), rc); ++ RETURN_FALSE; ++ } ++ ++ if (lerrcode != LDAP_SUCCESS) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Result is: %s (%d)", ldap_err2string(lerrcode), lerrcode); ++ RETURN_FALSE; ++ } ++ ++ if (lserverctrls == NULL) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "No server controls in result"); ++ RETURN_FALSE; ++ } ++ ++ lctrl = ldap_find_control(LDAP_CONTROL_PAGEDRESULTS, lserverctrls); ++ if (lctrl == NULL) { ++ ldap_controls_free(lserverctrls); ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "No paged results control response in result"); ++ RETURN_FALSE; ++ } ++ ++ ber = ber_init(&lctrl->ldctl_value); ++ if (ber == NULL) { ++ ldap_controls_free(lserverctrls); ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to alloc BER decoding resources for paged results control response"); ++ RETURN_FALSE; ++ } ++ ++ tag = ber_scanf(ber, "{io}", &lestimated, &lcookie ); ++ (void)ber_free(ber, 1); ++ ++ if (tag == LBER_ERROR) { ++ ldap_controls_free(lserverctrls); ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to decode paged results control response"); ++ RETURN_FALSE; ++ } ++ ++ if (lestimated < 0) { ++ ldap_controls_free(lserverctrls); ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid paged results control response value"); ++ RETURN_FALSE; ++ } ++ ++ ldap_controls_free(lserverctrls); ++ ++ if (myargcount == 4) { ++ zval_dtor(*estimated); ++ ZVAL_LONG(*estimated, lestimated); ++ } ++ ++ zval_dtor(*cookie); ++ if (lcookie.bv_len == 0) { ++ ZVAL_EMPTY_STRING(*cookie); ++ } else { ++ ZVAL_STRINGL(*cookie, lcookie.bv_val, lcookie.bv_len, 1); ++ } ++ ldap_memfree(lcookie.bv_val); ++ ++ RETURN_TRUE; ++} ++/* }}} */ ++#endif ++ ++#ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST ++/* {{{ proto bool ldap_ctrl_ppolicy(resource link [, bool iscritical]) ++ Inject password policy control */ ++PHP_FUNCTION(ldap_ctrl_ppolicy) ++{ ++ php_set_no_value_server_ctrl(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_CONTROL_PASSWORDPOLICYREQUEST, "passwordPolicy"); ++} ++/* }}} */ ++ ++/* {{{ proto bool ldap_ctrl_ppolicy_resp(resource link, resource result [, expire [, grace [, error[, errmsg]]]]) ++ Extract password policy control response */ ++PHP_FUNCTION(ldap_ctrl_ppolicy_resp) ++{ ++ zval **link, **result, **ppexpire, **ppgrace, **pperror, **pperrmsg; ++ int lexpire, lgrace; ++ LDAPPasswordPolicyError lerror; ++ ldap_linkdata *ld; ++ LDAPMessage *ldap_result; ++ LDAPControl **lserverctrls, *lctrl; ++ int rc, pperrmsg_len, lerrcode, myargcount = ZEND_NUM_ARGS(); ++ ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ|ZZZZ", &link, &result, &ppexpire, &ppgrace, &pperror, &pperrmsg) != SUCCESS) { ++ WRONG_PARAM_COUNT; ++ } ++ ++ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link); ++ ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, result, -1, "ldap result", le_result); ++ ++ rc = ldap_parse_result(ld->link, ++ ldap_result, ++ &lerrcode, ++ NULL, /* matcheddn */ ++ NULL, /* errmsg */ ++ NULL, /* referrals */ ++ &lserverctrls, ++ 0); ++ ++ if (rc != LDAP_SUCCESS) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to parse result: %s (%d)", ldap_err2string(rc), rc); ++ RETURN_FALSE; ++ } ++ ++ if (lerrcode != LDAP_SUCCESS && lerrcode != LDAP_INVALID_CREDENTIALS) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Result is: %s (%d)", ldap_err2string(lerrcode), lerrcode); ++ RETURN_FALSE; ++ } ++ ++ if (lserverctrls == NULL) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "No server controls in result"); ++ RETURN_FALSE; ++ } ++ ++ lctrl = ldap_find_control(LDAP_CONTROL_PASSWORDPOLICYRESPONSE, lserverctrls); ++ if (lctrl == NULL) { ++ ldap_controls_free(lserverctrls); ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "No password policy control response in result"); ++ RETURN_FALSE; ++ } ++ ++ lerrcode = ldap_parse_passwordpolicy_control(ld->link, lctrl, &lexpire, &lgrace, &lerror); ++ ldap_controls_free(lserverctrls); ++ if (lerrcode != LDAP_SUCCESS) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to parse password policy control response: %s (%d)", ldap_err2string(lerrcode), lerrcode); ++ RETURN_FALSE; ++ } ++ ++ switch (myargcount) { ++ case 6: ++ zval_dtor(*pperrmsg); ++ ZVAL_STRING(*pperrmsg, (char *)ldap_passwordpolicy_err2txt(lerror), 1); ++ ++ case 5: ++ zval_dtor(*pperror); ++ ZVAL_LONG(*pperror, (long)lerror); ++ ++ case 4: ++ zval_dtor(*ppgrace); ++ ZVAL_LONG(*ppgrace, (long)lgrace); ++ } ++ ++ zval_dtor(*ppexpire); ++ ZVAL_LONG(*ppexpire, (long)lexpire); ++ ++ RETURN_TRUE; ++} ++/* }}} */ ++#endif ++ ++#ifdef LDAP_CONTROL_NOOP ++/* {{{ proto bool ldap_ctrl_noop(resource link, bool iscritical) ++ Inject control*/ ++PHP_FUNCTION(ldap_ctrl_noop) ++{ ++ php_set_no_value_server_ctrl(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_CONTROL_NOOP, "no-op"); ++} ++/* }}} */ ++#endif ++ ++#ifdef LDAP_CONTROL_MANAGEDIT ++/* {{{ proto bool ldap_ctrl_manageDIT(resource link [, bool iscritical]) ++ Inject control*/ ++PHP_FUNCTION(ldap_ctrl_manageDIT) ++{ ++ php_set_no_value_server_ctrl(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_CONTROL_MANAGEDIT, "manageDIT"); ++} ++/* }}} */ ++#endif ++ ++#ifdef LDAP_CONTROL_X_PERMISSIVE_MODIFY ++/* {{{ proto bool ldap_ctrl_permissive_modify(resource link [, bool iscritical]) ++ Inject control*/ ++PHP_FUNCTION(ldap_ctrl_permissive_modify) ++{ ++ php_set_no_value_server_ctrl(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_CONTROL_X_PERMISSIVE_MODIFY, "permissive modify"); ++} ++/* }}} */ ++#endif ++/* }}} */ ++ ++#ifdef HAVE_LDAP_REFRESH ++/* {{{ proto ? ldap_refresh(resource link , string dn , int ttl, [int *newttl]) ++ DDS refresh extended operation */ ++PHP_FUNCTION(ldap_refresh) ++{ ++ zval **link, **dn, **ttl, **newttl; ++ struct berval ldn; ++ ber_int_t lttl; ++ ber_int_t lnewttl; ++ ldap_linkdata *ld; ++ LDAP *ldap; ++ LDAPMessage *ldap_res; ++ int rc, msgid, myargcount = ZEND_NUM_ARGS(); ++ ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZZ|Z", &link, &dn, &ttl, &newttl) != SUCCESS) { ++ WRONG_PARAM_COUNT; ++ } ++ ++ if (Z_TYPE_PP(link) == IS_NULL) { ++ ldap = NULL; ++ } else { ++ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, ++ link, -1, "ldap link", le_link); ++ ldap = ld->link; ++ } ++ ++ ldn.bv_len = 0; ++ convert_to_string_ex(dn); ++ ldn.bv_val = Z_STRVAL_PP(dn); ++ ldn.bv_len = Z_STRLEN_PP(dn); ++ ++ convert_to_long_ex(ttl); ++ lttl = (ber_int_t)Z_LVAL_PP(ttl); ++ ++ /* asynchronous call */ ++ rc = ldap_refresh_s(ld->link, &ldn, lttl, &lnewttl, NULL, NULL); ++ if (rc != LDAP_SUCCESS ) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, ++ "Refresh extended operation failed: %s (%d)", ++ ldap_err2string(rc), rc); ++ RETURN_FALSE; ++ } ++ ++ if (myargcount == 4) { ++ zval_dtor(*newttl); ++ ZVAL_LONG(*newttl, (long)lnewttl); ++ } ++ RETURN_TRUE; ++} ++#else ++/* TODO: implement based on ldap_extended_operation_s() */ ++/* }}} */ ++#endif ++ ++/* {{{ arginfo */ ++ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_connect, 0, 0, 0) ++ ZEND_ARG_INFO(0, hostname) ++ ZEND_ARG_INFO(0, port) ++#ifdef HAVE_ORALDAP ++ ZEND_ARG_INFO(0, wallet) ++ ZEND_ARG_INFO(0, wallet_passwd) ++ ZEND_ARG_INFO(0, authmode) ++#endif ++ZEND_END_ARG_INFO() ++ ++ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_resource, 0, 0, 1) ++ ZEND_ARG_INFO(0, link_identifier) ++ZEND_END_ARG_INFO() ++ ++ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_bind, 0, 0, 1) ++ ZEND_ARG_INFO(0, link_identifier) ++ ZEND_ARG_INFO(0, bind_rdn) ++ ZEND_ARG_INFO(0, bind_password) ++ZEND_END_ARG_INFO() ++ ++#ifdef HAVE_LDAP_SASL ++ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_sasl_bind, 0, 0, 1) ++ ZEND_ARG_INFO(0, link) ++ ZEND_ARG_INFO(0, binddn) ++ ZEND_ARG_INFO(0, password) ++ ZEND_ARG_INFO(0, sasl_mech) ++ ZEND_ARG_INFO(0, sasl_realm) ++ ZEND_ARG_INFO(0, sasl_authz_id) ++ ZEND_ARG_INFO(0, props) ++ZEND_END_ARG_INFO() ++#endif ++ ++ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_read, 0, 0, 3) ++ ZEND_ARG_INFO(0, link_identifier) ++ ZEND_ARG_INFO(0, base_dn) ++ ZEND_ARG_INFO(0, filter) ++ ZEND_ARG_INFO(0, attributes) ++ ZEND_ARG_INFO(0, attrsonly) ++ ZEND_ARG_INFO(0, sizelimit) ++ ZEND_ARG_INFO(0, timelimit) ++ ZEND_ARG_INFO(0, deref) ++ZEND_END_ARG_INFO() + + ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_list, 0, 0, 3) + ZEND_ARG_INFO(0, link_identifier) + ZEND_ARG_INFO(0, base_dn) +@@ -3007,8 +4399,9 @@ + ZEND_ARG_INFO(1, errcode) + ZEND_ARG_INFO(1, matcheddn) + ZEND_ARG_INFO(1, errmsg) + ZEND_ARG_INFO(1, referrals) ++ ZEND_ARG_INFO(1, serverctrls) + ZEND_END_ARG_INFO() + #endif + #endif + +@@ -3027,8 +4420,40 @@ + ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_8859_to_t61, 0, 0, 1) + ZEND_ARG_INFO(0, value) + ZEND_END_ARG_INFO() + #endif ++ ++#ifdef HAVE_LDAP_EXTENDED_OPERATION_S ++ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_exop, 0, 0, 5) ++ ZEND_ARG_INFO(0, link) ++ ZEND_ARG_INFO(0, reqoid) ++ ZEND_ARG_INFO(1, reqdata) ++ ZEND_ARG_INFO(1, repoid) ++ ZEND_ARG_INFO(1, repdata) ++ZEND_END_ARG_INFO() ++ ++ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_exop_passwd, 0, 0, 5) ++ ZEND_ARG_INFO(0, link) ++ ZEND_ARG_INFO(1, user) ++ ZEND_ARG_INFO(1, oldpw) ++ ZEND_ARG_INFO(1, newpw) ++ ZEND_ARG_INFO(1, newpasswd) ++ZEND_END_ARG_INFO() ++ ++ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_exop_whoami, 0, 0, 2) ++ ZEND_ARG_INFO(0, link) ++ ZEND_ARG_INFO(1, authzid) ++ZEND_END_ARG_INFO() ++#endif ++ ++#ifdef HAVE_LDAP_REFRESH ++ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_refresh, 0, 0, 4) ++ ZEND_ARG_INFO(0, link) ++ ZEND_ARG_INFO(0, dn) ++ ZEND_ARG_INFO(1, ttl) ++ ZEND_ARG_INFO(0, newttl) ++ZEND_END_ARG_INFO() ++#endif + /* }}} */ + + /* + This is just a small subset of the functionality provided by the LDAP library. All the +@@ -3091,9 +4516,22 @@ + #endif + #ifdef HAVE_LDAP_START_TLS_S + PHP_FE(ldap_start_tls, arginfo_ldap_resource) + #endif ++#ifdef HAVE_LDAP_EXTENDED_OPERATION_S ++ PHP_FE(ldap_exop, ++ arginfo_ldap_exop) ++ PHP_FE(ldap_exop_passwd, ++ arginfo_ldap_exop_passwd) ++ PHP_FE(ldap_exop_whoami, ++ arginfo_ldap_exop_whoami) ++#endif ++#ifdef HAVE_LDAP_REFRESH ++ PHP_FE(ldap_refresh, ++ arginfo_ldap_refresh) + #endif ++#endif ++ + + #if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC) + PHP_FE(ldap_set_rebind_proc, arginfo_ldap_set_rebind_proc) + #endif +@@ -3102,8 +4540,33 @@ + PHP_FE(ldap_t61_to_8859, arginfo_ldap_t61_to_8859) + PHP_FE(ldap_8859_to_t61, arginfo_ldap_8859_to_t61) + #endif + ++/* routines to handle standard track controls, Pierangelo Masarati */ ++#ifdef LDAP_CONTROL_MANAGEDSAIT ++ PHP_FE(ldap_ctrl_manageDSAit, NULL) ++#endif ++#ifdef LDAP_CONTROL_PAGEDRESULTS ++ PHP_FE(ldap_ctrl_paged_results, NULL) /* fourth_arg_force_ref */ ++ PHP_FE(ldap_ctrl_paged_results_resp, NULL) /* arg3to4of4_force_ref */ ++#endif ++#ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST ++ PHP_FE(ldap_ctrl_ppolicy, NULL) ++ PHP_FE(ldap_ctrl_ppolicy_resp, NULL) /* arg3to6of6_force_ref */ ++#endif ++#ifdef LDAP_CONTROL_NOOP ++ PHP_FE(ldap_ctrl_noop, NULL) ++#endif ++#ifdef LDAP_CONTROL_MANAGEDIT ++ PHP_FE(ldap_ctrl_manageDIT, NULL) ++#endif ++#ifdef LDAP_CONTROL_X_PERMISSIVE_MODIFY ++ PHP_FE(ldap_ctrl_permissive_modify, NULL) ++#endif ++/* end of ando mod */ ++ ++ ++ + #ifdef LDAP_CONTROL_PAGEDRESULTS + PHP_FE(ldap_control_paged_result, arginfo_ldap_control_paged_result) + PHP_FE(ldap_control_paged_result_response, arginfo_ldap_control_paged_result_response) + #endif +@@ -3128,8 +4591,10 @@ + STANDARD_MODULE_PROPERTIES_EX + }; + /* }}} */ + ++ ++ + /* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 +--- ext/ldap/php_ldap.h.orig 2015-03-18 06:33:59.000000000 +0100 ++++ ext/ldap/php_ldap.h 2015-04-13 05:57:02.000000000 +0200 +@@ -28,16 +28,148 @@ + #endif + + #include <ldap.h> + ++#define HAVE_3ARG_SETREBINDPROC ++#define HAVE_LDAP_ADD_EXT_S ++#define HAVE_LDAP_MODIFY_EXT_S ++#define HAVE_LDAP_COMPARE_EXT_S ++#define HAVE_LDAP_DELETE_EXT_S ++#define HAVE_LDAP_PARSE_EXTENDED_RESULT ++#define HAVE_LDAP_PARSE_PASSWD ++#define HAVE_LDAP_PARSE_WHOAMI ++#define HAVE_LDAP_EXTENDED_OPERATION_S ++#define HAVE_LDAP_PASSWD_S ++#define HAVE_LDAP_WHOAMI_S ++#define HAVE_LDAP_REFRESH ++#define HAVE_LDAP_SASL ++#define HAVE_LDAP_EXTENDED_OPERATION_S ++#define HAVE_LDAP_REFRESH ++#define HAVE_LDAP_EXTENDED_OPERATION_S ++#define HAVE_LDAP_REFRESH ++#define HAVE_LDAP_EXTENDED_OPERATION ++ + extern zend_module_entry ldap_module_entry; + #define ldap_module_ptr &ldap_module_entry + + /* LDAP functions */ + PHP_MINIT_FUNCTION(ldap); + PHP_MSHUTDOWN_FUNCTION(ldap); + PHP_MINFO_FUNCTION(ldap); + ++#ifdef HAVE_LDAP_EXTENDED_OPERATION ++ ++#endif ++ ++#ifdef LDAP_CONTROL_MANAGEDSAIT ++/* RFC 3296 */ ++PHP_FUNCTION(ldap_ctrl_manageDSAit); ++#endif ++#ifdef LDAP_CONTROL_PROXY_AUTHZ ++/* <draft-weltman-ldapv3-proxy> (a Work in Progress) */ ++PHP_FUNCTION(ldap_ctrl_proxy_authz); ++#endif ++#ifdef LDAP_CONTROL_SUBENTRIES ++/* RFC 3672 */ ++PHP_FUNCTION(ldap_ctrl_subentries); ++#endif ++#ifdef LDAP_CONTROL_VALUESRETURNFILTER ++/* RFC 3876 */ ++PHP_FUNCTION(ldap_ctrl_vlv); ++#endif ++#ifdef LDAP_CONTROL_ASSERT ++/* <draft-zeilenga-ldap-assert> (a Work in Progress) */ ++PHP_FUNCTION(ldap_ctrl_assert); ++#endif ++#ifdef LDAP_CONTROL_PRE_READ ++/* <draft-zeilenga-ldap-readentry> (a Work in Progress) */ ++PHP_FUNCTION(ldap_ctrl_preread); ++PHP_FUNCTION(ldap_ctrl_postread); ++#endif ++#ifdef LDAP_CONTROL_SORTREQUEST ++/* RFC 2891 */ ++PHP_FUNCTION(ldap_ctrl_sort); ++PHP_FUNCTION(ldap_ctrl_sort_resp); ++#endif ++#ifdef LDAP_CONTROL_PAGEDRESULTS ++/* RFC 2696 */ ++PHP_FUNCTION(ldap_ctrl_paged_results); ++PHP_FUNCTION(ldap_ctrl_paged_results_resp); ++#endif ++#ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST ++/* <draft-behera-ldap-password-policy> (a Work in Progress) */ ++PHP_FUNCTION(ldap_ctrl_ppolicy); ++PHP_FUNCTION(ldap_ctrl_ppolicy_resp); ++#endif ++#ifdef LDAP_CONTROL_NOOP ++/* <draft-zeilenga-ldap-noop> (a Work in Progress) */ ++PHP_FUNCTION(ldap_ctrl_noop); ++#endif ++#ifdef LDAP_CONTROL_NO_SUBORDINATES ++/* don't know anything about it */ ++#endif ++#ifdef LDAP_CONTROL_MANAGEDIT ++/* no spec; partially implemented in OpenLDAP 2.3 */ ++PHP_FUNCTION(ldap_ctrl_manageDIT); ++#endif ++#ifdef LDAP_CONTROL_SLURP ++/* don't know anything about it */ ++#endif ++#ifdef LDAP_CONTROL_VALSORT ++/* <> */ ++PHP_FUNCTION(ldap_ctrl_valsort); ++#endif ++#ifdef LDAP_CONTROL_SYNC ++/* <draft-zeilenga-ldup-sync> (a Work in Progress) */ ++PHP_FUNCTION(ldap_ctrl_sync); ++PHP_FUNCTION(ldap_ctrl_sync_state); ++PHP_FUNCTION(ldap_ctrl_sync_done); ++/* TODO: need to handle the SYNC intermediate response message (LDAPIRM) */ ++#endif ++#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR ++/* <draft-sermersheim-ldap-chaining> (a Work in Progress) */ ++PHP_FUNCTION(ldap_ctrl_chaining); ++#endif ++#ifdef LDAP_CONTROL_X_INCREMENTAL_VALUES ++/* MS Active Directory */ ++PHP_FUNCTION(ldap_ctrl_incremental_values); ++#endif ++#ifdef LDAP_CONTROL_X_DOMAIN_SCOPE ++/* MS Active Directory */ ++PHP_FUNCTION(ldap_ctrl_domain_scope); ++#endif ++#ifdef LDAP_CONTROL_X_PERMISSIVE_MODIFY ++/* MS Active Directory */ ++PHP_FUNCTION(ldap_ctrl_permissive_modify); ++#endif ++#ifdef LDAP_CONTROL_X_SEARCH_OPTIONS ++/* MS Active Directory */ ++PHP_FUNCTION(ldap_ctrl_search_options); ++#endif ++#ifdef LDAP_CONTROL_X_TREE_DELETE ++/* MS Active Directory */ ++PHP_FUNCTION(ldap_ctrl_tree_delete); ++#endif ++#ifdef LDAP_CONTROL_X_EXTENDED_DN ++/* MS Active Directory */ ++PHP_FUNCTION(ldap_ctrl_extended_dn); ++#endif ++#ifdef LDAP_CONTROL_DUPENT ++/* <draft-ietf-ldapext-ldapv3-dupent> (a Work in Progress) */ ++PHP_FUNCTION(ldap_ctrl_dupent); ++PHP_FUNCTION(ldap_ctrl_dupent_resp); ++PHP_FUNCTION(ldap_ctrl_dupent_done_resp); ++#endif ++#ifdef LDAP_CONTROL_PERSIST_REQUEST ++/* ? */ ++#endif ++#ifdef LDAP_CONTROL_VLVREQUEST ++/* <draft-ietf-ldapext-ldapv3-vlv> (a Work in Progress) */ ++PHP_FUNCTION(ldap_ctrl_vlv); ++PHP_FUNCTION(ldap_ctrl_vlv_resp); ++#endif ++ ++ + ZEND_BEGIN_MODULE_GLOBALS(ldap) + long num_links; + long max_links; + ZEND_END_MODULE_GLOBALS(ldap) diff --git a/databases/php-ldap/files/ldap-ctrl-exop.patch b/databases/php-ldap/files/ldap-ctrl-exop55.patch index 3261200c435..d9569bfa05f 100755..100644 --- a/databases/php-ldap/files/ldap-ctrl-exop.patch +++ b/databases/php-ldap/files/ldap-ctrl-exop55.patch @@ -1,7 +1,7 @@ -$NetBSD: ldap-ctrl-exop.patch,v 1.3 2012/10/29 08:50:29 manu Exp $ +$NetBSD$ /* * Copyright (c) 2007-2009 Pierangelo Masarati - * Copyright (c) 2009,2012 Emmanuel Dreyfus + * Copyright (c) 2009,2015 Emmanuel Dreyfus * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,23 +24,8 @@ $NetBSD: ldap-ctrl-exop.patch,v 1.3 2012/10/29 08:50:29 manu Exp $ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ ---- ext/ldap/config.m4.orig 2012-10-25 10:15:34.000000000 +0200 -+++ ext/ldap/config.m4 2012-10-25 10:15:34.000000000 +0200 -@@ -172,9 +172,11 @@ - fi - - dnl Solaris 2.8 claims to be 2004 API, but doesn't have - dnl ldap_parse_reference() nor ldap_start_tls_s() -- AC_CHECK_FUNCS([ldap_parse_result ldap_parse_reference ldap_start_tls_s]) -+ AC_CHECK_FUNCS([ldap_parse_result ldap_parse_extended_result ldap_parse_whoami ldap_parse_passwd ldap_parse_reference]) -+ AC_CHECK_FUNCS([ldap_extended_operation_s ldap_start_tls_s ldap_whoami_s ldap_passwd_s]) -+ AC_CHECK_FUNCS([ldap_search_ext_s ldap_add_ext_s ldap_modify_ext_s ldap_delete_ext_s ldap_compare_ext_s]) - - dnl - dnl SASL check - dnl ---- ext/ldap/ldap.c.orig 2012-10-25 10:15:34.000000000 +0200 -+++ ext/ldap/ldap.c 2012-10-25 18:05:38.000000000 +0200 +--- ext/ldap/ldap.c.orig 2015-03-18 10:45:50.000000000 +0100 ++++ ext/ldap/ldap.c 2015-04-10 14:54:51.000000000 +0200 @@ -66,8 +66,13 @@ #elif defined(HAVE_LDAP_SASL_SASL_H) #include <sasl/sasl.h> @@ -104,7 +89,7 @@ $NetBSD: ldap-ctrl-exop.patch,v 1.3 2012/10/29 08:50:29 manu Exp $ { ldap_resultentry *entry = (ldap_resultentry *)rsrc->ptr; -@@ -194,8 +214,21 @@ +@@ -203,8 +223,21 @@ REGISTER_LONG_CONSTANT("GSLC_SSL_ONEWAY_AUTH", GSLC_SSL_ONEWAY_AUTH, CONST_PERSISTENT | CONST_CS); REGISTER_LONG_CONSTANT("GSLC_SSL_TWOWAY_AUTH", GSLC_SSL_TWOWAY_AUTH, CONST_PERSISTENT | CONST_CS); #endif @@ -126,7 +111,7 @@ $NetBSD: ldap-ctrl-exop.patch,v 1.3 2012/10/29 08:50:29 manu Exp $ le_result = zend_register_list_destructors_ex(_free_ldap_result, NULL, "ldap result", module_number); le_result_entry = zend_register_list_destructors_ex(_free_ldap_result_entry, NULL, "ldap result entry", module_number); -@@ -276,15 +309,176 @@ +@@ -285,15 +318,176 @@ DISPLAY_INI_ENTRIES(); } /* }}} */ @@ -304,7 +289,7 @@ $NetBSD: ldap-ctrl-exop.patch,v 1.3 2012/10/29 08:50:29 manu Exp $ char *wallet = NULL, *walletpasswd = NULL; int walletlen = 0, walletpasswdlen = 0; long authmode = GSLC_SSL_NO_AUTH; -@@ -318,23 +512,41 @@ +@@ -327,23 +521,41 @@ ld = ecalloc(1, sizeof(ldap_linkdata)); @@ -353,27 +338,28 @@ $NetBSD: ldap-ctrl-exop.patch,v 1.3 2012/10/29 08:50:29 manu Exp $ if (ldap == NULL) { efree(ld); RETURN_FALSE; -@@ -391,17 +603,32 @@ +@@ -429,17 +641,33 @@ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Password contains a null byte"); + RETURN_FALSE; } - ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link); - - if ((rc = ldap_bind_s(ld->link, ldap_bind_dn, ldap_bind_pw, LDAP_AUTH_SIMPLE)) != LDAP_SUCCESS) { +#ifdef LDAP_API_FEATURE_X_OPENLDAP + { -+ struct berval cred; ++ struct berval cred; + + /* ldap_bind_s() is deprecated; use ldap_sasl_bind_s() instead */ + cred.bv_val = ldap_bind_pw; + cred.bv_len = ldap_bind_pw ? ldap_bind_pwlen : 0; + rc = ldap_sasl_bind_s(ld->link, ldap_bind_dn, LDAP_SASL_SIMPLE, &cred, -+ NULL, NULL, /* no controls right now */ -+ NULL); /* we don't care about the server's credentials */ ++ NULL, NULL, /* no controls right now */ ++ NULL); /* we don't care about the server's credentials */ + } +#else + rc = ldap_bind_s(ld->link, ldap_bind_dn, ldap_bind_pw, LDAP_AUTH_SIMPLE); +#endif + if ( rc != LDAP_SUCCESS) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to bind to server: %s", ldap_err2string(rc)); RETURN_FALSE; } else { @@ -387,7 +373,7 @@ $NetBSD: ldap-ctrl-exop.patch,v 1.3 2012/10/29 08:50:29 manu Exp $ typedef struct { char *mech; char *realm; -@@ -524,8 +751,9 @@ +@@ -562,8 +790,9 @@ _php_sasl_freedefs(ctx); } /* }}} */ @@ -397,7 +383,7 @@ $NetBSD: ldap-ctrl-exop.patch,v 1.3 2012/10/29 08:50:29 manu Exp $ /* {{{ proto bool ldap_unbind(resource link) Unbind from LDAP directory */ PHP_FUNCTION(ldap_unbind) -@@ -1221,9 +1449,14 @@ +@@ -1259,9 +1488,14 @@ for (i = 0; i<count; i++) { add_index_string(return_value, i, ldap_value[i], 1); } @@ -412,7 +398,7 @@ $NetBSD: ldap-ctrl-exop.patch,v 1.3 2012/10/29 08:50:29 manu Exp $ /* }}} */ /* {{{ proto string ldap_dn2ufn(string dn) -@@ -1254,38 +1487,67 @@ +@@ -1292,38 +1526,67 @@ /* added to fix use of ldap_modify_add for doing an ldap_add, gerrit thomson. */ #define PHP_LD_FULL_ADD 0xff /* {{{ php_ldap_do_modify @@ -490,7 +476,7 @@ $NetBSD: ldap-ctrl-exop.patch,v 1.3 2012/10/29 08:50:29 manu Exp $ ldap_mods[i] = emalloc(sizeof(LDAPMod)); ldap_mods[i]->mod_op = oper | LDAP_MOD_BVALUES; ldap_mods[i]->mod_type = NULL; -@@ -1343,19 +1605,78 @@ +@@ -1381,19 +1644,78 @@ zend_hash_move_forward(Z_ARRVAL_P(entry)); } ldap_mods[num_attribs] = NULL; @@ -517,11 +503,6 @@ $NetBSD: ldap-ctrl-exop.patch,v 1.3 2012/10/29 08:50:29 manu Exp $ - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Add: %s", ldap_err2string(i)); - RETVAL_FALSE; - } else RETVAL_TRUE; -- } else { -- if ((i = ldap_modify_ext_s(ld->link, dn, ldap_mods, NULL, NULL)) != LDAP_SUCCESS) { -- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Modify: %s", ldap_err2string(i)); -- RETVAL_FALSE; -- } else RETVAL_TRUE; +#ifdef HAVE_LDAP_ADD_EXT_S + if (ext) { + rc = ldap_add_ext(ld->link, dn, ldap_mods, lsctrls, lcctrls, &msgid); @@ -533,7 +514,11 @@ $NetBSD: ldap-ctrl-exop.patch,v 1.3 2012/10/29 08:50:29 manu Exp $ + rc = ldap_add_s(ld->link, dn, ldap_mods); +#endif /* ! HAVE_LDAP_ADD_EXT_S */ + -+ } else { + } else { +- if ((i = ldap_modify_ext_s(ld->link, dn, ldap_mods, NULL, NULL)) != LDAP_SUCCESS) { +- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Modify: %s", ldap_err2string(i)); +- RETVAL_FALSE; +- } else RETVAL_TRUE; +#ifdef HAVE_LDAP_MODIFY_EXT_S + if (ext) { + rc = ldap_modify_ext(ld->link, dn, ldap_mods, lsctrls, lcctrls, &msgid); @@ -578,7 +563,7 @@ $NetBSD: ldap-ctrl-exop.patch,v 1.3 2012/10/29 08:50:29 manu Exp $ errexit: for (i = 0; i < num_attribs; i++) { -@@ -1368,46 +1689,57 @@ +@@ -1406,46 +1728,57 @@ } efree(num_berval); efree(ldap_mods); @@ -642,7 +627,7 @@ $NetBSD: ldap-ctrl-exop.patch,v 1.3 2012/10/29 08:50:29 manu Exp $ /* {{{ proto bool ldap_delete(resource link, string dn) Delete an entry from a directory */ PHP_FUNCTION(ldap_delete) -@@ -1482,38 +1814,109 @@ +@@ -1869,38 +2202,109 @@ RETURN_STRING(ldap_err2string(ld_errno), 1); } /* }}} */ @@ -741,7 +726,7 @@ $NetBSD: ldap-ctrl-exop.patch,v 1.3 2012/10/29 08:50:29 manu Exp $ +#else /* ! HAVE_LDAP_COMPARE_EXT_S */ + char *ldap_value; + -+ ldap_value = Z_STRVAL_PP(value); ++ ldap_value = Z_STRVAL_PP(&value); + rc = ldap_compare_s(ld->link, ldap_dn, ldap_attr, ldap_value); +#endif /* ! HAVE_LDAP_COMPARE_EXT_S */ + @@ -771,19 +756,19 @@ $NetBSD: ldap-ctrl-exop.patch,v 1.3 2012/10/29 08:50:29 manu Exp $ /* }}} */ /* {{{ proto bool ldap_sort(resource link, resource result, string sortfilter) -@@ -1545,59 +1948,230 @@ +@@ -1932,58 +2336,232 @@ RETURN_TRUE; } /* }}} */ --#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 +-#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP -/* {{{ proto bool ldap_get_option(resource link, int option, mixed retval) - Get the current value of various session-wide parameters */ -PHP_FUNCTION(ldap_get_option) +/* {{{ Extended API that returns result instead of just bool + * to allow further manipulation by the ldap_parse_*() funcs, + * Pierangelo Masarati */ -+ ++ +/* {{{ proto result ldap_bind_ext(resource link [, string dn, string password]) + Bind to LDAP directory */ +PHP_FUNCTION(ldap_bind_ext) @@ -798,9 +783,10 @@ $NetBSD: ldap-ctrl-exop.patch,v 1.3 2012/10/29 08:50:29 manu Exp $ - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rlz", &link, &option, &retval) != SUCCESS) { - return; + int rc, msgid, lerr; -+ LDAPMessage *ldap_res; -+ ++ LDAPMessage *ldap_res; ++ + 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) { ++ + RETURN_FALSE; } @@ -817,15 +803,15 @@ $NetBSD: ldap-ctrl-exop.patch,v 1.3 2012/10/29 08:50:29 manu Exp $ -#ifdef LDAP_OPT_RESTART - case LDAP_OPT_RESTART: +#ifdef LDAP_API_FEATURE_X_OPENLDAP -+ { -+ struct berval cred; -+ ++ { ++ struct berval cred; ++ + /* ldap_bind() is deprecated; use ldap_sasl_bind() instead */ + cred.bv_val = ldap_bind_pw; + cred.bv_len = ldap_bind_pw ? ldap_bind_pwlen : 0; -+ ++ + rc = ldap_sasl_bind(ld->link, ldap_bind_dn, LDAP_SASL_SIMPLE, &cred, -+ NULL, NULL, /* no controls right now */ ++ NULL, NULL, /* no controls right now */ + &msgid); + if (rc != LDAP_SUCCESS) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to bind: %s", ldap_err2string(rc)); @@ -841,12 +827,6 @@ $NetBSD: ldap-ctrl-exop.patch,v 1.3 2012/10/29 08:50:29 manu Exp $ #endif - { - int val; -+ -+ rc = ldap_result(ld->link, msgid, LDAP_MSG_ALL, NULL, &ldap_res); -+ if (rc != LDAP_RES_BIND) { -+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to get bind result: %s", ldap_err2string(rc)); -+ RETURN_FALSE; -+ } - if (ldap_get_option(ld->link, option, &val)) { - RETURN_FALSE; @@ -858,10 +838,10 @@ $NetBSD: ldap-ctrl-exop.patch,v 1.3 2012/10/29 08:50:29 manu Exp $ - case LDAP_OPT_NETWORK_TIMEOUT: - { - struct timeval *timeout = NULL; -+ ZEND_REGISTER_RESOURCE(return_value, ldap_res, le_result); -+ rc = ldap_parse_result(ld->link, ldap_res, &lerr, NULL, NULL, NULL, NULL, 0); -+ if (rc == LDAP_SUCCESS) { -+ rc = lerr; ++ rc = ldap_result(ld->link, msgid, LDAP_MSG_ALL, NULL, &ldap_res); ++ if (rc != LDAP_RES_BIND) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to get bind result: %s", ldap_err2string(rc)); ++ RETURN_FALSE; + } - if (ldap_get_option(ld->link, LDAP_OPT_NETWORK_TIMEOUT, (void *) &timeout)) { @@ -874,7 +854,13 @@ $NetBSD: ldap-ctrl-exop.patch,v 1.3 2012/10/29 08:50:29 manu Exp $ - RETURN_FALSE; - } - zval_dtor(retval); -- ZVAL_LONG(retval, timeout->tv_sec); ++ ZEND_REGISTER_RESOURCE(return_value, ldap_res, le_result); ++ rc = ldap_parse_result(ld->link, ldap_res, &lerr, NULL, NULL, NULL, NULL, 0); ++ if (rc == LDAP_SUCCESS) { ++ rc = lerr; ++ } ++ ++ + if (rc != LDAP_SUCCESS) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to bind to server: %s", ldap_err2string(rc)); + } @@ -897,12 +883,13 @@ $NetBSD: ldap-ctrl-exop.patch,v 1.3 2012/10/29 08:50:29 manu Exp $ +} +/* }}} */ + ++ +/* {{{ proto result ldap_mod_add_ext(resource link, string dn, array entry) + Add attribute values to current */ +PHP_FUNCTION(ldap_mod_add_ext) +{ + php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_ADD, 1); -+} ++} +/* }}} */ + +/* {{{ proto result ldap_mod_del_ext(resource link, string dn, array entry) @@ -910,7 +897,7 @@ $NetBSD: ldap-ctrl-exop.patch,v 1.3 2012/10/29 08:50:29 manu Exp $ +PHP_FUNCTION(ldap_mod_del_ext) +{ + php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_DELETE, 1); -+} ++} +/* }}} */ + +/* {{{ proto result ldap_delete_ext(resource link, string dn) @@ -1039,12 +1026,11 @@ $NetBSD: ldap-ctrl-exop.patch,v 1.3 2012/10/29 08:50:29 manu Exp $ + RETURN_FALSE; + } + zval_dtor(retval); -+ ZVAL_LONG(retval, timeout->tv_sec); + ZVAL_LONG(retval, timeout->tv_sec); ldap_memfree(timeout); } break; #elif defined(LDAP_X_OPT_CONNECT_TIMEOUT) - case LDAP_X_OPT_CONNECT_TIMEOUT: -@@ -1820,21 +2394,23 @@ +@@ -2207,21 +2785,23 @@ } /* }}} */ @@ -1067,13 +1053,13 @@ $NetBSD: ldap-ctrl-exop.patch,v 1.3 2012/10/29 08:50:29 manu Exp $ - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rrz|zzz", &link, &result, &errcode, &matcheddn, &errmsg, &referrals) != SUCCESS) { - return; -+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rrz|zzzz", &link, &result, &errcode, &matcheddn, &errmsg, &referrals, &serverctrls) != SUCCESS) { ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rrz|zzzz", &link, &result, &errcode, &matcheddn, &errmsg, &referrals, &serverctrls) != SUCCESS) { + WRONG_PARAM_COUNT; } ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link); ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, &result, -1, "ldap result", le_result); -@@ -1842,9 +2418,9 @@ +@@ -2229,9 +2809,9 @@ rc = ldap_parse_result(ld->link, ldap_result, &lerrcode, myargcount > 3 ? &lmatcheddn : NULL, myargcount > 4 ? &lerrmsg : NULL, @@ -1084,7 +1070,7 @@ $NetBSD: ldap-ctrl-exop.patch,v 1.3 2012/10/29 08:50:29 manu Exp $ if (rc != LDAP_SUCCESS) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to parse result: %s", ldap_err2string(rc)); RETURN_FALSE; -@@ -1854,19 +2430,15 @@ +@@ -2241,19 +2821,15 @@ ZVAL_LONG(errcode, lerrcode); /* Reverse -> fall through */ @@ -1110,7 +1096,7 @@ $NetBSD: ldap-ctrl-exop.patch,v 1.3 2012/10/29 08:50:29 manu Exp $ zval_dtor(errmsg); if (lerrmsg == NULL) { ZVAL_EMPTY_STRING(errmsg); -@@ -1887,8 +2459,142 @@ +@@ -2274,8 +2850,142 @@ } /* }}} */ #endif @@ -1253,7 +1239,7 @@ $NetBSD: ldap-ctrl-exop.patch,v 1.3 2012/10/29 08:50:29 manu Exp $ Return first reference */ PHP_FUNCTION(ldap_first_reference) { -@@ -2184,60 +2890,742 @@ +@@ -2758,54 +3468,736 @@ } /* }}} */ #endif @@ -1373,12 +1359,6 @@ $NetBSD: ldap-ctrl-exop.patch,v 1.3 2012/10/29 08:50:29 manu Exp $ -ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_list, 0, 0, 3) - ZEND_ARG_INFO(0, link_identifier) -- ZEND_ARG_INFO(0, base_dn) -- ZEND_ARG_INFO(0, filter) -- ZEND_ARG_INFO(0, attributes) -- ZEND_ARG_INFO(0, attrsonly) -- ZEND_ARG_INFO(0, sizelimit) -- ZEND_ARG_INFO(0, timelimit) + RETURN_TRUE; + } + @@ -2033,17 +2013,11 @@ $NetBSD: ldap-ctrl-exop.patch,v 1.3 2012/10/29 08:50:29 manu Exp $ + +ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_list, 0, 0, 3) + ZEND_ARG_INFO(0, link_identifier) -+ ZEND_ARG_INFO(0, base_dn) -+ ZEND_ARG_INFO(0, filter) -+ ZEND_ARG_INFO(0, attributes) -+ ZEND_ARG_INFO(0, attrsonly) -+ ZEND_ARG_INFO(0, sizelimit) -+ ZEND_ARG_INFO(0, timelimit) - ZEND_ARG_INFO(0, deref) - ZEND_END_ARG_INFO() - - ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_search, 0, 0, 3) -@@ -2411,8 +3799,9 @@ + ZEND_ARG_INFO(0, base_dn) + ZEND_ARG_INFO(0, filter) + ZEND_ARG_INFO(0, attributes) + ZEND_ARG_INFO(0, attrsonly) +@@ -3007,8 +4399,9 @@ ZEND_ARG_INFO(1, errcode) ZEND_ARG_INFO(1, matcheddn) ZEND_ARG_INFO(1, errmsg) @@ -2053,7 +2027,7 @@ $NetBSD: ldap-ctrl-exop.patch,v 1.3 2012/10/29 08:50:29 manu Exp $ #endif #endif -@@ -2431,8 +3820,40 @@ +@@ -3027,8 +4420,40 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_8859_to_t61, 0, 0, 1) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() @@ -2094,7 +2068,7 @@ $NetBSD: ldap-ctrl-exop.patch,v 1.3 2012/10/29 08:50:29 manu Exp $ /* This is just a small subset of the functionality provided by the LDAP library. All the -@@ -2494,10 +3915,23 @@ +@@ -3091,9 +4516,22 @@ #endif #ifdef HAVE_LDAP_START_TLS_S PHP_FE(ldap_start_tls, arginfo_ldap_resource) @@ -2110,49 +2084,48 @@ $NetBSD: ldap-ctrl-exop.patch,v 1.3 2012/10/29 08:50:29 manu Exp $ +#ifdef HAVE_LDAP_REFRESH + PHP_FE(ldap_refresh, + arginfo_ldap_refresh) -+#endif #endif - ++#endif + + #if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC) PHP_FE(ldap_set_rebind_proc, arginfo_ldap_set_rebind_proc) #endif - -@@ -2505,8 +3939,33 @@ +@@ -3102,8 +4540,33 @@ PHP_FE(ldap_t61_to_8859, arginfo_ldap_t61_to_8859) PHP_FE(ldap_8859_to_t61, arginfo_ldap_8859_to_t61) #endif +/* routines to handle standard track controls, Pierangelo Masarati */ +#ifdef LDAP_CONTROL_MANAGEDSAIT -+ PHP_FE(ldap_ctrl_manageDSAit, NULL) ++ PHP_FE(ldap_ctrl_manageDSAit, NULL) +#endif +#ifdef LDAP_CONTROL_PAGEDRESULTS -+ PHP_FE(ldap_ctrl_paged_results, NULL) /* fourth_arg_force_ref */ -+ PHP_FE(ldap_ctrl_paged_results_resp, NULL) /* arg3to4of4_force_ref */ ++ PHP_FE(ldap_ctrl_paged_results, NULL) /* fourth_arg_force_ref */ ++ PHP_FE(ldap_ctrl_paged_results_resp, NULL) /* arg3to4of4_force_ref */ +#endif +#ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST -+ PHP_FE(ldap_ctrl_ppolicy, NULL) -+ PHP_FE(ldap_ctrl_ppolicy_resp, NULL) /* arg3to6of6_force_ref */ ++ PHP_FE(ldap_ctrl_ppolicy, NULL) ++ PHP_FE(ldap_ctrl_ppolicy_resp, NULL) /* arg3to6of6_force_ref */ +#endif +#ifdef LDAP_CONTROL_NOOP -+ PHP_FE(ldap_ctrl_noop, NULL) ++ PHP_FE(ldap_ctrl_noop, NULL) +#endif +#ifdef LDAP_CONTROL_MANAGEDIT -+ PHP_FE(ldap_ctrl_manageDIT, NULL) ++ PHP_FE(ldap_ctrl_manageDIT, NULL) +#endif +#ifdef LDAP_CONTROL_X_PERMISSIVE_MODIFY -+ PHP_FE(ldap_ctrl_permissive_modify, NULL) ++ PHP_FE(ldap_ctrl_permissive_modify, NULL) +#endif +/* end of ando mod */ + + + - PHP_FE_END - }; - /* }}} */ - -@@ -2527,8 +3986,10 @@ + #ifdef LDAP_CONTROL_PAGEDRESULTS + PHP_FE(ldap_control_paged_result, arginfo_ldap_control_paged_result) + PHP_FE(ldap_control_paged_result_response, arginfo_ldap_control_paged_result_response) + #endif +@@ -3128,8 +4591,10 @@ STANDARD_MODULE_PROPERTIES_EX }; /* }}} */ @@ -2163,9 +2136,36 @@ $NetBSD: ldap-ctrl-exop.patch,v 1.3 2012/10/29 08:50:29 manu Exp $ * Local variables: * tab-width: 4 * c-basic-offset: 4 ---- ext/ldap/php_ldap.h.orig 2012-10-25 10:15:34.000000000 +0200 -+++ ext/ldap/php_ldap.h 2012-10-25 10:15:34.000000000 +0200 -@@ -36,8 +36,121 @@ +--- ext/ldap/php_ldap.h.orig 2015-03-18 10:45:50.000000000 +0100 ++++ ext/ldap/php_ldap.h 2015-04-12 11:22:11.000000000 +0200 +@@ -28,16 +28,148 @@ + #endif + + #include <ldap.h> + ++#define HAVE_3ARG_SETREBINDPROC ++#define HAVE_LDAP_ADD_EXT_S ++#define HAVE_LDAP_MODIFY_EXT_S ++#define HAVE_LDAP_COMPARE_EXT_S ++#define HAVE_LDAP_DELETE_EXT_S ++#define HAVE_LDAP_PARSE_EXTENDED_RESULT ++#define HAVE_LDAP_PARSE_PASSWD ++#define HAVE_LDAP_PARSE_WHOAMI ++#define HAVE_LDAP_EXTENDED_OPERATION_S ++#define HAVE_LDAP_PASSWD_S ++#define HAVE_LDAP_WHOAMI_S ++#define HAVE_LDAP_REFRESH ++#define HAVE_LDAP_SASL ++#define HAVE_LDAP_EXTENDED_OPERATION_S ++#define HAVE_LDAP_REFRESH ++#define HAVE_LDAP_EXTENDED_OPERATION_S ++#define HAVE_LDAP_REFRESH ++#define HAVE_LDAP_EXTENDED_OPERATION ++ + extern zend_module_entry ldap_module_entry; + #define ldap_module_ptr &ldap_module_entry + + /* LDAP functions */ PHP_MINIT_FUNCTION(ldap); PHP_MSHUTDOWN_FUNCTION(ldap); PHP_MINFO_FUNCTION(ldap); diff --git a/databases/php-ldap/files/ldap-ctrl-exop56.patch b/databases/php-ldap/files/ldap-ctrl-exop56.patch new file mode 100644 index 00000000000..0bf6b06da82 --- /dev/null +++ b/databases/php-ldap/files/ldap-ctrl-exop56.patch @@ -0,0 +1,2263 @@ +--- ext/ldap/ldap.c.orig 2015-03-19 01:19:30.000000000 +0100 ++++ ext/ldap/ldap.c 2015-04-13 05:51:05.000000000 +0200 +@@ -66,8 +66,13 @@ + #elif defined(HAVE_LDAP_SASL_SASL_H) + #include <sasl/sasl.h> + #endif + ++/* XXX Not detected by configure... */ ++#ifdef LDAP_EXOP_REFRESH ++#define HAVE_LDAP_REFRESH 1 ++#endif ++ + #define PHP_LDAP_ESCAPE_FILTER 0x01 + #define PHP_LDAP_ESCAPE_DN 0x02 + + typedef struct { +@@ -91,31 +96,46 @@ + #ifdef COMPILE_DL_LDAP + ZEND_GET_MODULE(ldap) + #endif + ++ ++/* {{{ proto void _close_ldap_link() ++ close a connection and free LDAP resources */ + static void _close_ldap_link(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */ + { + ldap_linkdata *ld = (ldap_linkdata *)rsrc->ptr; + +- ldap_unbind_s(ld->link); +-#if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC) ++ /* ldap_unbind_s() is deprecated; ++ * the distinction between ldap_unbind() and ldap_unbind_s() is moot */ ++#ifdef LDAP_API_FEATURE_X_OPENLDAP ++ ldap_unbind_ext(ld->link, NULL, NULL); ++#ifdef HAVE_3ARG_SETREBINDPROC ++ + if (ld->rebindproc != NULL) { + zval_dtor(ld->rebindproc); + FREE_ZVAL(ld->rebindproc); + } + #endif ++#else /* ! LDAP_API_FEATURE_X_OPENLDAP */ ++ ldap_unbind_s(ld->link); ++#endif /* ! LDAP_API_FEATURE_X_OPENLDAP */ ++ + efree(ld); + LDAPG(num_links)--; + } + /* }}} */ + ++/* {{{ proto void _free_ldap_result() ++ free the result of an LDAP operation */ + static void _free_ldap_result(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */ + { + LDAPMessage *result = (LDAPMessage *)rsrc->ptr; + ldap_msgfree(result); + } + /* }}} */ + ++/* {{{ proto void _free_ldap_result_entry() ++ free an entry resulting from an LDAP search operation */ + static void _free_ldap_result_entry(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */ + { + ldap_resultentry *entry = (ldap_resultentry *)rsrc->ptr; + +@@ -206,8 +226,21 @@ + REGISTER_LONG_CONSTANT("GSLC_SSL_ONEWAY_AUTH", GSLC_SSL_ONEWAY_AUTH, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("GSLC_SSL_TWOWAY_AUTH", GSLC_SSL_TWOWAY_AUTH, CONST_PERSISTENT | CONST_CS); + #endif + ++#ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST ++ REGISTER_LONG_CONSTANT("PP_passwordExpired", PP_passwordExpired, CONST_PERSISTENT | CONST_CS); ++ REGISTER_LONG_CONSTANT("PP_accountLocked", PP_accountLocked, CONST_PERSISTENT | CONST_CS); ++ REGISTER_LONG_CONSTANT("PP_changeAfterReset", PP_changeAfterReset, CONST_PERSISTENT | CONST_CS); ++ REGISTER_LONG_CONSTANT("PP_passwordModNotAllowed", PP_passwordModNotAllowed, CONST_PERSISTENT | CONST_CS); ++ REGISTER_LONG_CONSTANT("PP_mustSupplyOldPassword", PP_mustSupplyOldPassword, CONST_PERSISTENT | CONST_CS); ++ REGISTER_LONG_CONSTANT("PP_insufficientPasswordQuality", PP_insufficientPasswordQuality, CONST_PERSISTENT | CONST_CS); ++ REGISTER_LONG_CONSTANT("PP_passwordTooShort", PP_passwordTooShort, CONST_PERSISTENT | CONST_CS); ++ REGISTER_LONG_CONSTANT("PP_passwordTooYoung", PP_passwordTooYoung, CONST_PERSISTENT | CONST_CS); ++ REGISTER_LONG_CONSTANT("PP_passwordInHistory", PP_passwordInHistory, CONST_PERSISTENT | CONST_CS); ++ REGISTER_LONG_CONSTANT("PP_noError", PP_noError, CONST_PERSISTENT | CONST_CS); ++#endif /* LDAP_CONTROL_PASSWORDPOLICYREQUEST */ ++ + REGISTER_LONG_CONSTANT("LDAP_ESCAPE_FILTER", PHP_LDAP_ESCAPE_FILTER, CONST_PERSISTENT | CONST_CS); + REGISTER_LONG_CONSTANT("LDAP_ESCAPE_DN", PHP_LDAP_ESCAPE_DN, CONST_PERSISTENT | CONST_CS); + + le_link = zend_register_list_destructors_ex(_close_ldap_link, NULL, "ldap link", module_number); +@@ -291,15 +324,176 @@ + DISPLAY_INI_ENTRIES(); + } + /* }}} */ + ++ ++/* {{{ proto int _php_parse_referrals_resp() ++ parse an array of LDAP referrals into a zval array */ ++static int _php_parse_referrals_resp(char ***lreferralsp, zval **referrals) ++{ ++ int num_referrals = 0; ++ ++ if (*lreferralsp != NULL) { ++ char **refp = *lreferralsp; ++ ++ while (*refp) { ++ add_next_index_string(*referrals, *refp, 1); ++ refp++; ++ num_referrals++; ++ } ++#ifdef LDAP_API_FEATURE_X_OPENLDAP ++ ber_memvfree((void **)*lreferralsp); ++#else ++ ldap_value_free(*lreferralsp); ++#endif ++ *lreferralsp = NULL; ++ } ++ ++ return num_referrals; ++} ++/* }}} */ ++ ++/* {{{ proto int _php_parse_controls() ++ parse an array of zvals into an array of LDAP controls */ ++static int _php_parse_controls(zval **ctrls, LDAPControl ***lctrlsp) ++{ ++ LDAPControl *lctrl, **lctrls, **lctrlp; ++ zval **ctrlval, **val; ++ int ncontrols; ++ char error = 0; ++ ++ ++ if ((Z_TYPE_PP(ctrls) != IS_ARRAY) || !(ncontrols = zend_hash_num_elements(Z_ARRVAL_PP(ctrls)))) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expected non-empty array value"); ++ return 0; ++ } ++ ++ lctrls = safe_emalloc((1 + ncontrols), sizeof(*lctrls), 0); ++ *lctrls = NULL; ++ lctrlp = lctrls; ++ zend_hash_internal_pointer_reset(Z_ARRVAL_PP(ctrls)); ++ while (zend_hash_get_current_data(Z_ARRVAL_PP(ctrls), (void**)&ctrlval) == SUCCESS) { ++ if (Z_TYPE_PP(ctrlval) != IS_ARRAY) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "The array value must contain only arrays, where each array is a control"); ++ error = 1; ++ break; ++ } ++ if (zend_hash_find(Z_ARRVAL_PP(ctrlval), "oid", sizeof("oid"), (void **) &val) == FAILURE) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Control must have an oid key"); ++ error = 1; ++ break; ++ } ++ lctrl = *lctrlp = emalloc(sizeof(**lctrlp)); ++ convert_to_string_ex(val); ++ lctrl->ldctl_oid = Z_STRVAL_PP(val); ++ if (zend_hash_find(Z_ARRVAL_PP(ctrlval), "value", sizeof("value"), (void **) &val) == SUCCESS) { ++ convert_to_string_ex(val); ++ lctrl->ldctl_value.bv_val = Z_STRVAL_PP(val); ++ lctrl->ldctl_value.bv_len = Z_STRLEN_PP(val); ++ } else { ++ lctrl->ldctl_value.bv_val = NULL; ++ lctrl->ldctl_value.bv_len = 0; ++ } ++ if (zend_hash_find(Z_ARRVAL_PP(ctrlval), "iscritical", sizeof("iscritical"), (void **) &val) == SUCCESS) { ++ convert_to_boolean_ex(val); ++ lctrl->ldctl_iscritical = Z_BVAL_PP(val); ++ } else { ++ lctrl->ldctl_iscritical = 0; ++ } ++ ++ ++lctrlp; ++ *lctrlp = NULL; ++ zend_hash_move_forward(Z_ARRVAL_PP(ctrls)); ++ } ++ if (!error) { ++ *lctrlsp = lctrls; ++ } ++ return ncontrols; ++} ++/* }}} */ ++ ++/* {{{ proto void _php_free_controls() ++ frees an array of LDAP controls as parsed (and malloc'ed) by _php_parse_controls */ ++static void _php_free_controls(LDAPControl ***lctrlsp) ++{ ++ LDAPControl **lctrlp; ++ ++ for (lctrlp = *lctrlsp; *lctrlp; lctrlp++) { ++ efree(*lctrlp); ++ } ++ efree(*lctrlsp); ++ *lctrlsp = NULL; ++} ++/* }}} */ ++ ++/* {{{ proto void _php_parse_controls_resp() ++ parse an array of LDAP controls into a zval array */ ++static int _php_parse_controls_resp(LDAPControl ***lctrlsp, zval **ctrls) ++{ ++ int num_ctrls = 0; ++ ++ if (*lctrlsp != NULL) { ++ int error = 0; ++ LDAPControl **ctrlp = *lctrlsp; ++ ++ while (*ctrlp) { ++ zval *ctrlval = NULL; ++ ++ if ( (*ctrlp)->ldctl_oid == NULL ) { ++ error = 1; ++ break; ++ } ++ ++ MAKE_STD_ZVAL(ctrlval); ++ array_init(ctrlval); ++ ++ add_assoc_string(ctrlval, "oid", (*ctrlp)->ldctl_oid, 1); ++ if ( (*ctrlp)->ldctl_value.bv_len ) { ++ add_assoc_stringl(ctrlval, "value", (*ctrlp)->ldctl_value.bv_val, (*ctrlp)->ldctl_value.bv_len, 1); ++ } ++ ++ /* As per <draft-ietf-ldapbis-protocol>: ++ * ++ * 4.1.11 ++ ++ The criticality field only has meaning in controls attached to ++ request messages (except UnbindRequest). For controls attached to ++ response messages and the UnbindRequest, the criticality field SHOULD ++ be FALSE, and MUST be ignored by the receiving protocol peer. ++ ++ */ ++ ++ add_next_index_zval(*ctrls, ctrlval); ++ ++ num_ctrls++; ++ ctrlp++; ++ } ++ ldap_controls_free(*lctrlsp); ++ *lctrlsp = NULL; ++ ++ if (error) { ++ /* ... */ ++ return -1; ++ } ++ } ++ ++ return num_ctrls; ++} ++/* }}} */ ++ + /* {{{ proto resource ldap_connect([string host [, int port [, string wallet [, string wallet_passwd [, int authmode]]]]]) + Connect to an LDAP server */ + PHP_FUNCTION(ldap_connect) + { + char *host = NULL; + int hostlen; +- long port = 389; /* Default port */ ++ int port = ++#ifdef LDAP_API_FEATURE_X_OPENLDAP ++ LDAP_PORT ++#else /* ! LDAP_API_FEATURE_X_OPENLDAP */ ++ 389 /* Default port */ ++#endif /* ! LDAP_API_FEATURE_X_OPENLDAP */ ++ ; + #ifdef HAVE_ORALDAP + char *wallet = NULL, *walletpasswd = NULL; + int walletlen = 0, walletpasswdlen = 0; + long authmode = GSLC_SSL_NO_AUTH; +@@ -333,23 +527,41 @@ + + ld = ecalloc(1, sizeof(ldap_linkdata)); + + #ifdef LDAP_API_FEATURE_X_OPENLDAP +- if (host != NULL && strchr(host, '/')) { +- int rc; ++ /* OpenLDAP provides a specific call to detect valid LDAP URIs; ++ * ldap_init()/ldap_open() is deprecated, use ldap_initialize() instead. ++ */ ++ { ++ int rc; ++ char *url = host; ++ ++ if (!ldap_is_ldap_url(url)) { ++ int urllen = hostlen + sizeof( "ldap://:65535" ); ++ ++ if (port <= 0 || port > 65535) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid port number: %ld", port); ++ RETURN_FALSE; ++ } ++ ++ url = emalloc(urllen); ++ snprintf( url, urllen, "ldap://%s:%d", host ? host : "", port ); ++ } + +- rc = ldap_initialize(&ldap, host); ++ rc = ldap_initialize(&ldap, url); + if (rc != LDAP_SUCCESS) { + efree(ld); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not create session handle: %s", ldap_err2string(rc)); + RETURN_FALSE; + } +- } else { +- ldap = ldap_init(host, port); ++ ++ if (url != host) { ++ efree(url); ++ } + } +-#else ++#else /* ! LDAP_API_FEATURE_X_OPENLDAP */ + ldap = ldap_open(host, port); +-#endif ++#endif /* ! LDAP_API_FEATURE_X_OPENLDAP */ + + if (ldap == NULL) { + efree(ld); + RETURN_FALSE; +@@ -435,17 +647,33 @@ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Password contains a null byte"); + RETURN_FALSE; + } + +- if ((rc = ldap_bind_s(ld->link, ldap_bind_dn, ldap_bind_pw, LDAP_AUTH_SIMPLE)) != LDAP_SUCCESS) { ++#ifdef LDAP_API_FEATURE_X_OPENLDAP ++ { ++ struct berval cred; ++ ++ /* ldap_bind_s() is deprecated; use ldap_sasl_bind_s() instead */ ++ cred.bv_val = ldap_bind_pw; ++ cred.bv_len = ldap_bind_pw ? ldap_bind_pwlen : 0; ++ rc = ldap_sasl_bind_s(ld->link, ldap_bind_dn, LDAP_SASL_SIMPLE, &cred, ++ NULL, NULL, /* no controls right now */ ++ NULL); /* we don't care about the server's credentials */ ++ } ++#else ++ rc = ldap_bind_s(ld->link, ldap_bind_dn, ldap_bind_pw, LDAP_AUTH_SIMPLE); ++#endif ++ if ( rc != LDAP_SUCCESS) { ++ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to bind to server: %s", ldap_err2string(rc)); + RETURN_FALSE; + } else { + RETURN_TRUE; + } + } + /* }}} */ + ++/* {{{ SASL bind stuff */ + #ifdef HAVE_LDAP_SASL + typedef struct { + char *mech; + char *realm; +@@ -568,8 +796,9 @@ + _php_sasl_freedefs(ctx); + } + /* }}} */ + #endif /* HAVE_LDAP_SASL */ ++/* }}} */ + + /* {{{ proto bool ldap_unbind(resource link) + Unbind from LDAP directory */ + PHP_FUNCTION(ldap_unbind) +@@ -1265,9 +1494,14 @@ + for (i = 0; i<count; i++) { + add_index_string(return_value, i, ldap_value[i], 1); + } + ++#ifdef LDAP_API_FEATURE_X_OPENLDAP ++ /* ldap_value_free() is deprecated */ ++ ber_memvfree((void **)ldap_value); ++#else /* ! LDAP_API_FEATURE_X_OPENLDAP */ + ldap_value_free(ldap_value); ++#endif /* ! LDAP_API_FEATURE_X_OPENLDAP */ + } + /* }}} */ + + /* {{{ proto string ldap_dn2ufn(string dn) +@@ -1298,38 +1532,67 @@ + /* added to fix use of ldap_modify_add for doing an ldap_add, gerrit thomson. */ + #define PHP_LD_FULL_ADD 0xff + /* {{{ php_ldap_do_modify + */ +-static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper) ++static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper, int ext) + { +- zval *link, *entry, **value, **ivalue; ++ zval *link, *entry, **value, **ivalue, **sctrls, **cctrls; + ldap_linkdata *ld; + char *dn; + LDAPMod **ldap_mods; + int i, j, num_attribs, num_values, dn_len; + int *num_berval; + char *attribute; + ulong index; + int is_full_add=0; /* flag for full add operation so ldap_mod_add can be put back into oper, gerrit THomson */ ++ int rc, msgid, myargcount = ZEND_NUM_ARGS(); ++ LDAPMessage *ldap_res; ++ LDAPControl **lsctrls = NULL, **lcctrls = NULL; ++ if (ext) { ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsaZZ", &link, &dn, &dn_len, &entry, &sctrls, &cctrls) != SUCCESS) ++ WRONG_PARAM_COUNT; ++ } else { ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsa", &link, &dn, &dn_len, &entry) != SUCCESS) ++ WRONG_PARAM_COUNT; ++ } + +- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsa", &link, &dn, &dn_len, &entry) != SUCCESS) { +- return; +- } ++ if (Z_TYPE_PP(&entry) != IS_ARRAY) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expected Array as the last element"); ++ RETURN_FALSE; ++ } + +- ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link); + +- num_attribs = zend_hash_num_elements(Z_ARRVAL_P(entry)); +- ldap_mods = safe_emalloc((num_attribs+1), sizeof(LDAPMod *), 0); +- num_berval = safe_emalloc(num_attribs, sizeof(int), 0); +- zend_hash_internal_pointer_reset(Z_ARRVAL_P(entry)); + + /* added by gerrit thomson to fix ldap_add using ldap_mod_add */ + if (oper == PHP_LD_FULL_ADD) { + oper = LDAP_MOD_ADD; + is_full_add = 1; + } + /* end additional , gerrit thomson */ + ++ if (myargcount > 3) { ++ if (is_full_add) { ++#ifndef HAVE_LDAP_ADD_EXT_S ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "ldap_add_ext not available"); ++ RETURN_FALSE; ++#endif /* ! HAVE_LDAP_ADD_EXT_S */ ++ ++ } else { ++#ifndef HAVE_LDAP_MODIFY_EXT_S ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "ldap_modify_ext not available"); ++ RETURN_FALSE; ++#endif /* ! HAVE_LDAP_MODIFY_EXT_S */ ++ } ++ } ++ ++ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link); ++ ++ num_attribs = zend_hash_num_elements(Z_ARRVAL_P(entry)); ++ ldap_mods = safe_emalloc((num_attribs+1), sizeof(LDAPMod *), 0); ++ num_berval = safe_emalloc(num_attribs, sizeof(int), 0); ++ zend_hash_internal_pointer_reset(Z_ARRVAL_P(entry)); ++ ++ + for (i = 0; i < num_attribs; i++) { + ldap_mods[i] = emalloc(sizeof(LDAPMod)); + ldap_mods[i]->mod_op = oper | LDAP_MOD_BVALUES; + ldap_mods[i]->mod_type = NULL; +@@ -1387,19 +1650,78 @@ + zend_hash_move_forward(Z_ARRVAL_P(entry)); + } + ldap_mods[num_attribs] = NULL; + ++ if (ext) { ++ switch (myargcount) { ++ case 5: ++ if (_php_parse_controls(cctrls, &lcctrls) == 0) { ++ RETVAL_FALSE; ++ goto errexit; ++ } ++ ++ case 4: ++ if (_php_parse_controls(sctrls, &lsctrls) == 0) { ++ RETVAL_FALSE; ++ goto errexit; ++ } ++ } ++ } ++ + /* check flag to see if do_mod was called to perform full add , gerrit thomson */ + if (is_full_add == 1) { +- if ((i = ldap_add_s(ld->link, dn, ldap_mods)) != LDAP_SUCCESS) { +- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Add: %s", ldap_err2string(i)); +- RETVAL_FALSE; +- } else RETVAL_TRUE; ++#ifdef HAVE_LDAP_ADD_EXT_S ++ if (ext) { ++ rc = ldap_add_ext(ld->link, dn, ldap_mods, lsctrls, lcctrls, &msgid); ++ ++ } else { ++ rc = ldap_add_ext_s(ld->link, dn, ldap_mods, NULL, NULL); ++ } ++#else /* ! HAVE_LDAP_ADD_EXT_S */ ++ rc = ldap_add_s(ld->link, dn, ldap_mods); ++#endif /* ! HAVE_LDAP_ADD_EXT_S */ ++ + } else { +- if ((i = ldap_modify_ext_s(ld->link, dn, ldap_mods, NULL, NULL)) != LDAP_SUCCESS) { +- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Modify: %s", ldap_err2string(i)); +- RETVAL_FALSE; +- } else RETVAL_TRUE; ++#ifdef HAVE_LDAP_MODIFY_EXT_S ++ if (ext) { ++ rc = ldap_modify_ext(ld->link, dn, ldap_mods, lsctrls, lcctrls, &msgid); ++ ++ } else { ++ rc = ldap_modify_ext_s(ld->link, dn, ldap_mods, NULL, NULL); ++ } ++#else /* ! HAVE_LDAP_MODIFY_EXT_S */ ++ rc = ldap_modify_s(ld->link, dn, ldap_mods); ++#endif /* ! HAVE_LDAP_MODIFY_EXT_S */ ++ } ++ ++ if (rc != LDAP_SUCCESS) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s: %s", is_full_add ? "Add" : "Modify", ldap_err2string(i)); ++ RETVAL_FALSE; ++ ++ } else { ++ if (ext) { ++ rc = ldap_result(ld->link, msgid, LDAP_MSG_ALL, NULL, &ldap_res); ++ if ((is_full_add && rc != LDAP_RES_ADD) || (!is_full_add && rc != LDAP_RES_MODIFY)) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s: unable to collect result", is_full_add ? "Add" : "Modify"); ++ RETVAL_FALSE; ++ ++ } else { ++ int lerr; ++ ++ ZEND_REGISTER_RESOURCE(return_value, ldap_res, le_result); ++ rc = ldap_parse_result(ld->link, ldap_res, &lerr, NULL, NULL, NULL, NULL, 0); ++ if (rc == LDAP_SUCCESS) { ++ rc = lerr; ++ } ++ ++ if (rc != LDAP_SUCCESS) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s failed: %s", is_full_add ? "Add" : "Modify", ldap_err2string(rc)); ++ } ++ } ++ ++ } else { ++ RETVAL_TRUE; ++ } + } + + errexit: + for (i = 0; i < num_attribs; i++) { +@@ -1412,46 +1734,57 @@ + } + efree(num_berval); + efree(ldap_mods); + ++ if (ext) { ++ if (lsctrls) { ++ _php_free_controls(&lsctrls); ++ } ++ if (lcctrls) { ++ _php_free_controls(&lcctrls); ++ } ++ } ++ + return; + } + /* }}} */ + + /* {{{ proto bool ldap_add(resource link, string dn, array entry) + Add entries to LDAP directory */ + PHP_FUNCTION(ldap_add) + { +- /* 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 */ +- php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_LD_FULL_ADD); ++ /* 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 */ ++ php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_LD_FULL_ADD, 0); + } + /* }}} */ + +-/* three functions for attribute base modifications, gerrit Thomson */ ++/* {{{ Three functions for attribute base modifications, gerrit Thomson */ + + /* {{{ proto bool ldap_mod_replace(resource link, string dn, array entry) + Replace attribute values with new ones */ + PHP_FUNCTION(ldap_mod_replace) + { +- php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_REPLACE); ++ php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_REPLACE, 0); + } + /* }}} */ + + /* {{{ proto bool ldap_mod_add(resource link, string dn, array entry) + Add attribute values to current */ + PHP_FUNCTION(ldap_mod_add) + { +- php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_ADD); ++ php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_ADD, 0); + } + /* }}} */ + + /* {{{ proto bool ldap_mod_del(resource link, string dn, array entry) ++ + Delete attribute values */ + PHP_FUNCTION(ldap_mod_del) + { +- php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_DELETE); ++ php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_DELETE, 0); + } + /* }}} */ ++/* }}} */ + + /* {{{ proto bool ldap_delete(resource link, string dn) + Delete an entry from a directory */ + PHP_FUNCTION(ldap_delete) +@@ -1875,38 +2208,109 @@ + RETURN_STRING(ldap_err2string(ld_errno), 1); + } + /* }}} */ + +-/* {{{ proto bool ldap_compare(resource link, string dn, string attr, string value) +- Determine if an entry has a specific value for one of its attributes */ +-PHP_FUNCTION(ldap_compare) ++/* {{{ proto void php_ldap_do_compare */ ++void php_ldap_do_compare(INTERNAL_FUNCTION_PARAMETERS, int ext) + { +- zval *link; +- char *dn, *attr, *value; ++ zval *link, *dn, *attr, *value, **sctrls, **cctrls; ++ char *ldap_dn, *ldap_attr; + int dn_len, attr_len, value_len; + ldap_linkdata *ld; +- int errno; ++ int rc, msgid, lerr, myargcount = ZEND_NUM_ARGS(); ++ LDAPMessage *ldap_res; ++ LDAPControl **lsctrls = NULL, **lcctrls = NULL; + +- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsss", &link, &dn, &dn_len, &attr, &attr_len, &value, &value_len) != SUCCESS) { +- return; ++ if (ext) { ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsss|ZZ", &link, &dn, &dn_len, &attr, &attr_len, &value, &value_len, &sctrls, &cctrls) != SUCCESS) { ++ WRONG_PARAM_COUNT; ++ } ++ } else { ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsss", &link, &dn, &dn_len, &attr, &attr_len, &value, &value_len) != SUCCESS) { ++ WRONG_PARAM_COUNT; ++ } + } + + ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link); + +- errno = ldap_compare_s(ld->link, dn, attr, value); +- +- switch (errno) { +- case LDAP_COMPARE_TRUE: +- RETURN_TRUE; +- break; ++ if (ext) { ++ struct berval ldap_bvalue; ++ switch (myargcount) { ++ case 6: ++ _php_parse_controls(cctrls, &lcctrls); ++ case 5: ++ _php_parse_controls(sctrls, &lsctrls); ++ } + +- case LDAP_COMPARE_FALSE: ++ ldap_bvalue.bv_val = Z_STRVAL_PP(&value); ++ ldap_bvalue.bv_len = Z_STRLEN_PP(&value); ++ rc = ldap_compare_ext(ld->link, ldap_dn, ldap_attr, &ldap_bvalue, lsctrls, lcctrls, &msgid); ++ if (lsctrls) { ++ _php_free_controls(&lsctrls); ++ } ++ if (lcctrls) { ++ _php_free_controls(&lcctrls); ++ } ++ if (rc != LDAP_SUCCESS) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Compare: %s", ldap_err2string(rc)); + RETURN_FALSE; +- break; ++ } ++ ++ rc = ldap_result(ld->link, msgid, LDAP_MSG_ALL, NULL, &ldap_res); ++ if (rc != LDAP_RES_COMPARE) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Compare: unable to get result"); ++ RETURN_FALSE; ++ } ++ ++ ZEND_REGISTER_RESOURCE(return_value, ldap_res, le_result); ++ rc = ldap_parse_result(ld->link, ldap_res, &lerr, NULL, NULL, NULL, NULL, 0); ++ if (rc == LDAP_SUCCESS) { ++ rc = lerr; ++ } ++ ++ switch (rc) { ++ case LDAP_COMPARE_TRUE: ++ case LDAP_COMPARE_FALSE: ++ break; ++ ++ default: ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Compare failed: %s", ldap_err2string(rc)); ++ break; ++ } ++ ++ } else { ++#ifdef HAVE_LDAP_COMPARE_EXT_S ++ struct berval ldap_bvalue; ++ ++ ldap_bvalue.bv_val = Z_STRVAL_PP(&value); ++ ldap_bvalue.bv_len = Z_STRLEN_PP(&value); ++ rc = ldap_compare_ext_s(ld->link, ldap_dn, ldap_attr, &ldap_bvalue, NULL, NULL); ++#else /* ! HAVE_LDAP_COMPARE_EXT_S */ ++ char *ldap_value; ++ ++ ldap_value = Z_STRVAL_PP(&value); ++ rc = ldap_compare_s(ld->link, ldap_dn, ldap_attr, ldap_value); ++#endif /* ! HAVE_LDAP_COMPARE_EXT_S */ ++ ++ switch (rc) { ++ case LDAP_COMPARE_TRUE: ++ RETURN_TRUE; ++ break; ++ ++ case LDAP_COMPARE_FALSE: ++ RETURN_FALSE; ++ break; ++ } ++ ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Compare: %s", ldap_err2string(rc)); ++ RETURN_LONG(-1); + } +- +- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Compare: %s", ldap_err2string(errno)); +- RETURN_LONG(-1); ++} ++/* {{{ proto bool ldap_compare(resource link, string dn, string attr, string valu) ++ Determine if an entry has a specific value for one of its attributes */ ++PHP_FUNCTION(ldap_compare) ++{ ++ php_ldap_do_compare(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); + } + /* }}} */ + + /* {{{ proto bool ldap_sort(resource link, resource result, string sortfilter) +@@ -1938,59 +2342,233 @@ + RETURN_TRUE; + } + /* }}} */ + +-#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP +-/* {{{ proto bool ldap_get_option(resource link, int option, mixed retval) +- Get the current value of various session-wide parameters */ +-PHP_FUNCTION(ldap_get_option) ++/* {{{ Extended API that returns result instead of just bool ++ * to allow further manipulation by the ldap_parse_*() funcs, ++ * Pierangelo Masarati */ ++ ++/* {{{ proto result ldap_bind_ext(resource link [, string dn, string password]) ++ Bind to LDAP directory */ ++PHP_FUNCTION(ldap_bind_ext) + { +- zval *link, *retval; ++ zval *link; ++ char *ldap_bind_dn = NULL, *ldap_bind_pw = NULL; ++ int ldap_bind_dnlen, ldap_bind_pwlen; + ldap_linkdata *ld; +- long option; +- +- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rlz", &link, &option, &retval) != SUCCESS) { +- return; ++ int rc, msgid, lerr; ++ LDAPMessage *ldap_res; ++ ++ 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) { ++ ++ RETURN_FALSE; + } + + ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link); + +- switch (option) { +- /* options with int value */ +- case LDAP_OPT_DEREF: +- case LDAP_OPT_SIZELIMIT: +- case LDAP_OPT_TIMELIMIT: +- case LDAP_OPT_PROTOCOL_VERSION: +- case LDAP_OPT_ERROR_NUMBER: +- case LDAP_OPT_REFERRALS: +-#ifdef LDAP_OPT_RESTART +- case LDAP_OPT_RESTART: ++#ifdef LDAP_API_FEATURE_X_OPENLDAP ++ { ++ struct berval cred; ++ ++ /* ldap_bind() is deprecated; use ldap_sasl_bind() instead */ ++ cred.bv_val = ldap_bind_pw; ++ cred.bv_len = ldap_bind_pw ? ldap_bind_pwlen : 0; ++ ++ rc = ldap_sasl_bind(ld->link, ldap_bind_dn, LDAP_SASL_SIMPLE, &cred, ++ NULL, NULL, /* no controls right now */ ++ &msgid); ++ if (rc != LDAP_SUCCESS) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to bind: %s", ldap_err2string(rc)); ++ RETURN_FALSE; ++ } ++ } ++#else ++ msgid = ldap_bind(ld->link, ldap_bind_dn, ldap_bind_pw, LDAP_AUTH_SIMPLE); ++ if (msgid == -1) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to bind"); ++ RETURN_FALSE; ++ } + #endif +- { +- int val; + +- if (ldap_get_option(ld->link, option, &val)) { +- RETURN_FALSE; +- } +- zval_dtor(retval); +- ZVAL_LONG(retval, val); +- } break; +-#ifdef LDAP_OPT_NETWORK_TIMEOUT +- case LDAP_OPT_NETWORK_TIMEOUT: +- { +- struct timeval *timeout = NULL; ++ rc = ldap_result(ld->link, msgid, LDAP_MSG_ALL, NULL, &ldap_res); ++ if (rc != LDAP_RES_BIND) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to get bind result: %s", ldap_err2string(rc)); ++ RETURN_FALSE; ++ } + +- if (ldap_get_option(ld->link, LDAP_OPT_NETWORK_TIMEOUT, (void *) &timeout)) { +- if (timeout) { +- ldap_memfree(timeout); +- } +- RETURN_FALSE; +- } +- if (!timeout) { +- RETURN_FALSE; +- } +- zval_dtor(retval); +- ZVAL_LONG(retval, timeout->tv_sec); ++ ZEND_REGISTER_RESOURCE(return_value, ldap_res, le_result); ++ rc = ldap_parse_result(ld->link, ldap_res, &lerr, NULL, NULL, NULL, NULL, 0); ++ if (rc == LDAP_SUCCESS) { ++ rc = lerr; ++ } ++ ++ ++ if (rc != LDAP_SUCCESS) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to bind to server: %s", ldap_err2string(rc)); ++ } ++} ++/* }}} */ ++ ++/* {{{ proto result ldap_add_ext(resource link, string dn, array entry) ++ Add entries to LDAP directory; returns result */ ++PHP_FUNCTION(ldap_add_ext) ++{ ++ php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_LD_FULL_ADD, 1); ++} ++/* }}} */ ++ ++/* {{{ proto result ldap_mod_replace_ext(resource link, string dn, array entry) ++ Replace attribute values with new ones */ ++PHP_FUNCTION(ldap_mod_replace_ext) ++{ ++ php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_REPLACE, 1); ++} ++/* }}} */ ++ ++ ++/* {{{ proto result ldap_mod_add_ext(resource link, string dn, array entry) ++ Add attribute values to current */ ++PHP_FUNCTION(ldap_mod_add_ext) ++{ ++ php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_ADD, 1); ++} ++/* }}} */ ++ ++/* {{{ proto result ldap_mod_del_ext(resource link, string dn, array entry) ++ Delete attribute values */ ++PHP_FUNCTION(ldap_mod_del_ext) ++{ ++ php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_DELETE, 1); ++} ++/* }}} */ ++ ++/* {{{ proto result ldap_delete_ext(resource link, string dn) ++ Delete an entry from a directory */ ++PHP_FUNCTION(ldap_delete_ext) ++{ ++ zval **link, **dn, **sctrls, **cctrls; ++ ldap_linkdata *ld; ++ char *ldap_dn; ++ int rc, dn_len, msgid, lerr, myargcount = ZEND_NUM_ARGS(); ++ LDAPMessage *ldap_res; ++ LDAPControl **lsctrls = NULL, **lcctrls = NULL; ++ ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|ZZ", &link, &dn, &dn_len, &sctrls, &cctrls) == FAILURE) { ++ WRONG_PARAM_COUNT; ++ } ++ ++ switch (myargcount) { ++ case 4: ++ _php_parse_controls(cctrls, &lcctrls); ++ ++ case 3: ++ _php_parse_controls(sctrls, &lsctrls); ++ } ++ ++ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link); ++ ++ convert_to_string_ex(dn); ++ ldap_dn = Z_STRVAL_PP(dn); ++ ++#ifdef HAVE_LDAP_DELETE_EXT_S ++ rc = ldap_delete_ext_s(ld->link, ldap_dn, NULL, NULL); ++#else /* ! HAVE_LDAP_DELETE_EXT_S */ ++ rc = ldap_delete_s(ld->link, ldap_dn); ++#endif /* ! HAVE_LDAP_DELETE_EXT_S */ ++ if (lsctrls) { ++ _php_free_controls(&lsctrls); ++ } ++ if (lcctrls) { ++ _php_free_controls(&lcctrls); ++ } ++ if (rc != LDAP_SUCCESS) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Delete: %s", ldap_err2string(rc)); ++ RETURN_FALSE; ++ } ++ ++ rc = ldap_result(ld->link, msgid, LDAP_MSG_ALL, NULL, &ldap_res); ++ if (rc != LDAP_RES_DELETE) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Delete: unable to get result"); ++ RETURN_FALSE; ++ } ++ ++ ZEND_REGISTER_RESOURCE(return_value, ldap_res, le_result); ++ rc = ldap_parse_result(ld->link, ldap_res, &lerr, NULL, NULL, NULL, NULL, 0); ++ if (rc == LDAP_SUCCESS) { ++ rc = lerr; ++ } ++ ++ if (rc != LDAP_SUCCESS) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Delete failed: %s", ldap_err2string(rc)); ++ } ++} ++/* }}} */ ++ ++/* }}} End of extended API, Pierangelo Masarati */ ++ ++ ++/* {{{ proto result ldap_compare_ext(resource link, string dn, string attr, string value) ++ Determine if an entry has a specific value for one of its attributes */ ++PHP_FUNCTION(ldap_compare_ext) ++{ ++ php_ldap_do_compare(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); ++} ++/* }}} */ ++ ++/* }}} End of extended API, Pierangelo Masarati */ ++ ++ ++#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 ++/* {{{ proto bool ldap_get_option(resource link, int option, mixed retval) ++ Get the current value of various session-wide parameters */ ++PHP_FUNCTION(ldap_get_option) ++{ ++ zval *link, *retval; ++ ldap_linkdata *ld; ++ long option; ++ ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rlz", &link, &option, &retval) != SUCCESS) { ++ return; ++ } ++ ++ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link); ++ ++ switch (option) { ++ /* options with int value */ ++ case LDAP_OPT_DEREF: ++ case LDAP_OPT_SIZELIMIT: ++ case LDAP_OPT_TIMELIMIT: ++ case LDAP_OPT_PROTOCOL_VERSION: ++ case LDAP_OPT_ERROR_NUMBER: ++ case LDAP_OPT_REFERRALS: ++#ifdef LDAP_OPT_RESTART ++ case LDAP_OPT_RESTART: ++#endif ++ { ++ int val; ++ ++ if (ldap_get_option(ld->link, option, &val)) { ++ RETURN_FALSE; ++ } ++ zval_dtor(retval); ++ ZVAL_LONG(retval, val); ++ } break; ++#ifdef LDAP_OPT_NETWORK_TIMEOUT ++ case LDAP_OPT_NETWORK_TIMEOUT: ++ { ++ struct timeval *timeout = NULL; ++ ++ if (ldap_get_option(ld->link, LDAP_OPT_NETWORK_TIMEOUT, (void *) &timeout)) { ++ if (timeout) { ++ ldap_memfree(timeout); ++ } ++ RETURN_FALSE; ++ } ++ if (!timeout) { ++ RETURN_FALSE; ++ } ++ zval_dtor(retval); ++ ZVAL_LONG(retval, timeout->tv_sec); + ldap_memfree(timeout); + } break; + #elif defined(LDAP_X_OPT_CONNECT_TIMEOUT) + case LDAP_X_OPT_CONNECT_TIMEOUT: +@@ -2213,21 +2791,23 @@ + } + /* }}} */ + + #ifdef HAVE_LDAP_PARSE_RESULT +-/* {{{ proto bool ldap_parse_result(resource link, resource result, int errcode, string matcheddn, string errmsg, array referrals) ++/* {{{ proto bool ldap_parse_result(resource link, resource result, int errcode [, string matcheddn [, string errmsg [, array referrals [, array serverctrls]]]]) + Extract information from result */ + PHP_FUNCTION(ldap_parse_result) + { +- zval *link, *result, *errcode, *matcheddn, *errmsg, *referrals; ++ zval *link, *result, *errcode, *matcheddn, *errmsg, *referrals, *serverctrls; + ldap_linkdata *ld; + LDAPMessage *ldap_result; +- char **lreferrals, **refp; ++ LDAPControl **lserverctrls; ++ char **lreferrals; + char *lmatcheddn, *lerrmsg; + int rc, lerrcode, myargcount = ZEND_NUM_ARGS(); ++ /* int matcheddn_len, errmsg_len; */ + +- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rrz|zzz", &link, &result, &errcode, &matcheddn, &errmsg, &referrals) != SUCCESS) { +- return; ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rrz|zzzz", &link, &result, &errcode, &matcheddn, &errmsg, &referrals, &serverctrls) != SUCCESS) { ++ WRONG_PARAM_COUNT; + } + + ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link); + ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, &result, -1, "ldap result", le_result); +@@ -2235,9 +2815,9 @@ + rc = ldap_parse_result(ld->link, ldap_result, &lerrcode, + myargcount > 3 ? &lmatcheddn : NULL, + myargcount > 4 ? &lerrmsg : NULL, + myargcount > 5 ? &lreferrals : NULL, +- NULL /* &serverctrls */, ++ myargcount > 6 ? &lserverctrls : NULL, + 0); + if (rc != LDAP_SUCCESS) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to parse result: %s", ldap_err2string(rc)); + RETURN_FALSE; +@@ -2247,19 +2827,15 @@ + ZVAL_LONG(errcode, lerrcode); + + /* Reverse -> fall through */ + switch (myargcount) { ++ case 7: ++ /* use arg #7 as the array of controls returned by the server */ ++ zval_dtor(serverctrls); ++ array_init(serverctrls); ++ _php_parse_controls_resp(&lserverctrls, &serverctrls); + case 6: +- zval_dtor(referrals); +- array_init(referrals); +- if (lreferrals != NULL) { +- refp = lreferrals; +- while (*refp) { +- add_next_index_string(referrals, *refp, 1); +- refp++; +- } +- ldap_value_free(lreferrals); +- } ++ _php_parse_referrals_resp(&lreferrals, &referrals); + case 5: + zval_dtor(errmsg); + if (lerrmsg == NULL) { + ZVAL_EMPTY_STRING(errmsg); +@@ -2280,8 +2856,142 @@ + } + /* }}} */ + #endif + ++/* {{{ Extended operation response parsing, Pierangelo Masarati */ ++#ifdef HAVE_LDAP_PARSE_EXTENDED_RESULT ++/* {{{ proto bool ldap_parse_exop(resource link, resource result [, string retoid [, string retdata]]) ++ Extract information from extended operation result */ ++PHP_FUNCTION(ldap_parse_exop) ++{ ++ zval *link, *result, *retoid, *retdata; ++ ldap_linkdata *ld; ++ LDAPMessage *ldap_result; ++ char *lretoid; ++ struct berval *lretdata; ++ int rc, myargcount = ZEND_NUM_ARGS(); ++ ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr|zz", &link, &result, &retoid, &retdata) == SUCCESS) { ++ WRONG_PARAM_COUNT; ++ } ++ ++ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link); ++ ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, &result, -1, "ldap result", le_result); ++ ++ rc = ldap_parse_extended_result(ld->link, ldap_result, ++ myargcount > 2 ? &lretoid: NULL, ++ myargcount > 3 ? &lretdata: NULL, ++ 0); ++ if (rc != LDAP_SUCCESS) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to parse extended operation result: %s", ldap_err2string(rc)); ++ RETURN_FALSE; ++ } ++ ++ /* Reverse -> fall through */ ++ switch (myargcount) { ++ case 4: ++ /* use arg #4 as the data returned by the server */ ++ zval_dtor(retdata); ++ if (lretdata == NULL) { ++ ZVAL_EMPTY_STRING(retdata); ++ } else { ++ ZVAL_STRINGL(retdata, lretdata->bv_val, lretdata->bv_len, 1); ++ ldap_memfree(lretdata->bv_val); ++ ldap_memfree(lretdata); ++ } ++ case 3: ++ zval_dtor(retoid); ++ if (lretoid == NULL) { ++ ZVAL_EMPTY_STRING(retoid); ++ } else { ++ ZVAL_STRING(retoid, lretoid, 1); ++ ldap_memfree(lretoid); ++ } ++ } ++ RETURN_TRUE; ++} ++/* }}} */ ++ ++#ifdef HAVE_LDAP_PARSE_PASSWD ++/* {{{ proto bool ldap_parse_exop_passwd(resource link, resource result, string newpasswd) ++ Extract information from RFC 3062 password modify extended operation result */ ++PHP_FUNCTION(ldap_parse_exop_passwd) ++{ ++ zval **link, **result, **newpasswd; ++ ldap_linkdata *ld; ++ LDAPMessage *ldap_result; ++ struct berval lnewpasswd; ++ int rc, myargcount = ZEND_NUM_ARGS(); ++ ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZZ", &link, &result, &newpasswd) != SUCCESS) { ++ WRONG_PARAM_COUNT; ++ } ++ ++ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link); ++ ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, result, -1, "ldap result", le_result); ++ ++ rc = ldap_parse_passwd(ld->link, ldap_result, &lnewpasswd); ++ if (rc != LDAP_SUCCESS) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to parse passwd modify extended operation result: %s", ldap_err2string(rc)); ++ RETURN_FALSE; ++ } ++ ++ zval_dtor(*newpasswd); ++ if (lnewpasswd.bv_len == 0) { ++ ZVAL_EMPTY_STRING(*newpasswd); ++ } else { ++ ZVAL_STRINGL(*newpasswd, lnewpasswd.bv_val, lnewpasswd.bv_len, 1); ++ ldap_memfree(lnewpasswd.bv_val); ++ } ++ ++ RETURN_TRUE; ++} ++#else ++/* TODO: implement based on ldap_parse_exop() */ ++/* }}} */ ++#endif ++ ++#ifdef HAVE_LDAP_PARSE_WHOAMI ++/* {{{ proto bool ldap_parse_exop_whoami(resource link, resource result, string authzid) ++ Extract information from <draft-zeilenga-ldap-authzid> whoami extended operation result (a Work in Progress) */ ++PHP_FUNCTION(ldap_parse_exop_whoami) ++{ ++ zval **link, **result, **authzid; ++ ldap_linkdata *ld; ++ LDAPMessage *ldap_result; ++ struct berval *lauthzid; ++ int rc, myargcount = ZEND_NUM_ARGS(); ++ ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZZ", &link, &result, &authzid) != SUCCESS) { ++ WRONG_PARAM_COUNT; ++ } ++ ++ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link); ++ ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, result, -1, "ldap result", le_result); ++ ++ rc = ldap_parse_whoami(ld->link, ldap_result, &lauthzid ); ++ if (rc != LDAP_SUCCESS) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to parse whoami extended operation result: %s", ldap_err2string(rc)); ++ RETURN_FALSE; ++ } ++ ++ zval_dtor(*authzid); ++ if (lauthzid == NULL) { ++ ZVAL_EMPTY_STRING(*authzid); ++ } else { ++ ZVAL_STRINGL(*authzid, lauthzid->bv_val, lauthzid->bv_len, 1); ++ ldap_memfree(lauthzid->bv_val); ++ ldap_memfree(lauthzid); ++ } ++ RETURN_TRUE; ++} ++#else ++/* TODO: implement based on ldap_parse_extended_result() */ ++/* }}} */ ++#endif ++/* }}} */ ++#endif ++ + /* {{{ proto resource ldap_first_reference(resource link, resource result) + Return first reference */ + PHP_FUNCTION(ldap_first_reference) + { +@@ -2841,53 +3551,735 @@ + } + /* }}} */ + #endif + +-/* {{{ arginfo */ +-ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_connect, 0, 0, 0) +- ZEND_ARG_INFO(0, hostname) +- ZEND_ARG_INFO(0, port) +-#ifdef HAVE_ORALDAP +- ZEND_ARG_INFO(0, wallet) +- ZEND_ARG_INFO(0, wallet_passwd) +- ZEND_ARG_INFO(0, authmode) +-#endif +-ZEND_END_ARG_INFO() ++/* {{{ Extended operations, Pierangelo Masarati */ ++#ifdef HAVE_LDAP_EXTENDED_OPERATION_S ++/* {{{ proto ? ldap_exop(resource link, string reqoid [, string reqdata [, string retoid [, string retdata]]]) ++ Extended operation */ ++PHP_FUNCTION(ldap_exop) ++{ ++ zval **link, **reqoid, **reqdata, **retoid, **retdata; ++ char *lreqoid, *lretoid = NULL; ++ struct berval lreqdata, *lretdata = NULL; ++ ldap_linkdata *ld; ++ LDAP *ldap; ++ LDAPMessage *ldap_res; ++ int rc, msgid, myargcount = ZEND_NUM_ARGS(); ++ /* int reqoid_len, reqdata_len, retdata_len, retoid_len, retdat_len; */ + +-ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_resource, 0, 0, 1) +- ZEND_ARG_INFO(0, link_identifier) +-ZEND_END_ARG_INFO() ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ|ZZZ", &link, &reqoid, &reqdata, &retoid, &retdata) != SUCCESS) { ++ WRONG_PARAM_COUNT; ++ } + +-ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_bind, 0, 0, 1) +- ZEND_ARG_INFO(0, link_identifier) +- ZEND_ARG_INFO(0, bind_rdn) +- ZEND_ARG_INFO(0, bind_password) +-ZEND_END_ARG_INFO() ++ if (Z_TYPE_PP(link) == IS_NULL) { ++ ldap = NULL; ++ } else { ++ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link); ++ ldap = ld->link; ++ } + +-#ifdef HAVE_LDAP_SASL +-ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_sasl_bind, 0, 0, 1) +- ZEND_ARG_INFO(0, link) +- ZEND_ARG_INFO(0, binddn) +- ZEND_ARG_INFO(0, password) +- ZEND_ARG_INFO(0, sasl_mech) +- ZEND_ARG_INFO(0, sasl_realm) +- ZEND_ARG_INFO(0, sasl_authz_id) +- ZEND_ARG_INFO(0, props) +-ZEND_END_ARG_INFO() +-#endif ++ switch (myargcount) { ++ case 5: ++ case 4: ++ case 3: ++ convert_to_string_ex(reqdata); ++ lreqdata.bv_val = Z_STRVAL_PP(reqdata); ++ lreqdata.bv_len = Z_STRLEN_PP(reqdata); ++ /* fallthru */ ++ case 2: ++ convert_to_string_ex(reqoid); ++ lreqoid = Z_STRVAL_PP(reqoid); ++ } ++ ++ if (myargcount > 3) { ++ /* synchronous call */ ++ rc = ldap_extended_operation_s(ld->link, lreqoid, ++ lreqdata.bv_len > 0 ? &lreqdata: NULL, ++ NULL, ++ NULL, ++ &lretoid, ++ myargcount > 4 ? &lretdata : NULL ); ++ if (rc != LDAP_SUCCESS ) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Extended operation %s failed: %s (%d)", lreqoid, ldap_err2string(rc), rc); ++ RETURN_FALSE; ++ } + +-ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_read, 0, 0, 3) +- ZEND_ARG_INFO(0, link_identifier) +- ZEND_ARG_INFO(0, base_dn) +- ZEND_ARG_INFO(0, filter) +- ZEND_ARG_INFO(0, attributes) +- ZEND_ARG_INFO(0, attrsonly) +- ZEND_ARG_INFO(0, sizelimit) +- ZEND_ARG_INFO(0, timelimit) +- ZEND_ARG_INFO(0, deref) +-ZEND_END_ARG_INFO() ++ /* Reverse -> fall through */ ++ switch (myargcount) { ++ case 5: ++ /* use arg #4 as the data returned by the server */ ++ zval_dtor(*retdata); ++ if (lretdata == NULL) { ++ ZVAL_EMPTY_STRING(*retdata); ++ } else { ++ ZVAL_STRINGL(*retdata, lretdata->bv_val, lretdata->bv_len, 1); ++ ldap_memfree(lretdata->bv_val); ++ ldap_memfree(lretdata); ++ } ++ case 4: ++ zval_dtor(*retoid); ++ if (lretoid == NULL) { ++ ZVAL_EMPTY_STRING(*retoid); ++ } else { ++ ZVAL_STRING(*retoid, lretoid, 1); ++ ldap_memfree(lretoid); ++ } ++ } + +-ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_list, 0, 0, 3) ++ RETURN_TRUE; ++ } ++ ++ /* asynchronous call */ ++ rc = ldap_extended_operation(ld->link, lreqoid, ++ lreqdata.bv_len > 0 ? &lreqdata: NULL, ++ NULL, NULL, &msgid); ++ if (rc != LDAP_SUCCESS ) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Extended operation %s failed: %s (%d)", lreqoid, ldap_err2string(rc), rc); ++ RETURN_FALSE; ++ } ++ ++ rc = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res); ++ if (rc == -1) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Extended operation %s failed", lreqoid); ++ RETURN_FALSE; ++ } ++ ++ /* return a PHP control object */ ++ array_init(return_value); ++ ++ ZEND_REGISTER_RESOURCE(return_value, ldap_res, le_result); ++} ++/* }}} */ ++ ++#ifdef HAVE_LDAP_PASSWD_S ++/* {{{ proto ? ldap_exop_passwd(resource link [, string user [, string oldpw [, string newpw [, string newpasswd ]]]]) ++ Passwd modify extended operation */ ++PHP_FUNCTION(ldap_exop_passwd) ++{ ++ zval **link, **user, **newpw, **oldpw, **newpasswd; ++ struct berval luser, loldpw, lnewpw, lnewpasswd; ++ ldap_linkdata *ld; ++ LDAP *ldap; ++ LDAPMessage *ldap_res; ++ int rc, msgid, myargcount = ZEND_NUM_ARGS(); ++ ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|ZZZZ", &link, &user, &oldpw, &newpw, &newpasswd) == FAILURE) { ++ WRONG_PARAM_COUNT; ++ } ++ ++ if (Z_TYPE_PP(link) == IS_NULL) { ++ ldap = NULL; ++ } else { ++ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link); ++ ldap = ld->link; ++ } ++ ++ luser.bv_len = 0; ++ loldpw.bv_len = 0; ++ lnewpw.bv_len = 0; ++ ++ switch (myargcount) { ++ case 5: ++ case 4: ++ convert_to_string_ex(newpw); ++ lnewpw.bv_val = Z_STRVAL_PP(newpw); ++ lnewpw.bv_len = Z_STRLEN_PP(newpw); ++ ++ case 3: ++ convert_to_string_ex(oldpw); ++ loldpw.bv_val = Z_STRVAL_PP(oldpw); ++ loldpw.bv_len = Z_STRLEN_PP(oldpw); ++ ++ case 2: ++ convert_to_string_ex(user); ++ luser.bv_val = Z_STRVAL_PP(user); ++ luser.bv_len = Z_STRLEN_PP(user); ++ } ++ ++ if (myargcount > 4 || lnewpw.bv_len > 0) { ++ /* synchronous call */ ++ rc = ldap_passwd_s(ld->link, &luser, ++ loldpw.bv_len > 0 ? &loldpw : NULL, ++ /* loldpw.bv_len > 0 ? &loldpw : NULL, */ ++ lnewpw.bv_len > 0 ? &lnewpw : NULL, ++ &lnewpasswd, NULL, NULL); ++ if (rc != LDAP_SUCCESS ) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Passwd modify extended operation failed: %s (%d)", ldap_err2string(rc), rc); ++ RETURN_FALSE; ++ } ++ ++ if (myargcount > 4) { ++ zval_dtor(*newpasswd); ++ if (lnewpasswd.bv_len == 0) { ++ ZVAL_EMPTY_STRING(*newpasswd); ++ } else { ++ ZVAL_STRINGL(*newpasswd, lnewpasswd.bv_val, lnewpasswd.bv_len, 1); ++ } ++ } ++ ++ ldap_memfree(lnewpasswd.bv_val); ++ ++ RETURN_TRUE; ++ } ++ ++ /* asynchronous call */ ++ rc = ldap_passwd(ld->link, &luser, ++ loldpw.bv_len > 0 ? &loldpw : NULL, ++ lnewpw.bv_len > 0 ? &lnewpw : NULL, ++ NULL, NULL, &msgid); ++ if (rc != LDAP_SUCCESS ) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Passwd modify extended operation failed: %s (%d)", ldap_err2string(rc), rc); ++ RETURN_FALSE; ++ } ++ ++ rc = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res); ++ if (rc == -1) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Passwd modify extended operation failed"); ++ RETURN_FALSE; ++ } ++ ++ /* return a PHP control object */ ++ array_init(return_value); ++ ++ ZEND_REGISTER_RESOURCE(return_value, ldap_res, le_result); ++} ++#else ++/* TODO: implement based on ldap_extended_operation_s() */ ++/* }}} */ ++#endif ++ ++#ifdef HAVE_LDAP_WHOAMI_S ++/* {{{ proto bool ldap_exop_whoami(resource link [, string authzid]) ++ Whoami extended operation */ ++PHP_FUNCTION(ldap_exop_whoami) ++{ ++ zval **link, **authzid; ++ struct berval *lauthzid; ++ ldap_linkdata *ld; ++ LDAP *ldap; ++ LDAPMessage *ldap_res; ++ int rc, msgid, myargcount = ZEND_NUM_ARGS(); ++ ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|Z", &link, &authzid) == FAILURE) { ++ WRONG_PARAM_COUNT; ++ } ++ ++ if (Z_TYPE_PP(link) == IS_NULL) { ++ ldap = NULL; ++ } else { ++ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link); ++ ldap = ld->link; ++ } ++ ++ if (myargcount == 2) { ++ /* synchronous call */ ++ rc = ldap_whoami_s(ld->link, &lauthzid, NULL, NULL); ++ if (rc != LDAP_SUCCESS ) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Whoami extended operation failed: %s (%d)", ldap_err2string(rc), rc); ++ RETURN_FALSE; ++ } ++ ++ zval_dtor(*authzid); ++ if (lauthzid == NULL) { ++ ZVAL_EMPTY_STRING(*authzid); ++ } else { ++ ZVAL_STRINGL(*authzid, lauthzid->bv_val, lauthzid->bv_len, 1); ++ ldap_memfree(lauthzid->bv_val); ++ ldap_memfree(lauthzid); ++ } ++ ++ RETURN_TRUE; ++ } ++ ++ /* asynchronous call */ ++ rc = ldap_whoami(ld->link, NULL, NULL, &msgid); ++ if (rc != LDAP_SUCCESS ) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Whoami extended operation failed: %s (%d)", ldap_err2string(rc), rc); ++ RETURN_FALSE; ++ } ++ ++ rc = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res); ++ if (rc == -1) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Whoami extended operation failed"); ++ RETURN_FALSE; ++ } ++ ++ /* return a PHP control object */ ++ array_init(return_value); ++ ++ ZEND_REGISTER_RESOURCE(return_value, ldap_res, le_result); ++} ++#else ++/* TODO: implement based on ldap_extended_operation_s() */ ++#endif ++/* }}} */ ++#endif ++/* }}} */ ++ ++/* {{{ LDAP controls encoding/decoding, Pierangelo Masarati */ ++/* {{{ php_set_no_value_server_ctrl ++ */ ++void php_set_no_value_server_ctrl(INTERNAL_FUNCTION_PARAMETERS, const char *oid, const char *msg) ++{ ++ zval **link, **iscritical; ++ ldap_linkdata *ld; ++ LDAP *ldap; ++ LDAPControl ctrl = { 0 }, *ctrlsp[2]; ++ int rc, myargcount = ZEND_NUM_ARGS(); ++ ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|Z", &link, &iscritical) != SUCCESS) { ++ WRONG_PARAM_COUNT; ++ } ++ ++ if (Z_TYPE_PP(link) == IS_NULL) { ++ ldap = NULL; ++ ++ } else { ++ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link); ++ ldap = ld->link; ++ } ++ ++ if (myargcount == 2) { ++ convert_to_boolean_ex(iscritical); ++ ctrl.ldctl_iscritical = Z_BVAL_PP(iscritical); ++ } ++ ++ ctrl.ldctl_oid = (char *)oid; ++ ++ if (ldap) { ++ /* directly set the option */ ++ ctrlsp[0] = &ctrl; ++ ctrlsp[1] = NULL; ++ ++ rc = ldap_set_option(ldap, LDAP_OPT_SERVER_CONTROLS, ctrlsp); ++ if (rc != LDAP_SUCCESS) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set %s control: %s (%d)", msg, ldap_err2string(rc), rc); ++ RETURN_FALSE; ++ } ++ ++ } else { ++ /* return a PHP control object */ ++ array_init(return_value); ++ ++ add_assoc_string(return_value, "oid", ctrl.ldctl_oid, 1); ++ if (ctrl.ldctl_iscritical) { ++ add_assoc_bool(return_value, "iscritical", ctrl.ldctl_iscritical); ++ } ++ } ++ ++ RETURN_TRUE; ++} ++/* }}} */ ++ ++#ifdef LDAP_CONTROL_MANAGEDSAIT ++/* {{{ proto bool ldap_ctrl_manageDSAit(resource link [, bool iscritical]) ++ Inject manageDSAit control */ ++PHP_FUNCTION(ldap_ctrl_manageDSAit) ++{ ++ php_set_no_value_server_ctrl(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_CONTROL_MANAGEDSAIT, "manageDSAit"); ++} ++/* }}} */ ++#endif ++ ++#ifdef LDAP_CONTROL_PAGEDRESULTS ++/* {{{ proto bool ldap_ctrl_paged_results(resource link, int pagesize [, bool iscritical [, string cookie]]) ++ Inject paged results control*/ ++PHP_FUNCTION(ldap_ctrl_paged_results) ++{ ++ zval **link, **pagesize, **iscritical, **cookie; ++ int lpagesize = 0; ++ struct berval lcookie = { 0, NULL }; ++ ldap_linkdata *ld; ++ LDAP *ldap; ++ BerElement *ber = NULL; ++ LDAPControl ctrl, *ctrlsp[2]; ++ int rc, myargcount = ZEND_NUM_ARGS(); ++ ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ|ZZ", &link, &pagesize, &iscritical, &cookie) != SUCCESS) { ++ WRONG_PARAM_COUNT; ++ } ++ ++ if (Z_TYPE_PP(link) == IS_NULL) { ++ ldap = NULL; ++ } else { ++ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link); ++ ldap = ld->link; ++ } ++ ++ ber = ber_alloc_t(LBER_USE_DER); ++ if (ber == NULL) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to alloc BER encoding resources for paged results control"); ++ RETURN_FALSE; ++ } ++ ++ ctrl.ldctl_iscritical = 0; ++ ++ switch (myargcount) { ++ case 4: ++ convert_to_string_ex(cookie); ++ lcookie.bv_val = Z_STRVAL_PP(cookie); ++ lcookie.bv_len = Z_STRLEN_PP(cookie); ++ /* fallthru */ ++ case 3: ++ convert_to_boolean_ex(iscritical); ++ ctrl.ldctl_iscritical = Z_BVAL_PP(iscritical); ++ /* fallthru */ ++ } ++ convert_to_long_ex(pagesize); ++ lpagesize = Z_LVAL_PP(pagesize); ++ ++ ber_printf(ber, "{iO}", lpagesize, &lcookie ); ++ rc = ber_flatten2( ber, &ctrl.ldctl_value, 0 ); ++ if ( rc == -1 ) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to BER encode paged results control"); ++ RETURN_FALSE; ++ } ++ ++ ctrl.ldctl_oid = LDAP_CONTROL_PAGEDRESULTS; ++ ++ if (ldap) { ++ /* directly set the option */ ++ ctrlsp[0] = &ctrl; ++ ctrlsp[1] = NULL; ++ ++ rc = ldap_set_option(ldap, LDAP_OPT_SERVER_CONTROLS, ctrlsp); ++ if (rc != LDAP_SUCCESS) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set paged results control: %s (%d)", ldap_err2string(rc), rc); ++ RETURN_FALSE; ++ } ++ ++ } else { ++ /* return a PHP control object */ ++ array_init(return_value); ++ ++ add_assoc_string(return_value, "oid", ctrl.ldctl_oid, 1); ++ if ( ctrl.ldctl_value.bv_len ) { ++ add_assoc_stringl(return_value, "value", ctrl.ldctl_value.bv_val, ctrl.ldctl_value.bv_len, 1); ++ } ++ if (ctrl.ldctl_iscritical) { ++ add_assoc_bool(return_value, "iscritical", ctrl.ldctl_iscritical); ++ } ++ } ++ ++ if (ber != NULL) { ++ ber_free(ber, 1); ++ } ++} ++/* }}} */ ++ ++/* {{{ proto bool ldap_ctrl_paged_results_resp(resource link, resource result [, string cookie [, int estimated]]) ++ Extract paged results control response */ ++PHP_FUNCTION(ldap_ctrl_paged_results_resp) ++{ ++ zval **link, **result, **cookie, **estimated; ++ struct berval lcookie; ++ int lestimated; ++ ldap_linkdata *ld; ++ LDAPMessage *ldap_result; ++ LDAPControl **lserverctrls, *lctrl; ++ BerElement *ber; ++ ber_tag_t tag; ++ int rc, lerrcode, myargcount = ZEND_NUM_ARGS(); ++ ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ|ZZ", &link, &result, &cookie, &estimated) != SUCCESS) { ++ WRONG_PARAM_COUNT; ++ } ++ ++ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link); ++ ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, result, -1, "ldap result", le_result); ++ ++ rc = ldap_parse_result(ld->link, ++ ldap_result, ++ &lerrcode, ++ NULL, /* matcheddn */ ++ NULL, /* errmsg */ ++ NULL, /* referrals */ ++ &lserverctrls, ++ 0); ++ ++ if (rc != LDAP_SUCCESS) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to parse result: %s (%d)", ldap_err2string(rc), rc); ++ RETURN_FALSE; ++ } ++ ++ if (lerrcode != LDAP_SUCCESS) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Result is: %s (%d)", ldap_err2string(lerrcode), lerrcode); ++ RETURN_FALSE; ++ } ++ ++ if (lserverctrls == NULL) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "No server controls in result"); ++ RETURN_FALSE; ++ } ++ ++ lctrl = ldap_find_control(LDAP_CONTROL_PAGEDRESULTS, lserverctrls); ++ if (lctrl == NULL) { ++ ldap_controls_free(lserverctrls); ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "No paged results control response in result"); ++ RETURN_FALSE; ++ } ++ ++ ber = ber_init(&lctrl->ldctl_value); ++ if (ber == NULL) { ++ ldap_controls_free(lserverctrls); ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to alloc BER decoding resources for paged results control response"); ++ RETURN_FALSE; ++ } ++ ++ tag = ber_scanf(ber, "{io}", &lestimated, &lcookie ); ++ (void)ber_free(ber, 1); ++ ++ if (tag == LBER_ERROR) { ++ ldap_controls_free(lserverctrls); ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to decode paged results control response"); ++ RETURN_FALSE; ++ } ++ ++ if (lestimated < 0) { ++ ldap_controls_free(lserverctrls); ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid paged results control response value"); ++ RETURN_FALSE; ++ } ++ ++ ldap_controls_free(lserverctrls); ++ ++ if (myargcount == 4) { ++ zval_dtor(*estimated); ++ ZVAL_LONG(*estimated, lestimated); ++ } ++ ++ zval_dtor(*cookie); ++ if (lcookie.bv_len == 0) { ++ ZVAL_EMPTY_STRING(*cookie); ++ } else { ++ ZVAL_STRINGL(*cookie, lcookie.bv_val, lcookie.bv_len, 1); ++ } ++ ldap_memfree(lcookie.bv_val); ++ ++ RETURN_TRUE; ++} ++/* }}} */ ++#endif ++ ++#ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST ++/* {{{ proto bool ldap_ctrl_ppolicy(resource link [, bool iscritical]) ++ Inject password policy control */ ++PHP_FUNCTION(ldap_ctrl_ppolicy) ++{ ++ php_set_no_value_server_ctrl(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_CONTROL_PASSWORDPOLICYREQUEST, "passwordPolicy"); ++} ++/* }}} */ ++ ++/* {{{ proto bool ldap_ctrl_ppolicy_resp(resource link, resource result [, expire [, grace [, error[, errmsg]]]]) ++ Extract password policy control response */ ++PHP_FUNCTION(ldap_ctrl_ppolicy_resp) ++{ ++ zval **link, **result, **ppexpire, **ppgrace, **pperror, **pperrmsg; ++ int lexpire, lgrace; ++ LDAPPasswordPolicyError lerror; ++ ldap_linkdata *ld; ++ LDAPMessage *ldap_result; ++ LDAPControl **lserverctrls, *lctrl; ++ int rc, pperrmsg_len, lerrcode, myargcount = ZEND_NUM_ARGS(); ++ ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ|ZZZZ", &link, &result, &ppexpire, &ppgrace, &pperror, &pperrmsg) != SUCCESS) { ++ WRONG_PARAM_COUNT; ++ } ++ ++ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link); ++ ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, result, -1, "ldap result", le_result); ++ ++ rc = ldap_parse_result(ld->link, ++ ldap_result, ++ &lerrcode, ++ NULL, /* matcheddn */ ++ NULL, /* errmsg */ ++ NULL, /* referrals */ ++ &lserverctrls, ++ 0); ++ ++ if (rc != LDAP_SUCCESS) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to parse result: %s (%d)", ldap_err2string(rc), rc); ++ RETURN_FALSE; ++ } ++ ++ if (lerrcode != LDAP_SUCCESS && lerrcode != LDAP_INVALID_CREDENTIALS) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Result is: %s (%d)", ldap_err2string(lerrcode), lerrcode); ++ RETURN_FALSE; ++ } ++ ++ if (lserverctrls == NULL) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "No server controls in result"); ++ RETURN_FALSE; ++ } ++ ++ lctrl = ldap_find_control(LDAP_CONTROL_PASSWORDPOLICYRESPONSE, lserverctrls); ++ if (lctrl == NULL) { ++ ldap_controls_free(lserverctrls); ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "No password policy control response in result"); ++ RETURN_FALSE; ++ } ++ ++ lerrcode = ldap_parse_passwordpolicy_control(ld->link, lctrl, &lexpire, &lgrace, &lerror); ++ ldap_controls_free(lserverctrls); ++ if (lerrcode != LDAP_SUCCESS) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to parse password policy control response: %s (%d)", ldap_err2string(lerrcode), lerrcode); ++ RETURN_FALSE; ++ } ++ ++ switch (myargcount) { ++ case 6: ++ zval_dtor(*pperrmsg); ++ ZVAL_STRING(*pperrmsg, (char *)ldap_passwordpolicy_err2txt(lerror), 1); ++ ++ case 5: ++ zval_dtor(*pperror); ++ ZVAL_LONG(*pperror, (long)lerror); ++ ++ case 4: ++ zval_dtor(*ppgrace); ++ ZVAL_LONG(*ppgrace, (long)lgrace); ++ } ++ ++ zval_dtor(*ppexpire); ++ ZVAL_LONG(*ppexpire, (long)lexpire); ++ ++ RETURN_TRUE; ++} ++/* }}} */ ++#endif ++ ++#ifdef LDAP_CONTROL_NOOP ++/* {{{ proto bool ldap_ctrl_noop(resource link, bool iscritical) ++ Inject control*/ ++PHP_FUNCTION(ldap_ctrl_noop) ++{ ++ php_set_no_value_server_ctrl(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_CONTROL_NOOP, "no-op"); ++} ++/* }}} */ ++#endif ++ ++#ifdef LDAP_CONTROL_MANAGEDIT ++/* {{{ proto bool ldap_ctrl_manageDIT(resource link [, bool iscritical]) ++ Inject control*/ ++PHP_FUNCTION(ldap_ctrl_manageDIT) ++{ ++ php_set_no_value_server_ctrl(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_CONTROL_MANAGEDIT, "manageDIT"); ++} ++/* }}} */ ++#endif ++ ++#ifdef LDAP_CONTROL_X_PERMISSIVE_MODIFY ++/* {{{ proto bool ldap_ctrl_permissive_modify(resource link [, bool iscritical]) ++ Inject control*/ ++PHP_FUNCTION(ldap_ctrl_permissive_modify) ++{ ++ php_set_no_value_server_ctrl(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_CONTROL_X_PERMISSIVE_MODIFY, "permissive modify"); ++} ++/* }}} */ ++#endif ++/* }}} */ ++ ++#ifdef HAVE_LDAP_REFRESH ++/* {{{ proto ? ldap_refresh(resource link , string dn , int ttl, [int *newttl]) ++ DDS refresh extended operation */ ++PHP_FUNCTION(ldap_refresh) ++{ ++ zval **link, **dn, **ttl, **newttl; ++ struct berval ldn; ++ ber_int_t lttl; ++ ber_int_t lnewttl; ++ ldap_linkdata *ld; ++ LDAP *ldap; ++ LDAPMessage *ldap_res; ++ int rc, msgid, myargcount = ZEND_NUM_ARGS(); ++ ++ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZZ|Z", &link, &dn, &ttl, &newttl) != SUCCESS) { ++ WRONG_PARAM_COUNT; ++ } ++ ++ if (Z_TYPE_PP(link) == IS_NULL) { ++ ldap = NULL; ++ } else { ++ ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, ++ link, -1, "ldap link", le_link); ++ ldap = ld->link; ++ } ++ ++ ldn.bv_len = 0; ++ convert_to_string_ex(dn); ++ ldn.bv_val = Z_STRVAL_PP(dn); ++ ldn.bv_len = Z_STRLEN_PP(dn); ++ ++ convert_to_long_ex(ttl); ++ lttl = (ber_int_t)Z_LVAL_PP(ttl); ++ ++ /* asynchronous call */ ++ rc = ldap_refresh_s(ld->link, &ldn, lttl, &lnewttl, NULL, NULL); ++ if (rc != LDAP_SUCCESS ) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, ++ "Refresh extended operation failed: %s (%d)", ++ ldap_err2string(rc), rc); ++ RETURN_FALSE; ++ } ++ ++ if (myargcount == 4) { ++ zval_dtor(*newttl); ++ ZVAL_LONG(*newttl, (long)lnewttl); ++ } ++ RETURN_TRUE; ++} ++#else ++/* TODO: implement based on ldap_extended_operation_s() */ ++/* }}} */ ++#endif ++ ++/* {{{ arginfo */ ++ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_connect, 0, 0, 0) ++ ZEND_ARG_INFO(0, hostname) ++ ZEND_ARG_INFO(0, port) ++#ifdef HAVE_ORALDAP ++ ZEND_ARG_INFO(0, wallet) ++ ZEND_ARG_INFO(0, wallet_passwd) ++ ZEND_ARG_INFO(0, authmode) ++#endif ++ZEND_END_ARG_INFO() ++ ++ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_resource, 0, 0, 1) ++ ZEND_ARG_INFO(0, link_identifier) ++ZEND_END_ARG_INFO() ++ ++ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_bind, 0, 0, 1) ++ ZEND_ARG_INFO(0, link_identifier) ++ ZEND_ARG_INFO(0, bind_rdn) ++ ZEND_ARG_INFO(0, bind_password) ++ZEND_END_ARG_INFO() ++ ++#ifdef HAVE_LDAP_SASL ++ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_sasl_bind, 0, 0, 1) ++ ZEND_ARG_INFO(0, link) ++ ZEND_ARG_INFO(0, binddn) ++ ZEND_ARG_INFO(0, password) ++ ZEND_ARG_INFO(0, sasl_mech) ++ ZEND_ARG_INFO(0, sasl_realm) ++ ZEND_ARG_INFO(0, sasl_authz_id) ++ ZEND_ARG_INFO(0, props) ++ZEND_END_ARG_INFO() ++#endif ++ ++ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_read, 0, 0, 3) ++ ZEND_ARG_INFO(0, link_identifier) ++ ZEND_ARG_INFO(0, base_dn) ++ ZEND_ARG_INFO(0, filter) ++ ZEND_ARG_INFO(0, attributes) ++ ZEND_ARG_INFO(0, attrsonly) ++ ZEND_ARG_INFO(0, sizelimit) ++ ZEND_ARG_INFO(0, timelimit) ++ ZEND_ARG_INFO(0, deref) ++ZEND_END_ARG_INFO() ++ ++ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_list, 0, 0, 3) + ZEND_ARG_INFO(0, link_identifier) + ZEND_ARG_INFO(0, base_dn) + ZEND_ARG_INFO(0, filter) + ZEND_ARG_INFO(0, attributes) +@@ -3090,8 +4482,9 @@ + ZEND_ARG_INFO(1, errcode) + ZEND_ARG_INFO(1, matcheddn) + ZEND_ARG_INFO(1, errmsg) + ZEND_ARG_INFO(1, referrals) ++ ZEND_ARG_INFO(1, serverctrls) + ZEND_END_ARG_INFO() + #endif + #endif + +@@ -3116,8 +4509,40 @@ + ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_8859_to_t61, 0, 0, 1) + ZEND_ARG_INFO(0, value) + ZEND_END_ARG_INFO() + #endif ++ ++#ifdef HAVE_LDAP_EXTENDED_OPERATION_S ++ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_exop, 0, 0, 5) ++ ZEND_ARG_INFO(0, link) ++ ZEND_ARG_INFO(0, reqoid) ++ ZEND_ARG_INFO(1, reqdata) ++ ZEND_ARG_INFO(1, repoid) ++ ZEND_ARG_INFO(1, repdata) ++ZEND_END_ARG_INFO() ++ ++ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_exop_passwd, 0, 0, 5) ++ ZEND_ARG_INFO(0, link) ++ ZEND_ARG_INFO(1, user) ++ ZEND_ARG_INFO(1, oldpw) ++ ZEND_ARG_INFO(1, newpw) ++ ZEND_ARG_INFO(1, newpasswd) ++ZEND_END_ARG_INFO() ++ ++ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_exop_whoami, 0, 0, 2) ++ ZEND_ARG_INFO(0, link) ++ ZEND_ARG_INFO(1, authzid) ++ZEND_END_ARG_INFO() ++#endif ++ ++#ifdef HAVE_LDAP_REFRESH ++ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_refresh, 0, 0, 4) ++ ZEND_ARG_INFO(0, link) ++ ZEND_ARG_INFO(0, dn) ++ ZEND_ARG_INFO(1, ttl) ++ ZEND_ARG_INFO(0, newttl) ++ZEND_END_ARG_INFO() ++#endif + /* }}} */ + + /* + This is just a small subset of the functionality provided by the LDAP library. All the +@@ -3180,9 +4605,22 @@ + #endif + #ifdef HAVE_LDAP_START_TLS_S + PHP_FE(ldap_start_tls, arginfo_ldap_resource) + #endif ++#ifdef HAVE_LDAP_EXTENDED_OPERATION_S ++ PHP_FE(ldap_exop, ++ arginfo_ldap_exop) ++ PHP_FE(ldap_exop_passwd, ++ arginfo_ldap_exop_passwd) ++ PHP_FE(ldap_exop_whoami, ++ arginfo_ldap_exop_whoami) ++#endif ++#ifdef HAVE_LDAP_REFRESH ++ PHP_FE(ldap_refresh, ++ arginfo_ldap_refresh) + #endif ++#endif ++ + + #if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC) + PHP_FE(ldap_set_rebind_proc, arginfo_ldap_set_rebind_proc) + #endif +@@ -3193,8 +4631,33 @@ + PHP_FE(ldap_t61_to_8859, arginfo_ldap_t61_to_8859) + PHP_FE(ldap_8859_to_t61, arginfo_ldap_8859_to_t61) + #endif + ++/* routines to handle standard track controls, Pierangelo Masarati */ ++#ifdef LDAP_CONTROL_MANAGEDSAIT ++ PHP_FE(ldap_ctrl_manageDSAit, NULL) ++#endif ++#ifdef LDAP_CONTROL_PAGEDRESULTS ++ PHP_FE(ldap_ctrl_paged_results, NULL) /* fourth_arg_force_ref */ ++ PHP_FE(ldap_ctrl_paged_results_resp, NULL) /* arg3to4of4_force_ref */ ++#endif ++#ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST ++ PHP_FE(ldap_ctrl_ppolicy, NULL) ++ PHP_FE(ldap_ctrl_ppolicy_resp, NULL) /* arg3to6of6_force_ref */ ++#endif ++#ifdef LDAP_CONTROL_NOOP ++ PHP_FE(ldap_ctrl_noop, NULL) ++#endif ++#ifdef LDAP_CONTROL_MANAGEDIT ++ PHP_FE(ldap_ctrl_manageDIT, NULL) ++#endif ++#ifdef LDAP_CONTROL_X_PERMISSIVE_MODIFY ++ PHP_FE(ldap_ctrl_permissive_modify, NULL) ++#endif ++/* end of ando mod */ ++ ++ ++ + #ifdef LDAP_CONTROL_PAGEDRESULTS + PHP_FE(ldap_control_paged_result, arginfo_ldap_control_paged_result) + PHP_FE(ldap_control_paged_result_response, arginfo_ldap_control_paged_result_response) + #endif +@@ -3219,8 +4682,10 @@ + STANDARD_MODULE_PROPERTIES_EX + }; + /* }}} */ + ++ ++ + /* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 +--- ext/ldap/php_ldap.h.orig 2015-03-19 01:19:30.000000000 +0100 ++++ ext/ldap/php_ldap.h 2015-04-13 05:48:10.000000000 +0200 +@@ -28,16 +28,148 @@ + #endif + + #include <ldap.h> + ++#define HAVE_3ARG_SETREBINDPROC ++#define HAVE_LDAP_ADD_EXT_S ++#define HAVE_LDAP_MODIFY_EXT_S ++#define HAVE_LDAP_COMPARE_EXT_S ++#define HAVE_LDAP_DELETE_EXT_S ++#define HAVE_LDAP_PARSE_EXTENDED_RESULT ++#define HAVE_LDAP_PARSE_PASSWD ++#define HAVE_LDAP_PARSE_WHOAMI ++#define HAVE_LDAP_EXTENDED_OPERATION_S ++#define HAVE_LDAP_PASSWD_S ++#define HAVE_LDAP_WHOAMI_S ++#define HAVE_LDAP_REFRESH ++#define HAVE_LDAP_SASL ++#define HAVE_LDAP_EXTENDED_OPERATION_S ++#define HAVE_LDAP_REFRESH ++#define HAVE_LDAP_EXTENDED_OPERATION_S ++#define HAVE_LDAP_REFRESH ++#define HAVE_LDAP_EXTENDED_OPERATION ++ + extern zend_module_entry ldap_module_entry; + #define ldap_module_ptr &ldap_module_entry + + /* LDAP functions */ + PHP_MINIT_FUNCTION(ldap); + PHP_MSHUTDOWN_FUNCTION(ldap); + PHP_MINFO_FUNCTION(ldap); + ++#ifdef HAVE_LDAP_EXTENDED_OPERATION ++ ++#endif ++ ++#ifdef LDAP_CONTROL_MANAGEDSAIT ++/* RFC 3296 */ ++PHP_FUNCTION(ldap_ctrl_manageDSAit); ++#endif ++#ifdef LDAP_CONTROL_PROXY_AUTHZ ++/* <draft-weltman-ldapv3-proxy> (a Work in Progress) */ ++PHP_FUNCTION(ldap_ctrl_proxy_authz); ++#endif ++#ifdef LDAP_CONTROL_SUBENTRIES ++/* RFC 3672 */ ++PHP_FUNCTION(ldap_ctrl_subentries); ++#endif ++#ifdef LDAP_CONTROL_VALUESRETURNFILTER ++/* RFC 3876 */ ++PHP_FUNCTION(ldap_ctrl_vlv); ++#endif ++#ifdef LDAP_CONTROL_ASSERT ++/* <draft-zeilenga-ldap-assert> (a Work in Progress) */ ++PHP_FUNCTION(ldap_ctrl_assert); ++#endif ++#ifdef LDAP_CONTROL_PRE_READ ++/* <draft-zeilenga-ldap-readentry> (a Work in Progress) */ ++PHP_FUNCTION(ldap_ctrl_preread); ++PHP_FUNCTION(ldap_ctrl_postread); ++#endif ++#ifdef LDAP_CONTROL_SORTREQUEST ++/* RFC 2891 */ ++PHP_FUNCTION(ldap_ctrl_sort); ++PHP_FUNCTION(ldap_ctrl_sort_resp); ++#endif ++#ifdef LDAP_CONTROL_PAGEDRESULTS ++/* RFC 2696 */ ++PHP_FUNCTION(ldap_ctrl_paged_results); ++PHP_FUNCTION(ldap_ctrl_paged_results_resp); ++#endif ++#ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST ++/* <draft-behera-ldap-password-policy> (a Work in Progress) */ ++PHP_FUNCTION(ldap_ctrl_ppolicy); ++PHP_FUNCTION(ldap_ctrl_ppolicy_resp); ++#endif ++#ifdef LDAP_CONTROL_NOOP ++/* <draft-zeilenga-ldap-noop> (a Work in Progress) */ ++PHP_FUNCTION(ldap_ctrl_noop); ++#endif ++#ifdef LDAP_CONTROL_NO_SUBORDINATES ++/* don't know anything about it */ ++#endif ++#ifdef LDAP_CONTROL_MANAGEDIT ++/* no spec; partially implemented in OpenLDAP 2.3 */ ++PHP_FUNCTION(ldap_ctrl_manageDIT); ++#endif ++#ifdef LDAP_CONTROL_SLURP ++/* don't know anything about it */ ++#endif ++#ifdef LDAP_CONTROL_VALSORT ++/* <> */ ++PHP_FUNCTION(ldap_ctrl_valsort); ++#endif ++#ifdef LDAP_CONTROL_SYNC ++/* <draft-zeilenga-ldup-sync> (a Work in Progress) */ ++PHP_FUNCTION(ldap_ctrl_sync); ++PHP_FUNCTION(ldap_ctrl_sync_state); ++PHP_FUNCTION(ldap_ctrl_sync_done); ++/* TODO: need to handle the SYNC intermediate response message (LDAPIRM) */ ++#endif ++#ifdef LDAP_CONTROL_X_CHAINING_BEHAVIOR ++/* <draft-sermersheim-ldap-chaining> (a Work in Progress) */ ++PHP_FUNCTION(ldap_ctrl_chaining); ++#endif ++#ifdef LDAP_CONTROL_X_INCREMENTAL_VALUES ++/* MS Active Directory */ ++PHP_FUNCTION(ldap_ctrl_incremental_values); ++#endif ++#ifdef LDAP_CONTROL_X_DOMAIN_SCOPE ++/* MS Active Directory */ ++PHP_FUNCTION(ldap_ctrl_domain_scope); ++#endif ++#ifdef LDAP_CONTROL_X_PERMISSIVE_MODIFY ++/* MS Active Directory */ ++PHP_FUNCTION(ldap_ctrl_permissive_modify); ++#endif ++#ifdef LDAP_CONTROL_X_SEARCH_OPTIONS ++/* MS Active Directory */ ++PHP_FUNCTION(ldap_ctrl_search_options); ++#endif ++#ifdef LDAP_CONTROL_X_TREE_DELETE ++/* MS Active Directory */ ++PHP_FUNCTION(ldap_ctrl_tree_delete); ++#endif ++#ifdef LDAP_CONTROL_X_EXTENDED_DN ++/* MS Active Directory */ ++PHP_FUNCTION(ldap_ctrl_extended_dn); ++#endif ++#ifdef LDAP_CONTROL_DUPENT ++/* <draft-ietf-ldapext-ldapv3-dupent> (a Work in Progress) */ ++PHP_FUNCTION(ldap_ctrl_dupent); ++PHP_FUNCTION(ldap_ctrl_dupent_resp); ++PHP_FUNCTION(ldap_ctrl_dupent_done_resp); ++#endif ++#ifdef LDAP_CONTROL_PERSIST_REQUEST ++/* ? */ ++#endif ++#ifdef LDAP_CONTROL_VLVREQUEST ++/* <draft-ietf-ldapext-ldapv3-vlv> (a Work in Progress) */ ++PHP_FUNCTION(ldap_ctrl_vlv); ++PHP_FUNCTION(ldap_ctrl_vlv_resp); ++#endif ++ ++ + ZEND_BEGIN_MODULE_GLOBALS(ldap) + long num_links; + long max_links; + ZEND_END_MODULE_GLOBALS(ldap) diff --git a/databases/php-ldap/options.mk b/databases/php-ldap/options.mk index 15bd8d3710d..90cb61b06f5 100644 --- a/databases/php-ldap/options.mk +++ b/databases/php-ldap/options.mk @@ -1,4 +1,4 @@ -# $NetBSD: options.mk,v 1.3 2011/04/13 13:23:05 adam Exp $ +# $NetBSD: options.mk,v 1.4 2015/04/13 08:04:17 manu Exp $ PKG_OPTIONS_VAR= PKG_OPTIONS.php-ldap PKG_SUPPORTED_OPTIONS= sasl exop @@ -15,7 +15,7 @@ CONFIGURE_ARGS+= --with-ldap-sasl=${PREFIX} .if !empty(PKG_OPTIONS:Mexop) USE_TOOLS+= patch -EXOP_PATCH= ${FILESDIR}/ldap-ctrl-exop.patch +EXOP_PATCH= ${FILESDIR}/ldap-ctrl-exop${PKG_PHP_VERSION}.patch post-patch: ${PATCH} -d ${WRKSRC} -p2 --forward --quiet < ${EXOP_PATCH} .endif |