]> granicus.if.org Git - php/commitdiff
Added support for VLV controls request and response
authorCôme Chilliet <mcmic@php.net>
Thu, 14 Sep 2017 13:50:05 +0000 (15:50 +0200)
committerCôme Chilliet <mcmic@php.net>
Thu, 21 Sep 2017 08:05:42 +0000 (10:05 +0200)
ext/ldap/ldap.c
ext/ldap/tests/ldap_search_sort_controls.phpt

index dbe68a3d6155543268bd6a0016b9b4b8a7cff3fe..1b19e0599a25ffba889f00cd3186f11fe9d8a52a 100644 (file)
@@ -245,6 +245,27 @@ static void _php_ldap_control_to_array(LDAP *ld, LDAPControl* ctrl, zval* array,
                } 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);
@@ -455,6 +476,72 @@ static int _php_ldap_control_from_array(LDAP *ld, LDAPControl** ctrl, zval* arra
                                        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;
index a9781b6029706343efdd61b0ee02d33e3208e6c4..16504a69975074eacb424e5dd60b6599c9d0a45e 100644 (file)
@@ -1,5 +1,5 @@
 --TEST--
-ldap_search() test with sort controls
+ldap_search() test with sort and VLV controls
 --CREDITS--
 Côme Chilliet <mcmic@php.net>
 --SKIPIF--
@@ -8,6 +8,7 @@ require_once('skipif.inc');
 require_once('skipifbindfailure.inc');
 require_once('skipifcontrol.inc');
 skipifunsupportedcontrol(LDAP_CONTROL_SORTREQUEST);
+skipifunsupportedcontrol(LDAP_CONTROL_VLVREQUEST);
 ?>
 --FILE--
 <?php
@@ -16,10 +17,9 @@ include "connect.inc";
 $link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version);
 insert_dummy_data($link, $base);
 
-$dn = "$base";
-$filter = "(cn=*)";
+/* First test with only SORT control */
 var_dump(
-       $result = ldap_search($link, $base, $filter, array('cn'), 0, 0, 0, LDAP_DEREF_NEVER,
+       $result = ldap_search($link, $base, '(cn=*)', array('cn'), 0, 0, 0, LDAP_DEREF_NEVER,
                [
                        [
                                'oid' => LDAP_CONTROL_SORTREQUEST,
@@ -36,6 +36,39 @@ var_dump(
        $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--
@@ -114,4 +147,61 @@ array(1) {
     }
   }
 }
+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===