summaryrefslogtreecommitdiff
path: root/databases/php-ldap/files/ldap-ctrl-exop71.patch
diff options
context:
space:
mode:
Diffstat (limited to 'databases/php-ldap/files/ldap-ctrl-exop71.patch')
-rw-r--r--databases/php-ldap/files/ldap-ctrl-exop71.patch561
1 files changed, 561 insertions, 0 deletions
diff --git a/databases/php-ldap/files/ldap-ctrl-exop71.patch b/databases/php-ldap/files/ldap-ctrl-exop71.patch
new file mode 100644
index 00000000000..112aad548f7
--- /dev/null
+++ b/databases/php-ldap/files/ldap-ctrl-exop71.patch
@@ -0,0 +1,561 @@
+From upstream:
+git diff 035a27cbc63d87a6acc761ce51109bcf47f9c27b \
+ ed8bfcc6ea60c9d5b8c6b10f9e5175237fe28751 -- ext/ldap/ldap.c \
+ ext/ldap/config.m4 ext/ldap/config.w32
+
+Addditionnal uncommitted yet modification for ldap_exop_refresh
+(NB: previous patch had ldap_refresh with different prototype)
+
+--- ext/ldap/config.m4.orig
++++ ext/ldap/config.m4
+@@ -203,9 +203,9 @@
+ 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 ldap_control_find])
++ AC_CHECK_FUNCS([ldap_parse_result ldap_parse_reference ldap_start_tls_s ldap_control_find ldap_parse_extended_result ldap_extended_operation ldap_extended_operation_s ldap_passwd_s ldap_whoami_s ldap_refresh_s])
+
+ dnl
+ dnl SASL check
+ dnl
+--- ext/ldap/config.w32.orig
++++ ext/ldap/config.w32
+@@ -20,8 +20,14 @@
+ AC_DEFINE('HAVE_LDAP_SASL', 1);
+ AC_DEFINE('HAVE_LDAP_SASL_SASL_H', 1);
+ AC_DEFINE('LDAP_DEPRECATED', 1);
+ AC_DEFINE('HAVE_LDAP_CONTROL_FIND', 1);
++ AC_DEFINE('HAVE_LDAP_PARSE_EXTENDED_RESULT', 1);
++ AC_DEFINE('HAVE_LDAP_EXTENDED_OPERATION_S', 1);
++ AC_DEFINE('HAVE_LDAP_PASSWD_S', 1);
++ AC_DEFINE('HAVE_LDAP_WHOAMI_S', 1);
++ AC_DEFINE('HAVE_LDAP_REFRESH_S', 1);
++ AC_DEFINE('HAVE_LDAP_EXTENDED_OPERATION', 1);
+
+ } else {
+ WARNING("ldap not enabled; libraries and headers not found");
+ }
+--- ext/ldap/ldap.c.orig
++++ ext/ldap/ldap.c
+@@ -288,8 +288,86 @@
+
+ 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);
+
++#ifdef HAVE_LDAP_EXTENDED_OPERATION_S
++ REGISTER_STRING_CONSTANT("LDAP_EXOP_START_TLS", LDAP_EXOP_START_TLS, CONST_PERSISTENT | CONST_CS);
++ REGISTER_STRING_CONSTANT("LDAP_EXOP_MODIFY_PASSWD", LDAP_EXOP_MODIFY_PASSWD, CONST_PERSISTENT | CONST_CS);
++ REGISTER_STRING_CONSTANT("LDAP_EXOP_REFRESH", LDAP_EXOP_REFRESH, CONST_PERSISTENT | CONST_CS);
++ REGISTER_STRING_CONSTANT("LDAP_EXOP_WHO_AM_I", LDAP_EXOP_WHO_AM_I, CONST_PERSISTENT | CONST_CS);
++ REGISTER_STRING_CONSTANT("LDAP_EXOP_TURN", LDAP_EXOP_TURN, CONST_PERSISTENT | CONST_CS);
++#endif
++
++/* LDAP Controls */
++/* standard track controls */
++#ifdef LDAP_CONTROL_MANAGEDSAIT
++ /* RFC 3296 */
++ REGISTER_STRING_CONSTANT("LDAP_CONTROL_MANAGEDSAIT", LDAP_CONTROL_MANAGEDSAIT, CONST_PERSISTENT | CONST_CS);
++#endif
++#ifdef LDAP_CONTROL_PROXY_AUTHZ
++ /* RFC 4370 */
++ REGISTER_STRING_CONSTANT("LDAP_CONTROL_PROXY_AUTHZ", LDAP_CONTROL_PROXY_AUTHZ, CONST_PERSISTENT | CONST_CS);
++#endif
++#ifdef LDAP_CONTROL_SUBENTRIES
++ /* RFC 3672 */
++ REGISTER_STRING_CONSTANT("LDAP_CONTROL_SUBENTRIES", LDAP_CONTROL_SUBENTRIES, CONST_PERSISTENT | CONST_CS);
++#endif
++#ifdef LDAP_CONTROL_VALUESRETURNFILTER
++ /* RFC 3876 */
++ REGISTER_STRING_CONSTANT("LDAP_CONTROL_VALUESRETURNFILTER", LDAP_CONTROL_VALUESRETURNFILTER, CONST_PERSISTENT | CONST_CS);
++#endif
++#ifdef LDAP_CONTROL_ASSERT
++ /* RFC 4528 */
++ REGISTER_STRING_CONSTANT("LDAP_CONTROL_ASSERT", LDAP_CONTROL_ASSERT, CONST_PERSISTENT | CONST_CS);
++ /* RFC 4527 */
++ REGISTER_STRING_CONSTANT("LDAP_CONTROL_PRE_READ", LDAP_CONTROL_PRE_READ, CONST_PERSISTENT | CONST_CS);
++ REGISTER_STRING_CONSTANT("LDAP_CONTROL_POST_READ", LDAP_CONTROL_POST_READ, CONST_PERSISTENT | CONST_CS);
++#endif
++#ifdef LDAP_CONTROL_SORTREQUEST
++ /* RFC 2891 */
++ REGISTER_STRING_CONSTANT("LDAP_CONTROL_SORTREQUEST", LDAP_CONTROL_SORTREQUEST, CONST_PERSISTENT | CONST_CS);
++ REGISTER_STRING_CONSTANT("LDAP_CONTROL_SORTRESPONSE", LDAP_CONTROL_SORTRESPONSE, CONST_PERSISTENT | CONST_CS);
++#endif
++/* non-standard track controls */
++#ifdef LDAP_CONTROL_PAGEDRESULTS
++ /* RFC 2696 */
++ REGISTER_STRING_CONSTANT("LDAP_CONTROL_PAGEDRESULTS", LDAP_CONTROL_PAGEDRESULTS, CONST_PERSISTENT | CONST_CS);
++#endif
++#ifdef LDAP_CONTROL_AUTHZID_REQUEST
++ /* RFC 3829 */
++ REGISTER_STRING_CONSTANT("LDAP_CONTROL_AUTHZID_REQUEST", LDAP_CONTROL_AUTHZID_REQUEST, CONST_PERSISTENT | CONST_CS);
++ REGISTER_STRING_CONSTANT("LDAP_CONTROL_AUTHZID_RESPONSE", LDAP_CONTROL_AUTHZID_RESPONSE, CONST_PERSISTENT | CONST_CS);
++#endif
++#ifdef LDAP_CONTROL_SYNC
++ /* LDAP Content Synchronization Operation -- RFC 4533 */
++ REGISTER_STRING_CONSTANT("LDAP_CONTROL_SYNC", LDAP_CONTROL_SYNC, CONST_PERSISTENT | CONST_CS);
++ REGISTER_STRING_CONSTANT("LDAP_CONTROL_SYNC_STATE", LDAP_CONTROL_SYNC_STATE, CONST_PERSISTENT | CONST_CS);
++ REGISTER_STRING_CONSTANT("LDAP_CONTROL_SYNC_DONE", LDAP_CONTROL_SYNC_DONE, CONST_PERSISTENT | CONST_CS);
++#endif
++#ifdef LDAP_CONTROL_DONTUSECOPY
++ /* LDAP Don't Use Copy Control (RFC 6171) */
++ REGISTER_STRING_CONSTANT("LDAP_CONTROL_DONTUSECOPY", LDAP_CONTROL_DONTUSECOPY, CONST_PERSISTENT | CONST_CS);
++#endif
++#ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
++ /* Password policy Controls */
++ REGISTER_STRING_CONSTANT("LDAP_CONTROL_PASSWORDPOLICYREQUEST", LDAP_CONTROL_PASSWORDPOLICYREQUEST, CONST_PERSISTENT | CONST_CS);
++ REGISTER_STRING_CONSTANT("LDAP_CONTROL_PASSWORDPOLICYRESPONSE", LDAP_CONTROL_PASSWORDPOLICYRESPONSE, CONST_PERSISTENT | CONST_CS);
++#endif
++#ifdef LDAP_CONTROL_X_INCREMENTAL_VALUES
++ /* MS Active Directory controls */
++ REGISTER_STRING_CONSTANT("LDAP_CONTROL_X_INCREMENTAL_VALUES", LDAP_CONTROL_X_INCREMENTAL_VALUES, CONST_PERSISTENT | CONST_CS);
++ REGISTER_STRING_CONSTANT("LDAP_CONTROL_X_DOMAIN_SCOPE", LDAP_CONTROL_X_DOMAIN_SCOPE, CONST_PERSISTENT | CONST_CS);
++ REGISTER_STRING_CONSTANT("LDAP_CONTROL_X_PERMISSIVE_MODIFY", LDAP_CONTROL_X_PERMISSIVE_MODIFY, CONST_PERSISTENT | CONST_CS);
++ REGISTER_STRING_CONSTANT("LDAP_CONTROL_X_SEARCH_OPTIONS", LDAP_CONTROL_X_SEARCH_OPTIONS, CONST_PERSISTENT | CONST_CS);
++ REGISTER_STRING_CONSTANT("LDAP_CONTROL_X_TREE_DELETE", LDAP_CONTROL_X_TREE_DELETE, CONST_PERSISTENT | CONST_CS);
++ REGISTER_STRING_CONSTANT("LDAP_CONTROL_X_EXTENDED_DN", LDAP_CONTROL_X_EXTENDED_DN, CONST_PERSISTENT | CONST_CS);
++#endif
++#ifdef LDAP_CONTROL_X_INCREMENTAL_VALUES
++ /* LDAP VLV */
++ REGISTER_STRING_CONSTANT("LDAP_CONTROL_VLVREQUEST", LDAP_CONTROL_VLVREQUEST, CONST_PERSISTENT | CONST_CS);
++ REGISTER_STRING_CONSTANT("LDAP_CONTROL_VLVRESPONSE", LDAP_CONTROL_VLVRESPONSE, CONST_PERSISTENT | CONST_CS);
++#endif
++
+ 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);
+
+@@ -2270,11 +2348,41 @@
+ zval_ptr_dtor(retval);
+ ZVAL_STRING(retval, val);
+ ldap_memfree(val);
+ } break;
+-/* options not implemented
+ case LDAP_OPT_SERVER_CONTROLS:
+ case LDAP_OPT_CLIENT_CONTROLS:
++ {
++ zval tmp1;
++ int num_entries;
++ LDAPControl **ctrls = NULL, **ctrlp;
++
++ if (ldap_get_option(ld->link, option, &ctrls) || ctrls == NULL) {
++ if (ctrls) {
++ ldap_memfree(ctrls);
++ }
++ RETURN_FALSE;
++ }
++
++ zval_ptr_dtor(retval);
++ array_init(retval);
++ num_entries = 0;
++ ctrlp = ctrls;
++ while (*ctrlp != NULL)
++ {
++ array_init(&tmp1);
++ add_assoc_string(&tmp1, "oid", (*ctrlp)->ldctl_oid);
++ add_assoc_bool(&tmp1, "iscritical", ((*ctrlp)->ldctl_iscritical != 0));
++ if ((*ctrlp)->ldctl_value.bv_len) {
++ add_assoc_stringl(&tmp1, "value", (*ctrlp)->ldctl_value.bv_val, (*ctrlp)->ldctl_value.bv_len);
++ }
++ zend_hash_index_update(Z_ARRVAL_P(retval), num_entries, &tmp1);
++ num_entries++;
++ ctrlp++;
++ }
++ ldap_controls_free(ctrls);
++ } break;
++/* options not implemented
+ case LDAP_OPT_API_INFO:
+ case LDAP_OPT_API_FEATURE_INFO:
+ */
+ default:
+@@ -2569,8 +2677,69 @@
+ }
+ /* }}} */
+ #endif
+
++/* {{{ Extended operation response parsing, Pierangelo Masarati */
++#ifdef HAVE_LDAP_PARSE_EXTENDED_RESULT
++/* {{{ proto bool ldap_parse_exop(resource link, resource result [, string retdata [, string retoid]])
++ Extract information from extended operation result */
++PHP_FUNCTION(ldap_parse_exop)
++{
++ zval *link, *result, *retdata, *retoid;
++ ldap_linkdata *ld;
++ LDAPMessage *ldap_result;
++ char *lretoid;
++ struct berval *lretdata;
++ int rc, myargcount = ZEND_NUM_ARGS();
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS(), "rr|z/z/", &link, &result, &retdata, &retoid) != SUCCESS) {
++ WRONG_PARAM_COUNT;
++ }
++
++ if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
++ RETURN_FALSE;
++ }
++
++ if ((ldap_result = (LDAPMessage *)zend_fetch_resource(Z_RES_P(result), "ldap result", le_result)) == NULL) {
++ RETURN_FALSE;
++ }
++
++ rc = ldap_parse_extended_result(ld->link, ldap_result,
++ myargcount > 3 ? &lretoid: NULL,
++ myargcount > 2 ? &lretdata: NULL,
++ 0);
++ if (rc != LDAP_SUCCESS) {
++ php_error_docref(NULL, E_WARNING, "Unable to parse extended operation result: %s", ldap_err2string(rc));
++ RETURN_FALSE;
++ }
++
++ /* Reverse -> fall through */
++ switch (myargcount) {
++ case 4:
++ zval_dtor(retoid);
++ if (lretoid == NULL) {
++ ZVAL_EMPTY_STRING(retoid);
++ } else {
++ ZVAL_STRING(retoid, lretoid);
++ ldap_memfree(lretoid);
++ }
++ case 3:
++ /* use arg #3 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);
++ ldap_memfree(lretdata->bv_val);
++ ldap_memfree(lretdata);
++ }
++ }
++ RETURN_TRUE;
++}
++/* }}} */
++#endif
++/* }}} */
++
+ /* {{{ proto resource ldap_first_reference(resource link, resource result)
+ Return first reference */
+ PHP_FUNCTION(ldap_first_reference)
+ {
+@@ -3156,8 +3325,245 @@
+ }
+ /* }}} */
+ #endif
+
++/* {{{ Extended operations, Pierangelo Masarati */
++#ifdef HAVE_LDAP_EXTENDED_OPERATION_S
++/* {{{ proto ? ldap_exop(resource link, string reqoid [, string reqdata [, string retdata [, string retoid]]])
++ Extended operation */
++PHP_FUNCTION(ldap_exop)
++{
++ zval *link, *reqoid, *reqdata, *retdata, *retoid;
++ char *lreqoid, *lretoid = NULL;
++ struct berval lreqdata, *lretdata = NULL;
++ ldap_linkdata *ld;
++ LDAPMessage *ldap_res;
++ int rc, msgid, myargcount = ZEND_NUM_ARGS();
++ /* int reqoid_len, reqdata_len, retdata_len, retoid_len, retdat_len; */
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS(), "rz|zz/z/", &link, &reqoid, &reqdata, &retdata, &retoid) != SUCCESS) {
++ WRONG_PARAM_COUNT;
++ }
++
++ if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
++ RETURN_FALSE;
++ }
++
++ switch (myargcount) {
++ case 5:
++ case 4:
++ case 3:
++ convert_to_string_ex(reqdata);
++ lreqdata.bv_val = Z_STRVAL_P(reqdata);
++ lreqdata.bv_len = Z_STRLEN_P(reqdata);
++ /* fallthru */
++ case 2:
++ convert_to_string_ex(reqoid);
++ lreqoid = Z_STRVAL_P(reqoid);
++ }
++
++ if (myargcount > 3) {
++ /* synchronous call */
++ rc = ldap_extended_operation_s(ld->link, lreqoid,
++ lreqdata.bv_len > 0 ? &lreqdata: NULL,
++ NULL,
++ NULL,
++ myargcount > 4 ? &lretoid : NULL,
++ &lretdata );
++ if (rc != LDAP_SUCCESS ) {
++ php_error_docref(NULL, E_WARNING, "Extended operation %s failed: %s (%d)", lreqoid, ldap_err2string(rc), rc);
++ RETURN_FALSE;
++ }
++
++ /* Reverse -> fall through */
++ switch (myargcount) {
++ case 5:
++ zval_dtor(retoid);
++ if (lretoid == NULL) {
++ ZVAL_EMPTY_STRING(retoid);
++ } else {
++ ZVAL_STRING(retoid, lretoid);
++ ldap_memfree(lretoid);
++ }
++ 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);
++ ldap_memfree(lretdata->bv_val);
++ ldap_memfree(lretdata);
++ }
++ }
++
++ 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, 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, E_WARNING, "Extended operation %s failed", lreqoid);
++ RETURN_FALSE;
++ }
++
++ /* return a PHP control object */
++ RETVAL_RES(zend_register_resource(ldap_res, le_result));
++}
++/* }}} */
++#endif
++
++#ifdef HAVE_LDAP_PASSWD_S
++/* {{{ proto bool|string ldap_exop_passwd(resource link [, string user [, string oldpw [, string newpw ]]])
++ Passwd modify extended operation */
++PHP_FUNCTION(ldap_exop_passwd)
++{
++ zval *link, *user, *newpw, *oldpw;
++ struct berval luser, loldpw, lnewpw, lgenpasswd;
++ ldap_linkdata *ld;
++ int rc, myargcount = ZEND_NUM_ARGS();
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|zzz", &link, &user, &oldpw, &newpw) == FAILURE) {
++ WRONG_PARAM_COUNT;
++ }
++
++ if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
++ RETURN_FALSE;
++ }
++
++ luser.bv_len = 0;
++ loldpw.bv_len = 0;
++ lnewpw.bv_len = 0;
++
++ switch (myargcount) {
++ case 4:
++ convert_to_string_ex(newpw);
++ lnewpw.bv_val = Z_STRVAL_P(newpw);
++ lnewpw.bv_len = Z_STRLEN_P(newpw);
++
++ case 3:
++ convert_to_string_ex(oldpw);
++ loldpw.bv_val = Z_STRVAL_P(oldpw);
++ loldpw.bv_len = Z_STRLEN_P(oldpw);
++
++ case 2:
++ convert_to_string_ex(user);
++ luser.bv_val = Z_STRVAL_P(user);
++ luser.bv_len = Z_STRLEN_P(user);
++ }
++
++ /* synchronous call */
++ rc = ldap_passwd_s(ld->link, &luser,
++ loldpw.bv_len > 0 ? &loldpw : NULL,
++ lnewpw.bv_len > 0 ? &lnewpw : NULL,
++ &lgenpasswd, NULL, NULL);
++ if (rc != LDAP_SUCCESS ) {
++ php_error_docref(NULL, E_WARNING, "Passwd modify extended operation failed: %s (%d)", ldap_err2string(rc), rc);
++ RETURN_FALSE;
++ }
++
++ if (lnewpw.bv_len == 0) {
++ if (lgenpasswd.bv_len == 0) {
++ RETVAL_EMPTY_STRING();
++ } else {
++ RETVAL_STRINGL(lgenpasswd.bv_val, lgenpasswd.bv_len);
++ }
++ } else {
++ RETURN_TRUE;
++ }
++
++ ldap_memfree(lgenpasswd.bv_val);
++}
++/* }}} */
++#endif
++
++#ifdef HAVE_LDAP_WHOAMI_S
++/* {{{ proto bool|string ldap_exop_whoami(resource link)
++ Whoami extended operation */
++PHP_FUNCTION(ldap_exop_whoami)
++{
++ zval *link;
++ struct berval *lauthzid;
++ ldap_linkdata *ld;
++ int rc, myargcount = ZEND_NUM_ARGS();
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &link) == FAILURE) {
++ WRONG_PARAM_COUNT;
++ }
++
++ if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
++ RETURN_FALSE;
++ }
++
++ /* synchronous call */
++ rc = ldap_whoami_s(ld->link, &lauthzid, NULL, NULL);
++ if (rc != LDAP_SUCCESS ) {
++ php_error_docref(NULL, E_WARNING, "Whoami extended operation failed: %s (%d)", ldap_err2string(rc), rc);
++ RETURN_FALSE;
++ }
++
++ if (lauthzid == NULL) {
++ RETVAL_EMPTY_STRING();
++ } else {
++ RETVAL_STRINGL(lauthzid->bv_val, lauthzid->bv_len);
++ ldap_memfree(lauthzid->bv_val);
++ ldap_memfree(lauthzid);
++ }
++}
++/* }}} */
++#endif
++
++#ifdef HAVE_LDAP_REFRESH_S
++/* {{{ proto int ldap_exop_refresh(resource link , string dn , int ttl)
++ DDS refresh extended operation */
++PHP_FUNCTION(ldap_exop_refresh)
++{
++ zval *link, *dn, *ttl;
++ struct berval ldn;
++ ber_int_t lttl;
++ ber_int_t newttl;
++ ldap_linkdata *ld;
++ int rc;
++
++ if (zend_parse_parameters(ZEND_NUM_ARGS(), "rzz", &link, &dn, &ttl) != SUCCESS) {
++ WRONG_PARAM_COUNT;
++ }
++
++ if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) {
++ RETURN_FALSE;
++ }
++
++ ldn.bv_len = 0;
++ convert_to_string_ex(dn);
++ ldn.bv_val = Z_STRVAL_P(dn);
++ ldn.bv_len = Z_STRLEN_P(dn);
++
++ convert_to_long_ex(ttl);
++ lttl = (ber_int_t)Z_LVAL_P(ttl);
++
++ rc = ldap_refresh_s(ld->link, &ldn, lttl, &newttl, NULL, NULL);
++ if (rc != LDAP_SUCCESS ) {
++ php_error_docref(NULL, E_WARNING,
++ "Refresh extended operation failed: %s (%d)",
++ ldap_err2string(rc), rc);
++ RETURN_FALSE;
++ }
++
++ RETURN_LONG(newttl);
++}
++/* }}} */
++#endif
++
++/* }}} */
++
+ /* {{{ arginfo */
+ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_connect, 0, 0, 0)
+ ZEND_ARG_INFO(0, hostname)
+ ZEND_ARG_INFO(0, port)
+@@ -3431,8 +3837,50 @@
+ 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(0, reqdata)
++ ZEND_ARG_INFO(1, retdata)
++ ZEND_ARG_INFO(1, retoid)
++ZEND_END_ARG_INFO()
++#endif
++
++#ifdef HAVE_LDAP_PASSWD_S
++ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_exop_passwd, 0, 0, 4)
++ ZEND_ARG_INFO(0, link)
++ ZEND_ARG_INFO(0, user)
++ ZEND_ARG_INFO(0, oldpw)
++ ZEND_ARG_INFO(0, newpw)
++ZEND_END_ARG_INFO()
++#endif
++
++#ifdef HAVE_LDAP_WHOAMI_S
++ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_exop_whoami, 0, 0, 1)
++ ZEND_ARG_INFO(0, link)
++ZEND_END_ARG_INFO()
++#endif
++
++#ifdef HAVE_LDAP_REFRESH_S
++ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_exop_refresh, 0, 0, 3)
++ ZEND_ARG_INFO(0, link)
++ ZEND_ARG_INFO(0, dn)
++ ZEND_ARG_INFO(0, ttl)
++ZEND_END_ARG_INFO()
++#endif
++
++#ifdef HAVE_LDAP_PARSE_EXTENDED_RESULT
++ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_parse_exop, 0, 0, 4)
++ ZEND_ARG_INFO(0, link)
++ ZEND_ARG_INFO(0, result)
++ ZEND_ARG_INFO(1, retdata)
++ ZEND_ARG_INFO(1, retoid)
++ZEND_END_ARG_INFO()
++#endif
+ /* }}} */
+
+ /*
+ This is just a small subset of the functionality provided by the LDAP library. All the
+@@ -3495,8 +3943,23 @@
+ #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)
++#endif
++#ifdef HAVE_LDAP_PASSWD_S
++ PHP_FE(ldap_exop_passwd, arginfo_ldap_exop_passwd)
++#endif
++#ifdef HAVE_LDAP_WHOAMI_S
++ PHP_FE(ldap_exop_whoami, arginfo_ldap_exop_whoami)
++#endif
++#ifdef HAVE_LDAP_REFRESH_S
++ PHP_FE(ldap_exop_refresh, arginfo_ldap_exop_refresh)
++#endif
++#ifdef HAVE_LDAP_PARSE_EXTENDED_RESULT
++ PHP_FE(ldap_parse_exop, arginfo_ldap_parse_exop)
++#endif
+ #endif
+
+ #if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC)
+ PHP_FE(ldap_set_rebind_proc, arginfo_ldap_set_rebind_proc)