मुझे Zend_Ldap के विकास के दौरान एक ही समस्या से मारा गया है ज़ेंड फ्रेमवर्क के लिए। मैं यह समझाने की कोशिश करूंगा कि वास्तविक समस्या क्या है, लेकिन इसे कम करने के लिए: PHP 5.4 तक, एक असीमित PHP (ext/ldap
) संस्करण के साथ एक सक्रिय निर्देशिका से पेज किए गए परिणामों का उपयोग करना संभव नहीं था क्योंकि वास्तव में सीमाएं विस्तार।
आइए पूरी चीज़ को सुलझाने का प्रयास करें ... Microsoft सक्रिय निर्देशिका सर्वर-साइड परिणाम पेजिंग को पूरा करने के लिए एक तथाकथित सर्वर नियंत्रण का उपयोग करती है। यह नियंत्रण RFC 2696 "LDAP Control Extension for Simple Paged Results Manipulation" में वर्णित है।
ext/php
क्रमशः अपने ldap_set_option()
और LDAP_OPT_SERVER_CONTROLS
और LDAP_OPT_CLIENT_CONTROLS
विकल्प के माध्यम से LDAP नियंत्रण विस्तार में कोई प्रदान करता है। पेज किए गए नियंत्रण को सेट करने के लिए आपको नियंत्रण-ओआईडी की आवश्यकता होती है, जो 1.2.840.113556.1.4.319
है, और हमें यह जानने की आवश्यकता है कि नियंत्रण-मूल्य को कैसे एन्कोड किया जाए (यह RFC में वर्णित है)।
$pageSize = 100;
$pageControl = array(
'oid' => '1.2.840.113556.1.4.319', // the control-oid
'iscritical' => true, // the operation should fail if the server is not able to support this control
'value' => sprintf ("%c%c%c%c%c%c%c", 48, 5, 2, 1, $pageSize, 4, 0) // the required BER-encoded control-value
);
:
realSearchControlValue ::= SEQUENCE {
size INTEGER (0..maxInt),
-- requested page size from client
-- result set size estimate from server
cookie OCTET STRING
}
तो हम LDAP क्वेरी को क्रियान्वित करने से पहले उपयुक्त सर्वर नियंत्रण सेट कर सकते हैं: मूल्य संख्या एन्कोड (RFC से नकल) निम्न क्रम के संस्करण लपेटकर ओकटेट स्ट्रिंग है
यह हमें एलडीएपी/एडी सर्वर पर एक पेजेड क्वेरी भेजने की अनुमति देता है। लेकिन हम कैसे जानते हैं कि अनुसरण करने के लिए और अधिक पृष्ठ हैं और हम कैसे निर्दिष्ट करते हैं कि किस नियंत्रण-मूल्य के साथ हमें अपनी अगली क्वेरी भेजनी है?
यह वह जगह है जहां हम अटक रहे हैं ... सर्वर एक परिणाम सेट के साथ प्रतिक्रिया करता है जिसमें आवश्यक पेजिंग जानकारी शामिल है लेकिन PHP में परिणाम सेट से बिल्कुल इस जानकारी को पुनर्प्राप्त करने के लिए कोई तरीका नहीं है। PHP एलडीएपी एपीआई फ़ंक्शन ldap_parse_result()
के लिए एक रैपर प्रदान करता है लेकिन आवश्यक अंतिम पैरामीटर serverctrlsp
PHP फ़ंक्शन से अवगत नहीं है, इसलिए आवश्यक जानकारी पुनर्प्राप्त करने का कोई तरीका नहीं है। एक bug report इस मुद्दे के लिए दायर किया गया है लेकिन ldap_parse_result()
समारोह आवश्यक पैरामीटर प्रदान की तो 2005 के बाद से कोई जवाब नहीं आया है, पृष्ठांकित परिणामों का उपयोग की तरह
$l = ldap_connect('somehost.mydomain.com');
$pageSize = 100;
$pageControl = array(
'oid' => '1.2.840.113556.1.4.319',
'iscritical' => true,
'value' => sprintf ("%c%c%c%c%c%c%c", 48, 5, 2, 1, $pageSize, 4, 0)
);
$controls = array($pageControl);
ldap_set_option($l, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_bind($l, 'CN=bind-user,OU=my-users,DC=mydomain,DC=com', 'bind-user-password');
$continue = true;
while ($continue) {
ldap_set_option($l, LDAP_OPT_SERVER_CONTROLS, $controls);
$sr = ldap_search($l, 'OU=some-ou,DC=mydomain,DC=com', 'cn=*', array('sAMAccountName'), null, null, null, null);
ldap_parse_result ($l, $sr, $errcode, $matcheddn, $errmsg, $referrals, $serverctrls); // (*)
if (isset($serverctrls)) {
foreach ($serverctrls as $i) {
if ($i["oid"] == '1.2.840.113556.1.4.319') {
$i["value"]{8} = chr($pageSize);
$i["iscritical"] = true;
$controls = array($i);
break;
}
}
}
$info = ldap_get_entries($l, $sr);
if ($info["count"] < $pageSize) {
$continue = false;
}
for ($entry = ldap_first_entry($l, $sr); $entry != false; $entry = ldap_next_entry($l, $entry)) {
$dn = ldap_get_dn($l, $entry);
}
}
काम करेगा जैसा कि आप देख कोड (*)
की एक पंक्ति है जो पूरी चीज बेकार है। मेरे रास्ते पर हालांकि इस विषय पर छेड़छाड़ की जानकारी मुझे आईनाकी एरेनाज़ा द्वारा PHP 4.3.10 ext/ldap
के खिलाफ एक पैच मिला लेकिन मैंने कोशिश नहीं की और न ही मुझे पता है कि पैच को PHP5 ext/ldap
पर लागू किया जा सकता है या नहीं। पैच ldap_parse_result()
फैली पीएचपी करने के लिए 7 वीं पैरामीटर बेनकाब करने के लिए:
--- ldap.c 2004-06-01 23:05:33.000000000 +0200
+++ /usr/src/php4/php4-4.3.10/ext/ldap/ldap.c 2005-09-03 17:02:03.000000000 +0200
@@ -74,7 +74,7 @@
ZEND_DECLARE_MODULE_GLOBALS(ldap)
static unsigned char third_argument_force_ref[] = { 3, BYREF_NONE, BYREF_NONE, BYREF_FORCE };
-static unsigned char arg3to6of6_force_ref[] = { 6, BYREF_NONE, BYREF_NONE, BYREF_FORCE, BYREF_FORCE, BYREF_FORCE, BYREF_FORCE };
+static unsigned char arg3to7of7_force_ref[] = { 7, BYREF_NONE, BYREF_NONE, BYREF_FORCE, BYREF_FORCE, BYREF_FORCE, BYREF_FORCE, BYREF_FORCE };
static int le_link, le_result, le_result_entry, le_ber_entry;
@@ -124,7 +124,7 @@
#if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP
PHP_FE(ldap_get_option, third_argument_force_ref)
PHP_FE(ldap_set_option, NULL)
- PHP_FE(ldap_parse_result, arg3to6of6_force_ref)
+ PHP_FE(ldap_parse_result, arg3to7of7_force_ref)
PHP_FE(ldap_first_reference, NULL)
PHP_FE(ldap_next_reference, NULL)
#ifdef HAVE_LDAP_PARSE_REFERENCE
@@ -1775,14 +1775,15 @@
Extract information from result */
PHP_FUNCTION(ldap_parse_result)
{
- pval **link, **result, **errcode, **matcheddn, **errmsg, **referrals;
+ pval **link, **result, **errcode, **matcheddn, **errmsg, **referrals, **serverctrls;
ldap_linkdata *ld;
LDAPMessage *ldap_result;
+ LDAPControl **lserverctrls, **ctrlp, *ctrl;
char **lreferrals, **refp;
char *lmatcheddn, *lerrmsg;
int rc, lerrcode, myargcount = ZEND_NUM_ARGS();
- if (myargcount 6 || zend_get_parameters_ex(myargcount, &link, &result, &errcode, &matcheddn, &errmsg, &referrals) == FAILURE) {
+ if (myargcount 7 || zend_get_parameters_ex(myargcount, &link, &result, &errcode, &matcheddn, &errmsg, &referrals, &serverctrls) == FAILURE) {
WRONG_PARAM_COUNT;
}
@@ -1793,7 +1794,7 @@
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(E_WARNING, "%s(): Unable to parse result: %s", get_active_function_name(TSRMLS_C), ldap_err2string(rc));
@@ -1805,6 +1806,29 @@
/* Reverse -> fall through */
switch(myargcount) {
+ case 7 :
+ zval_dtor(*serverctrls);
+
+ if (lserverctrls != NULL) {
+ array_init(*serverctrls);
+ ctrlp = lserverctrls;
+
+ while (*ctrlp != NULL) {
+ zval *ctrl_array;
+
+ ctrl = *ctrlp;
+ MAKE_STD_ZVAL(ctrl_array);
+ array_init(ctrl_array);
+
+ add_assoc_string(ctrl_array, "oid", ctrl->ldctl_oid,1);
+ add_assoc_bool(ctrl_array, "iscritical", ctrl->ldctl_iscritical);
+ add_assoc_stringl(ctrl_array, "value", ctrl->ldctl_value.bv_val,
+ ctrl->ldctl_value.bv_len,1);
+ add_next_index_zval (*serverctrls, ctrl_array);
+ ctrlp++;
+ }
+ ldap_controls_free (lserverctrls);
+ }
case 6 :
zval_dtor(*referrals);
if (array_init(*referrals) == FAILURE) {
वास्तव में एकमात्र विकल्प सक्रिय निर्देशिका विन्यास बदल सकते हैं और अधिक से अधिक परिणाम सीमा बढ़ाने का होगा छोड़ दिया है। प्रासंगिक विकल्प को MaxPageSize
कहा जाता है और ntdsutil.exe
का उपयोग करके बदला जा सकता है - कृपया "How to view and set LDAP policy in Active Directory by using Ntdsutil.exe" देखें।
संपादित (COM के संदर्भ में):
या आप इसके विपरीत जाने के लिए और के रूप में linkeykanal द्वारा प्रदान में सुझाव दिया ADODB के माध्यम से COM-दृष्टिकोण का उपयोग कर सकते हैं।
शानदार उत्तर! बहुत बहुत धन्यवाद, इससे मुझे बहुत मदद मिली! – Christian
अब इसकी स्थिति क्या है कि PHP 5.4 पेजेड एलडीएपी परिणामों का समर्थन करता है? – Squazic
@ स्क्वैज़िक: नीचे दिए गए जवाब http://stackoverflow.com/a/10140166/11354 देखें। लगता है कि PHP 5.4 के साथ शुरू करने योग्य लगता है। –