Ben Zend Framework için Zend_Ldap geliştirirken aynı sorundan vurdu oldum. Ben asıl sorunun ne olduğunu anlatmaya çalışacağım, ama kısa yapmak için: nedeniyle tam olarak bu uzantı strong> sınırlamalar it's currently not possible to use paged results from an Active Directory with an unpatched PHP (ext/ldap
) sürümü.
Kullanıcının şeyi çözmeye çalışalım ... Microsoft Active Directory sunucu tarafı sonucu sayfalama gerçekleştirmek için bir sözde sunucu denetimi kullanır. Bu kontrol ist RFC 2696 "LDAP Control Extension for Simple Paged Results Manipulation" tarif edilmiştir.
ext/php
ile ldap_set_option()
and the LDAP_OPT_SERVER_CONTROLS
ve LDAP_OPT_CLIENT_CONTROLS
seçeneği sırasıyla aracılığıyla LDAP kontrolü uzantıları için bir erişim sunuyor. Sayfalı kontrolünü ayarlamak için denetimi-oid, (bu RFC açıklanan) 1.2.840.113556.1.4.319
, ve biz kontrol değerini kodlamak için bilmek gerekir gerekiyor. Değeri (RFC kopyalanan) aşağıdaki SEQUENCE BER kodlu sürümünü sararak bir sekizli dize:
realSearchControlValue ::= SEQUENCE {
size INTEGER (0..maxInt),
-- requested page size from client
-- result set size estimate from server
cookie OCTET STRING
}
Bu yüzden önce LDAP sorgusunu yürütme uygun sunucu kontrolü ayarlayabilirsiniz:
$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
);
Bu bize LDAP / AD sunucusuna bir sayfalık sorgu göndermek için izin verir. Ama takip etmek daha fazla sayfa varsa nasıl anlarım ve nasıl biz bizim bir sonraki sorgu göndermek zorunda olan kontrol değeri ile belirtebilirim?
Biz saplanıyor giriyoruz ... sunucu belleği gerekli bilgileri içeren bir sonuç kümesi ile yanıt ancak PHP sonuç kümesinden tam olarak bu bilgileri almak için bir yöntem yoktur. PHP LDAP API işlevi ldap_parse_result()
but the required last parameter serverctrlsp
PHP işlevine maruz kalmayan bir sarıcı sağlar, böylece gerekli bilgileri almak için hiçbir yolu yoktur. A bug report bu sorun için dava açılmıştır, ancak 2005 yılından bu yana herhangi bir yanıt olmuştur. ldap_parse_result()
function disk belleği sonuçları gibi çalışacak kullanarak, istenen parametreyi sağlanmışsa
$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);
}
}
Eğer tek bir kod satırı var gördüğünüz gibi (*)
Bu her şey işe yaramaz hale getirir. Benim yolda bu konuda bilgi seyrek olsa ben bir Iñaki Arenaza tarafından PHP 4.3.10 ext/ldap
karşı yama bulundu ama ne ben bunu denemek ne yama bir PHP5'ta {uygulanabilir olmadığını ben biliyorum yaptım [(1)]}. Yama ldap_parse_result()
PHP 7. parametre açığa kadar uzanır:
--- 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) {
Aslında sol tek seçenek Active Directory yapılandırmasını değiştirmek ve maksimum sonuç sınırını yükseltmek olacaktır. İlgili seçeneği MaxPageSize
denir ve ntdsutil.exe
ile değiştirilebilir - "How to view and set LDAP policy in Active Directory by using Ntdsutil.exe" bakın.
EDIT (COM referans):
Ya da yuvarlak başka bir yol gitmek ve link eykanal tarafından sağlanan önerildiği gibi ADODB üzerinden COM-yaklaşımı kullanabilirsiniz.