php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Return to Bug #64317
Patch ldap_modify_batch.patch revision 2013-02-27 23:35 UTC by ondra dot hosek at gmail dot com

Patch ldap_modify_batch.patch for LDAP related Bug #64317

Patch version 2013-02-27 23:35 UTC

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

Developer: ondra.hosek@gmail.com

diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c
index 3cfa209..430bee4 100644
--- a/ext/ldap/ldap.c
+++ b/ext/ldap/ldap.c
@@ -152,6 +152,15 @@ PHP_MINIT_FUNCTION(ldap)
 	REGISTER_LONG_CONSTANT("LDAP_DEREF_FINDING", LDAP_DEREF_FINDING, CONST_PERSISTENT | CONST_CS);
 	REGISTER_LONG_CONSTANT("LDAP_DEREF_ALWAYS", LDAP_DEREF_ALWAYS, CONST_PERSISTENT | CONST_CS);
 
+	/* Constants to be used with ldap_modify_batch() */
+	REGISTER_LONG_CONSTANT("LDAP_MODIFY_BATCH_ADD", LDAP_MODIFY_BATCH_ADD, CONST_PERSISTENT | CONST_CS);
+	REGISTER_LONG_CONSTANT("LDAP_MODIFY_BATCH_REMOVE", LDAP_MODIFY_BATCH_REMOVE, CONST_PERSISTENT | CONST_CS);
+	REGISTER_LONG_CONSTANT("LDAP_MODIFY_BATCH_REMOVE_ALL", LDAP_MODIFY_BATCH_REMOVE_ALL, CONST_PERSISTENT | CONST_CS);
+	REGISTER_LONG_CONSTANT("LDAP_MODIFY_BATCH_REPLACE", LDAP_MODIFY_BATCH_REPLACE, CONST_PERSISTENT | CONST_CS);
+	REGISTER_STRING_CONSTANT("LDAP_MODIFY_BATCH_ATTRIB", LDAP_MODIFY_BATCH_ATTRIB, CONST_PERSISTENT | CONST_CS);
+	REGISTER_STRING_CONSTANT("LDAP_MODIFY_BATCH_MODTYPE", LDAP_MODIFY_BATCH_MODTYPE, CONST_PERSISTENT | CONST_CS);
+	REGISTER_STRING_CONSTANT("LDAP_MODIFY_BATCH_VALUES", LDAP_MODIFY_BATCH_VALUES, CONST_PERSISTENT | CONST_CS);
+
 #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10
 	/* LDAP options */
 	REGISTER_LONG_CONSTANT("LDAP_OPT_DEREF", LDAP_OPT_DEREF, CONST_PERSISTENT | CONST_CS);
@@ -1432,6 +1441,356 @@ PHP_FUNCTION(ldap_delete)
 }
 /* }}} */
 
+/* {{{ _ldap_str_equal_to_const
+ */
+static int _ldap_str_equal_to_const(const char *str, uint str_len, const char *cstr)
+{
+	int i;
+
+	if (strlen(cstr) != str_len)
+		return 0;
+
+	for (i = 0; i < str_len; ++i) {
+		if (str[i] != cstr[i]) {
+			return 0;
+		}
+	}
+
+	return 1;
+}
+/* }}} */
+
+/* {{{ _ldap_strlen_max
+ */
+static int _ldap_strlen_max(const char *str, uint max_len)
+{
+	int i;
+
+	for (i = 0; i < max_len; ++i) {
+		if (str[i] == '\0') {
+			return i;
+		}
+	}
+
+	return max_len;
+}
+/* }}} */
+
+/* {{{ _ldap_hash_fetch
+ */
+static void _ldap_hash_fetch(zval *hashTbl, const char *key, zval **out)
+{
+	zval **fetched;
+	if (zend_hash_find(Z_ARRVAL_P(hashTbl), key, strlen(key)+1, (void **) &fetched) == SUCCESS) {
+		*out = *fetched;
+	}
+	else {
+		*out = NULL;
+	}
+}
+/* }}} */
+
+/* {{{ proto bool ldap_modify_batch(resource link, string dn, array modifs)
+   Perform multiple modifications as part of one operation */
+PHP_FUNCTION(ldap_modify_batch)
+{
+	ldap_linkdata *ld;
+	zval *link, *mods, *mod, *modinfo, *modval;
+	zval *attrib, *modtype, *vals;
+	zval **fetched;
+	char *dn;
+	int dn_len;
+	int i, j, k;
+	int num_mods, num_modprops, num_modvals;
+	LDAPMod **ldap_mods;
+	uint oper;
+
+	/*
+	$mods = array(
+		array(
+			"attrib" => "unicodePwd",
+			"modtype" => LDAP_MODIFY_BATCH_REMOVE,
+			"values" => array($oldpw)
+		),
+		array(
+			"attrib" => "unicodePwd",
+			"modtype" => LDAP_MODIFY_BATCH_ADD,
+			"values" => array($newpw)
+		),
+		array(
+			"attrib" => "userPrincipalName",
+			"modtype" => LDAP_MODIFY_BATCH_REPLACE,
+			"values" => array("janitor@corp.contoso.com")
+		),
+		array(
+			"attrib" => "userCert",
+			"modtype" => LDAP_MODIFY_BATCH_REMOVE_ALL
+		)
+    );
+    */
+
+    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsa", &link, &dn, &dn_len, &mods) != SUCCESS) {
+        return;
+    }
+
+	ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
+
+	/* perform validation */
+	{
+		char *modkey;
+		uint modkeylen;
+		long modtype;
+
+		/* to store the wrongly-typed keys */
+		char *tmpStr;
+		uint tmpUint;
+		ulong tmpUlong;
+
+		/* make sure the DN contains no NUL bytes */
+		if (_ldap_strlen_max(dn, dn_len) != dn_len) {
+			php_error_docref(NULL TSRMLS_CC, E_WARNING, "DN must not contain NUL bytes");
+			RETURN_FALSE;
+		}
+
+		/* make sure the top level is a normal array */
+		zend_hash_internal_pointer_reset(Z_ARRVAL_P(mods));
+		if (zend_hash_get_current_key_type(Z_ARRVAL_P(mods)) != HASH_KEY_IS_LONG) {
+			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Modifications array must not be string-indexed");
+			RETURN_FALSE;
+		}
+
+		num_mods = zend_hash_num_elements(Z_ARRVAL_P(mods));
+
+		for (i = 0; i < num_mods; i++) {
+			/* is the numbering consecutive? */
+			if (zend_hash_index_find(Z_ARRVAL_P(mods), i, (void **) &fetched) != SUCCESS) {
+				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Modifications array must have consecutive indices 0, 1, ...");
+				RETURN_FALSE;
+			}
+			mod = *fetched;
+
+			/* is it an array? */
+			if (Z_TYPE_P(mod) != IS_ARRAY) {
+				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Each entry of modifications array must be an array itself");
+				RETURN_FALSE;
+			}
+
+			/* for the modification hashtable... */
+			zend_hash_internal_pointer_reset(Z_ARRVAL_P(mod));
+			num_modprops = zend_hash_num_elements(Z_ARRVAL_P(mod));
+
+			for (j = 0; j < num_modprops; j++) {
+				/* are the keys strings? */
+				if (zend_hash_get_current_key_ex(Z_ARRVAL_P(mod), &modkey, &modkeylen, &tmpUlong, 0, NULL) != HASH_KEY_IS_STRING) {
+					php_error_docref(NULL TSRMLS_CC, E_WARNING, "Each entry of modifications array must be string-indexed");
+					RETURN_FALSE;
+				}
+
+				/* modkeylen includes the terminating NUL byte; remove that */
+				--modkeylen;
+
+				/* is this a valid entry? */
+				if (
+					!_ldap_str_equal_to_const(modkey, modkeylen, LDAP_MODIFY_BATCH_ATTRIB) &&
+					!_ldap_str_equal_to_const(modkey, modkeylen, LDAP_MODIFY_BATCH_MODTYPE) &&
+					!_ldap_str_equal_to_const(modkey, modkeylen, LDAP_MODIFY_BATCH_VALUES)
+				) {
+					php_error_docref(NULL TSRMLS_CC, E_WARNING, "The only allowed keys in entries of the modifications array are 'attrib', 'modtype' and 'values'");
+					RETURN_FALSE;
+				}
+
+				zend_hash_get_current_data(Z_ARRVAL_P(mod), (void **) &fetched);
+				modinfo = *fetched;
+
+				/* does the value type match the key? */
+				if (_ldap_str_equal_to_const(modkey, modkeylen, LDAP_MODIFY_BATCH_ATTRIB)) {
+					if (Z_TYPE_P(modinfo) != IS_STRING) {
+						php_error_docref(NULL TSRMLS_CC, E_WARNING, "A '" LDAP_MODIFY_BATCH_ATTRIB "' value must be a string");
+						RETURN_FALSE;
+					}
+
+					if (Z_STRLEN_P(modinfo) != _ldap_strlen_max(Z_STRVAL_P(modinfo), Z_STRLEN_P(modinfo))) {
+						php_error_docref(NULL TSRMLS_CC, E_WARNING, "A '" LDAP_MODIFY_BATCH_ATTRIB "' value must not contain NUL bytes");
+						RETURN_FALSE;
+					}
+				}
+				else if (_ldap_str_equal_to_const(modkey, modkeylen, LDAP_MODIFY_BATCH_MODTYPE)) {
+					if (Z_TYPE_P(modinfo) != IS_LONG) {
+						php_error_docref(NULL TSRMLS_CC, E_WARNING, "A '" LDAP_MODIFY_BATCH_MODTYPE "' value must be a long");
+						RETURN_FALSE;
+					}
+
+					/* is the value in range? */
+					modtype = Z_LVAL_P(modinfo);
+					if (
+						modtype != LDAP_MODIFY_BATCH_ADD &&
+						modtype != LDAP_MODIFY_BATCH_REMOVE &&
+						modtype != LDAP_MODIFY_BATCH_REPLACE &&
+						modtype != LDAP_MODIFY_BATCH_REMOVE_ALL
+					) {
+						php_error_docref(NULL TSRMLS_CC, E_WARNING, "The '" LDAP_MODIFY_BATCH_MODTYPE "' value must match one of the LDAP_MODIFY_BATCH_* constants");
+						RETURN_FALSE;
+					}
+
+					/* if it's REMOVE_ALL, there must not be a values array; otherwise, there must */
+					if (modtype == LDAP_MODIFY_BATCH_REMOVE_ALL) {
+						if (zend_hash_exists(Z_ARRVAL_P(mod), LDAP_MODIFY_BATCH_VALUES, strlen(LDAP_MODIFY_BATCH_VALUES) + 1)) {
+							php_error_docref(NULL TSRMLS_CC, E_WARNING, "If '" LDAP_MODIFY_BATCH_MODTYPE "' is LDAP_MODIFY_BATCH_REMOVE_ALL, a '" LDAP_MODIFY_BATCH_VALUES "' array must not be provided");
+							RETURN_FALSE;
+						}
+					}
+					else {
+						if (!zend_hash_exists(Z_ARRVAL_P(mod), LDAP_MODIFY_BATCH_VALUES, strlen(LDAP_MODIFY_BATCH_VALUES) + 1)) {
+							php_error_docref(NULL TSRMLS_CC, E_WARNING, "If '" LDAP_MODIFY_BATCH_MODTYPE "' is not LDAP_MODIFY_BATCH_REMOVE_ALL, a '" LDAP_MODIFY_BATCH_VALUES "' array must be provided");
+							RETURN_FALSE;
+						}
+					}
+				}
+				else if (_ldap_str_equal_to_const(modkey, modkeylen, LDAP_MODIFY_BATCH_VALUES)) {
+					if (Z_TYPE_P(modinfo) != IS_ARRAY) {
+						php_error_docref(NULL TSRMLS_CC, E_WARNING, "A '" LDAP_MODIFY_BATCH_VALUES "' value must be an array");
+						RETURN_FALSE;
+					}
+
+					/* is the array not empty? */
+					num_modvals = zend_hash_num_elements(Z_ARRVAL_P(modinfo));
+					if (num_modvals == 0) {
+						php_error_docref(NULL TSRMLS_CC, E_WARNING, "A '" LDAP_MODIFY_BATCH_VALUES "' array must have at least one element");
+						RETURN_FALSE;
+					}
+
+					/* are its keys integers? */
+					if (zend_hash_get_current_key_type(Z_ARRVAL_P(modinfo)) != HASH_KEY_IS_LONG) {
+						php_error_docref(NULL TSRMLS_CC, E_WARNING, "A '" LDAP_MODIFY_BATCH_VALUES "' array must not be string-indexed");
+						RETURN_FALSE;
+					}
+
+					/* are the keys consecutive? */
+					for (k = 0; k < num_modvals; k++) {
+						if (zend_hash_index_find(Z_ARRVAL_P(modinfo), k, (void **) &fetched) != SUCCESS) {
+							php_error_docref(NULL TSRMLS_CC, E_WARNING, "A '" LDAP_MODIFY_BATCH_VALUES "' array must have consecutive indices 0, 1, ...");
+							RETURN_FALSE;
+						}
+						modval = *fetched;
+
+						/* is the data element a string? */
+						if (Z_TYPE_P(modval) != IS_STRING) {
+							php_error_docref(NULL TSRMLS_CC, E_WARNING, "Each element of a '" LDAP_MODIFY_BATCH_VALUES "' array must be a string");
+							RETURN_FALSE;
+						}
+					}
+				}
+
+				zend_hash_move_forward(Z_ARRVAL_P(mod));
+			}
+		}
+	}
+	/* validation was successful */
+
+	/* allocate array of modifications */
+	ldap_mods = safe_emalloc((num_mods+1), sizeof(LDAPMod *), 0);
+
+    /* for each modification */
+	for (i = 0; i < num_mods; i++) {
+		/* allocate the modification struct */
+		ldap_mods[i] = emalloc(sizeof(LDAPMod));
+
+		/* fetch the relevant data */
+		zend_hash_index_find(Z_ARRVAL_P(mods), i, (void **) &fetched);
+		mod = *fetched;
+
+		_ldap_hash_fetch(mod, LDAP_MODIFY_BATCH_ATTRIB, &attrib);
+		_ldap_hash_fetch(mod, LDAP_MODIFY_BATCH_MODTYPE, &modtype);
+		_ldap_hash_fetch(mod, LDAP_MODIFY_BATCH_VALUES, &vals);
+
+		/* map the modification type */
+		switch (Z_LVAL_P(modtype)) {
+			case LDAP_MODIFY_BATCH_ADD:
+				oper = LDAP_MOD_ADD;
+				break;
+			case LDAP_MODIFY_BATCH_REMOVE:
+			case LDAP_MODIFY_BATCH_REMOVE_ALL:
+				oper = LDAP_MOD_DELETE;
+				break;
+			case LDAP_MODIFY_BATCH_REPLACE:
+				oper = LDAP_MOD_REPLACE;
+				break;
+			default:
+				php_error_docref(NULL TSRMLS_CC, E_ERROR, "Unknown and uncaught modification type.");
+				RETURN_FALSE;
+		}
+
+		/* fill in the basic info */
+		ldap_mods[i]->mod_op = oper | LDAP_MOD_BVALUES;
+		ldap_mods[i]->mod_type = estrndup(Z_STRVAL_P(attrib), Z_STRLEN_P(attrib));
+
+		if (Z_LVAL_P(modtype) == LDAP_MODIFY_BATCH_REMOVE_ALL) {
+			/* no values */
+			ldap_mods[i]->mod_bvalues = NULL;
+		}
+		else {
+			/* allocate space for the values as part of this modification */
+			num_modvals = zend_hash_num_elements(Z_ARRVAL_P(vals));
+			ldap_mods[i]->mod_bvalues = emalloc((num_modvals+1) * sizeof(struct berval *));
+
+			/* for each value */
+			for (j = 0; j < num_modvals; j++) {
+				/* fetch it */
+				zend_hash_index_find(Z_ARRVAL_P(vals), j, (void **) &fetched);
+				modval = *fetched;
+
+				/* allocate the data struct */
+				ldap_mods[i]->mod_bvalues[j] = emalloc(sizeof(struct berval));
+
+				/* fill it */
+				ldap_mods[i]->mod_bvalues[j]->bv_len = Z_STRLEN_P(modval);
+				ldap_mods[i]->mod_bvalues[j]->bv_val = estrndup(Z_STRVAL_P(modval), Z_STRLEN_P(modval));
+			}
+
+			/* NULL-terminate values */
+			ldap_mods[i]->mod_bvalues[num_modvals] = NULL;
+		}
+	}
+
+	/* NULL-terminate modifications */
+	ldap_mods[num_mods] = NULL;
+
+	/* perform (finally) */
+	if ((i = ldap_modify_ext_s(ld->link, dn, ldap_mods, NULL, NULL)) != LDAP_SUCCESS) {
+		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Batch Modify: %s", ldap_err2string(i));
+		RETVAL_FALSE;
+	} else RETVAL_TRUE;
+
+	/* clean up */
+	{
+		for (i = 0; i < num_mods; i++) {
+			/* attribute */
+			efree(ldap_mods[i]->mod_type);
+
+			if (ldap_mods[i]->mod_bvalues != NULL) {
+				/* each BER value */
+				for (j = 0; ldap_mods[i]->mod_bvalues[j] != NULL; j++) {
+					/* free the data bytes */
+					efree(ldap_mods[i]->mod_bvalues[j]->bv_val);
+
+					/* free the bvalue struct */
+					efree(ldap_mods[i]->mod_bvalues[j]);
+				}
+
+				/* the BER value array */
+				efree(ldap_mods[i]->mod_bvalues);
+			}
+
+			/* the modification */
+			efree(ldap_mods[i]);
+		}
+
+		/* the modifications array */
+		efree(ldap_mods);
+	}
+}
+/* }}} */
+
 /* {{{ proto int ldap_errno(resource link)
    Get the current ldap error number */
 PHP_FUNCTION(ldap_errno)
@@ -2515,6 +2874,12 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_modify, 0, 0, 3)
 	ZEND_ARG_INFO(0, entry)
 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_INFO(0, modifications_info)
+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)
@@ -2668,6 +3033,7 @@ const zend_function_entry ldap_functions[] = {
 	PHP_FE(ldap_dn2ufn,									arginfo_ldap_dn2ufn)
 	PHP_FE(ldap_add,									arginfo_ldap_add)
 	PHP_FE(ldap_delete,									arginfo_ldap_delete)
+	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 */
diff --git a/ext/ldap/php_ldap.h b/ext/ldap/php_ldap.h
index 2ed8fd8..d8d5d4a 100644
--- a/ext/ldap/php_ldap.h
+++ b/ext/ldap/php_ldap.h
@@ -50,4 +50,14 @@ ZEND_END_MODULE_GLOBALS(ldap)
 
 #define phpext_ldap_ptr ldap_module_ptr
 
+/* Constants for ldap_modify_batch */
+#define LDAP_MODIFY_BATCH_ADD        0x01
+#define LDAP_MODIFY_BATCH_REMOVE     0x02
+#define LDAP_MODIFY_BATCH_REMOVE_ALL 0x12
+#define LDAP_MODIFY_BATCH_REPLACE    0x03
+
+#define LDAP_MODIFY_BATCH_ATTRIB     "attrib"
+#define LDAP_MODIFY_BATCH_MODTYPE    "modtype"
+#define LDAP_MODIFY_BATCH_VALUES     "values"
+
 #endif /* PHP_LDAP_H */
diff --git a/ext/ldap/tests/ldap_modify_batch_basic.phpt b/ext/ldap/tests/ldap_modify_batch_basic.phpt
new file mode 100644
index 0000000..4f6705c
--- /dev/null
+++ b/ext/ldap/tests/ldap_modify_batch_basic.phpt
@@ -0,0 +1,109 @@
+--TEST--
+ldap_modify_batch() - Basic batch modify operation
+--CREDITS--
+Patrick Allaert <patrickallaert@php.net>
+Ondřej Hošek <ondra.hosek@gmail.com>
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+<?php require_once('skipifbindfailure.inc'); ?>
+--FILE--
+<?php
+require "connect.inc";
+
+$link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version);
+insert_dummy_data($link);
+
+$mods = array(
+	array(
+		"attrib"	=> "telephoneNumber",
+		"modtype"	=> LDAP_MODIFY_BATCH_ADD,
+		"values"	=> array(
+			"+1 555 5551717"
+		)
+	),
+	array(
+		"attrib"	=> "sn",
+		"modtype"	=> LDAP_MODIFY_BATCH_REPLACE,
+		"values"	=> array("Brown-Smith")
+	),
+	array(
+		"attrib"	=> "description",
+		"modtype"	=> LDAP_MODIFY_BATCH_REMOVE_ALL
+	)
+);
+
+var_dump(
+	ldap_modify_batch($link, "cn=userA,dc=my-domain,dc=com", $mods),
+	ldap_get_entries($link, ldap_search($link, "dc=my-domain,dc=com", "(sn=Brown-Smith)"))
+);
+?>
+===DONE===
+--CLEAN--
+<?php
+require "connect.inc";
+
+$link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version);
+
+remove_dummy_data($link);
+?>
+--EXPECT--
+bool(true)
+array(2) {
+  ["count"]=>
+  int(1)
+  [0]=>
+  array(12) {
+    ["objectclass"]=>
+    array(2) {
+      ["count"]=>
+      int(1)
+      [0]=>
+      string(6) "person"
+    }
+    [0]=>
+    string(11) "objectclass"
+    ["cn"]=>
+    array(2) {
+      ["count"]=>
+      int(1)
+      [0]=>
+      string(5) "userA"
+    }
+    [1]=>
+    string(2) "cn"
+    ["userpassword"]=>
+    array(2) {
+      ["count"]=>
+      int(1)
+      [0]=>
+      string(4) "oops"
+    }
+    [2]=>
+    string(12) "userpassword"
+    ["telephonenumber"]=>
+    array(3) {
+      ["count"]=>
+      int(2)
+      [0]=>
+      string(14) "xx-xx-xx-xx-xx"
+      [1]=>
+      string(14) "+1 555 5551717"
+    }
+    [3]=>
+    string(15) "telephonenumber"
+    ["sn"]=>
+    array(2) {
+      ["count"]=>
+      int(1)
+      [0]=>
+      string(11) "Brown-Smith"
+    }
+    [4]=>
+    string(2) "sn"
+    ["count"]=>
+    int(5)
+    ["dn"]=>
+    string(28) "cn=userA,dc=my-domain,dc=com"
+  }
+}
+===DONE===
diff --git a/ext/ldap/tests/ldap_modify_batch_error.phpt b/ext/ldap/tests/ldap_modify_batch_error.phpt
new file mode 100644
index 0000000..687c371
--- /dev/null
+++ b/ext/ldap/tests/ldap_modify_batch_error.phpt
@@ -0,0 +1,104 @@
+--TEST--
+ldap_modify_batch() - Batch modify operations that should fail
+--CREDITS--
+Patrick Allaert <patrickallaert@php.net>
+Ondřej Hošek <ondra.hosek@gmail.com>
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+<?php require_once('skipifbindfailure.inc'); ?>
+--FILE--
+<?php
+require "connect.inc";
+
+$link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version);
+
+$addGivenName = array(
+	array(
+		"attrib"	=> "givenName",
+		"modtype"	=> LDAP_MODIFY_BATCH_ADD,
+		"values"	=> array("Jack")
+	)
+);
+
+// Too few parameters
+var_dump(ldap_modify_batch());
+var_dump(ldap_modify_batch($link));
+var_dump(ldap_modify_batch($link, "dc=my-domain,dc=com"));
+
+// Too many parameters
+var_dump(ldap_modify_batch($link, "dc=my-domain,dc=com", $addGivenName, "Invalid additional parameter"));
+
+// DN not found
+var_dump(ldap_modify_batch($link, "dc=my-domain,dc=com", $addGivenName));
+
+// Invalid DN
+var_dump(ldap_modify_batch($link, "weirdAttribute=val", $addGivenName));
+
+// prepare
+$entry = array(
+	"objectClass"	=> array(
+		"top",
+		"dcObject",
+		"organization"),
+	"dc"			=> "my-domain",
+	"o"				=> "my-domain",
+);
+
+ldap_add($link, "dc=my-domain,dc=com", $entry);
+
+// invalid domain
+$mods = array(
+	array(
+		"attrib"	=> "dc",
+		"modtype"	=> LDAP_MODIFY_BATCH_REPLACE,
+		"values"	=> array("Wrong Domain")
+	)
+);
+
+var_dump(ldap_modify_batch($link, "dc=my-domain,dc=com", $mods));
+
+// invalid attribute
+$mods = array(
+	array(
+		"attrib"	=> "weirdAttribute",
+		"modtype"	=> LDAP_MODIFY_BATCH_ADD,
+		"values"	=> array("weirdVal", "anotherWeirdval")
+	)
+);
+
+var_dump(ldap_modify_batch($link, "dc=my-domain,dc=com", $mods));
+?>
+===DONE===
+--CLEAN--
+<?php
+require "connect.inc";
+
+$link = ldap_connect_and_bind($host, $port, $user, $passwd, $protocol_version);
+
+ldap_delete($link, "dc=my-domain,dc=com");
+?>
+--EXPECTF--
+Warning: ldap_modify_batch() expects exactly 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
+NULL
+
+Warning: ldap_modify_batch() expects exactly 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
+NULL
+
+Warning: ldap_modify_batch(): Batch Modify: No such object in %s on line %d
+bool(false)
+
+Warning: ldap_modify_batch(): Batch Modify: Invalid DN syntax in %s on line %d
+bool(false)
+
+Warning: ldap_modify_batch(): Batch Modify: Naming violation in %s on line %d
+bool(false)
+
+Warning: ldap_modify_batch(): Batch Modify: Undefined attribute type in %s on line %d
+bool(false)
+===DONE===
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Apr 19 18:01:28 2024 UTC