php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Return to Bug #51869
Patch php-5.2_ldap-pagination.patch revision 2010-05-20 09:38 UTC by jeanseb at au-fil-du dot net

Patch php-5.2_ldap-pagination.patch for LDAP related Bug #51869

Patch version 2010-05-20 09:38 UTC

Return to Bug #51869 | Download this patch
Patch Revisions:

Developer: jeanseb@au-fil-du.net

Index: ext/ldap/ldap.c
===================================================================
--- ext/ldap/ldap.c	(révision 39622)
+++ ext/ldap/ldap.c	(révision 39985)
@@ -19,6 +19,8 @@
    |          Jani Taskinen  <sniper@iki.fi>                              |
    |          Stig Venaas    <venaas@uninett.no>                          |
    |          Doug Goldstein <cardoe@cardoe.com>                          |
+   |          Pierangelo Masarati <ando@OpenLDAP.org>                     |
+   |          Iñaki Arenaza <iarenuno@eteo.mondragon.edu>                 |
    | PHP 4.0 updates:  Zeev Suraski <zeev@zend.com>                       |
    +----------------------------------------------------------------------+
  */
@@ -83,6 +85,13 @@
 static PHP_GINIT_FUNCTION(ldap);
 
 static
+	ZEND_BEGIN_ARG_INFO(arg3to4of4_force_ref, 0)
+		ZEND_ARG_PASS_INFO(0)
+		ZEND_ARG_PASS_INFO(0)
+		ZEND_ARG_PASS_INFO(1)
+		ZEND_ARG_PASS_INFO(1)
+	ZEND_END_ARG_INFO();
+static
 	ZEND_BEGIN_ARG_INFO(arg3to6of6_force_ref, 0)
 		ZEND_ARG_PASS_INFO(0)
 		ZEND_ARG_PASS_INFO(0)
@@ -166,6 +175,10 @@
 	PHP_FE(ldap_8859_to_t61,							NULL)
 #endif
 
+#ifdef LDAP_CONTROL_PAGEDRESULTS
+	PHP_FE(ldap_ctrl_paged_results,		fourth_arg_force_ref)
+	PHP_FE(ldap_ctrl_paged_results_resp,	arg3to4of4_force_ref)
+#endif
 	{NULL, NULL, NULL}
 };
 /* }}} */
@@ -2289,6 +2302,193 @@
 /* }}} */
 #endif
 
+#ifdef LDAP_CONTROL_PAGEDRESULTS
+/* {{{ proto bool ldap_ctrl_paged_results(resource link, int pagesize [, bool iscritical [, string cookie]])
+   Inject paged results control*/
+PHP_FUNCTION(ldap_ctrl_paged_results) 
+{
+	zval **link, **pagesize, **iscritical, **cookie;
+	int lpagesize = 0;
+	struct berval lcookie = { 0, NULL };
+	ldap_linkdata *ld;
+	LDAP *ldap;
+	BerElement *ber = NULL;
+	LDAPControl	ctrl, *ctrlsp[2];
+	int rc, myargcount = ZEND_NUM_ARGS();
+
+	if (myargcount < 2 || myargcount > 4 || zend_get_parameters_ex(myargcount, &link, &pagesize, &iscritical, &cookie) == FAILURE) {
+		WRONG_PARAM_COUNT;
+	}
+
+	if (Z_TYPE_PP(link) == IS_NULL) {
+		ldap = NULL;
+	} else {
+		ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
+		ldap = ld->link;
+	}
+
+	ber = ber_alloc_t(LBER_USE_DER);
+	if (ber == NULL) {
+		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to alloc BER encoding resources for paged results control");
+		RETURN_FALSE;
+	}
+
+	ctrl.ldctl_iscritical = 0;
+
+	switch (myargcount) {
+	case 4:
+		convert_to_string_ex(cookie);
+		lcookie.bv_val = Z_STRVAL_PP(cookie);
+		lcookie.bv_len = Z_STRLEN_PP(cookie);
+		/* fallthru */
+	case 3:
+		convert_to_boolean_ex(iscritical);
+		ctrl.ldctl_iscritical = Z_BVAL_PP(iscritical);
+		/* fallthru */
+	}
+	convert_to_long_ex(pagesize);
+	lpagesize = Z_LVAL_PP(pagesize);
+
+	if (ber_printf(ber, "{iO}", lpagesize, &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 (myargcount < 3 || myargcount > 4 || zend_get_parameters_ex(myargcount, &link, &result, &cookie, &estimated) == FAILURE) {
+		WRONG_PARAM_COUNT;
+	}
+
+	ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
+	ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, result, -1, "ldap result", le_result);
+
+	rc = ldap_parse_result(ld->link,
+				ldap_result,
+				&lerrcode,
+				NULL,		/* matcheddn */
+				NULL,		/* errmsg */
+				NULL,		/* referrals */
+				&lserverctrls,
+				0);
+
+	if (rc != LDAP_SUCCESS) {
+		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to parse result: %s (%d)", ldap_err2string(rc), rc);
+		RETURN_FALSE;
+	}
+
+	if (lerrcode != LDAP_SUCCESS) {
+		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Result is: %s (%d)", ldap_err2string(lerrcode), lerrcode);
+		RETURN_FALSE;
+	}
+
+	if (lserverctrls == NULL) {
+		php_error_docref(NULL TSRMLS_CC, E_WARNING, "No server controls in result");
+		RETURN_FALSE;
+	}
+
+	lctrl = ldap_find_control(LDAP_CONTROL_PAGEDRESULTS, lserverctrls);
+	if (lctrl == NULL) {
+		ldap_controls_free(lserverctrls);
+		php_error_docref(NULL TSRMLS_CC, E_WARNING, "No paged results control response in result");
+		RETURN_FALSE;
+	}
+
+	ber = ber_init(&lctrl->ldctl_value);
+	if (ber == NULL) {
+		ldap_controls_free(lserverctrls);
+		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to alloc BER decoding resources for paged results control response");
+		RETURN_FALSE;
+	}
+
+	tag = ber_scanf(ber, "{io}", &lestimated, &lcookie );
+	(void)ber_free(ber, 1);
+
+	if (tag == LBER_ERROR) {
+		ldap_controls_free(lserverctrls);
+		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to decode paged results control response");
+		RETURN_FALSE;
+	}
+
+	if (lestimated < 0) {
+		ldap_controls_free(lserverctrls);
+		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid paged results control response value");
+		RETURN_FALSE;
+	}
+
+	ldap_controls_free(lserverctrls);
+
+	if (myargcount == 4) {
+		zval_dtor(*estimated);
+		ZVAL_LONG(*estimated, lestimated);
+	}
+
+	zval_dtor(*cookie);
+	if (lcookie.bv_len == 0) {
+		ZVAL_EMPTY_STRING(*cookie);
+	} else {
+		ZVAL_STRINGL(*cookie, lcookie.bv_val, lcookie.bv_len, 1);
+	}
+	ldap_memfree(lcookie.bv_val);
+
+	RETURN_TRUE;
+}
+/* }}} */
+#endif
 /*
  * Local variables:
  * tab-width: 4
Index: ext/ldap/tests/ldap_ctrl_paged_results_variation1.phpt
===================================================================
--- ext/ldap/tests/ldap_ctrl_paged_results_variation1.phpt	(révision 0)
+++ ext/ldap/tests/ldap_ctrl_paged_results_variation1.phpt	(révision 39985)
@@ -0,0 +1,56 @@
+--TEST--
+ldap_ldap_ctrl_paged_results() test (fetching the first page)
+--CREDITS--
+Jean-Sebastien Hedde <jeanseb@au-fil-du.net>
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifbindfailure.inc');
+?>
+--FILE--
+<?php
+include "connect.inc";
+
+$link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version);
+insert_dummy_data($link);
+
+$dn = "dc=my-domain,dc=com";
+$filter = "(cn=*)";
+var_dump(
+	ldap_ctrl_paged_results($link, 1),
+	$result = ldap_search($link, $dn, $filter, array('cn')),
+	ldap_get_entries($link, $result)
+);
+?>
+===DONE===
+--CLEAN--
+<?php
+include "connect.inc";
+
+$link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version);
+remove_dummy_data($link);
+?>
+--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===
Index: ext/ldap/tests/ldap_ctrl_paged_results_variation2.phpt
===================================================================
--- ext/ldap/tests/ldap_ctrl_paged_results_variation2.phpt	(révision 0)
+++ ext/ldap/tests/ldap_ctrl_paged_results_variation2.phpt	(révision 39985)
@@ -0,0 +1,72 @@
+--TEST--
+ldap_ldap_ctrl_paged_results() test (fetching the first page with a pagesize=2)
+--CREDITS--
+Jean-Sebastien Hedde <jeanseb@au-fil-du.net>
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifbindfailure.inc');
+?>
+--FILE--
+<?php
+include "connect.inc";
+
+$link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version);
+insert_dummy_data($link);
+
+$dn = "dc=my-domain,dc=com";
+$filter = "(cn=*)";
+var_dump(
+	ldap_ctrl_paged_results($link, 2),
+	$result = ldap_search($link, $dn, $filter, array('cn')),
+	ldap_get_entries($link, $result)
+);
+?>
+===DONE===
+--CLEAN--
+<?php
+include "connect.inc";
+
+$link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version);
+remove_dummy_data($link);
+?>
+--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===
Index: ext/ldap/tests/ldap_ctrl_paged_results_variation3.phpt
===================================================================
--- ext/ldap/tests/ldap_ctrl_paged_results_variation3.phpt	(révision 0)
+++ ext/ldap/tests/ldap_ctrl_paged_results_variation3.phpt	(révision 39985)
@@ -0,0 +1,100 @@
+--TEST--
+ldap_ldap_ctrl_paged_results() test (fetching the first page then the next final page)
+--CREDITS--
+Jean-Sebastien Hedde <jeanseb@au-fil-du.net>
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifbindfailure.inc');
+?>
+--FILE--
+<?php
+include "connect.inc";
+
+$link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version);
+insert_dummy_data($link);
+
+$dn = "dc=my-domain,dc=com";
+$filter = "(cn=*)";
+$cookie = '';
+var_dump(
+	ldap_ctrl_paged_results($link, 2, true, $cookie),
+	$result = ldap_search($link, $dn, $filter, array('cn')),
+	ldap_get_entries($link, $result),
+	ldap_ctrl_paged_results_resp($link, $result, &$cookie),
+	ldap_ctrl_paged_results($link, 20, true, &$cookie),
+	$result = ldap_search($link, $dn, $filter, array('cn')),
+	ldap_get_entries($link, $result)
+);
+?>
+===DONE===
+--CLEAN--
+<?php
+include "connect.inc";
+
+$link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version);
+remove_dummy_data($link);
+?>
+--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===
Index: ext/ldap/php_ldap.h
===================================================================
--- ext/ldap/php_ldap.h	(révision 39622)
+++ ext/ldap/php_ldap.h	(révision 39985)
@@ -15,6 +15,8 @@
    | Authors: Amitay Isaacs <amitay@w-o-i.com>                            |
    |          Eric Warnke   <ericw@albany.edu>                            |
    |          Jani Taskinen <sniper@iki.fi>                               |
+   |          Pierangelo Masarati <ando@OpenLDAP.org>                     |
+   |          Iñaki Arenaza <iarenuno@eteo.mondragon.edu>                 |
    +----------------------------------------------------------------------+
 */
 
@@ -96,6 +98,11 @@
 PHP_FUNCTION(ldap_8859_to_t61);
 #endif
 
+#ifdef LDAP_CONTROL_PAGEDRESULTS
+/* RFC 2696 */
+PHP_FUNCTION(ldap_ctrl_paged_results);
+PHP_FUNCTION(ldap_ctrl_paged_results_resp);
+#endif
 ZEND_BEGIN_MODULE_GLOBALS(ldap)
 	long num_links;
 	long max_links;
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Apr 19 05:01:29 2024 UTC