diff --git a/ext/ldap/config.m4 b/ext/ldap/config.m4 index f77ff5a4c55a6..59af4211f19aa 100644 --- a/ext/ldap/config.m4 +++ b/ext/ldap/config.m4 @@ -204,7 +204,7 @@ if test "$PHP_LDAP" != "no"; then 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 ldap_parse_extended_result ldap_extended_operation ldap_extended_operation_s ldap_passwd_s ldap_whoami_s ldap_refresh_s]) + 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 ldap_whoami_s ldap_refresh_s]) dnl dnl SASL check diff --git a/ext/ldap/config.w32 b/ext/ldap/config.w32 index 626375502ea90..a608ff7132969 100644 --- a/ext/ldap/config.w32 +++ b/ext/ldap/config.w32 @@ -23,7 +23,7 @@ if (PHP_LDAP != "no") { 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_PASSWD', 1); AC_DEFINE('HAVE_LDAP_WHOAMI_S', 1); AC_DEFINE('HAVE_LDAP_REFRESH_S', 1); AC_DEFINE('HAVE_LDAP_EXTENDED_OPERATION', 1); diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index 9740bad9f1912..1b19e0599a25f 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -19,6 +19,7 @@ | Jani Taskinen | | Stig Venaas | | Doug Goldstein | + | Côme Chilliet | | PHP 4.0 updates: Zeev Suraski | +----------------------------------------------------------------------+ */ @@ -135,6 +136,524 @@ static void _free_ldap_result_entry(zend_resource *rsrc) /* {{{ */ } /* }}} */ +/* {{{ Parse controls from and to arrays */ +static void _php_ldap_control_to_array(LDAP *ld, LDAPControl* ctrl, zval* array, int request) +{ + array_init(array); + + add_assoc_string(array, "oid", ctrl->ldctl_oid); + if (request) { + /* iscritical field only makes sense in request controls (which may be obtained by ldap_get_option) */ + add_assoc_bool(array, "iscritical", (ctrl->ldctl_iscritical != 0)); + } + + // If it is a known oid, parse to values + if (strcmp(ctrl->ldctl_oid, LDAP_CONTROL_PASSWORDPOLICYRESPONSE) == 0) { + int expire = 0, grace = 0, rc; + LDAPPasswordPolicyError pperr; + zval value; + + rc = ldap_parse_passwordpolicy_control(ld, ctrl, &expire, &grace, &pperr); + if ( rc == LDAP_SUCCESS ) { + array_init(&value); + add_assoc_long(&value, "expire", expire); + add_assoc_long(&value, "grace", grace); + + if ( pperr != PP_noError ) { + add_assoc_long(&value, "error", pperr); + } + add_assoc_zval(array, "value", &value); + } else { + add_assoc_null(array, "value"); + } + } else if (strcmp(ctrl->ldctl_oid, LDAP_CONTROL_PAGEDRESULTS) == 0) { + int lestimated, rc; + struct berval lcookie; + zval value; + + if (ctrl->ldctl_value.bv_len) { + rc = ldap_parse_pageresponse_control(ld, ctrl, &lestimated, &lcookie); + } else { + /* ldap_parse_pageresponse_control will crash if value is empty */ + rc = -1; + } + if ( rc == LDAP_SUCCESS ) { + array_init(&value); + add_assoc_long(&value, "size", lestimated); + add_assoc_stringl(&value, "cookie", lcookie.bv_val, lcookie.bv_len); + add_assoc_zval(array, "value", &value); + } else { + add_assoc_null(array, "value"); + } + } else if ((strcmp(ctrl->ldctl_oid, LDAP_CONTROL_PRE_READ) == 0) || (strcmp(ctrl->ldctl_oid, LDAP_CONTROL_POST_READ) == 0)) { + BerElement *ber; + struct berval bv; + + ber = ber_init(&ctrl->ldctl_value); + if (ber == NULL) { + add_assoc_null(array, "value"); + } else if (ber_scanf(ber, "{m{" /*}}*/, &bv) == LBER_ERROR) { + add_assoc_null(array, "value"); + } else { + zval value; + + array_init(&value); + add_assoc_stringl(&value, "dn", bv.bv_val, bv.bv_len); + + while (ber_scanf(ber, "{m" /*}*/, &bv) != LBER_ERROR) { + int i; + BerVarray vals = NULL; + zval tmp; + + if (ber_scanf(ber, "[W]", &vals) == LBER_ERROR || vals == NULL) + { + break; + } + + array_init(&tmp); + for (i = 0; vals[i].bv_val != NULL; i++) { + add_next_index_stringl(&tmp, vals[i].bv_val, vals[i].bv_len); + } + add_assoc_zval(&value, bv.bv_val, &tmp); + + ber_bvarray_free(vals); + } + add_assoc_zval(array, "value", &value); + } + + if (ber != NULL) { + ber_free(ber, 1); + } + } else if (strcmp(ctrl->ldctl_oid, LDAP_CONTROL_SORTRESPONSE) == 0) { + zval value; + int errcode, rc; + char* attribute; + + if (ctrl->ldctl_value.bv_len) { + rc = ldap_parse_sortresponse_control(ld, ctrl, &errcode, &attribute); + } else { + rc = -1; + } + if ( rc == LDAP_SUCCESS ) { + array_init(&value); + add_assoc_long(&value, "errcode", errcode); + if (attribute) { + add_assoc_string(&value, "attribute", attribute); + ldap_memfree(attribute); + } + add_assoc_zval(array, "value", &value); + } else { + add_assoc_null(array, "value"); + } + } else if (strcmp(ctrl->ldctl_oid, LDAP_CONTROL_VLVRESPONSE) == 0) { + int target, count, errcode, rc; + struct berval *context; + zval value; + + if (ctrl->ldctl_value.bv_len) { + rc = ldap_parse_vlvresponse_control(ld, ctrl, &target, &count, &context, &errcode); + } else { + rc = -1; + } + if ( rc == LDAP_SUCCESS ) { + array_init(&value); + add_assoc_long(&value, "target", target); + add_assoc_long(&value, "count", count); + add_assoc_long(&value, "errcode", errcode); + add_assoc_stringl(&value, "context", context->bv_val, context->bv_len); + add_assoc_zval(array, "value", &value); + } else { + add_assoc_null(array, "value"); + } + ber_bvfree(context); + } else { + if (ctrl->ldctl_value.bv_len) { + add_assoc_stringl(array, "value", ctrl->ldctl_value.bv_val, ctrl->ldctl_value.bv_len); + } else { + add_assoc_null(array, "value"); + } + } +} + +static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* array) +{ + zval* val; + char * control_oid = NULL; + int control_iscritical = 0, rc = LDAP_SUCCESS; + char** ldap_attrs = NULL; + LDAPSortKey** sort_keys = NULL; + + if ((val = zend_hash_str_find(Z_ARRVAL_P(array), "oid", sizeof("oid") - 1)) == NULL) { + php_error_docref(NULL, E_WARNING, "Control must have an oid key"); + return -1; + } + convert_to_string_ex(val); + control_oid = Z_STRVAL_P(val); + + if ((val = zend_hash_str_find(Z_ARRVAL_P(array), "iscritical", sizeof("iscritical") - 1)) != NULL) { + convert_to_boolean_ex(val); + control_iscritical = (Z_TYPE_P(val) == IS_TRUE); + } else { + control_iscritical = 0; + } + + struct berval *control_value = NULL; + + if ((val = zend_hash_str_find(Z_ARRVAL_P(array), "value", sizeof("value") - 1)) != NULL) { + if (Z_TYPE_P(val) != IS_ARRAY) { + convert_to_string_ex(val); + control_value = ber_memalloc(sizeof * control_value); + if (control_value == NULL) { + rc = -1; + php_error_docref(NULL, E_WARNING, "Failed to allocate control value"); + } else { + control_value->bv_val = Z_STRVAL_P(val); + control_value->bv_len = Z_STRLEN_P(val); + } + } else if (strcmp(control_oid, LDAP_CONTROL_PAGEDRESULTS) == 0) { + zval* tmp; + int pagesize = 1; + struct berval cookie = { 0, NULL }; + if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "size", sizeof("size") - 1)) != NULL) { + convert_to_long_ex(tmp); + pagesize = Z_LVAL_P(tmp); + } + if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "cookie", sizeof("cookie") - 1)) != NULL) { + convert_to_string_ex(tmp); + cookie.bv_val = Z_STRVAL_P(tmp); + cookie.bv_len = Z_STRLEN_P(tmp); + } + control_value = ber_memalloc(sizeof * control_value); + if (control_value == NULL) { + rc = -1; + php_error_docref(NULL, E_WARNING, "Failed to allocate control value"); + } else { + rc = ldap_create_page_control_value(ld, pagesize, &cookie, control_value); + if (rc != LDAP_SUCCESS) { + php_error_docref(NULL, E_WARNING, "Failed to create paged result control value: %s (%d)", ldap_err2string(rc), rc); + } + } + } else if (strcmp(control_oid, LDAP_CONTROL_ASSERT) == 0) { + zval* tmp; + char* assert; + if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "filter", sizeof("filter") - 1)) == NULL) { + rc = -1; + php_error_docref(NULL, E_WARNING, "Filter missing from assert control value array"); + } else { + convert_to_string_ex(tmp); + assert = Z_STRVAL_P(tmp); + control_value = ber_memalloc(sizeof * control_value); + if (control_value == NULL) { + rc = -1; + php_error_docref(NULL, E_WARNING, "Failed to allocate control value"); + } else { + // ldap_create_assertion_control_value does not reset ld_errno, we need to do it ourselves + // See http://www.openldap.org/its/index.cgi/Incoming?id=8674 + int success = LDAP_SUCCESS; + ldap_set_option(ld, LDAP_OPT_RESULT_CODE, &success); + rc = ldap_create_assertion_control_value(ld, assert, control_value); + if (rc != LDAP_SUCCESS) { + php_error_docref(NULL, E_WARNING, "Failed to create assert control value: %s (%d)", ldap_err2string(rc), rc); + } + } + } + } else if (strcmp(control_oid, LDAP_CONTROL_VALUESRETURNFILTER) == 0) { + zval* tmp; + if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "filter", sizeof("filter") - 1)) == NULL) { + rc = -1; + php_error_docref(NULL, E_WARNING, "Filter missing from control value array"); + } else { + BerElement *vrber = ber_alloc_t(LBER_USE_DER); + control_value = ber_memalloc(sizeof * control_value); + if ((control_value == NULL) || (vrber == NULL)) { + rc = -1; + php_error_docref(NULL, E_WARNING, "Failed to allocate control value"); + } else { + convert_to_string_ex(tmp); + if (ldap_put_vrFilter(vrber, Z_STRVAL_P(tmp)) == -1) { + ber_free(vrber, 1); + rc = -1; + php_error_docref(NULL, E_WARNING, "Failed to create control value: Bad ValuesReturnFilter: %s", Z_STRVAL_P(tmp)); + } else { + if (ber_flatten2(vrber, control_value, 0) == -1) { + rc = -1; + } + ber_free(vrber, 1); + } + } + } + } else if ((strcmp(control_oid, LDAP_CONTROL_PRE_READ) == 0) || (strcmp(control_oid, LDAP_CONTROL_POST_READ) == 0)) { + zval* tmp; + if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "attrs", sizeof("attrs") - 1)) == NULL) { + rc = -1; + php_error_docref(NULL, E_WARNING, "Attributes list missing from control value array"); + } else { + BerElement *ber = ber_alloc_t(LBER_USE_DER); + + control_value = ber_memalloc(sizeof * control_value); + if ((control_value == NULL) || (ber == NULL)) { + rc = -1; + php_error_docref(NULL, E_WARNING, "Failed to allocate control value"); + } else { + int num_attribs, i; + zval* attr; + + num_attribs = zend_hash_num_elements(Z_ARRVAL_P(tmp)); + ldap_attrs = safe_emalloc((num_attribs+1), sizeof(char *), 0); + + for (i = 0; iattributeType = Z_STRVAL_P(tmp); + + if ((tmp = zend_hash_str_find(Z_ARRVAL_P(sortkey), "oid", sizeof("oid") - 1)) != NULL) { + convert_to_string_ex(tmp); + sort_keys[i]->orderingRule = Z_STRVAL_P(tmp); + } else { + sort_keys[i]->orderingRule = NULL; + } + + if ((tmp = zend_hash_str_find(Z_ARRVAL_P(sortkey), "reverse", sizeof("reverse") - 1)) != NULL) { + convert_to_boolean_ex(tmp); + sort_keys[i]->reverseOrder = (Z_TYPE_P(tmp) == IS_TRUE); + } else { + sort_keys[i]->reverseOrder = 0; + } + } + sort_keys[num_keys] = NULL; + control_value = ber_memalloc(sizeof * control_value); + if (control_value == NULL) { + rc = -1; + php_error_docref(NULL, E_WARNING, "Failed to allocate control value"); + } else { + rc = ldap_create_sort_control_value(ld, sort_keys, control_value); + if (rc != LDAP_SUCCESS) { + php_error_docref(NULL, E_WARNING, "Failed to create sort control value: %s (%d)", ldap_err2string(rc), rc); + } + } + } else if (strcmp(control_oid, LDAP_CONTROL_VLVREQUEST) == 0) { + zval* tmp; + LDAPVLVInfo vlvInfo; + struct berval attrValue; + struct berval context; + + if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "before", sizeof("before") - 1)) != NULL) { + convert_to_long_ex(tmp); + vlvInfo.ldvlv_before_count = Z_LVAL_P(tmp); + } else { + rc = -1; + php_error_docref(NULL, E_WARNING, "Before key missing from array value for VLV control"); + goto failure; + } + + if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "after", sizeof("after") - 1)) != NULL) { + convert_to_long_ex(tmp); + vlvInfo.ldvlv_after_count = Z_LVAL_P(tmp); + } else { + rc = -1; + php_error_docref(NULL, E_WARNING, "After key missing from array value for VLV control"); + goto failure; + } + + if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "attrvalue", sizeof("attrvalue") - 1)) != NULL) { + convert_to_string_ex(tmp); + attrValue.bv_val = Z_STRVAL_P(tmp); + attrValue.bv_len = Z_STRLEN_P(tmp); + vlvInfo.ldvlv_attrvalue = &attrValue; + } else if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "offset", sizeof("offset") - 1)) != NULL) { + vlvInfo.ldvlv_attrvalue = NULL; + convert_to_long_ex(tmp); + vlvInfo.ldvlv_offset = Z_LVAL_P(tmp); + if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "count", sizeof("count") - 1)) != NULL) { + convert_to_long_ex(tmp); + vlvInfo.ldvlv_count = Z_LVAL_P(tmp); + } else { + rc = -1; + php_error_docref(NULL, E_WARNING, "Count key missing from array value for VLV control"); + goto failure; + } + } else { + rc = -1; + php_error_docref(NULL, E_WARNING, "Missing either attrvalue or offset key from array value for VLV control"); + goto failure; + } + + if ((tmp = zend_hash_str_find(Z_ARRVAL_P(val), "context", sizeof("context") - 1)) != NULL) { + convert_to_string_ex(tmp); + context.bv_val = Z_STRVAL_P(tmp); + context.bv_len = Z_STRLEN_P(tmp); + vlvInfo.ldvlv_context = &context; + } else { + vlvInfo.ldvlv_context = NULL; + } + + control_value = ber_memalloc(sizeof * control_value); + if (control_value == NULL) { + rc = -1; + php_error_docref(NULL, E_WARNING, "Failed to allocate control value"); + } else { + rc = ldap_create_vlv_control_value(ld, &vlvInfo, control_value); + if (rc != LDAP_SUCCESS) { + php_error_docref(NULL, E_WARNING, "Failed to create VLV control value: %s (%d)", ldap_err2string(rc), rc); + } + } + } else { + php_error_docref(NULL, E_WARNING, "Control OID %s does not expect an array as value", control_oid); + rc = -1; + } + } + + if (rc == LDAP_SUCCESS) { + rc = ldap_control_create(control_oid, control_iscritical, control_value, 1, ctrl); + } + +failure: + if (control_value != NULL) { + ber_memfree(control_value); + control_value = NULL; + } + if (ldap_attrs != NULL) { + efree(ldap_attrs); + } + if (sort_keys != NULL) { + LDAPSortKey** sortp = sort_keys; + while (*sortp) { + efree(*sortp); + sortp++; + } + efree(sort_keys); + sort_keys = NULL; + } + + if (rc == LDAP_SUCCESS) { + return LDAP_SUCCESS; + } + + // Failed + *ctrl = NULL; + return -1; +} + +static void _php_ldap_controls_to_array(LDAP *ld, LDAPControl** ctrls, zval* array, int request) +{ + zval tmp1; + LDAPControl **ctrlp; + + array_init(array); + if (ctrls == NULL) { + return; + } + ctrlp = ctrls; + while (*ctrlp != NULL) { + _php_ldap_control_to_array(ld, *ctrlp, &tmp1, request); + add_assoc_zval(array, (*ctrlp)->ldctl_oid, &tmp1); + ctrlp++; + } + ldap_controls_free(ctrls); +} + +static LDAPControl** _php_ldap_controls_from_array(LDAP *ld, zval* array) +{ + int ncontrols; + LDAPControl** ctrlp, **ctrls = NULL; + zval* ctrlarray; + int error = 0; + + ncontrols = zend_hash_num_elements(Z_ARRVAL_P(array)); + ctrls = safe_emalloc((1 + ncontrols), sizeof(*ctrls), 0); + *ctrls = NULL; + ctrlp = ctrls; + ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(array), ctrlarray) { + if (Z_TYPE_P(ctrlarray) != IS_ARRAY) { + php_error_docref(NULL, E_WARNING, "The array value must contain only arrays, where each array is a control"); + error = 1; + break; + } + + if (_php_ldap_control_from_array(ld, ctrlp, ctrlarray) == LDAP_SUCCESS) { + ++ctrlp; + } else { + error = 1; + break; + } + + *ctrlp = NULL; + } ZEND_HASH_FOREACH_END(); + + if (error) { + ctrlp = ctrls; + while (*ctrlp) { + ldap_control_free(*ctrlp); + ctrlp++; + } + efree(ctrls); + ctrls = NULL; + } + + return ctrls; +} + +static void _php_ldap_controls_free (LDAPControl*** ctrls) +{ + LDAPControl **ctrlp; + + if (*ctrls) { + ctrlp = *ctrls; + while (*ctrlp) { + ldap_control_free(*ctrlp); + ctrlp++; + } + efree(*ctrls); + *ctrls = NULL; + } +} +/* }}} */ + /* {{{ PHP_INI_BEGIN */ PHP_INI_BEGIN() @@ -355,7 +874,7 @@ PHP_MINIT_FUNCTION(ldap) 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 +#ifdef LDAP_CONTROL_VLVREQUEST /* 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); @@ -637,6 +1156,83 @@ PHP_FUNCTION(ldap_bind) } /* }}} */ +/* {{{ proto resource ldap_bind_ext(resource link [, string dn [, string password [, serverctrls]]]) + Bind to LDAP directory */ +PHP_FUNCTION(ldap_bind_ext) +{ + zval *serverctrls = NULL; + zval *link; + char *ldap_bind_dn = NULL, *ldap_bind_pw = NULL; + size_t ldap_bind_dnlen, ldap_bind_pwlen; + ldap_linkdata *ld; + LDAPControl **lserverctrls = NULL; + LDAPMessage *ldap_res; + int rc; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|ssa", &link, &ldap_bind_dn, &ldap_bind_dnlen, &ldap_bind_pw, &ldap_bind_pwlen, &serverctrls) != SUCCESS) { + RETURN_FALSE; + } + + if ((ld = (ldap_linkdata *)zend_fetch_resource(Z_RES_P(link), "ldap link", le_link)) == NULL) { + RETURN_FALSE; + } + + if (ldap_bind_dn != NULL && memchr(ldap_bind_dn, '\0', ldap_bind_dnlen) != NULL) { + _set_lderrno(ld->link, LDAP_INVALID_CREDENTIALS); + php_error_docref(NULL, E_WARNING, "DN contains a null byte"); + RETURN_FALSE; + } + + if (ldap_bind_pw != NULL && memchr(ldap_bind_pw, '\0', ldap_bind_pwlen) != NULL) { + _set_lderrno(ld->link, LDAP_INVALID_CREDENTIALS); + php_error_docref(NULL, E_WARNING, "Password contains a null byte"); + RETURN_FALSE; + } + + if (serverctrls) { + lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls); + if (lserverctrls == NULL) { + RETVAL_FALSE; + goto cleanup; + } + } + + { + /* ldap_simple_bind() is deprecated, use ldap_sasl_bind() instead */ + struct berval cred; + int msgid; + + cred.bv_val = ldap_bind_pw; + cred.bv_len = ldap_bind_pw ? ldap_bind_pwlen : 0; + /* asynchronous call */ + rc = ldap_sasl_bind(ld->link, ldap_bind_dn, LDAP_SASL_SIMPLE, &cred, + lserverctrls, NULL, &msgid); + if (rc != LDAP_SUCCESS ) { + php_error_docref(NULL, E_WARNING, "Unable to bind to server: %s (%d)", ldap_err2string(rc), rc); + RETVAL_FALSE; + goto cleanup; + } + + rc = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res); + if (rc == -1) { + php_error_docref(NULL, E_WARNING, "Bind operation failed"); + RETVAL_FALSE; + goto cleanup; + } + + /* return a PHP control object */ + RETVAL_RES(zend_register_resource(ldap_res, le_result)); + } + +cleanup: + if (lserverctrls) { + _php_ldap_controls_free(&lserverctrls); + } + + return; +} +/* }}} */ + #ifdef HAVE_LDAP_SASL typedef struct { char *mech; @@ -827,22 +1423,24 @@ static void php_set_opts(LDAP *ldap, int sizelimit, int timelimit, int deref, in */ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope) { - zval *link, *base_dn, *filter, *attrs = NULL, *attr; + zval *link, *base_dn, *filter, *attrs = NULL, *attr, *serverctrls = NULL; zend_long attrsonly, sizelimit, timelimit, deref; char *ldap_base_dn = NULL, *ldap_filter = NULL, **ldap_attrs = NULL; ldap_linkdata *ld = NULL; LDAPMessage *ldap_res; + LDAPControl **lserverctrls = NULL; int ldap_attrsonly = 0, ldap_sizelimit = -1, ldap_timelimit = -1, ldap_deref = -1; int old_ldap_sizelimit = -1, old_ldap_timelimit = -1, old_ldap_deref = -1; int num_attribs = 0, ret = 1, i, errno, argcount = ZEND_NUM_ARGS(); - if (zend_parse_parameters(argcount, "zzz|allll", &link, &base_dn, &filter, &attrs, &attrsonly, - &sizelimit, &timelimit, &deref) == FAILURE) { + if (zend_parse_parameters(argcount, "zzz|alllla", &link, &base_dn, &filter, &attrs, &attrsonly, + &sizelimit, &timelimit, &deref, &serverctrls) == FAILURE) { return; } /* Reverse -> fall through */ switch (argcount) { + case 9: case 8: ldap_deref = deref; case 7: @@ -945,10 +1543,20 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope) ldap_filter = Z_STRVAL_P(entry); } + if (argcount > 8) { + // We have to parse controls again for each link as they use it + _php_ldap_controls_free(&lserverctrls); + lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls); + if (lserverctrls == NULL) { + rcs[i] = -1; + continue; + } + } + php_set_opts(ld->link, ldap_sizelimit, ldap_timelimit, ldap_deref, &old_ldap_sizelimit, &old_ldap_timelimit, &old_ldap_deref); /* Run the actual search */ - ldap_search_ext(ld->link, ldap_base_dn, scope, ldap_filter, ldap_attrs, ldap_attrsonly, NULL, NULL, NULL, ldap_sizelimit, &rcs[i]); + ldap_search_ext(ld->link, ldap_base_dn, scope, ldap_filter, ldap_attrs, ldap_attrsonly, lserverctrls, NULL, NULL, ldap_sizelimit, &rcs[i]); lds[i] = ld; zend_hash_move_forward(Z_ARRVAL_P(link)); } @@ -986,10 +1594,18 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope) goto cleanup; } + if (argcount > 8) { + lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls); + if (lserverctrls == NULL) { + ret = 0; + goto cleanup; + } + } + php_set_opts(ld->link, ldap_sizelimit, ldap_timelimit, ldap_deref, &old_ldap_sizelimit, &old_ldap_timelimit, &old_ldap_deref); /* Run the actual search */ - errno = ldap_search_ext_s(ld->link, ldap_base_dn, scope, ldap_filter, ldap_attrs, ldap_attrsonly, NULL, NULL, NULL, ldap_sizelimit, &ldap_res); + errno = ldap_search_ext_s(ld->link, ldap_base_dn, scope, ldap_filter, ldap_attrs, ldap_attrsonly, lserverctrls, NULL, NULL, ldap_sizelimit, &ldap_res); if (errno != LDAP_SUCCESS && errno != LDAP_SIZELIMIT_EXCEEDED @@ -1027,10 +1643,13 @@ static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope) if (!ret) { RETVAL_BOOL(ret); } + if (lserverctrls) { + _php_ldap_controls_free(&lserverctrls); + } } /* }}} */ -/* {{{ proto resource ldap_read(resource|array link, string base_dn, string filter [, array attrs [, int attrsonly [, int sizelimit [, int timelimit [, int deref]]]]]) +/* {{{ proto resource ldap_read(resource|array link, string base_dn, string filter [, array attrs [, int attrsonly [, int sizelimit [, int timelimit [, int deref [, array servercontrols]]]]]]) Read an entry */ PHP_FUNCTION(ldap_read) { @@ -1038,7 +1657,7 @@ PHP_FUNCTION(ldap_read) } /* }}} */ -/* {{{ proto resource ldap_list(resource|array link, string base_dn, string filter [, array attrs [, int attrsonly [, int sizelimit [, int timelimit [, int deref]]]]]) +/* {{{ proto resource ldap_list(resource|array link, string base_dn, string filter [, array attrs [, int attrsonly [, int sizelimit [, int timelimit [, int deref [, array servercontrols]]]]]]) Single-level search */ PHP_FUNCTION(ldap_list) { @@ -1046,7 +1665,7 @@ PHP_FUNCTION(ldap_list) } /* }}} */ -/* {{{ proto resource ldap_search(resource|array link, string base_dn, string filter [, array attrs [, int attrsonly [, int sizelimit [, int timelimit [, int deref]]]]]) +/* {{{ proto resource ldap_search(resource|array link, string base_dn, string filter [, array attrs [, int attrsonly [, int sizelimit [, int timelimit [, int deref [, array servercontrols]]]]]]) Search LDAP tree under base_dn */ PHP_FUNCTION(ldap_search) { @@ -1535,20 +2154,23 @@ PHP_FUNCTION(ldap_dn2ufn) #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 *serverctrls = NULL; zval *link, *entry, *value, *ivalue; ldap_linkdata *ld; char *dn; LDAPMod **ldap_mods; - int i, j, num_attribs, num_values; + LDAPControl **lserverctrls = NULL; + LDAPMessage *ldap_res; + int i, j, num_attribs, num_values, msgid; size_t dn_len; int *num_berval; zend_string *attribute; zend_ulong index; int is_full_add=0; /* flag for full add operation so ldap_mod_add can be put back into oper, gerrit THomson */ - if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsa/", &link, &dn, &dn_len, &entry) != SUCCESS) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsa/|a", &link, &dn, &dn_len, &entry, &serverctrls) != SUCCESS) { return; } @@ -1616,7 +2238,7 @@ static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper) num_berval[i] = j; num_attribs = i + 1; RETVAL_FALSE; - goto errexit; + goto cleanup; } convert_to_string_ex(ivalue); ldap_mods[i]->mod_bvalues[j] = (struct berval *) emalloc (sizeof(struct berval)); @@ -1629,20 +2251,58 @@ static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper) } ldap_mods[num_attribs] = NULL; + if (serverctrls) { + lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls); + if (lserverctrls == NULL) { + RETVAL_FALSE; + goto cleanup; + } + } + /* check flag to see if do_mod was called to perform full add , gerrit thomson */ if (is_full_add == 1) { - if ((i = ldap_add_ext_s(ld->link, dn, ldap_mods, NULL, NULL)) != LDAP_SUCCESS) { + if (ext) { + i = ldap_add_ext(ld->link, dn, ldap_mods, lserverctrls, NULL, &msgid); + } else { + i = ldap_add_ext_s(ld->link, dn, ldap_mods, lserverctrls, NULL); + } + if (i != LDAP_SUCCESS) { php_error_docref(NULL, E_WARNING, "Add: %s", ldap_err2string(i)); RETVAL_FALSE; + } else if (ext) { + i = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res); + if (i == -1) { + php_error_docref(NULL, E_WARNING, "Add operation failed"); + RETVAL_FALSE; + goto cleanup; + } + + /* return a PHP control object */ + RETVAL_RES(zend_register_resource(ldap_res, le_result)); } else RETVAL_TRUE; } else { - if ((i = ldap_modify_ext_s(ld->link, dn, ldap_mods, NULL, NULL)) != LDAP_SUCCESS) { + if (ext) { + i = ldap_modify_ext(ld->link, dn, ldap_mods, lserverctrls, NULL, &msgid); + } else { + i = ldap_modify_ext_s(ld->link, dn, ldap_mods, lserverctrls, NULL); + } + if (i != LDAP_SUCCESS) { php_error_docref(NULL, E_WARNING, "Modify: %s", ldap_err2string(i)); RETVAL_FALSE; + } else if (ext) { + i = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res); + if (i == -1) { + php_error_docref(NULL, E_WARNING, "Modify operation failed"); + RETVAL_FALSE; + goto cleanup; + } + + /* return a PHP control object */ + RETVAL_RES(zend_register_resource(ldap_res, le_result)); } else RETVAL_TRUE; } -errexit: +cleanup: for (i = 0; i < num_attribs; i++) { efree(ldap_mods[i]->mod_type); for (j = 0; j < num_berval[i]; j++) { @@ -1654,56 +2314,95 @@ static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper) efree(num_berval); efree(ldap_mods); + if (lserverctrls) { + _php_ldap_controls_free(&lserverctrls); + } + return; } /* }}} */ -/* {{{ proto bool ldap_add(resource link, string dn, array entry) +/* {{{ proto bool ldap_add(resource link, string dn, array entry [, array servercontrols]) 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); + php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_LD_FULL_ADD, 0); +} +/* }}} */ + +/* {{{ proto resource ldap_add_ext(resource link, string dn, array entry [, array servercontrols]) + Add entries to LDAP directory */ +PHP_FUNCTION(ldap_add_ext) +{ + php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_LD_FULL_ADD, 1); } /* }}} */ /* three functions for attribute base modifications, gerrit Thomson */ -/* {{{ proto bool ldap_mod_replace(resource link, string dn, array entry) +/* {{{ proto bool ldap_mod_replace(resource link, string dn, array entry [, array servercontrols]) 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 resource ldap_mod_replace_ext(resource link, string dn, array entry [, array servercontrols]) + 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 bool ldap_mod_add(resource link, string dn, array entry) +/* {{{ proto bool ldap_mod_add(resource link, string dn, array entry [, array servercontrols]) 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) +/* {{{ proto resource ldap_mod_add(resource link, string dn, array entry [, array servercontrols]) + Add attribute values to current */ +PHP_FUNCTION(ldap_mod_add_ext) +{ + php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_ADD, 1); +} +/* }}} */ + +/* {{{ proto bool ldap_mod_del(resource link, string dn, array entry [, array servercontrols]) 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) +/* {{{ proto resource ldap_mod_del_ext(resource link, string dn, array entry [, array servercontrols]) + Delete attribute values */ +PHP_FUNCTION(ldap_mod_del_ext) { + php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_DELETE, 1); +} +/* }}} */ + +/* {{{ php_ldap_do_delete + */ +static void php_ldap_do_delete(INTERNAL_FUNCTION_PARAMETERS, int ext) +{ + zval *serverctrls = NULL; zval *link; ldap_linkdata *ld; + LDAPControl **lserverctrls = NULL; + LDAPMessage *ldap_res; char *dn; - int rc; + int rc, msgid; size_t dn_len; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &link, &dn, &dn_len) != SUCCESS) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs|a", &link, &dn, &dn_len, &serverctrls) != SUCCESS) { return; } @@ -1711,12 +2410,59 @@ PHP_FUNCTION(ldap_delete) RETURN_FALSE; } - if ((rc = ldap_delete_ext_s(ld->link, dn, NULL, NULL)) != LDAP_SUCCESS) { + if (serverctrls) { + lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls); + if (lserverctrls == NULL) { + RETVAL_FALSE; + goto cleanup; + } + } + + if (ext) { + rc = ldap_delete_ext(ld->link, dn, lserverctrls, NULL, &msgid); + } else { + rc = ldap_delete_ext_s(ld->link, dn, lserverctrls, NULL); + } + if (rc != LDAP_SUCCESS) { php_error_docref(NULL, E_WARNING, "Delete: %s", ldap_err2string(rc)); - RETURN_FALSE; + RETVAL_FALSE; + goto cleanup; + } else if (ext) { + rc = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res); + if (rc == -1) { + php_error_docref(NULL, E_WARNING, "Delete operation failed"); + RETVAL_FALSE; + goto cleanup; + } + + /* return a PHP control object */ + RETVAL_RES(zend_register_resource(ldap_res, le_result)); + } else { + RETVAL_TRUE; } - RETURN_TRUE; +cleanup: + if (lserverctrls) { + _php_ldap_controls_free(&lserverctrls); + } + + return; +} +/* }}} */ + +/* {{{ proto bool ldap_delete(resource link, string dn [, array servercontrols]) + Delete an entry from a directory */ +PHP_FUNCTION(ldap_delete) +{ + php_ldap_do_delete(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); +} +/* }}} */ + +/* {{{ proto resource ldap_delete_ext(resource link, string dn [, array servercontrols]) + Delete an entry from a directory */ +PHP_FUNCTION(ldap_delete_ext) +{ + php_ldap_do_delete(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); } /* }}} */ @@ -1763,10 +2509,11 @@ static void _ldap_hash_fetch(zval *hashTbl, const char *key, zval **out) } /* }}} */ -/* {{{ proto bool ldap_modify_batch(resource link, string dn, array modifs) +/* {{{ proto bool ldap_modify_batch(resource link, string dn, array modifs [, array servercontrols]) Perform multiple modifications as part of one operation */ PHP_FUNCTION(ldap_modify_batch) { + zval *serverctrls = NULL; ldap_linkdata *ld; zval *link, *mods, *mod, *modinfo, *modval; zval *attrib, *modtype, *vals; @@ -1776,6 +2523,7 @@ PHP_FUNCTION(ldap_modify_batch) int i, j, k; int num_mods, num_modprops, num_modvals; LDAPMod **ldap_mods; + LDAPControl **lserverctrls = NULL; uint32_t oper; /* @@ -1802,7 +2550,7 @@ PHP_FUNCTION(ldap_modify_batch) ); */ - if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsa/", &link, &dn, &dn_len, &mods) != SUCCESS) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsa/|a", &link, &dn, &dn_len, &mods, &serverctrls) != SUCCESS) { return; } @@ -2030,8 +2778,16 @@ PHP_FUNCTION(ldap_modify_batch) /* NULL-terminate modifications */ ldap_mods[num_mods] = NULL; + if (serverctrls) { + lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls); + if (lserverctrls == NULL) { + RETVAL_FALSE; + goto cleanup; + } + } + /* perform (finally) */ - if ((i = ldap_modify_ext_s(ld->link, dn, ldap_mods, NULL, NULL)) != LDAP_SUCCESS) { + if ((i = ldap_modify_ext_s(ld->link, dn, ldap_mods, lserverctrls, NULL)) != LDAP_SUCCESS) { php_error_docref(NULL, E_WARNING, "Batch Modify: %s", ldap_err2string(i)); RETVAL_FALSE; } else RETVAL_TRUE; @@ -2062,6 +2818,10 @@ PHP_FUNCTION(ldap_modify_batch) /* the modifications array */ efree(ldap_mods); + + if (lserverctrls) { + _php_ldap_controls_free(&lserverctrls); + } } } /* }}} */ @@ -2125,14 +2885,16 @@ PHP_FUNCTION(ldap_error) Determine if an entry has a specific value for one of its attributes */ PHP_FUNCTION(ldap_compare) { + zval *serverctrls = NULL; zval *link; char *dn, *attr, *value; size_t dn_len, attr_len, value_len; ldap_linkdata *ld; + LDAPControl **lserverctrls = NULL; int errno; struct berval lvalue; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsss", &link, &dn, &dn_len, &attr, &attr_len, &value, &value_len) != SUCCESS) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsss|a", &link, &dn, &dn_len, &attr, &attr_len, &value, &value_len, &serverctrls) != SUCCESS) { return; } @@ -2140,23 +2902,39 @@ PHP_FUNCTION(ldap_compare) RETURN_FALSE; } + if (serverctrls) { + lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls); + if (lserverctrls == NULL) { + RETVAL_FALSE; + goto cleanup; + } + } + lvalue.bv_val = value; lvalue.bv_len = value_len; - errno = ldap_compare_ext_s(ld->link, dn, attr, &lvalue, NULL, NULL); + errno = ldap_compare_ext_s(ld->link, dn, attr, &lvalue, lserverctrls, NULL); switch (errno) { case LDAP_COMPARE_TRUE: - RETURN_TRUE; + RETVAL_TRUE; break; case LDAP_COMPARE_FALSE: - RETURN_FALSE; + RETVAL_FALSE; break; + + default: + php_error_docref(NULL, E_WARNING, "Compare: %s", ldap_err2string(errno)); + RETVAL_LONG(-1); + } + +cleanup: + if (lserverctrls) { + _php_ldap_controls_free(&lserverctrls); } - php_error_docref(NULL, E_WARNING, "Compare: %s", ldap_err2string(errno)); - RETURN_LONG(-1); + return; } /* }}} */ @@ -2346,9 +3124,7 @@ PHP_FUNCTION(ldap_get_option) case LDAP_OPT_SERVER_CONTROLS: case LDAP_OPT_CLIENT_CONTROLS: { - zval tmp1; - int num_entries; - LDAPControl **ctrls = NULL, **ctrlp; + LDAPControl **ctrls = NULL; if (ldap_get_option(ld->link, option, &ctrls) || ctrls == NULL) { if (ctrls) { @@ -2356,24 +3132,7 @@ PHP_FUNCTION(ldap_get_option) } 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); + _php_ldap_controls_to_array(ld->link, ctrls, retval, 1); } break; /* options not implemented case LDAP_OPT_API_INFO: @@ -2539,62 +3298,24 @@ PHP_FUNCTION(ldap_set_option) case LDAP_OPT_SERVER_CONTROLS: case LDAP_OPT_CLIENT_CONTROLS: { - LDAPControl *ctrl, **ctrls, **ctrlp; - zval *ctrlval, *val; - int ncontrols; - char error=0; + LDAPControl **ctrls; + int rc; if (Z_TYPE_P(newval) != IS_ARRAY) { php_error_docref(NULL, E_WARNING, "Expected array value for this option"); RETURN_FALSE; } - ncontrols = zend_hash_num_elements(Z_ARRVAL_P(newval)); - ctrls = safe_emalloc((1 + ncontrols), sizeof(*ctrls), 0); - *ctrls = NULL; - ctrlp = ctrls; - ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(newval), ctrlval) { - if (Z_TYPE_P(ctrlval) != IS_ARRAY) { - php_error_docref(NULL, E_WARNING, "The array value must contain only arrays, where each array is a control"); - error = 1; - break; - } - if ((val = zend_hash_str_find(Z_ARRVAL_P(ctrlval), "oid", sizeof("oid") - 1)) == NULL) { - php_error_docref(NULL, E_WARNING, "Control must have an oid key"); - error = 1; - break; - } - ctrl = *ctrlp = emalloc(sizeof(**ctrlp)); - convert_to_string_ex(val); - ctrl->ldctl_oid = Z_STRVAL_P(val); - if ((val = zend_hash_str_find(Z_ARRVAL_P(ctrlval), "value", sizeof("value") - 1)) != NULL) { - convert_to_string_ex(val); - ctrl->ldctl_value.bv_val = Z_STRVAL_P(val); - ctrl->ldctl_value.bv_len = Z_STRLEN_P(val); - } else { - ctrl->ldctl_value.bv_val = NULL; - ctrl->ldctl_value.bv_len = 0; - } - if ((val = zend_hash_str_find(Z_ARRVAL_P(ctrlval), "iscritical", sizeof("iscritical") - 1)) != NULL) { - convert_to_boolean_ex(val); - ctrl->ldctl_iscritical = Z_TYPE_P(val) == IS_TRUE; - } else { - ctrl->ldctl_iscritical = 0; - } - ++ctrlp; - *ctrlp = NULL; - } ZEND_HASH_FOREACH_END(); - if (!error) { - error = ldap_set_option(ldap, option, ctrls); - } - ctrlp = ctrls; - while (*ctrlp) { - efree(*ctrlp); - ctrlp++; - } - efree(ctrls); - if (error) { + ctrls = _php_ldap_controls_from_array(ldap, newval); + + if (ctrls == NULL) { RETURN_FALSE; + } else { + rc = ldap_set_option(ldap, option, ctrls); + _php_ldap_controls_free(&ctrls); + if (rc != LDAP_SUCCESS) { + RETURN_FALSE; + } } } break; default: @@ -2605,18 +3326,19 @@ PHP_FUNCTION(ldap_set_option) /* }}} */ #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 &controls]]]]) 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; + LDAPControl **lserverctrls = NULL, **ctrlp = NULL; char **lreferrals, **refp; char *lmatcheddn, *lerrmsg; - int rc, lerrcode, myargcount = ZEND_NUM_ARGS(); + int rc, lerrcode, myargcount = ZEND_NUM_ARGS(), ber_decode_error_count = -1; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "rrz/|z/z/z/", &link, &result, &errcode, &matcheddn, &errmsg, &referrals) != SUCCESS) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "rrz/|z/z/z/z/", &link, &result, &errcode, &matcheddn, &errmsg, &referrals, &serverctrls) != SUCCESS) { return; } @@ -2632,7 +3354,7 @@ PHP_FUNCTION(ldap_parse_result) 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, E_WARNING, "Unable to parse result: %s", ldap_err2string(rc)); @@ -2644,6 +3366,8 @@ PHP_FUNCTION(ldap_parse_result) /* Reverse -> fall through */ switch (myargcount) { + case 7: + _php_ldap_controls_to_array(ld->link, lserverctrls, serverctrls, 0); case 6: zval_ptr_dtor(referrals); array_init(referrals); @@ -2845,18 +3569,21 @@ PHP_FUNCTION(ldap_parse_reference) /* }}} */ #endif -/* {{{ proto bool ldap_rename(resource link, string dn, string newrdn, string newparent, bool deleteoldrdn) - Modify the name of an entry */ -PHP_FUNCTION(ldap_rename) +/* {{{ php_ldap_do_rename + */ +static void php_ldap_do_rename(INTERNAL_FUNCTION_PARAMETERS, int ext) { + zval *serverctrls = NULL; zval *link; ldap_linkdata *ld; - int rc; + LDAPControl **lserverctrls = NULL; + LDAPMessage *ldap_res; + int rc, msgid; char *dn, *newrdn, *newparent; size_t dn_len, newrdn_len, newparent_len; zend_bool deleteoldrdn; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsssb", &link, &dn, &dn_len, &newrdn, &newrdn_len, &newparent, &newparent_len, &deleteoldrdn) != SUCCESS) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "rsssb|a", &link, &dn, &dn_len, &newrdn, &newrdn_len, &newparent, &newparent_len, &deleteoldrdn, &serverctrls) != SUCCESS) { return; } @@ -2869,20 +3596,74 @@ PHP_FUNCTION(ldap_rename) } #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP - rc = ldap_rename_s(ld->link, dn, newrdn, newparent, deleteoldrdn, NULL, NULL); + if (serverctrls) { + lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls); + if (lserverctrls == NULL) { + RETVAL_FALSE; + goto cleanup; + } + } + + if (ext) { + rc = ldap_rename(ld->link, dn, newrdn, newparent, deleteoldrdn, lserverctrls, NULL, &msgid); + } else { + rc = ldap_rename_s(ld->link, dn, newrdn, newparent, deleteoldrdn, lserverctrls, NULL); + } #else if (newparent_len != 0) { php_error_docref(NULL, E_WARNING, "You are using old LDAP API, newparent must be the empty string, can only modify RDN"); RETURN_FALSE; } + if (serverctrls) { + php_error_docref(NULL, E_WARNING, "You are using old LDAP API, controls are not supported"); + RETURN_FALSE; + } + if (ext) { + php_error_docref(NULL, E_WARNING, "You are using old LDAP API, ldap_rename_ext is not supported"); + RETURN_FALSE; + } /* could support old APIs but need check for ldap_modrdn2()/ldap_modrdn() */ rc = ldap_modrdn2_s(ld->link, dn, newrdn, deleteoldrdn); #endif - if (rc == LDAP_SUCCESS) { - RETURN_TRUE; + if (rc != LDAP_SUCCESS) { + RETVAL_FALSE; + } else if (ext) { + rc = ldap_result(ld->link, msgid, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res); + if (rc == -1) { + php_error_docref(NULL, E_WARNING, "Rename operation failed"); + RETVAL_FALSE; + goto cleanup; + } + + /* return a PHP control object */ + RETVAL_RES(zend_register_resource(ldap_res, le_result)); + } else { + RETVAL_TRUE; } - RETURN_FALSE; + +cleanup: + if (lserverctrls) { + _php_ldap_controls_free(&lserverctrls); + } + + return; +} +/* }}} */ + +/* {{{ proto bool ldap_rename(resource link, string dn, string newrdn, string newparent, bool deleteoldrdn [, array servercontrols]) + Modify the name of an entry */ +PHP_FUNCTION(ldap_rename) +{ + php_ldap_do_rename(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0); +} +/* }}} */ + +/* {{{ proto resource ldap_rename_ext(resource link, string dn, string newrdn, string newparent, bool deleteoldrdn [, array servercontrols]) + Modify the name of an entry */ +PHP_FUNCTION(ldap_rename_ext) +{ + php_ldap_do_rename(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1); } /* }}} */ @@ -3330,16 +4111,17 @@ PHP_FUNCTION(ldap_control_paged_result_response) Extended operation */ PHP_FUNCTION(ldap_exop) { - zval *servercontrols; + zval *serverctrls = NULL; zval *link, *retdata = NULL, *retoid = NULL; char *lretoid = NULL; zend_string *reqoid, *reqdata = NULL; struct berval lreqdata, *lretdata = NULL; ldap_linkdata *ld; LDAPMessage *ldap_res; + LDAPControl **lserverctrls = NULL; int rc, msgid; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "rS|S!zz/z/", &link, &reqoid, &reqdata, &servercontrols, &retdata, &retoid) != SUCCESS) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "rS|S!a!z/z/", &link, &reqoid, &reqdata, &serverctrls, &retdata, &retoid) != SUCCESS) { return; } @@ -3354,17 +4136,26 @@ PHP_FUNCTION(ldap_exop) lreqdata.bv_len = 0; } + if (serverctrls) { + lserverctrls = _php_ldap_controls_from_array(ld->link, serverctrls); + if (lserverctrls == NULL) { + RETVAL_FALSE; + goto cleanup; + } + } + if (retdata) { /* synchronous call */ rc = ldap_extended_operation_s(ld->link, ZSTR_VAL(reqoid), lreqdata.bv_len > 0 ? &lreqdata: NULL, - NULL, + lserverctrls, NULL, retoid ? &lretoid : NULL, &lretdata ); if (rc != LDAP_SUCCESS ) { php_error_docref(NULL, E_WARNING, "Extended operation %s failed: %s (%d)", ZSTR_VAL(reqoid), ldap_err2string(rc), rc); - RETURN_FALSE; + RETVAL_FALSE; + goto cleanup; } if (retoid) { @@ -3386,41 +4177,55 @@ PHP_FUNCTION(ldap_exop) ZVAL_EMPTY_STRING(retdata); } - RETURN_TRUE; + RETVAL_TRUE; + goto cleanup; } /* asynchronous call */ rc = ldap_extended_operation(ld->link, ZSTR_VAL(reqoid), lreqdata.bv_len > 0 ? &lreqdata: NULL, - NULL, NULL, &msgid); + lserverctrls, + NULL, + &msgid); if (rc != LDAP_SUCCESS ) { php_error_docref(NULL, E_WARNING, "Extended operation %s failed: %s (%d)", ZSTR_VAL(reqoid), ldap_err2string(rc), rc); - RETURN_FALSE; + RETVAL_FALSE; + goto cleanup; } 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", ZSTR_VAL(reqoid)); - RETURN_FALSE; + RETVAL_FALSE; + goto cleanup; } /* return a PHP control object */ RETVAL_RES(zend_register_resource(ldap_res, le_result)); + + cleanup: + if (lserverctrls) { + _php_ldap_controls_free(&lserverctrls); + } } /* }}} */ #endif -#ifdef HAVE_LDAP_PASSWD_S -/* {{{ proto bool|string ldap_exop_passwd(resource link [, string user [, string oldpw [, string newpw ]]]) +#ifdef HAVE_LDAP_PASSWD +/* {{{ proto bool|string ldap_exop_passwd(resource link [, string user [, string oldpw [, string newpw [, array ctrls]]]]) Passwd modify extended operation */ PHP_FUNCTION(ldap_exop_passwd) { - zval *link, *user, *newpw, *oldpw; + zval *link, *user, *newpw, *oldpw, *serverctrls; struct berval luser, loldpw, lnewpw, lgenpasswd; + LDAPControl **lserverctrls = NULL, **requestctrls = NULL; + LDAPControl *ctrl, **ctrlp; + LDAPMessage* ldap_res; ldap_linkdata *ld; - int rc, myargcount = ZEND_NUM_ARGS(); + int rc, myargcount = ZEND_NUM_ARGS(), msgid, err; + char* errmsg; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|zzz", &link, &user, &oldpw, &newpw) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|zzzz/", &link, &user, &oldpw, &newpw, &serverctrls) == FAILURE) { WRONG_PARAM_COUNT; } @@ -3433,6 +4238,17 @@ PHP_FUNCTION(ldap_exop_passwd) lnewpw.bv_len = 0; switch (myargcount) { + case 5: + requestctrls = safe_emalloc(2, sizeof(*requestctrls), 0); + *requestctrls = NULL; + ctrlp = requestctrls; + + if (ldap_create_passwordpolicy_control(ld->link, &ctrl) == LDAP_SUCCESS) { + *ctrlp = ctrl; + ++ctrlp; + } + + *ctrlp = NULL; case 4: convert_to_string_ex(newpw); lnewpw.bv_val = Z_STRVAL_P(newpw); @@ -3449,24 +4265,52 @@ PHP_FUNCTION(ldap_exop_passwd) luser.bv_len = Z_STRLEN_P(user); } - /* synchronous call */ - rc = ldap_passwd_s(ld->link, &luser, + /* asynchronous call to get result and controls */ + rc = ldap_passwd(ld->link, &luser, loldpw.bv_len > 0 ? &loldpw : NULL, lnewpw.bv_len > 0 ? &lnewpw : NULL, - &lgenpasswd, NULL, NULL); + requestctrls, + NULL, &msgid); if (rc != LDAP_SUCCESS ) { php_error_docref(NULL, 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 < 0) || !ldap_res) { + rc = _get_lderrno(ld->link); + php_error_docref(NULL, E_WARNING, "Passwd modify extended operation failed: %s (%d)", ldap_err2string(rc), rc); + RETURN_FALSE; + } + + rc = ldap_parse_passwd(ld->link, ldap_res, &lgenpasswd); + if( rc != LDAP_SUCCESS ) { + php_error_docref(NULL, E_WARNING, "Passwd modify extended operation failed: %s (%d)", ldap_err2string(rc), rc); + ldap_msgfree(ldap_res); + RETURN_FALSE; + } + + rc = ldap_parse_result(ld->link, ldap_res, &err, NULL, &errmsg, NULL, (myargcount > 4 ? &lserverctrls : NULL), 1); + 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 if (err == LDAP_SUCCESS) { + RETVAL_TRUE; } else { - RETURN_TRUE; + php_error_docref(NULL, E_WARNING, "Passwd modify extended operation failed: %s (%d)", (errmsg ? errmsg : ldap_err2string(err)), err); + RETVAL_FALSE; + } + + if (myargcount > 4) { + _php_ldap_controls_to_array(ld->link, lserverctrls, serverctrls, 0); } ldap_memfree(lgenpasswd.bv_val); @@ -3571,6 +4415,13 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_bind, 0, 0, 1) ZEND_ARG_INFO(0, bind_password) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_bind_ext, 0, 0, 1) + ZEND_ARG_INFO(0, link_identifier) + ZEND_ARG_INFO(0, bind_rdn) + ZEND_ARG_INFO(0, bind_password) + ZEND_ARG_INFO(0, servercontrols) +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) @@ -3592,6 +4443,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_read, 0, 0, 3) ZEND_ARG_INFO(0, sizelimit) ZEND_ARG_INFO(0, timelimit) ZEND_ARG_INFO(0, deref) + ZEND_ARG_INFO(0, servercontrols) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_list, 0, 0, 3) @@ -3603,6 +4455,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_list, 0, 0, 3) ZEND_ARG_INFO(0, sizelimit) ZEND_ARG_INFO(0, timelimit) ZEND_ARG_INFO(0, deref) + ZEND_ARG_INFO(0, servercontrols) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_search, 0, 0, 3) @@ -3614,6 +4467,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_search, 0, 0, 3) ZEND_ARG_INFO(0, sizelimit) ZEND_ARG_INFO(0, timelimit) ZEND_ARG_INFO(0, deref) + ZEND_ARG_INFO(0, servercontrols) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_count_entries, 0, 0, 2) @@ -3681,41 +4535,82 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_add, 0, 0, 3) ZEND_ARG_INFO(0, link_identifier) ZEND_ARG_INFO(0, dn) ZEND_ARG_INFO(0, entry) + ZEND_ARG_INFO(0, servercontrols) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_add_ext, 0, 0, 3) + ZEND_ARG_INFO(0, link_identifier) + ZEND_ARG_INFO(0, dn) + ZEND_ARG_INFO(0, entry) + ZEND_ARG_INFO(0, servercontrols) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_delete, 0, 0, 2) ZEND_ARG_INFO(0, link_identifier) ZEND_ARG_INFO(0, dn) + ZEND_ARG_INFO(0, servercontrols) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_delete_ext, 0, 0, 2) + ZEND_ARG_INFO(0, link_identifier) + ZEND_ARG_INFO(0, dn) + ZEND_ARG_INFO(0, servercontrols) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_modify, 0, 0, 3) ZEND_ARG_INFO(0, link_identifier) ZEND_ARG_INFO(0, dn) ZEND_ARG_INFO(0, entry) + ZEND_ARG_INFO(0, servercontrols) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_modify_batch, 0, 0, 3) ZEND_ARG_INFO(0, link_identifier) ZEND_ARG_INFO(0, dn) ZEND_ARG_ARRAY_INFO(0, modifications_info, 0) + ZEND_ARG_INFO(0, servercontrols) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_mod_add, 0, 0, 3) ZEND_ARG_INFO(0, link_identifier) ZEND_ARG_INFO(0, dn) ZEND_ARG_INFO(0, entry) + ZEND_ARG_INFO(0, servercontrols) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_mod_add_ext, 0, 0, 3) + ZEND_ARG_INFO(0, link_identifier) + ZEND_ARG_INFO(0, dn) + ZEND_ARG_INFO(0, entry) + ZEND_ARG_INFO(0, servercontrols) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_mod_replace, 0, 0, 3) ZEND_ARG_INFO(0, link_identifier) ZEND_ARG_INFO(0, dn) ZEND_ARG_INFO(0, entry) + ZEND_ARG_INFO(0, servercontrols) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_mod_replace_ext, 0, 0, 3) + ZEND_ARG_INFO(0, link_identifier) + ZEND_ARG_INFO(0, dn) + ZEND_ARG_INFO(0, entry) + ZEND_ARG_INFO(0, servercontrols) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_mod_del, 0, 0, 3) ZEND_ARG_INFO(0, link_identifier) ZEND_ARG_INFO(0, dn) ZEND_ARG_INFO(0, entry) + ZEND_ARG_INFO(0, servercontrols) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_mod_del_ext, 0, 0, 3) + ZEND_ARG_INFO(0, link_identifier) + ZEND_ARG_INFO(0, dn) + ZEND_ARG_INFO(0, entry) + ZEND_ARG_INFO(0, servercontrols) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_err2str, 0, 0, 1) @@ -3727,6 +4622,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_compare, 0, 0, 4) ZEND_ARG_INFO(0, dn) ZEND_ARG_INFO(0, attribute) ZEND_ARG_INFO(0, value) + ZEND_ARG_INFO(0, servercontrols) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_sort, 0, 0, 3) @@ -3758,6 +4654,16 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_rename, 0, 0, 5) ZEND_ARG_INFO(0, newrdn) ZEND_ARG_INFO(0, newparent) ZEND_ARG_INFO(0, deleteoldrdn) + ZEND_ARG_INFO(0, servercontrols) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_rename_ext, 0, 0, 5) + ZEND_ARG_INFO(0, link_identifier) + ZEND_ARG_INFO(0, dn) + ZEND_ARG_INFO(0, newrdn) + ZEND_ARG_INFO(0, newparent) + ZEND_ARG_INFO(0, deleteoldrdn) + ZEND_ARG_INFO(0, servercontrols) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_get_option, 0, 0, 3) @@ -3799,6 +4705,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_parse_result, 0, 0, 3) 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 @@ -3837,12 +4744,13 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_exop, 0, 0, 2) ZEND_END_ARG_INFO() #endif -#ifdef HAVE_LDAP_PASSWD_S -ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_exop_passwd, 0, 0, 4) +#ifdef HAVE_LDAP_PASSWD +ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_exop_passwd, 0, 0, 1) ZEND_ARG_INFO(0, link) ZEND_ARG_INFO(0, user) ZEND_ARG_INFO(0, oldpw) ZEND_ARG_INFO(0, newpw) + ZEND_ARG_INFO(1, serverctrls) ZEND_END_ARG_INFO() #endif @@ -3880,6 +4788,7 @@ const zend_function_entry ldap_functions[] = { PHP_FE(ldap_connect, arginfo_ldap_connect) PHP_FALIAS(ldap_close, ldap_unbind, arginfo_ldap_resource) PHP_FE(ldap_bind, arginfo_ldap_bind) + PHP_FE(ldap_bind_ext, arginfo_ldap_bind_ext) #ifdef HAVE_LDAP_SASL PHP_FE(ldap_sasl_bind, arginfo_ldap_sasl_bind) #endif @@ -3901,14 +4810,19 @@ const zend_function_entry ldap_functions[] = { PHP_FE(ldap_explode_dn, arginfo_ldap_explode_dn) PHP_FE(ldap_dn2ufn, arginfo_ldap_dn2ufn) PHP_FE(ldap_add, arginfo_ldap_add) + PHP_FE(ldap_add_ext, arginfo_ldap_add_ext) PHP_FE(ldap_delete, arginfo_ldap_delete) + PHP_FE(ldap_delete_ext, arginfo_ldap_delete_ext) PHP_FE(ldap_modify_batch, arginfo_ldap_modify_batch) PHP_FALIAS(ldap_modify, ldap_mod_replace, arginfo_ldap_modify) /* additional functions for attribute based modifications, Gerrit Thomson */ PHP_FE(ldap_mod_add, arginfo_ldap_mod_add) + PHP_FE(ldap_mod_add_ext, arginfo_ldap_mod_add_ext) PHP_FE(ldap_mod_replace, arginfo_ldap_mod_replace) + PHP_FE(ldap_mod_replace_ext, arginfo_ldap_mod_replace_ext) PHP_FE(ldap_mod_del, arginfo_ldap_mod_del) + PHP_FE(ldap_mod_del_ext, arginfo_ldap_mod_del_ext) /* end gjt mod */ PHP_FE(ldap_errno, arginfo_ldap_resource) @@ -3919,6 +4833,7 @@ const zend_function_entry ldap_functions[] = { #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP PHP_FE(ldap_rename, arginfo_ldap_rename) + PHP_FE(ldap_rename_ext, arginfo_ldap_rename_ext) PHP_FE(ldap_get_option, arginfo_ldap_get_option) PHP_FE(ldap_set_option, arginfo_ldap_set_option) PHP_FE(ldap_first_reference, arginfo_ldap_first_reference) @@ -3935,7 +4850,7 @@ const zend_function_entry ldap_functions[] = { #ifdef HAVE_LDAP_EXTENDED_OPERATION_S PHP_FE(ldap_exop, arginfo_ldap_exop) #endif -#ifdef HAVE_LDAP_PASSWD_S +#ifdef HAVE_LDAP_PASSWD PHP_FE(ldap_exop_passwd, arginfo_ldap_exop_passwd) #endif #ifdef HAVE_LDAP_WHOAMI_S diff --git a/ext/ldap/tests/connect.inc b/ext/ldap/tests/connect.inc index 1c2205056eb38..b6366c02ac788 100644 --- a/ext/ldap/tests/connect.inc +++ b/ext/ldap/tests/connect.inc @@ -69,6 +69,13 @@ function insert_dummy_data($link, $base) { "sn" => "testSN3", "userPassword" => "0r1g1na1 passw0rd", )); + ldap_add($link, "o=test2,$base", array( + "objectClass" => array( + "top", + "organization"), + "o" => "test2", + "l" => array("here", "there", "Antarctica"), + )); } function remove_dummy_data($link, $base) { @@ -76,5 +83,6 @@ function remove_dummy_data($link, $base) { ldap_delete($link, "cn=userA,$base"); ldap_delete($link, "cn=userB,$base"); ldap_delete($link, "o=test,$base"); + ldap_delete($link, "o=test2,$base"); } ?> diff --git a/ext/ldap/tests/ldap_add_error.phpt b/ext/ldap/tests/ldap_add_error.phpt index a53277da80908..533496a4b2d71 100644 --- a/ext/ldap/tests/ldap_add_error.phpt +++ b/ext/ldap/tests/ldap_add_error.phpt @@ -18,7 +18,7 @@ var_dump(ldap_add($link)); var_dump(ldap_add($link, "$base")); // Too many parameters -var_dump(ldap_add($link, "$base", array(), "Additional data")); +var_dump(ldap_add($link, "$base", array(), [], "Additional data")); var_dump(ldap_add($link, "$base", array())); @@ -97,16 +97,16 @@ $link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version); ldap_delete($link, "dc=my-domain,$base"); ?> --EXPECTF-- -Warning: ldap_add() expects exactly 3 parameters, 0 given in %s on line %d +Warning: ldap_add() expects at least 3 parameters, 0 given in %s on line %d NULL -Warning: ldap_add() expects exactly 3 parameters, 1 given in %s on line %d +Warning: ldap_add() expects at least 3 parameters, 1 given in %s on line %d NULL -Warning: ldap_add() expects exactly 3 parameters, 2 given in %s on line %d +Warning: ldap_add() expects at least 3 parameters, 2 given in %s on line %d NULL -Warning: ldap_add() expects exactly 3 parameters, 4 given in %s on line %d +Warning: ldap_add() expects at most 4 parameters, 5 given in %s on line %d NULL Warning: ldap_add(): Add: Protocol error in %s on line %d diff --git a/ext/ldap/tests/ldap_add_ext.phpt b/ext/ldap/tests/ldap_add_ext.phpt new file mode 100644 index 0000000000000..12916d98c3ca4 --- /dev/null +++ b/ext/ldap/tests/ldap_add_ext.phpt @@ -0,0 +1,94 @@ +--TEST-- +ldap_add_ext() - Add operation with controls +--CREDITS-- +Côme Chilliet +--SKIPIF-- + + + +--FILE-- + array( + "top", + "organization"), + "o" => "test_ldap_add_ext", + ), [['oid' => LDAP_CONTROL_POST_READ, 'iscritical' => TRUE, 'value' => ['attrs' => ['o']]]]), + ldap_parse_result($link, $result, $errcode, $matcheddn, $errmsg, $referrals, $ctrls), + $errcode, + $errmsg, + $ctrls[LDAP_CONTROL_POST_READ], + ldap_get_entries( + $link, + ldap_search($link, "$base", "(o=test_ldap_add_ext)") + ) +); +?> +===DONE=== +--CLEAN-- + +--EXPECTF-- +resource(%d) of type (ldap result) +bool(true) +int(0) +string(0) "" +array(2) { + ["oid"]=> + string(14) "1.3.6.1.1.13.2" + ["value"]=> + array(2) { + ["dn"]=> + string(%d) "o=test_ldap_add_ext,%s" + ["o"]=> + array(1) { + [0]=> + string(17) "test_ldap_add_ext" + } + } +} +array(2) { + ["count"]=> + int(1) + [0]=> + array(6) { + ["objectclass"]=> + array(3) { + ["count"]=> + int(2) + [0]=> + string(3) "top" + [1]=> + string(12) "organization" + } + [0]=> + string(11) "objectclass" + ["o"]=> + array(2) { + ["count"]=> + int(1) + [0]=> + string(17) "test_ldap_add_ext" + } + [1]=> + string(1) "o" + ["count"]=> + int(2) + ["dn"]=> + string(%d) "o=test_ldap_add_ext,%s" + } +} +===DONE=== diff --git a/ext/ldap/tests/ldap_bind_ext.phpt b/ext/ldap/tests/ldap_bind_ext.phpt new file mode 100644 index 0000000000000..3a9ca415bde4b --- /dev/null +++ b/ext/ldap/tests/ldap_bind_ext.phpt @@ -0,0 +1,72 @@ +--TEST-- +ldap_bind_ext() - Basic binding +--CREDITS-- +Côme Chilliet +--SKIPIF-- + + + +--FILE-- + LDAP_CONTROL_PASSWORDPOLICYREQUEST]]), + ldap_parse_result($link, $result, $errcode, $matcheddn, $errmsg, $referrals, $ctrls), + $errcode, + $errmsg, + $ctrls +); + +/* Failures */ +var_dump( + $result = ldap_bind_ext($link, $user, "wrongPassword", [['oid' => LDAP_CONTROL_PASSWORDPOLICYREQUEST]]), + ldap_parse_result($link, $result, $errcode, $matcheddn, $errmsg, $referrals, $ctrls), + $errcode, + $errmsg, + $ctrls, + $result = ldap_bind_ext($link, "unexistingProperty=weirdValue,$user", $passwd, [['oid' => LDAP_CONTROL_PASSWORDPOLICYREQUEST]]), + ldap_parse_result($link, $result, $errcode, $matcheddn, $errmsg, $referrals, $ctrls), + $errcode, + $errmsg, + $ctrls +); +?> +===DONE=== +--EXPECTF-- +resource(%d) of type (ldap result) +bool(true) +int(0) +string(0) "" +array(0) { +} +resource(%d) of type (ldap result) +bool(true) +int(0) +string(0) "" +array(0) { +} +resource(%d) of type (ldap result) +bool(true) +int(49) +string(0) "" +array(0) { +} +resource(%d) of type (ldap result) +bool(true) +int(34) +string(10) "invalid DN" +array(0) { +} +===DONE=== diff --git a/ext/ldap/tests/ldap_compare_error.phpt b/ext/ldap/tests/ldap_compare_error.phpt index 07393f6de657c..120dfab0595f0 100644 --- a/ext/ldap/tests/ldap_compare_error.phpt +++ b/ext/ldap/tests/ldap_compare_error.phpt @@ -19,7 +19,7 @@ var_dump(ldap_compare($link, $link)); var_dump(ldap_compare($link, $link, $link)); // Too many parameters -var_dump(ldap_compare($link, $link, $link, $link, "Additional data")); +var_dump(ldap_compare($link, $link, $link, $link, [], "Additional data")); var_dump( ldap_compare($link, "cn=userNotAvailable,$base", "sn", "testSN1"), @@ -36,16 +36,16 @@ $link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version); remove_dummy_data($link, $base); ?> --EXPECTF-- -Warning: ldap_compare() expects exactly 4 parameters, 1 given in %s on line %d +Warning: ldap_compare() expects at least 4 parameters, 1 given in %s on line %d NULL -Warning: ldap_compare() expects exactly 4 parameters, 2 given in %s on line %d +Warning: ldap_compare() expects at least 4 parameters, 2 given in %s on line %d NULL -Warning: ldap_compare() expects exactly 4 parameters, 3 given in %s on line %d +Warning: ldap_compare() expects at least 4 parameters, 3 given in %s on line %d NULL -Warning: ldap_compare() expects exactly 4 parameters, 5 given in %s on line %d +Warning: ldap_compare() expects at most 5 parameters, 6 given in %s on line %d NULL Warning: ldap_compare(): Compare: No such object in %s on line %d diff --git a/ext/ldap/tests/ldap_controls.phpt b/ext/ldap/tests/ldap_controls.phpt new file mode 100644 index 0000000000000..8a9c8f9f2227c --- /dev/null +++ b/ext/ldap/tests/ldap_controls.phpt @@ -0,0 +1,162 @@ +--TEST-- +Test the use of controls +--CREDITS-- +Côme Chilliet +--SKIPIF-- + +--FILE-- + LDAP_CONTROL_ASSERT, 'iscritical' => TRUE, 'value' => ['filter' => '(objectClass=organization)']]]), + ldap_get_entries($link, $result), + $result = ldap_search($link, "o=test,$base", "objectClass=*", array('o'), 0, 0, 0, LDAP_DEREF_NEVER, + [['oid' => LDAP_CONTROL_ASSERT, 'iscritical' => TRUE, 'value' => ['filter' => '(objectClass=organizationalUnit)']]]), + ldap_modify($link, "o=test,$base", ['description' => 'desc'], + [['oid' => LDAP_CONTROL_ASSERT, 'iscritical' => TRUE, 'value' => ['filter' => '(!(description=*))']]]), + $result = ldap_read($link, "o=test,$base", "objectClass=*", array('description')), + ldap_get_entries($link, $result), + ldap_modify($link, "o=test,$base", ['description' => 'desc2'], + [['oid' => LDAP_CONTROL_ASSERT, 'iscritical' => TRUE, 'value' => ['filter' => '(!(description=*))']]]), + $result = ldap_read($link, "o=test,$base", "objectClass=*", array('description')), + ldap_get_entries($link, $result), + ldap_delete($link, "o=test,$base", [['oid' => LDAP_CONTROL_ASSERT, 'iscritical' => TRUE, 'value' => ['filter' => '(description=desc2)']]]), + ldap_errno($link), + ldap_error($link), + ldap_rename($link, "o=test,$base", "o=test2", "", TRUE, [['oid' => LDAP_CONTROL_ASSERT, 'iscritical' => TRUE, 'value' => ['filter' => '(description=desc2)']]]), + ldap_compare($link, "o=test,$base", "o", "test"), + ldap_compare($link, "o=test,$base", "o", "test", [['oid' => LDAP_CONTROL_ASSERT, 'iscritical' => TRUE, 'value' => ['filter' => '(description=desc2)']]]), + ldap_compare($link, "o=test,$base", "o", "test", [['oid' => LDAP_CONTROL_ASSERT, 'iscritical' => TRUE, 'value' => ['filter' => '(description=desc)']]]) +); + +/* Test valuesreturnfilter control */ +var_dump( + $result = ldap_read($link, "o=test2,$base", "objectClass=*", ["l"]), + ldap_get_entries($link, $result)[0]['l'], + $result = ldap_read($link, "o=test2,$base", "objectClass=*", ["l"], 0, 0, 0, LDAP_DEREF_NEVER, + [['oid' => LDAP_CONTROL_VALUESRETURNFILTER, 'iscritical' => TRUE, 'value' => ['filter' => '(l=*here)']]]), + ldap_get_entries($link, $result)[0]['l'] +); +?> +===DONE=== +--CLEAN-- + +--EXPECTF-- +Warning: ldap_search(): Search: Assertion Failed in %s on line %d + +Warning: ldap_modify(): Modify: Assertion Failed in %s on line %d + +Warning: ldap_delete(): Delete: Assertion Failed in %s on line %d + +Warning: ldap_compare(): Compare: Assertion Failed in %s on line %d +resource(%d) of type (ldap result) +array(2) { + ["count"]=> + int(1) + [0]=> + array(4) { + ["o"]=> + array(2) { + ["count"]=> + int(1) + [0]=> + string(4) "test" + } + [0]=> + string(1) "o" + ["count"]=> + int(1) + ["dn"]=> + string(%d) "o=test,%s" + } +} +bool(false) +bool(true) +resource(%d) of type (ldap result) +array(2) { + ["count"]=> + int(1) + [0]=> + array(4) { + ["description"]=> + array(2) { + ["count"]=> + int(1) + [0]=> + string(4) "desc" + } + [0]=> + string(11) "description" + ["count"]=> + int(1) + ["dn"]=> + string(%d) "o=test,%s" + } +} +bool(false) +resource(%d) of type (ldap result) +array(2) { + ["count"]=> + int(1) + [0]=> + array(4) { + ["description"]=> + array(2) { + ["count"]=> + int(1) + [0]=> + string(4) "desc" + } + [0]=> + string(11) "description" + ["count"]=> + int(1) + ["dn"]=> + string(%d) "o=test,%s" + } +} +bool(false) +int(122) +string(16) "Assertion Failed" +bool(false) +bool(true) +int(-1) +bool(true) +resource(%d) of type (ldap result) +array(4) { + ["count"]=> + int(3) + [0]=> + string(4) "here" + [1]=> + string(5) "there" + [2]=> + string(10) "Antarctica" +} +resource(%d) of type (ldap result) +array(3) { + ["count"]=> + int(2) + [0]=> + string(4) "here" + [1]=> + string(5) "there" +} +===DONE=== diff --git a/ext/ldap/tests/ldap_delete_error.phpt b/ext/ldap/tests/ldap_delete_error.phpt index 1d160f1074f61..a34d7b39fe5e7 100644 --- a/ext/ldap/tests/ldap_delete_error.phpt +++ b/ext/ldap/tests/ldap_delete_error.phpt @@ -17,7 +17,7 @@ var_dump(ldap_delete()); var_dump(ldap_delete($link)); // Too many parameters -var_dump(ldap_delete($link, "$base", "Additional data")); +var_dump(ldap_delete($link, "$base", [], "Additional data")); // Invalid DN var_dump( @@ -41,13 +41,13 @@ require "connect.inc"; $link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version); ?> --EXPECTF-- -Warning: ldap_delete() expects exactly 2 parameters, 0 given in %s on line %d +Warning: ldap_delete() expects at least 2 parameters, 0 given in %s on line %d NULL -Warning: ldap_delete() expects exactly 2 parameters, 1 given in %s on line %d +Warning: ldap_delete() expects at least 2 parameters, 1 given in %s on line %d NULL -Warning: ldap_delete() expects exactly 2 parameters, 3 given in %s on line %d +Warning: ldap_delete() expects at most 3 parameters, 4 given in %s on line %d NULL Warning: ldap_delete(): Delete: Invalid DN syntax in %s on line %d diff --git a/ext/ldap/tests/ldap_delete_ext.phpt b/ext/ldap/tests/ldap_delete_ext.phpt new file mode 100644 index 0000000000000..c4d0264088708 --- /dev/null +++ b/ext/ldap/tests/ldap_delete_ext.phpt @@ -0,0 +1,71 @@ +--TEST-- +ldap_delete_ext() - Delete operation with controls +--CREDITS-- +Côme Chilliet +--SKIPIF-- + + + +--FILE-- + array( + "top", + "dcObject", + "organization"), + "dc" => "my-domain", + "o" => "my-domain", +)); + +var_dump( + $result = ldap_delete_ext($link, "dc=my-domain,$base", + [['oid' => LDAP_CONTROL_PRE_READ, 'iscritical' => TRUE, 'value' => ['attrs' => ['dc', 'o']]]] + ), + ldap_parse_result($link, $result, $errcode, $matcheddn, $errmsg, $referrals, $ctrls), + $errcode, + $errmsg, + $ctrls[LDAP_CONTROL_PRE_READ], + @ldap_search($link, "dc=my-domain,$base", "(o=my-domain)") +); +?> +===DONE=== +--CLEAN-- + +--EXPECTF-- +resource(%d) of type (ldap result) +bool(true) +int(0) +string(0) "" +array(2) { + ["oid"]=> + string(14) "1.3.6.1.1.13.1" + ["value"]=> + array(3) { + ["dn"]=> + string(%d) "dc=my-domain,%s" + ["dc"]=> + array(1) { + [0]=> + string(9) "my-domain" + } + ["o"]=> + array(1) { + [0]=> + string(9) "my-domain" + } + } +} +bool(false) +===DONE=== diff --git a/ext/ldap/tests/ldap_exop.phpt b/ext/ldap/tests/ldap_exop.phpt index 48038cf230241..f5543c0e4edb2 100644 --- a/ext/ldap/tests/ldap_exop.phpt +++ b/ext/ldap/tests/ldap_exop.phpt @@ -42,6 +42,8 @@ var_dump( ldap_exop($link, LDAP_EXOP_WHO_AM_I, NULL, NULL, $retdata, $retoid), $retdata, $retoid, + ldap_exop($link, LDAP_EXOP_WHO_AM_I, NULL, [['oid' => LDAP_CONTROL_PROXY_AUTHZ, 'value' => "dn:cn=userA,$base"]], $retdata), + $retdata, $r = ldap_exop($link, LDAP_EXOP_WHO_AM_I), ldap_parse_exop($link, $r, $retdata2), $retdata2, @@ -66,6 +68,8 @@ remove_dummy_data($link, $base); bool(true) string(%d) "dn:%s" string(0) "" +bool(true) +string(%d) "dn:cn=user%s" resource(%d) of type (ldap result) bool(true) string(%d) "dn:%s" diff --git a/ext/ldap/tests/ldap_exop_passwd.phpt b/ext/ldap/tests/ldap_exop_passwd.phpt index 2f0d4cb599723..e50b30760ce5e 100644 --- a/ext/ldap/tests/ldap_exop_passwd.phpt +++ b/ext/ldap/tests/ldap_exop_passwd.phpt @@ -16,7 +16,8 @@ insert_dummy_data($link, $base); // and optionally returns the NEW password if none was passed. // ldap_exop_passwd(resource link [, string user [, string oldpw [, string newpw [, string newpasswd ]]]]) var_dump( - $genpw = ldap_exop_passwd($link, "cn=userA,$base", "oops", ""), + $genpw = ldap_exop_passwd($link, "cn=userA,$base", "oops", "", $ctrls), + $ctrls, $genpw = ldap_exop_passwd($link, "cn=userA,$base"), test_bind($host, $port, "cn=userA,$base", $genpw, $protocol_version), ldap_exop_passwd($link, "cn=userA,$base", $genpw, "newPassword"), @@ -34,6 +35,8 @@ remove_dummy_data($link, $base); ?> --EXPECTF-- string(%d) "%s" +array(0) { +} string(%d) "%s" bool(true) bool(true) diff --git a/ext/ldap/tests/ldap_exop_passwd_error.phpt b/ext/ldap/tests/ldap_exop_passwd_error.phpt index d858bd4bdcdd4..bfb0cbcae23d8 100644 --- a/ext/ldap/tests/ldap_exop_passwd_error.phpt +++ b/ext/ldap/tests/ldap_exop_passwd_error.phpt @@ -12,7 +12,8 @@ require "connect.inc"; $link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version); insert_dummy_data($link, $base); -var_dump(ldap_exop_passwd($link, "cn=userA,$base", "wrongPassword", "newPassword")); +var_dump(ldap_exop_passwd($link, "cn=userA,$base", "wrongPassword", "newPassword", $ctrls)); +var_dump($ctrls); var_dump(ldap_error($link)); var_dump(ldap_errno($link)); var_dump(test_bind($host, $port, "cn=userA,$base", "newPassword", $protocol_version)); @@ -27,8 +28,10 @@ $link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version); remove_dummy_data($link, $base); ?> --EXPECTF-- -Warning: ldap_exop_passwd(): Passwd modify extended operation failed: Server is unwilling to perform (53) in %s on line %d +Warning: ldap_exop_passwd(): Passwd modify extended operation failed: %s (53) in %s on line %d bool(false) +array(0) { +} string(30) "Server is unwilling to perform" int(53) diff --git a/ext/ldap/tests/ldap_first_reference_basic.phpt b/ext/ldap/tests/ldap_first_reference_basic.phpt index 312a81cc8072f..9c83c9127d357 100644 --- a/ext/ldap/tests/ldap_first_reference_basic.phpt +++ b/ext/ldap/tests/ldap_first_reference_basic.phpt @@ -30,8 +30,7 @@ include "connect.inc"; $link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version); // Referral can only be removed with Manage DSA IT Control -ldap_set_option($link, LDAP_OPT_SERVER_CONTROLS, array(array("oid" => LDAP_CONTROL_MANAGEDSAIT))); -ldap_delete($link, "cn=userref,$base"); +ldap_delete($link, "cn=userref,$base", [['oid' => LDAP_CONTROL_MANAGEDSAIT, 'iscritical' => TRUE]]); remove_dummy_data($link, $base); ?> --EXPECTF-- diff --git a/ext/ldap/tests/ldap_get_option_controls.phpt b/ext/ldap/tests/ldap_get_option_controls.phpt index 3b55685d5e8f2..abe35497d6e43 100644 --- a/ext/ldap/tests/ldap_get_option_controls.phpt +++ b/ext/ldap/tests/ldap_get_option_controls.phpt @@ -30,7 +30,17 @@ $controls_set = array( array( 'oid' => LDAP_CONTROL_PAGEDRESULTS, 'iscritical' => TRUE, - 'value' => build_ctrl_paged_value(1, '') + 'value' => build_ctrl_paged_value(1, 'opaque') + ) +); +$controls_set2 = array( + array( + 'oid' => LDAP_CONTROL_PAGEDRESULTS, + 'iscritical' => TRUE, + 'value' => array( + 'size' => 1, + 'cookie' => '', + ) ) ); var_dump( @@ -38,10 +48,10 @@ var_dump( ldap_get_option($link, LDAP_OPT_SERVER_CONTROLS, $controls_get), ldap_set_option($link, LDAP_OPT_SERVER_CONTROLS, $controls_set), ldap_get_option($link, LDAP_OPT_SERVER_CONTROLS, $controls_get), - count($controls_get), - $controls_get[0]['oid'], - $controls_get[0]['iscritical'], - bin2hex($controls_get[0]['value']), + $controls_get, + ldap_set_option($link, LDAP_OPT_SERVER_CONTROLS, $controls_set2), + ldap_get_option($link, LDAP_OPT_SERVER_CONTROLS, $controls_get), + $controls_get, $result = ldap_search($link, $base, "(objectClass=person)", array('cn')), ldap_get_entries($link, $result)['count'], ldap_set_option($link, LDAP_OPT_SERVER_CONTROLS, array()), @@ -57,14 +67,44 @@ $link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version); remove_dummy_data($link, $base); ?> --EXPECTF-- -string(14) "30050201010400" +string(26) "300b02010104066f7061717565" bool(false) bool(true) bool(true) -int(1) -string(22) "1.2.840.113556.1.4.319" +array(1) { + ["1.2.840.113556.1.4.319"]=> + array(3) { + ["oid"]=> + string(22) "1.2.840.113556.1.4.319" + ["iscritical"]=> + bool(true) + ["value"]=> + array(2) { + ["size"]=> + int(1) + ["cookie"]=> + string(6) "opaque" + } + } +} bool(true) -string(14) "30050201010400" +bool(true) +array(1) { + ["1.2.840.113556.1.4.319"]=> + array(3) { + ["oid"]=> + string(22) "1.2.840.113556.1.4.319" + ["iscritical"]=> + bool(true) + ["value"]=> + array(2) { + ["size"]=> + int(1) + ["cookie"]=> + string(0) "" + } + } +} resource(%d) of type (ldap result) int(1) bool(true) diff --git a/ext/ldap/tests/ldap_get_option_variation.phpt b/ext/ldap/tests/ldap_get_option_variation.phpt index 759936ec629b6..a18318849fc05 100644 --- a/ext/ldap/tests/ldap_get_option_variation.phpt +++ b/ext/ldap/tests/ldap_get_option_variation.phpt @@ -66,14 +66,16 @@ bool(true) int(0) bool(true) array(2) { - [0]=> - array(2) { + ["1.2.752.58.10.1"]=> + array(3) { ["oid"]=> string(15) "1.2.752.58.10.1" ["iscritical"]=> bool(true) + ["value"]=> + NULL } - [1]=> + ["1.2.752.58.1.10"]=> array(3) { ["oid"]=> string(15) "1.2.752.58.1.10" @@ -85,14 +87,16 @@ array(2) { } bool(true) array(2) { - [0]=> - array(2) { + ["1.2.752.58.10.1"]=> + array(3) { ["oid"]=> string(15) "1.2.752.58.10.1" ["iscritical"]=> bool(true) + ["value"]=> + NULL } - [1]=> + ["1.2.752.58.1.10"]=> array(3) { ["oid"]=> string(15) "1.2.752.58.1.10" diff --git a/ext/ldap/tests/ldap_list_error.phpt b/ext/ldap/tests/ldap_list_error.phpt index 51bcaa583f195..817622e7252e4 100644 --- a/ext/ldap/tests/ldap_list_error.phpt +++ b/ext/ldap/tests/ldap_list_error.phpt @@ -17,7 +17,7 @@ var_dump(ldap_list($link)); var_dump(ldap_list($link, $link)); // Too many parameters -var_dump(ldap_list($link, "$base", "(objectClass=*)", array(), 0, 0, 0, 0 , "Additional data")); +var_dump(ldap_list($link, "$base", "(objectClass=*)", array(), 0, 0, 0, 0, [], "Additional data")); ?> ===DONE=== --EXPECTF-- @@ -30,6 +30,6 @@ NULL Warning: ldap_list() expects at least 3 parameters, 2 given in %s on line %d NULL -Warning: ldap_list() expects at most 8 parameters, 9 given in %s on line %d +Warning: ldap_list() expects at most 9 parameters, 10 given in %s on line %d NULL ===DONE=== diff --git a/ext/ldap/tests/ldap_mod_add_error.phpt b/ext/ldap/tests/ldap_mod_add_error.phpt index c04e2cbd3d2ce..4bfbaa5551ef7 100644 --- a/ext/ldap/tests/ldap_mod_add_error.phpt +++ b/ext/ldap/tests/ldap_mod_add_error.phpt @@ -18,7 +18,7 @@ var_dump(ldap_mod_add($link)); var_dump(ldap_mod_add($link, "$base")); // Too many parameters -var_dump(ldap_mod_add($link, "$base", array(), "Additional data")); +var_dump(ldap_mod_add($link, "$base", array(), [], "Additional data")); // DN not found var_dump(ldap_mod_add($link, "dc=my-domain,$base", array())); @@ -57,16 +57,16 @@ $link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version); ldap_delete($link, "dc=my-domain,$base"); ?> --EXPECTF-- -Warning: ldap_mod_add() expects exactly 3 parameters, 0 given in %s on line %d +Warning: ldap_mod_add() expects at least 3 parameters, 0 given in %s on line %d NULL -Warning: ldap_mod_add() expects exactly 3 parameters, 1 given in %s on line %d +Warning: ldap_mod_add() expects at least 3 parameters, 1 given in %s on line %d NULL -Warning: ldap_mod_add() expects exactly 3 parameters, 2 given in %s on line %d +Warning: ldap_mod_add() expects at least 3 parameters, 2 given in %s on line %d NULL -Warning: ldap_mod_add() expects exactly 3 parameters, 4 given in %s on line %d +Warning: ldap_mod_add() expects at most 4 parameters, 5 given in %s on line %d NULL Warning: ldap_mod_add(): Modify: No such object in %s on line %d diff --git a/ext/ldap/tests/ldap_mod_del_error.phpt b/ext/ldap/tests/ldap_mod_del_error.phpt index 679adb6e6e17c..129d6472c12ef 100644 --- a/ext/ldap/tests/ldap_mod_del_error.phpt +++ b/ext/ldap/tests/ldap_mod_del_error.phpt @@ -18,7 +18,7 @@ var_dump(ldap_mod_del($link)); var_dump(ldap_mod_del($link, "$base")); // Too many parameters -var_dump(ldap_mod_del($link, "$base", array(), "Additional data")); +var_dump(ldap_mod_del($link, "$base", array(), [], "Additional data")); // DN not found var_dump(ldap_mod_del($link, "dc=my-domain,$base", array())); @@ -39,16 +39,16 @@ $link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version); ldap_delete($link, "dc=my-domain,$base"); ?> --EXPECTF-- -Warning: ldap_mod_del() expects exactly 3 parameters, 0 given in %s on line %d +Warning: ldap_mod_del() expects at least 3 parameters, 0 given in %s on line %d NULL -Warning: ldap_mod_del() expects exactly 3 parameters, 1 given in %s on line %d +Warning: ldap_mod_del() expects at least 3 parameters, 1 given in %s on line %d NULL -Warning: ldap_mod_del() expects exactly 3 parameters, 2 given in %s on line %d +Warning: ldap_mod_del() expects at least 3 parameters, 2 given in %s on line %d NULL -Warning: ldap_mod_del() expects exactly 3 parameters, 4 given in %s on line %d +Warning: ldap_mod_del() expects at most 4 parameters, 5 given in %s on line %d NULL Warning: ldap_mod_del(): Modify: No such object in %s on line %d diff --git a/ext/ldap/tests/ldap_mod_ext.phpt b/ext/ldap/tests/ldap_mod_ext.phpt new file mode 100644 index 0000000000000..391ecbf9097e0 --- /dev/null +++ b/ext/ldap/tests/ldap_mod_ext.phpt @@ -0,0 +1,172 @@ +--TEST-- +ldap_mod_ext() - Modify operations with controls +--CREDITS-- +Patrick Allaert +# Belgian PHP Testfest 2009 +--SKIPIF-- + + + +--FILE-- + "Domain description", +); + +var_dump( + $result = ldap_mod_add_ext($link, "o=test,$base", $entry, + [ + ['oid' => LDAP_CONTROL_PRE_READ, 'iscritical' => TRUE, 'value' => ['attrs' => ['description']]], + ['oid' => LDAP_CONTROL_POST_READ, 'iscritical' => TRUE, 'value' => ['attrs' => ['description']]], + ] + ), + ldap_parse_result($link, $result, $errcode, $matcheddn, $errmsg, $referrals, $ctrls), + $errcode, + $errmsg, + $ctrls, + ldap_get_entries( + $link, + ldap_search($link, "o=test,$base", "(Description=Domain description)") + ), + $result = ldap_mod_del_ext($link, "o=test,$base", $entry, + [ + ['oid' => LDAP_CONTROL_PRE_READ, 'iscritical' => TRUE, 'value' => ['attrs' => ['description']]], + ['oid' => LDAP_CONTROL_POST_READ, 'iscritical' => TRUE, 'value' => ['attrs' => ['description']]], + ] + ), + ldap_parse_result($link, $result, $errcode, $matcheddn, $errmsg, $referrals, $ctrls), + $errcode, + $errmsg, + $ctrls, + ldap_get_entries( + $link, + ldap_search($link, "o=test,$base", "(Description=Domain description)") + ) +); +?> +===DONE=== +--CLEAN-- + +--EXPECTF-- +resource(%d) of type (ldap result) +bool(true) +int(0) +string(0) "" +array(2) { + ["1.3.6.1.1.13.1"]=> + array(2) { + ["oid"]=> + string(14) "1.3.6.1.1.13.1" + ["value"]=> + array(1) { + ["dn"]=> + string(%d) "o=test,%s" + } + } + ["1.3.6.1.1.13.2"]=> + array(2) { + ["oid"]=> + string(14) "1.3.6.1.1.13.2" + ["value"]=> + array(2) { + ["dn"]=> + string(%d) "o=test,%s" + ["description"]=> + array(1) { + [0]=> + string(18) "Domain description" + } + } + } +} +array(2) { + ["count"]=> + int(1) + [0]=> + array(8) { + ["objectclass"]=> + array(3) { + ["count"]=> + int(2) + [0]=> + string(3) "top" + [1]=> + string(12) "organization" + } + [0]=> + string(11) "objectclass" + ["o"]=> + array(2) { + ["count"]=> + int(1) + [0]=> + string(4) "test" + } + [1]=> + string(1) "o" + ["description"]=> + array(2) { + ["count"]=> + int(1) + [0]=> + string(18) "Domain description" + } + [2]=> + string(11) "description" + ["count"]=> + int(3) + ["dn"]=> + string(%d) "o=test,%s" + } +} +resource(%d) of type (ldap result) +bool(true) +int(0) +string(0) "" +array(2) { + ["1.3.6.1.1.13.1"]=> + array(2) { + ["oid"]=> + string(14) "1.3.6.1.1.13.1" + ["value"]=> + array(2) { + ["dn"]=> + string(%d) "o=test,%s" + ["description"]=> + array(1) { + [0]=> + string(18) "Domain description" + } + } + } + ["1.3.6.1.1.13.2"]=> + array(2) { + ["oid"]=> + string(14) "1.3.6.1.1.13.2" + ["value"]=> + array(1) { + ["dn"]=> + string(%d) "o=test,%s" + } + } +} +array(1) { + ["count"]=> + int(0) +} +===DONE=== diff --git a/ext/ldap/tests/ldap_mod_replace_error.phpt b/ext/ldap/tests/ldap_mod_replace_error.phpt index f796568d0762d..4f435b13d2add 100644 --- a/ext/ldap/tests/ldap_mod_replace_error.phpt +++ b/ext/ldap/tests/ldap_mod_replace_error.phpt @@ -18,7 +18,7 @@ var_dump(ldap_mod_replace($link)); var_dump(ldap_mod_replace($link, "$base")); // Too many parameters -var_dump(ldap_mod_replace($link, "$base", array(), "Additional data")); +var_dump(ldap_mod_replace($link, "$base", array(), [], "Additional data")); // DN not found var_dump(ldap_mod_replace($link, "dc=my-domain,$base", array())); @@ -37,16 +37,16 @@ require "connect.inc"; $link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version); ?> --EXPECTF-- -Warning: ldap_mod_replace() expects exactly 3 parameters, 0 given in %s on line %d +Warning: ldap_mod_replace() expects at least 3 parameters, 0 given in %s on line %d NULL -Warning: ldap_mod_replace() expects exactly 3 parameters, 1 given in %s on line %d +Warning: ldap_mod_replace() expects at least 3 parameters, 1 given in %s on line %d NULL -Warning: ldap_mod_replace() expects exactly 3 parameters, 2 given in %s on line %d +Warning: ldap_mod_replace() expects at least 3 parameters, 2 given in %s on line %d NULL -Warning: ldap_mod_replace() expects exactly 3 parameters, 4 given in %s on line %d +Warning: ldap_mod_replace() expects at most 4 parameters, 5 given in %s on line %d NULL Warning: ldap_mod_replace(): Modify: No such object in %s on line %d diff --git a/ext/ldap/tests/ldap_modify_batch_error.phpt b/ext/ldap/tests/ldap_modify_batch_error.phpt index 2d72d491f8f31..a2d9ef9debe49 100644 --- a/ext/ldap/tests/ldap_modify_batch_error.phpt +++ b/ext/ldap/tests/ldap_modify_batch_error.phpt @@ -26,7 +26,7 @@ var_dump(ldap_modify_batch($link)); var_dump(ldap_modify_batch($link, "$base")); // Too many parameters -var_dump(ldap_modify_batch($link, "$base", $addGivenName, "Invalid additional parameter")); +var_dump(ldap_modify_batch($link, "$base", $addGivenName, [], "Invalid additional parameter")); // DN not found var_dump(ldap_modify_batch($link, "cn=not-found,$base", $addGivenName)); @@ -78,16 +78,16 @@ $link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version); ldap_delete($link, "dc=my-domain,$base"); ?> --EXPECTF-- -Warning: ldap_modify_batch() expects exactly 3 parameters, 0 given in %s on line %d +Warning: ldap_modify_batch() expects at least 3 parameters, 0 given in %s on line %d NULL -Warning: ldap_modify_batch() expects exactly 3 parameters, 1 given in %s on line %d +Warning: ldap_modify_batch() expects at least 3 parameters, 1 given in %s on line %d NULL -Warning: ldap_modify_batch() expects exactly 3 parameters, 2 given in %s on line %d +Warning: ldap_modify_batch() expects at least 3 parameters, 2 given in %s on line %d NULL -Warning: ldap_modify_batch() expects exactly 3 parameters, 4 given in %s on line %d +Warning: ldap_modify_batch() expects at most 4 parameters, 5 given in %s on line %d NULL Warning: ldap_modify_batch(): Batch Modify: No such object in %s on line %d diff --git a/ext/ldap/tests/ldap_modify_error.phpt b/ext/ldap/tests/ldap_modify_error.phpt index 0ca2ea49dc04c..31069bb98c962 100644 --- a/ext/ldap/tests/ldap_modify_error.phpt +++ b/ext/ldap/tests/ldap_modify_error.phpt @@ -18,7 +18,7 @@ var_dump(ldap_modify($link)); var_dump(ldap_modify($link, "$base")); // Too many parameters -var_dump(ldap_modify($link, "$base", array(), "Additional data")); +var_dump(ldap_modify($link, "$base", array(), [], "Additional data")); // DN not found var_dump(ldap_modify($link, "cn=not-found,$base", array())); @@ -57,16 +57,16 @@ $link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version); ldap_delete($link, "dc=my-domain,$base"); ?> --EXPECTF-- -Warning: ldap_modify() expects exactly 3 parameters, 0 given in %s on line %d +Warning: ldap_modify() expects at least 3 parameters, 0 given in %s on line %d NULL -Warning: ldap_modify() expects exactly 3 parameters, 1 given in %s on line %d +Warning: ldap_modify() expects at least 3 parameters, 1 given in %s on line %d NULL -Warning: ldap_modify() expects exactly 3 parameters, 2 given in %s on line %d +Warning: ldap_modify() expects at least 3 parameters, 2 given in %s on line %d NULL -Warning: ldap_modify() expects exactly 3 parameters, 4 given in %s on line %d +Warning: ldap_modify() expects at most 4 parameters, 5 given in %s on line %d NULL Warning: ldap_modify(): Modify: No such object in %s on line %d diff --git a/ext/ldap/tests/ldap_next_reference_basic.phpt b/ext/ldap/tests/ldap_next_reference_basic.phpt index d92f69de0a0be..2476e02c5776c 100644 --- a/ext/ldap/tests/ldap_next_reference_basic.phpt +++ b/ext/ldap/tests/ldap_next_reference_basic.phpt @@ -35,9 +35,8 @@ include "connect.inc"; $link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version); // Referral can only be removed with Manage DSA IT Control -ldap_set_option($link, LDAP_OPT_SERVER_CONTROLS, array(array("oid" => LDAP_CONTROL_MANAGEDSAIT))); -ldap_delete($link, "cn=userref,$base"); -ldap_delete($link, "cn=userref2,$base"); +ldap_delete($link, "cn=userref,$base", [['oid' => LDAP_CONTROL_MANAGEDSAIT, 'iscritical' => TRUE]]); +ldap_delete($link, "cn=userref2,$base", [['oid' => LDAP_CONTROL_MANAGEDSAIT, 'iscritical' => TRUE]]); remove_dummy_data($link, $base); ?> --EXPECTF-- diff --git a/ext/ldap/tests/ldap_parse_result_basic.phpt b/ext/ldap/tests/ldap_parse_result_basic.phpt index a4c03ee19772a..e2a975d5b198c 100644 --- a/ext/ldap/tests/ldap_parse_result_basic.phpt +++ b/ext/ldap/tests/ldap_parse_result_basic.phpt @@ -31,8 +31,7 @@ include "connect.inc"; $link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version); // Referral can only be removed with Manage DSA IT Control -ldap_set_option($link, LDAP_OPT_SERVER_CONTROLS, array(array("oid" => LDAP_CONTROL_MANAGEDSAIT))); -ldap_delete($link, "cn=userref,$base"); +ldap_delete($link, "cn=userref,$base", [['oid' => LDAP_CONTROL_MANAGEDSAIT, 'iscritical' => TRUE]]); remove_dummy_data($link, $base); ?> --EXPECTF-- diff --git a/ext/ldap/tests/ldap_parse_result_controls.phpt b/ext/ldap/tests/ldap_parse_result_controls.phpt new file mode 100644 index 0000000000000..711507f6c02fd --- /dev/null +++ b/ext/ldap/tests/ldap_parse_result_controls.phpt @@ -0,0 +1,47 @@ +--TEST-- +ldap_parse_result() - Test the parsing of controls from result object +--CREDITS-- +Côme Chilliet +--SKIPIF-- + + + +--FILE-- + +===DONE=== +--CLEAN-- + +--EXPECTF-- +bool(true) +resource(%d) of type (ldap result) +bool(true) +string(22) "1.2.840.113556.1.4.319" +int(%d) +string(%d) "%s" +int(1) +===DONE=== diff --git a/ext/ldap/tests/ldap_read_error.phpt b/ext/ldap/tests/ldap_read_error.phpt index 7d57172e0d637..08f6280490606 100644 --- a/ext/ldap/tests/ldap_read_error.phpt +++ b/ext/ldap/tests/ldap_read_error.phpt @@ -17,7 +17,7 @@ var_dump(ldap_read($link)); var_dump(ldap_read($link, $link)); // Too many parameters -var_dump(ldap_read($link, "$base", "(objectClass=*)", array(), 0, 0, 0, 0 , "Additional data")); +var_dump(ldap_read($link, "$base", "(objectClass=*)", array(), 0, 0, 0, 0, [], "Additional data")); ?> ===DONE=== --EXPECTF-- @@ -30,6 +30,6 @@ NULL Warning: ldap_read() expects at least 3 parameters, 2 given in %s on line %d NULL -Warning: ldap_read() expects at most 8 parameters, 9 given in %s on line %d +Warning: ldap_read() expects at most 9 parameters, 10 given in %s on line %d NULL ===DONE=== diff --git a/ext/ldap/tests/ldap_rename_error.phpt b/ext/ldap/tests/ldap_rename_error.phpt index 111717f0b013e..8a580e5c3486e 100644 --- a/ext/ldap/tests/ldap_rename_error.phpt +++ b/ext/ldap/tests/ldap_rename_error.phpt @@ -15,7 +15,7 @@ var_dump(ldap_rename($link, "cn=userNotFound,$base", "cn=userZ", "$base", true)) ?> ===DONE=== --EXPECTF-- -Warning: ldap_rename() expects exactly 5 parameters, 1 given in %s on line %d +Warning: ldap_rename() expects at least 5 parameters, 1 given in %s on line %d NULL bool(false) ===DONE=== diff --git a/ext/ldap/tests/ldap_rename_ext.phpt b/ext/ldap/tests/ldap_rename_ext.phpt new file mode 100644 index 0000000000000..bee180b6f7014 --- /dev/null +++ b/ext/ldap/tests/ldap_rename_ext.phpt @@ -0,0 +1,80 @@ +--TEST-- +ldap_rename_ext() - Rename operation with controls +--CREDITS-- +Côme Chilliet +--SKIPIF-- + + + +--FILE-- + LDAP_CONTROL_PRE_READ, 'iscritical' => TRUE, 'value' => ['attrs' => ['cn']]], + ['oid' => LDAP_CONTROL_POST_READ, 'iscritical' => TRUE, 'value' => ['attrs' => ['cn']]] + ] + ), + ldap_parse_result($link, $result, $errcode, $matcheddn, $errmsg, $referrals, $ctrls), + $errcode, + $errmsg, + $ctrls[LDAP_CONTROL_PRE_READ], + $ctrls[LDAP_CONTROL_POST_READ], + ldap_count_entries($link, ldap_search($link, "$base", "(cn=userA)", array("cn"))), + ldap_count_entries($link, ldap_search($link, "$base", "(cn=userZ)", array("cn"))) +); +?> +===DONE=== +--CLEAN-- + +--EXPECTF-- +resource(%d) of type (ldap result) +bool(true) +int(0) +string(0) "" +array(2) { + ["oid"]=> + string(14) "1.3.6.1.1.13.1" + ["value"]=> + array(2) { + ["dn"]=> + string(%d) "cn=userA,%s" + ["cn"]=> + array(1) { + [0]=> + string(5) "userA" + } + } +} +array(2) { + ["oid"]=> + string(14) "1.3.6.1.1.13.2" + ["value"]=> + array(2) { + ["dn"]=> + string(%d) "cn=userZ,%s" + ["cn"]=> + array(1) { + [0]=> + string(5) "userZ" + } + } +} +int(0) +int(1) +===DONE=== diff --git a/ext/ldap/tests/ldap_search_paged_result_controls.phpt b/ext/ldap/tests/ldap_search_paged_result_controls.phpt new file mode 100644 index 0000000000000..2187a54148d28 --- /dev/null +++ b/ext/ldap/tests/ldap_search_paged_result_controls.phpt @@ -0,0 +1,99 @@ +--TEST-- +ldap_search() test with paged result controls +--CREDITS-- +Côme Chilliet +--SKIPIF-- + +--FILE-- + LDAP_CONTROL_PAGEDRESULTS, 'value' => ['size' => 2]]]), + ldap_get_entries($link, $result), + ldap_parse_result($link, $result, $errcode , $matcheddn , $errmsg , $referrals, $controls), + $result = ldap_search($link, $dn, $filter, array('cn'), 0, 0, 0, LDAP_DEREF_NEVER, + [['oid' => LDAP_CONTROL_PAGEDRESULTS, 'value' => ['size' => 20, 'cookie' => $controls[LDAP_CONTROL_PAGEDRESULTS]['value']['cookie']]]]), + ldap_get_entries($link, $result) +); +?> +===DONE=== +--CLEAN-- + +--EXPECTF-- +resource(%d) of type (ldap result) +array(3) { + ["count"]=> + int(2) + [0]=> + array(4) { + ["cn"]=> + array(2) { + ["count"]=> + int(1) + [0]=> + string(5) "userA" + } + [0]=> + string(2) "cn" + ["count"]=> + int(1) + ["dn"]=> + string(%d) "cn=userA,%s" + } + [1]=> + array(4) { + ["cn"]=> + array(2) { + ["count"]=> + int(1) + [0]=> + string(5) "userB" + } + [0]=> + string(2) "cn" + ["count"]=> + int(1) + ["dn"]=> + string(%d) "cn=userB,%s" + } +} +bool(true) +resource(%d) of type (ldap result) +array(2) { + ["count"]=> + int(1) + [0]=> + array(4) { + ["cn"]=> + array(2) { + ["count"]=> + int(1) + [0]=> + string(5) "userC" + } + [0]=> + string(2) "cn" + ["count"]=> + int(1) + ["dn"]=> + string(%d) "cn=userC,cn=userB,%s" + } +} +===DONE=== diff --git a/ext/ldap/tests/ldap_search_sort_controls.phpt b/ext/ldap/tests/ldap_search_sort_controls.phpt new file mode 100644 index 0000000000000..16504a6997507 --- /dev/null +++ b/ext/ldap/tests/ldap_search_sort_controls.phpt @@ -0,0 +1,207 @@ +--TEST-- +ldap_search() test with sort and VLV controls +--CREDITS-- +Côme Chilliet +--SKIPIF-- + +--FILE-- + LDAP_CONTROL_SORTREQUEST, + 'iscritical' => TRUE, + 'value' => [ + ['attr' => 'cn', 'oid' => '2.5.13.3' /* caseIgnoreOrderingMatch */, 'reverse' => TRUE] + ] + ] + ] + ), + ldap_get_entries($link, $result), + ldap_parse_result($link, $result, $errcode , $matcheddn , $errmsg , $referrals, $controls), + $errcode, + $errmsg, + $controls +); + +/* Then with VLV control */ +var_dump( + $result = ldap_search($link, $base, '(cn=*)', array('cn'), 0, 0, 0, LDAP_DEREF_NEVER, + [ + [ + 'oid' => LDAP_CONTROL_SORTREQUEST, + 'iscritical' => TRUE, + 'value' => [ + ['attr' => 'cn', 'oid' => '2.5.13.3' /* caseIgnoreOrderingMatch */, 'reverse' => TRUE] + ] + ], + [ + 'oid' => LDAP_CONTROL_VLVREQUEST, + 'iscritical' => TRUE, + 'value' => [ + 'before' => 0, // Return 0 entry before target + 'after' => 1, // Return 1 entry after target + 'offset' => 2, // Target entry is the second one + 'count' => 0, // We have no idea how many entries there are + ] + ] + ] + ), + ldap_get_entries($link, $result), + ldap_parse_result($link, $result, $errcode , $matcheddn , $errmsg , $referrals, $controls), + array_keys($controls), + $controls[LDAP_CONTROL_SORTRESPONSE], + $controls[LDAP_CONTROL_VLVRESPONSE]['value']['target'], + $controls[LDAP_CONTROL_VLVRESPONSE]['value']['count'], + $controls[LDAP_CONTROL_VLVRESPONSE]['value']['errcode'], + bin2hex($controls[LDAP_CONTROL_VLVRESPONSE]['value']['context']) +); +?> +===DONE=== +--CLEAN-- + +--EXPECTF-- +resource(%d) of type (ldap result) +array(4) { + ["count"]=> + int(3) + [0]=> + array(4) { + ["cn"]=> + array(2) { + ["count"]=> + int(1) + [0]=> + string(5) "userC" + } + [0]=> + string(2) "cn" + ["count"]=> + int(1) + ["dn"]=> + string(%d) "cn=userC,cn=userB,%s" + } + [1]=> + array(4) { + ["cn"]=> + array(2) { + ["count"]=> + int(1) + [0]=> + string(5) "userB" + } + [0]=> + string(2) "cn" + ["count"]=> + int(1) + ["dn"]=> + string(%d) "cn=userB,%s" + } + [2]=> + array(4) { + ["cn"]=> + array(2) { + ["count"]=> + int(1) + [0]=> + string(5) "userA" + } + [0]=> + string(2) "cn" + ["count"]=> + int(1) + ["dn"]=> + string(%d) "cn=userA,%s" + } +} +bool(true) +int(0) +string(0) "" +array(1) { + ["1.2.840.113556.1.4.474"]=> + array(2) { + ["oid"]=> + string(22) "1.2.840.113556.1.4.474" + ["value"]=> + array(1) { + ["errcode"]=> + int(0) + } + } +} +resource(%d) of type (ldap result) +array(3) { + ["count"]=> + int(2) + [0]=> + array(4) { + ["cn"]=> + array(2) { + ["count"]=> + int(1) + [0]=> + string(5) "userB" + } + [0]=> + string(2) "cn" + ["count"]=> + int(1) + ["dn"]=> + string(%d) "cn=userB,%s" + } + [1]=> + array(4) { + ["cn"]=> + array(2) { + ["count"]=> + int(1) + [0]=> + string(5) "userA" + } + [0]=> + string(2) "cn" + ["count"]=> + int(1) + ["dn"]=> + string(%d) "cn=userA,%s" + } +} +bool(true) +array(2) { + [0]=> + string(22) "1.2.840.113556.1.4.474" + [1]=> + string(24) "2.16.840.1.113730.3.4.10" +} +array(2) { + ["oid"]=> + string(22) "1.2.840.113556.1.4.474" + ["value"]=> + array(1) { + ["errcode"]=> + int(0) + } +} +int(2) +int(3) +int(0) +string(%d) "%s" +===DONE=== diff --git a/ext/ldap/tests/ldap_set_option_variation.phpt b/ext/ldap/tests/ldap_set_option_variation.phpt index bb8a3f1051899..4c0a138552526 100644 --- a/ext/ldap/tests/ldap_set_option_variation.phpt +++ b/ext/ldap/tests/ldap_set_option_variation.phpt @@ -77,14 +77,16 @@ bool(true) bool(false) bool(true) array(2) { - [0]=> - array(2) { + ["1.2.752.58.10.1"]=> + array(3) { ["oid"]=> string(15) "1.2.752.58.10.1" ["iscritical"]=> bool(true) + ["value"]=> + NULL } - [1]=> + ["1.2.752.58.1.10"]=> array(3) { ["oid"]=> string(15) "1.2.752.58.1.10" @@ -96,14 +98,16 @@ array(2) { } bool(true) array(2) { - [0]=> - array(2) { + ["1.2.752.58.10.1"]=> + array(3) { ["oid"]=> string(15) "1.2.752.58.10.1" ["iscritical"]=> bool(true) + ["value"]=> + NULL } - [1]=> + ["1.2.752.58.1.10"]=> array(3) { ["oid"]=> string(15) "1.2.752.58.1.10" diff --git a/ext/ldap/tests/skipifcontrol.inc b/ext/ldap/tests/skipifcontrol.inc new file mode 100644 index 0000000000000..ae551d6add86f --- /dev/null +++ b/ext/ldap/tests/skipifcontrol.inc @@ -0,0 +1,13 @@ +