From 79baca329bc47b7ffeea9ac3d1838f2e387ec0ae Mon Sep 17 00:00:00 2001 From: Pierre Joye Date: Tue, 15 Jun 2010 19:47:28 +0000 Subject: [PATCH] - #42060, add paged results support --- NEWS | 3 + ext/ldap/ldap.c | 206 ++++++++++++++++++ .../ldap_ctrl_paged_results_variation1.phpt | 56 +++++ .../ldap_ctrl_paged_results_variation2.phpt | 72 ++++++ .../ldap_ctrl_paged_results_variation3.phpt | 100 +++++++++ 5 files changed, 437 insertions(+) create mode 100644 ext/ldap/tests/ldap_ctrl_paged_results_variation1.phpt create mode 100644 ext/ldap/tests/ldap_ctrl_paged_results_variation2.phpt create mode 100644 ext/ldap/tests/ldap_ctrl_paged_results_variation3.phpt diff --git a/NEWS b/NEWS index 1ea8ac4914..9f36ad8e57 100644 --- a/NEWS +++ b/NEWS @@ -77,6 +77,9 @@ functions. (Kalle) . y2k_compliance ini option. (Kalle) +- Implemented FR #42060 (Add paged Results support). (ando@OpenLDAP.org, + iarenuno@eteo.mondragon.edu, jeanseb@au-fil-du.net, remy.saissy@gmail.com) + - Fixed PDO objects binary incompatibility. (Dmitry) ?? ??? 20??, PHP 5.3.3 diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index 9fe3b97ac3..3f2375c258 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -2185,6 +2185,192 @@ PHP_FUNCTION(ldap_8859_to_t61) /* }}} */ #endif +#ifdef LDAP_CONTROL_PAGEDRESULTS +/* {{{ proto bool ldap_ctrl_paged_results(resource link, int pagesize [, bool iscritical [, string cookie]]) + Inject paged results control*/ +PHP_FUNCTION(ldap_ctrl_paged_results) +{ + int pagesize; + int iscritical; + zval *link, *cookie; + struct berval lcookie = { 0, NULL }; + ldap_linkdata *ld; + LDAP *ldap; + BerElement *ber = NULL; + LDAPControl ctrl, *ctrlsp[2]; + int rc, myargcount = ZEND_NUM_ARGS(); + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl|bz", &link, &pagesize, &iscritical, &cookie) != SUCCESS) { + return; + } + + if (Z_TYPE_PP(&link) == IS_NULL) { + ldap = NULL; + } else { + ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link); + ldap = ld->link; + } + + ber = ber_alloc_t(LBER_USE_DER); + if (ber == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to alloc BER encoding resources for paged results control"); + RETURN_FALSE; + } + + ctrl.ldctl_iscritical = 0; + + switch (myargcount) { + case 4: + convert_to_string_ex(&cookie); + lcookie.bv_val = Z_STRVAL_PP(&cookie); + lcookie.bv_len = Z_STRLEN_PP(&cookie); + /* fallthru */ + case 3: + ctrl.ldctl_iscritical = iscritical; + /* fallthru */ + } + + if (ber_printf(ber, "{iO}", pagesize, &lcookie) == LBER_ERROR) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to BER printf paged results control"); + RETVAL_BOOL(0); + goto lcpr_error_out; + } + rc = ber_flatten2(ber, &ctrl.ldctl_value, 0); + if (rc == LBER_ERROR) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to BER encode paged results control"); + RETVAL_BOOL(0); + goto lcpr_error_out; + } + + ctrl.ldctl_oid = LDAP_CONTROL_PAGEDRESULTS; + + if (ldap) { + /* directly set the option */ + ctrlsp[0] = &ctrl; + ctrlsp[1] = NULL; + + rc = ldap_set_option(ldap, LDAP_OPT_SERVER_CONTROLS, ctrlsp); + if (rc != LDAP_SUCCESS) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set paged results control: %s (%d)", ldap_err2string(rc), rc); + RETVAL_BOOL(0); + goto lcpr_error_out; + } + RETVAL_BOOL(1); + } else { + /* return a PHP control object */ + array_init(return_value); + + add_assoc_string(return_value, "oid", ctrl.ldctl_oid, 1); + if ( ctrl.ldctl_value.bv_len ) { + add_assoc_stringl(return_value, "value", ctrl.ldctl_value.bv_val, ctrl.ldctl_value.bv_len, 1); + } + if (ctrl.ldctl_iscritical) { + add_assoc_bool(return_value, "iscritical", ctrl.ldctl_iscritical); + } + } + +lcpr_error_out: + if (ber != NULL) { + ber_free(ber, 1); + } + return; +} +/* }}} */ + +/* {{{ proto bool ldap_ctrl_paged_results_resp(resource link, resource result [, string cookie [, int estimated]]) + Extract paged results control response */ +PHP_FUNCTION(ldap_ctrl_paged_results_resp) +{ + zval *link, *result, *cookie, *estimated; + struct berval lcookie; + int lestimated; + ldap_linkdata *ld; + LDAPMessage *ldap_result; + LDAPControl **lserverctrls, *lctrl; + BerElement *ber; + ber_tag_t tag; + int rc, lerrcode, myargcount = ZEND_NUM_ARGS(); + + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr|zz", &link, &result, &cookie, &estimated) != SUCCESS) { + return; + } + + ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link); + ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, &result, -1, "ldap result", le_result); + + rc = ldap_parse_result(ld->link, + ldap_result, + &lerrcode, + NULL, /* matcheddn */ + NULL, /* errmsg */ + NULL, /* referrals */ + &lserverctrls, + 0); + + if (rc != LDAP_SUCCESS) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to parse result: %s (%d)", ldap_err2string(rc), rc); + RETURN_FALSE; + } + + if (lerrcode != LDAP_SUCCESS) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Result is: %s (%d)", ldap_err2string(lerrcode), lerrcode); + RETURN_FALSE; + } + + if (lserverctrls == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "No server controls in result"); + RETURN_FALSE; + } + + lctrl = ldap_find_control(LDAP_CONTROL_PAGEDRESULTS, lserverctrls); + if (lctrl == NULL) { + ldap_controls_free(lserverctrls); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "No paged results control response in result"); + RETURN_FALSE; + } + + ber = ber_init(&lctrl->ldctl_value); + if (ber == NULL) { + ldap_controls_free(lserverctrls); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to alloc BER decoding resources for paged results control response"); + RETURN_FALSE; + } + + tag = ber_scanf(ber, "{io}", &lestimated, &lcookie); + (void)ber_free(ber, 1); + + if (tag == LBER_ERROR) { + ldap_controls_free(lserverctrls); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to decode paged results control response"); + RETURN_FALSE; + } + + if (lestimated < 0) { + ldap_controls_free(lserverctrls); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid paged results control response value"); + RETURN_FALSE; + } + + ldap_controls_free(lserverctrls); + if (myargcount == 4) { + zval_dtor(estimated); + ZVAL_LONG(estimated, lestimated); + } + zval_dtor(cookie); + + if (lcookie.bv_len == 0) { + ZVAL_EMPTY_STRING(cookie); + } else { + ZVAL_STRINGL(cookie, lcookie.bv_val, lcookie.bv_len, 1); + } + ldap_memfree(lcookie.bv_val); + + RETURN_TRUE; +} +/* }}} */ +#endif + /* {{{ arginfo */ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_connect, 0, 0, 0) ZEND_ARG_INFO(0, hostname) @@ -2364,6 +2550,22 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_sort, 0, 0, 3) ZEND_ARG_INFO(0, sortfilter) ZEND_END_ARG_INFO() +#ifdef LDAP_CONTROL_PAGEDRESULTS +ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_ctrl_paged_results, 0, 0, 2) + ZEND_ARG_INFO(0, link) + ZEND_ARG_INFO(0, pagesize) + ZEND_ARG_INFO(0, iscritical) + ZEND_ARG_INFO(0, cookie) +ZEND_END_ARG_INFO(); + +ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_ctrl_paged_results_resp, 0, 0, 2) + ZEND_ARG_INFO(0, link) + ZEND_ARG_INFO(0, result) + ZEND_ARG_INFO(1, cookie) + ZEND_ARG_INFO(1, estimated) +ZEND_END_ARG_INFO(); +#endif + #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_rename, 0, 0, 5) ZEND_ARG_INFO(0, link_identifier) @@ -2506,6 +2708,10 @@ const zend_function_entry ldap_functions[] = { PHP_FE(ldap_8859_to_t61, arginfo_ldap_8859_to_t61) #endif +#ifdef LDAP_CONTROL_PAGEDRESULTS + PHP_FE(ldap_ctrl_paged_results, arginfo_ldap_ctrl_paged_results) + PHP_FE(ldap_ctrl_paged_results_resp, arginfo_ldap_ctrl_paged_results_resp) +#endif {NULL, NULL, NULL} }; /* }}} */ diff --git a/ext/ldap/tests/ldap_ctrl_paged_results_variation1.phpt b/ext/ldap/tests/ldap_ctrl_paged_results_variation1.phpt new file mode 100644 index 0000000000..88879d974c --- /dev/null +++ b/ext/ldap/tests/ldap_ctrl_paged_results_variation1.phpt @@ -0,0 +1,56 @@ +--TEST-- +ldap_ldap_ctrl_paged_results() test (fetching the first page) +--CREDITS-- +Jean-Sebastien Hedde +--SKIPIF-- + +--FILE-- + +===DONE=== +--CLEAN-- + +--EXPECTF-- +bool(true) +resource(6) of type (ldap result) +array(2) { + ["count"]=> + int(1) + [0]=> + array(4) { + ["cn"]=> + array(2) { + ["count"]=> + int(1) + [0]=> + string(5) "userA" + } + [0]=> + string(2) "cn" + ["count"]=> + int(1) + ["dn"]=> + string(28) "cn=userA,dc=my-domain,dc=com" + } +} +===DONE=== diff --git a/ext/ldap/tests/ldap_ctrl_paged_results_variation2.phpt b/ext/ldap/tests/ldap_ctrl_paged_results_variation2.phpt new file mode 100644 index 0000000000..7be5a2c2f7 --- /dev/null +++ b/ext/ldap/tests/ldap_ctrl_paged_results_variation2.phpt @@ -0,0 +1,72 @@ +--TEST-- +ldap_ldap_ctrl_paged_results() test (fetching the first page with a pagesize=2) +--CREDITS-- +Jean-Sebastien Hedde +--SKIPIF-- + +--FILE-- + +===DONE=== +--CLEAN-- + +--EXPECTF-- +bool(true) +resource(6) 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(28) "cn=userA,dc=my-domain,dc=com" + } + [1]=> + array(4) { + ["cn"]=> + array(2) { + ["count"]=> + int(1) + [0]=> + string(5) "userB" + } + [0]=> + string(2) "cn" + ["count"]=> + int(1) + ["dn"]=> + string(28) "cn=userB,dc=my-domain,dc=com" + } +} +===DONE=== diff --git a/ext/ldap/tests/ldap_ctrl_paged_results_variation3.phpt b/ext/ldap/tests/ldap_ctrl_paged_results_variation3.phpt new file mode 100644 index 0000000000..3134c2badb --- /dev/null +++ b/ext/ldap/tests/ldap_ctrl_paged_results_variation3.phpt @@ -0,0 +1,100 @@ +--TEST-- +ldap_ldap_ctrl_paged_results() test (fetching the first page then the next final page) +--CREDITS-- +Jean-Sebastien Hedde +--SKIPIF-- + +--FILE-- + +===DONE=== +--CLEAN-- + +--EXPECTF-- +bool(true) +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(28) "cn=userA,dc=my-domain,dc=com" + } + [1]=> + array(4) { + ["cn"]=> + array(2) { + ["count"]=> + int(1) + [0]=> + string(5) "userB" + } + [0]=> + string(2) "cn" + ["count"]=> + int(1) + ["dn"]=> + string(28) "cn=userB,dc=my-domain,dc=com" + } +} +bool(true) +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(37) "cn=userC,cn=userB,dc=my-domain,dc=com" + } +} +===DONE=== -- 2.40.0