Electronics & Programming

develissimo

Open Source electronics development and programming

  • You are not logged in.
  • Root
  • » PHP
  • » [PHP-DEV] LDAP controls in response [RSS Feed]

#1 Nov. 8, 2005 22:31:11

Pierangelo M.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

[PHP-DEV] LDAP controls in response


Stig,

I need to use LDAP controls in PHP, including control response from
server to client, so I patched the 5.0.5/HEAD code to add an extra arg
to ldap_parse_result() and ldap_parse_reference(). I'd need this patch
in production at some point, that's why it would be great to see it
merged into the mainstream; however, I'm little familiar with the
internals of PHP, so please excuse me if I missed anything in coding and
in the submission procedure.

The very same patch applies to HEAD and to 5.0.5. If you don't mind,
I'm posting it to you right now, pending further work. It also includes
some extra work I did to eliminate some warnings from OpenLDAP 2.3, but
it works fine with 2.2 as well. All changes specific to OpenLDAP are
protected behind the LDAP_API_FEATURE_X_OPENLDAP macro. Unfortunately I
have no chances to check it with other APIs right now. I'm also
including a trivial script I tested with ./sapi/cli/php against the
server resulting from test003 of OpenLDAP 2.3; to reproduce, just

cd openldap/tests/
../run -k test003
cd php
../sapi/cli/php pagedResults.php

If the code looks fine, I plan to document the new API, which is
completely backwards compatible, and add some facilities to
encode/decode the control values; hopefully, I won't have to get to
writing a complete wrapper around liblber!

My idea is to provide dumb helpers that encode well-known controls
through a trivial API; e.g., for pagedResults:

ldap_control_paged_results($handler, $size, $iscritical)
ldap_control_paged_results_resp($result, &$cookie[, &$iscritical])

for passwdPolicy:

ldap_control_passwd_policy($handler)
ldap_control_passwd_policy_resp($result, &$warning, &$error)

Please let me know if you need me to do anything else.

Sincerely, p.

--
Pierangelo Masarati






Ing. Pierangelo Masarati

Responsabile Open Solution



SysNet s.n.c.

Via Dossi, 8 - 27100 Pavia - ITALIAhttp://www.sys-net.it------------------------------------------

Office: +39.02.23998309

Mobile: +39.333.4963172

Email:

------------------------------------------Index: ext/ldap/ldap.c
===================================================================
RCS file: /repository/php-src/ext/ldap/ldap.c,v
retrieving revision 1.162
diff -u -r1.162 ldap.c
--- ext/ldap/ldap.c 22 Aug 2005 12:22:08 -0000 1.162
+++ ext/ldap/ldap.c 8 Nov 2005 21:04:05 -0000
@@ -191,7 +191,9 @@
{
ldap_linkdata *ld = (ldap_linkdata *)rsrc->ptr;

- ldap_unbind_s(ld->link);
+ /* ldap_unbind_s() is deprecated;
+ * the distinction between ldap_unbind() and ldap_unbind_s() is moot */
+ ldap_unbind_ext(ld->link, NULL, NULL);
#if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC)
if (ld->rebindproc != NULL) {
zval_dtor(ld->rebindproc);
@@ -215,6 +217,79 @@
efree(entry);
}

+static int _parse_referrals_resp(char ***lreferralsp, zval **referrals)
+{
+ int num_referrals = 0;
+
+ if (*lreferralsp != NULL) {
+ char **refp = *lreferralsp;
+
+ while (*refp) {
+ add_next_index_string(*referrals, *refp, 1);
+ refp++;
+ num_referrals++;
+ }
+#ifdef LDAP_API_FEATURE_X_OPENLDAP
+ ber_memvfree((void **)*lreferralsp);
+#else
+ ldap_value_free(*lreferralsp);
+#endif
+ *lreferralsp = NULL;
+ }
+
+ add_assoc_long(*referrals, "count", num_referrals);
+
+ return num_referrals;
+}
+
+static int _parse_server_controls_resp(LDAPControl ***lserverctrlsp, zval **serverctrls)
+{
+ int num_serverctrls = 0;
+
+ if (*lserverctrlsp != NULL) {
+ int error = 0;
+ LDAPControl **ctrlp = *lserverctrlsp;
+
+ while (*ctrlp) {
+ zval *ctrlval = NULL;
+
+ if ( (*ctrlp)->ldctl_oid == NULL ) {
+ error = 1;
+ break;
+ }
+
+ MAKE_STD_ZVAL(ctrlval);
+ array_init(ctrlval);
+
+ add_assoc_string(ctrlval, "oid", (*ctrlp)->ldctl_oid, 1);
+ if ( (*ctrlp)->ldctl_value.bv_len ) {
+ add_assoc_stringl(ctrlval, "value", (*ctrlp)->ldctl_value.bv_val, (*ctrlp)->ldctl_value.bv_len, 1);
+ }
+ if ((*ctrlp)->ldctl_iscritical) {
+ add_assoc_bool(ctrlval, "iscritical", (*ctrlp)->ldctl_iscritical);
+ }
+
+ add_next_index_zval(*serverctrls, ctrlval);
+
+ num_serverctrls++;
+ ctrlp++;
+ }
+ ldap_controls_free(*lserverctrlsp);
+ *lserverctrlsp = NULL;
+
+ if (error) {
+ /* ... */
+ return -1;
+ }
+ }
+
+ if (num_serverctrls != -1) {
+ add_assoc_long(*serverctrls, "count", num_serverctrls);
+ }
+
+ return num_serverctrls;
+}
+
/* {{{ PHP_INI_BEGIN
*/
PHP_INI_BEGIN()
@@ -370,7 +445,11 @@
{
char *host = NULL;
int hostlen;
+#ifdef LDAP_API_FEATURE_X_OPENLDAP
+ long port = LDAP_PORT;
+#else
long port = 389; /* Default port */
+#endif
#ifdef HAVE_ORALDAP
char *wallet, *walletpasswd;
int walletlen, walletpasswdlen;
@@ -406,17 +485,33 @@
ld = ecalloc(1, sizeof(ldap_linkdata));

#ifdef LDAP_API_FEATURE_X_OPENLDAP
- if (host != NULL && strchr(host, '/')) {
- int rc;
+ /* OpenLDAP provides a specific call to detect valid LDAP URIs */
+ {
+ int rc;
+ char *url = host;
+
+ if (!ldap_is_ldap_url(url)) {
+ int urllen = hostlen + sizeof( "ldap://:65535"; );
+
+ if (port < 0 || port > 65535) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid port number: %ld", port);
+ RETURN_FALSE;
+ }
+
+ url = emalloc(urllen);
+ snprintf( url, urllen, "ldap://%s:%ld";, host ? host : "", port ? port : LDAP_PORT );
+ }

- rc = ldap_initialize(&ldap, host);
+ rc = ldap_initialize(&ldap, url);
if (rc != LDAP_SUCCESS) {
efree(ld);
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not create session handle: %s", ldap_err2string(rc));
RETURN_FALSE;
}
- } else {
- ldap = ldap_init(host, port);
+
+ if (url != host) {
+ efree(url);
+ }
}
#else
ldap = ldap_open(host, port);
@@ -479,7 +574,21 @@

ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);

- if ((rc = ldap_bind_s(ld->link, ldap_bind_dn, ldap_bind_pw, LDAP_AUTH_SIMPLE)) != LDAP_SUCCESS) {
+#ifdef LDAP_API_FEATURE_X_OPENLDAP
+ {
+ struct berval cred;
+
+ /* ldap_bind_s() is deprecated; use ldap_sasl_bind_s() instead */
+ cred.bv_val = ldap_bind_pw;
+ cred.bv_len = ldap_bind_pw ? ldap_bind_pwlen : 0;
+ rc = ldap_sasl_bind_s(ld->link, ldap_bind_dn, LDAP_SASL_SIMPLE, &cred,
+ NULL, NULL, /* no controls right now */
+ NULL); /* we don't care about the server's credentials */
+ }
+#else
+ rc = ldap_bind_s(ld->link, ldap_bind_dn, ldap_bind_pw, LDAP_AUTH_SIMPLE);
+#endif
+ if ( rc != LDAP_SUCCESS) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to bind to server: %s", ldap_err2string(rc));
RETURN_FALSE;
} else {
@@ -1030,7 +1139,6 @@
BerElement *ber;
char *attribute;
size_t attr_len;
- char **ldap_value;
char *dn;

if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &link, &result) == FAILURE) {
@@ -1061,16 +1169,18 @@
attribute = ldap_first_attribute(ldap, ldap_result_entry, &ber);

while (attribute != NULL) {
- ldap_value = ldap_get_values(ldap, ldap_result_entry, attribute);
- num_values = ldap_count_values(ldap_value);
+ struct berval **ldap_value;
+
+ ldap_value = ldap_get_values_len(ldap, ldap_result_entry, attribute);
+ num_values = ldap_count_values_len(ldap_value);

MAKE_STD_ZVAL(tmp2);
array_init(tmp2);
add_assoc_long(tmp2, "count", num_values);
for (i = 0; i < num_values; i++) {
- add_index_string(tmp2, i, ldap_value, 1);
+ add_index_stringl(tmp2, i, ldap_value->bv_val, ldap_value->bv_len, 1);
}
- ldap_value_free(ldap_value);
+ ldap_value_free_len(ldap_value);

attr_len = strlen(attribute);
zend_hash_update(Z_ARRVAL_P(tmp1), php_strtolower(attribute, attr_len), attr_len+1, (void *) &tmp2, sizeof(zval *), NULL);
@@ -1177,7 +1287,6 @@
ldap_linkdata *ld;
ldap_resultentry *resultentry;
char *attribute;
- char **ldap_value;
int i, num_values, num_attrib;
BerElement *ber;

@@ -1193,16 +1302,18 @@

attribute = ldap_first_attribute(ld->link, resultentry->data, &ber);
while (attribute != NULL) {
- ldap_value = ldap_get_values(ld->link, resultentry->data, attribute);
- num_values = ldap_count_values(ldap_value);
+ struct berval **ldap_value;
+
+ ldap_value = ldap_get_values_len(ld->link, resultentry->data, attribute);
+ num_values = ldap_count_values_len(ldap_value);

MAKE_STD_ZVAL(tmp);
array_init(tmp);
add_assoc_long(tmp, "count", num_values);
for (i = 0; i < num_values; i++) {
- add_index_string(tmp, i, ldap_value, 1);
+ add_index_stringl(tmp, i, ldap_value->bv_val, ldap_value->bv_len, 1);
}
- ldap_value_free(ldap_value);
+ ldap_value_free_len(ldap_value);

zend_hash_update(Z_ARRVAL_P(return_value), attribute, strlen(attribute)+1, (void *) &tmp, sizeof(zval *), NULL);
add_index_string(return_value, num_attrib, attribute, 1);
@@ -1231,7 +1342,7 @@
ldap_linkdata *ld;
ldap_resultentry *resultentry;
char *attribute;
- char **ldap_value;
+ struct berval **ldap_value;
int i, num_values;

if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &link, &result_entry, &attr) == FAILURE) {
@@ -1244,21 +1355,21 @@
convert_to_string_ex(attr);
attribute = Z_STRVAL_PP(attr);

- if ((ldap_value = ldap_get_values(ld->link, resultentry->data, attribute)) == NULL) {
+ if ((ldap_value = ldap_get_values_len(ld->link, resultentry->data, attribute)) == NULL) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot get the value(s) of attribute %s", ldap_err2string(_get_lderrno(ld->link)));
RETURN_FALSE;
}

- num_values = ldap_count_values(ldap_value);
+ num_values = ldap_count_values_len(ldap_value);

array_init(return_value);

for (i = 0; i<num_values; i++) {
- add_next_index_string(return_value, ldap_value, 1);
+ add_next_index_stringl(return_value, ldap_value->bv_val, ldap_value->bv_len, 1);
}

add_assoc_long(return_value, "count", num_values);
- ldap_value_free(ldap_value);
+ ldap_value_free_len(ldap_value);

}
/* }}} */
@@ -1363,7 +1474,11 @@
add_index_string(return_value, i, ldap_value, 1);
}

+#ifdef LDAP_API_FEATURE_X_OPENLDAP
+ ber_memvfree((void **)ldap_value);
+#else
ldap_value_free(ldap_value);
+#endif
}
/* }}} */

@@ -1933,14 +2048,15 @@
Extract information from result */
PHP_FUNCTION(ldap_parse_result)
{
- zval **link, **result, **errcode, **matcheddn, **errmsg, **referrals;
+ zval **link, **result, **errcode, **matcheddn, **errmsg, **referrals, **serverctrls;
ldap_linkdata *ld;
LDAPMessage *ldap_result;
- char **lreferrals, **refp;
+ LDAPControl **lserverctrls;
+ char **lreferrals;
char *lmatcheddn, *lerrmsg;
int rc, lerrcode, myargcount = ZEND_NUM_ARGS();

- if (myargcount < 3 || myargcount > 6 || zend_get_parameters_ex(myargcount, &link, &result, &errcode, &matcheddn, &errmsg, &referrals) == FAILURE) {
+ if (myargcount < 3 || myargcount > 7 || zend_get_parameters_ex(myargcount, &link, &result, &errcode, &matcheddn, &errmsg, &referrals, &serverctrls) == FAILURE) {
WRONG_PARAM_COUNT;
}

@@ -1951,7 +2067,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_docref(NULL TSRMLS_CC, E_WARNING, "Unable to parse result: %s", ldap_err2string(rc));
@@ -1963,17 +2079,15 @@

/* Reverse -> fall through */
switch (myargcount) {
+ case 7:
+ /* use arg #7 as the array of controls returned by the server */
+ zval_dtor(*serverctrls);
+ array_init(*serverctrls);
+ _parse_server_controls_resp(&lserverctrls, serverctrls);
case 6:
zval_dtor(*referrals);
array_init(*referrals);
- if (lreferrals != NULL) {
- refp = lreferrals;
- while (*refp) {
- add_next_index_string(*referrals, *refp, 1);
- refp++;
- }
- ldap_value_free(lreferrals);
- }
+ _parse_referrals_resp(&lreferrals, referrals);
case 5:
zval_dtor(*errmsg);
if (lerrmsg == NULL) {
@@ -2057,32 +2171,38 @@
Extract information from reference entry */
PHP_FUNCTION(ldap_parse_reference)
{
- zval **link, **result_entry, **referrals;
+ zval **link, **result_entry, **referrals, **serverctrls;
ldap_linkdata *ld;
ldap_resultentry *resultentry;
- char **lreferrals, **refp;
+ char **lreferrals;
+ LDAPControl **lserverctrls;
+ int myargcount = ZEND_NUM_ARGS();

- if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &link, &result_entry, &referrals) == FAILURE) {
+ if (myargcount < 3 || myargcount > 4 || zend_get_parameters_ex(4, &link, &result_entry, &referrals, &serverctrls) == FAILURE) {
WRONG_PARAM_COUNT;
}

ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
ZEND_FETCH_RESOURCE(resultentry, ldap_resultentry *, result_entry, -1, "ldap result entry", le_result_entry);

- if (ldap_parse_reference(ld->link, resultentry->data, &lreferrals, NULL /* &serverctrls */, 0) != LDAP_SUCCESS) {
+ if (ldap_parse_reference(ld->link, resultentry->data, &lreferrals, &lserverctrls, 0) != LDAP_SUCCESS) {
RETURN_FALSE;
}

- zval_dtor(*referrals);
- array_init(*referrals);
- if (lreferrals != NULL) {
- refp = lreferrals;
- while (*refp) {
- add_next_index_string(*referrals, *refp, 1);
- refp++;
- }
- ldap_value_free(lreferrals);
+
+ /* Reverse -> fall through */
+ switch (myargcount) {
+ case 4:
+ /* use arg #4 as the array of controls returned by the server */
+ zval_dtor(*serverctrls);
+ array_init(*serverctrls);
+ _parse_server_controls_resp(&lserverctrls, serverctrls);
+ case 3:
+ zval_dtor(*referrals);
+ array_init(*referrals);
+ _parse_referrals_resp(&lreferrals, referrals);
}
+
RETURN_TRUE;
}
/* }}} */pagedResults.phpDescription:application/php--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit:http://www.php.net/unsub.php

Attachments:
attachment pagedResults.php (3.0 KB)

Offline

#2 Nov. 8, 2005 22:38:11

Jani T.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

[PHP-DEV] LDAP controls in response


I quickly glanced through your patch and if you don't mind,
can you please separate the warning-fixes and functionality patch?
(one patch for fixes, one for adding new stuff :)

It's a bit too much to try and see what was added and what is supposed
to silence some warning.

--Jani


On Tue, 8 Nov 2005, Pierangelo Masarati wrote:Stig,

I need to use LDAP controls in PHP, including control response from
server to client, so I patched the 5.0.5/HEAD code to add an extra arg
to ldap_parse_result() and ldap_parse_reference(). I'd need this patch
in production at some point, that's why it would be great to see it
merged into the mainstream; however, I'm little familiar with the
internals of PHP, so please excuse me if I missed anything in coding and
in the submission procedure.

The very same patch applies to HEAD and to 5.0.5. If you don't mind,
I'm posting it to you right now, pending further work. It also includes
some extra work I did to eliminate some warnings from OpenLDAP 2.3, but
it works fine with 2.2 as well. All changes specific to OpenLDAP are
protected behind the LDAP_API_FEATURE_X_OPENLDAP macro. Unfortunately I
have no chances to check it with other APIs right now. I'm also
including a trivial script I tested with ./sapi/cli/php against the
server resulting from test003 of OpenLDAP 2.3; to reproduce, just

cd openldap/tests/
../run -k test003
cd php
../sapi/cli/php pagedResults.php

If the code looks fine, I plan to document the new API, which is
completely backwards compatible, and add some facilities to
encode/decode the control values; hopefully, I won't have to get to
writing a complete wrapper around liblber!

My idea is to provide dumb helpers that encode well-known controls
through a trivial API; e.g., for pagedResults:

ldap_control_paged_results($handler, $size, $iscritical)
ldap_control_paged_results_resp($result, &$cookie[, &$iscritical])

for passwdPolicy:

ldap_control_passwd_policy($handler)
ldap_control_passwd_policy_resp($result, &$warning, &$error)

Please let me know if you need me to do anything else.

Sincerely, p.--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit:http://www.php.net/unsub.php

Offline

#3 Nov. 8, 2005 23:18:52

Pierangelo M.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

[PHP-DEV] LDAP controls in response


On Wed, 2005-11-09 at 00:37 +0200, Jani Taskinen wrote:
> I quickly glanced through your patch and if you don't mind,
> can you please separate the warning-fixes and functionality patch?
> (one patch for fixes, one for adding new stuff :)
>
> It's a bit too much to try and see what was added and what is supposed
> to silence some warning.

Sure.

I quickly separated them by editing the patch, so you'll likely get some
fuzz message because of wrong line count. They should apply in any
order, though, because there was no code overlapping. I successfully
did warnings, controls.

Sincerely, p.





Ing. Pierangelo Masarati

Responsabile Open Solution



SysNet s.n.c.

Via Dossi, 8 - 27100 Pavia - ITALIAhttp://www.sys-net.it------------------------------------------

Office: +39.02.23998309

Mobile: +39.333.4963172

Email:

------------------------------------------Index: ext/ldap/ldap.c
===================================================================
RCS file: /repository/php-src/ext/ldap/ldap.c,v
retrieving revision 1.162
diff -u -r1.162 ldap.c
--- ext/ldap/ldap.c 22 Aug 2005 12:22:08 -0000 1.162
+++ ext/ldap/ldap.c 8 Nov 2005 21:04:05 -0000
@@ -191,7 +191,9 @@
{
ldap_linkdata *ld = (ldap_linkdata *)rsrc->ptr;

- ldap_unbind_s(ld->link);
+ /* ldap_unbind_s() is deprecated;
+ * the distinction between ldap_unbind() and ldap_unbind_s() is moot */
+ ldap_unbind_ext(ld->link, NULL, NULL);
#if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC)
if (ld->rebindproc != NULL) {
zval_dtor(ld->rebindproc);
@@ -370,7 +445,11 @@
{
char *host = NULL;
int hostlen;
+#ifdef LDAP_API_FEATURE_X_OPENLDAP
+ long port = LDAP_PORT;
+#else
long port = 389; /* Default port */
+#endif
#ifdef HAVE_ORALDAP
char *wallet, *walletpasswd;
int walletlen, walletpasswdlen;
@@ -406,17 +485,33 @@
ld = ecalloc(1, sizeof(ldap_linkdata));

#ifdef LDAP_API_FEATURE_X_OPENLDAP
- if (host != NULL && strchr(host, '/')) {
- int rc;
+ /* OpenLDAP provides a specific call to detect valid LDAP URIs */
+ {
+ int rc;
+ char *url = host;
+
+ if (!ldap_is_ldap_url(url)) {
+ int urllen = hostlen + sizeof( "ldap://:65535"; );
+
+ if (port < 0 || port > 65535) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid port number: %ld", port);
+ RETURN_FALSE;
+ }
+
+ url = emalloc(urllen);
+ snprintf( url, urllen, "ldap://%s:%ld";, host ? host : "", port ? port : LDAP_PORT );
+ }

- rc = ldap_initialize(&ldap, host);
+ rc = ldap_initialize(&ldap, url);
if (rc != LDAP_SUCCESS) {
efree(ld);
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not create session handle: %s", ldap_err2string(rc));
RETURN_FALSE;
}
- } else {
- ldap = ldap_init(host, port);
+
+ if (url != host) {
+ efree(url);
+ }
}
#else
ldap = ldap_open(host, port);
@@ -479,7 +574,21 @@

ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);

- if ((rc = ldap_bind_s(ld->link, ldap_bind_dn, ldap_bind_pw, LDAP_AUTH_SIMPLE)) != LDAP_SUCCESS) {
+#ifdef LDAP_API_FEATURE_X_OPENLDAP
+ {
+ struct berval cred;
+
+ /* ldap_bind_s() is deprecated; use ldap_sasl_bind_s() instead */
+ cred.bv_val = ldap_bind_pw;
+ cred.bv_len = ldap_bind_pw ? ldap_bind_pwlen : 0;
+ rc = ldap_sasl_bind_s(ld->link, ldap_bind_dn, LDAP_SASL_SIMPLE, &cred,
+ NULL, NULL, /* no controls right now */
+ NULL); /* we don't care about the server's credentials */
+ }
+#else
+ rc = ldap_bind_s(ld->link, ldap_bind_dn, ldap_bind_pw, LDAP_AUTH_SIMPLE);
+#endif
+ if ( rc != LDAP_SUCCESS) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to bind to server: %s", ldap_err2string(rc));
RETURN_FALSE;
} else {
@@ -1030,7 +1139,6 @@
BerElement *ber;
char *attribute;
size_t attr_len;
- char **ldap_value;
char *dn;

if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &link, &result) == FAILURE) {
@@ -1061,16 +1169,18 @@
attribute = ldap_first_attribute(ldap, ldap_result_entry, &ber);

while (attribute != NULL) {
- ldap_value = ldap_get_values(ldap, ldap_result_entry, attribute);
- num_values = ldap_count_values(ldap_value);
+ struct berval **ldap_value;
+
+ ldap_value = ldap_get_values_len(ldap, ldap_result_entry, attribute);
+ num_values = ldap_count_values_len(ldap_value);

MAKE_STD_ZVAL(tmp2);
array_init(tmp2);
add_assoc_long(tmp2, "count", num_values);
for (i = 0; i < num_values; i++) {
- add_index_string(tmp2, i, ldap_value, 1);
+ add_index_stringl(tmp2, i, ldap_value->bv_val, ldap_value->bv_len, 1);
}
- ldap_value_free(ldap_value);
+ ldap_value_free_len(ldap_value);

attr_len = strlen(attribute);
zend_hash_update(Z_ARRVAL_P(tmp1), php_strtolower(attribute, attr_len), attr_len+1, (void *) &tmp2, sizeof(zval *), NULL);
@@ -1177,7 +1287,6 @@
ldap_linkdata *ld;
ldap_resultentry *resultentry;
char *attribute;
- char **ldap_value;
int i, num_values, num_attrib;
BerElement *ber;

@@ -1193,16 +1302,18 @@

attribute = ldap_first_attribute(ld->link, resultentry->data, &ber);
while (attribute != NULL) {
- ldap_value = ldap_get_values(ld->link, resultentry->data, attribute);
- num_values = ldap_count_values(ldap_value);
+ struct berval **ldap_value;
+
+ ldap_value = ldap_get_values_len(ld->link, resultentry->data, attribute);
+ num_values = ldap_count_values_len(ldap_value);

MAKE_STD_ZVAL(tmp);
array_init(tmp);
add_assoc_long(tmp, "count", num_values);
for (i = 0; i < num_values; i++) {
- add_index_string(tmp, i, ldap_value, 1);
+ add_index_stringl(tmp, i, ldap_value->bv_val, ldap_value->bv_len, 1);
}
- ldap_value_free(ldap_value);
+ ldap_value_free_len(ldap_value);

zend_hash_update(Z_ARRVAL_P(return_value), attribute, strlen(attribute)+1, (void *) &tmp, sizeof(zval *), NULL);
add_index_string(return_value, num_attrib, attribute, 1);
@@ -1231,7 +1342,7 @@
ldap_linkdata *ld;
ldap_resultentry *resultentry;
char *attribute;
- char **ldap_value;
+ struct berval **ldap_value;
int i, num_values;

if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &link, &result_entry, &attr) == FAILURE) {
@@ -1244,21 +1355,21 @@
convert_to_string_ex(attr);
attribute = Z_STRVAL_PP(attr);

- if ((ldap_value = ldap_get_values(ld->link, resultentry->data, attribute)) == NULL) {
+ if ((ldap_value = ldap_get_values_len(ld->link, resultentry->data, attribute)) == NULL) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot get the value(s) of attribute %s", ldap_err2string(_get_lderrno(ld->link)));
RETURN_FALSE;
}

- num_values = ldap_count_values(ldap_value);
+ num_values = ldap_count_values_len(ldap_value);

array_init(return_value);

for (i = 0; i<num_values; i++) {
- add_next_index_string(return_value, ldap_value, 1);
+ add_next_index_stringl(return_value, ldap_value->bv_val, ldap_value->bv_len, 1);
}

add_assoc_long(return_value, "count", num_values);
- ldap_value_free(ldap_value);
+ ldap_value_free_len(ldap_value);

}
/* }}} */
@@ -1363,7 +1474,11 @@
add_index_string(return_value, i, ldap_value, 1);
}

+#ifdef LDAP_API_FEATURE_X_OPENLDAP
+ ber_memvfree((void **)ldap_value);
+#else
ldap_value_free(ldap_value);
+#endif
}
/* }}} */Index: ext/ldap/ldap.c
===================================================================
RCS file: /repository/php-src/ext/ldap/ldap.c,v
retrieving revision 1.162
diff -u -r1.162 ldap.c
--- ext/ldap/ldap.c 22 Aug 2005 12:22:08 -0000 1.162
+++ ext/ldap/ldap.c 8 Nov 2005 21:04:05 -0000
@@ -215,6 +217,79 @@
efree(entry);
}

+static int _parse_referrals_resp(char ***lreferralsp, zval **referrals)
+{
+ int num_referrals = 0;
+
+ if (*lreferralsp != NULL) {
+ char **refp = *lreferralsp;
+
+ while (*refp) {
+ add_next_index_string(*referrals, *refp, 1);
+ refp++;
+ num_referrals++;
+ }
+#ifdef LDAP_API_FEATURE_X_OPENLDAP
+ ber_memvfree((void **)*lreferralsp);
+#else
+ ldap_value_free(*lreferralsp);
+#endif
+ *lreferralsp = NULL;
+ }
+
+ add_assoc_long(*referrals, "count", num_referrals);
+
+ return num_referrals;
+}
+
+static int _parse_server_controls_resp(LDAPControl ***lserverctrlsp, zval **serverctrls)
+{
+ int num_serverctrls = 0;
+
+ if (*lserverctrlsp != NULL) {
+ int error = 0;
+ LDAPControl **ctrlp = *lserverctrlsp;
+
+ while (*ctrlp) {
+ zval *ctrlval = NULL;
+
+ if ( (*ctrlp)->ldctl_oid == NULL ) {
+ error = 1;
+ break;
+ }
+
+ MAKE_STD_ZVAL(ctrlval);
+ array_init(ctrlval);
+
+ add_assoc_string(ctrlval, "oid", (*ctrlp)->ldctl_oid, 1);
+ if ( (*ctrlp)->ldctl_value.bv_len ) {
+ add_assoc_stringl(ctrlval, "value", (*ctrlp)->ldctl_value.bv_val, (*ctrlp)->ldctl_value.bv_len, 1);
+ }
+ if ((*ctrlp)->ldctl_iscritical) {
+ add_assoc_bool(ctrlval, "iscritical", (*ctrlp)->ldctl_iscritical);
+ }
+
+ add_next_index_zval(*serverctrls, ctrlval);
+
+ num_serverctrls++;
+ ctrlp++;
+ }
+ ldap_controls_free(*lserverctrlsp);
+ *lserverctrlsp = NULL;
+
+ if (error) {
+ /* ... */
+ return -1;
+ }
+ }
+
+ if (num_serverctrls != -1) {
+ add_assoc_long(*serverctrls, "count", num_serverctrls);
+ }
+
+ return num_serverctrls;
+}
+
/* {{{ PHP_INI_BEGIN
*/
PHP_INI_BEGIN()
@@ -1933,14 +2048,15 @@
Extract information from result */
PHP_FUNCTION(ldap_parse_result)
{
- zval **link, **result, **errcode, **matcheddn, **errmsg, **referrals;
+ zval **link, **result, **errcode, **matcheddn, **errmsg, **referrals, **serverctrls;
ldap_linkdata *ld;
LDAPMessage *ldap_result;
- char **lreferrals, **refp;
+ LDAPControl **lserverctrls;
+ char **lreferrals;
char *lmatcheddn, *lerrmsg;
int rc, lerrcode, myargcount = ZEND_NUM_ARGS();

- if (myargcount < 3 || myargcount > 6 || zend_get_parameters_ex(myargcount, &link, &result, &errcode, &matcheddn, &errmsg, &referrals) == FAILURE) {
+ if (myargcount < 3 || myargcount > 7 || zend_get_parameters_ex(myargcount, &link, &result, &errcode, &matcheddn, &errmsg, &referrals, &serverctrls) == FAILURE) {
WRONG_PARAM_COUNT;
}

@@ -1951,7 +2067,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_docref(NULL TSRMLS_CC, E_WARNING, "Unable to parse result: %s", ldap_err2string(rc));
@@ -1963,17 +2079,15 @@

/* Reverse -> fall through */
switch (myargcount) {
+ case 7:
+ /* use arg #7 as the array of controls returned by the server */
+ zval_dtor(*serverctrls);
+ array_init(*serverctrls);
+ _parse_server_controls_resp(&lserverctrls, serverctrls);
case 6:
zval_dtor(*referrals);
array_init(*referrals);
- if (lreferrals != NULL) {
- refp = lreferrals;
- while (*refp) {
- add_next_index_string(*referrals, *refp, 1);
- refp++;
- }
- ldap_value_free(lreferrals);
- }
+ _parse_referrals_resp(&lreferrals, referrals);
case 5:
zval_dtor(*errmsg);
if (lerrmsg == NULL) {
@@ -2057,32 +2171,38 @@
Extract information from reference entry */
PHP_FUNCTION(ldap_parse_reference)
{
- zval **link, **result_entry, **referrals;
+ zval **link, **result_entry, **referrals, **serverctrls;
ldap_linkdata *ld;
ldap_resultentry *resultentry;
- char **lreferrals, **refp;
+ char **lreferrals;
+ LDAPControl **lserverctrls;
+ int myargcount = ZEND_NUM_ARGS();

- if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &link, &result_entry, &referrals) == FAILURE) {
+ if (myargcount < 3 || myargcount > 4 || zend_get_parameters_ex(4, &link, &result_entry, &referrals, &serverctrls) == FAILURE) {
WRONG_PARAM_COUNT;
}

ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
ZEND_FETCH_RESOURCE(resultentry, ldap_resultentry *, result_entry, -1, "ldap result entry", le_result_entry);

- if (ldap_parse_reference(ld->link, resultentry->data, &lreferrals, NULL /* &serverctrls */, 0) != LDAP_SUCCESS) {
+ if (ldap_parse_reference(ld->link, resultentry->data, &lreferrals, &lserverctrls, 0) != LDAP_SUCCESS) {
RETURN_FALSE;
}

- zval_dtor(*referrals);
- array_init(*referrals);
- if (lreferrals != NULL) {
- refp = lreferrals;
- while (*refp) {
- add_next_index_string(*referrals, *refp, 1);
- refp++;
- }
- ldap_value_free(lreferrals);
+
+ /* Reverse -> fall through */
+ switch (myargcount) {
+ case 4:
+ /* use arg #4 as the array of controls returned by the server */
+ zval_dtor(*serverctrls);
+ array_init(*serverctrls);
+ _parse_server_controls_resp(&lserverctrls, serverctrls);
+ case 3:
+ zval_dtor(*referrals);
+ array_init(*referrals);
+ _parse_referrals_resp(&lreferrals, referrals);
}
+
RETURN_TRUE;
}
/* }}} */--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit:http://www.php.net/unsub.php

Offline

#4 Nov. 9, 2005 05:06:04

Jani T.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

[PHP-DEV] LDAP controls in response


The "control-patch" looks okay. But the "warning-fix-patch" really doesn't.
You're actually changing some functions behaviour with some of those
changes. Maybe you didn't notice but there's ldap_get_values() and
ldap_get_values_len() separately. And there's ldap_bind() and
ldap_sasl_bind(),

--Jani

On Wed, 9 Nov 2005, Pierangelo Masarati wrote:On Wed, 2005-11-09 at 00:37 +0200, Jani Taskinen wrote:I quickly glanced through your patch and if you don't mind,
can you please separate the warning-fixes and functionality patch?
(one patch for fixes, one for adding new stuff :)

It's a bit too much to try and see what was added and what is supposed
to silence some warning.Sure.

I quickly separated them by editing the patch, so you'll likely get some
fuzz message because of wrong line count. They should apply in any
order, though, because there was no code overlapping. I successfully
did warnings, controls.

Sincerely, p.



Ing. Pierangelo Masarati
Responsabile Open Solution

SysNet s.n.c.
Via Dossi, 8 - 27100 Pavia - ITALIAhttp://www.sys-net.it------------------------------------------
Office: +39.02.23998309
Mobile: +39.333.4963172
Email:
--------------------------------------------
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit:http://www.php.net/unsub.php

Offline

#5 Nov. 9, 2005 07:20:25

Pierangelo M.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

[PHP-DEV] LDAP controls in response


On Wed, 2005-11-09 at 07:05 +0200, Jani Taskinen wrote:
> The "control-patch" looks okay. But the "warning-fix-patch" really
> doesn't.
> You're actually changing some functions behaviour with some of those
> changes. Maybe you didn't notice but there's ldap_get_values() and
> ldap_get_values_len() separately. And there's ldap_bind() and
> ldap_sasl_bind(),

What I'm doing is driven by the fact that the ldap_*value*() family, and
the ldap_bind*() are being deprecated (that is: they're in the library,
but they're not declared in ldap.h any more, and they are implemented as
wrappers to the replacements I'm using, at the cost of extra execution
time and resources, plus decent compiler warnings).

ldap_*value*_len() is the safe implementation of ldap_*value*(), because
it can also handle non-null terminated values; this doesn't inhibit the
handling null-terminated ones. Moreover, PHP needs the length of the
string anyway, so... Note that this would allow PHP to use only
ldap_get_values() for both, making the API more simple and robust (I
vaguely recall the issue that brought to implementing
ldap_get_values_len() in PHP, I think it was somewhere in PHP 3 and the
patch took a while to get there).

ldap_sasl_bind(), despite the misleading name, doesn't imply the use of
SASL: it's a neutral interface to authentication which, when passed the
LDAP_SASL_SIMPLE argument, exactly does LDAP's simple bind.
I understand its use is really misleading, given the presence of the
very same name in PHP for the function that actually wraps
ldap_sasl_interactive_bind_s(); however, this is an implementation
detail that wouldn't get exposed to end-users.

Anyway, none of these is an issue to me, so I'm fine with the controls
patch. A final comment: apart from some fuzziness complaints, both
patches apply also to PHP 4 without changes. This means we can get into
production immediately (well, after some testing... :)

Thanks, p.








Ing. Pierangelo Masarati

Responsabile Open Solution



SysNet s.n.c.

Via Dossi, 8 - 27100 Pavia - ITALIAhttp://www.sys-net.it------------------------------------------

Office: +39.02.23998309

Mobile: +39.333.4963172

Email:

------------------------------------------


--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit:http://www.php.net/unsub.php

Offline

#6 Nov. 9, 2005 08:05:08

Jani T.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

[PHP-DEV] LDAP controls in response


On Wed, 9 Nov 2005, Pierangelo Masarati wrote:On Wed, 2005-11-09 at 07:05 +0200, Jani Taskinen wrote:The "control-patch" looks okay. But the "warning-fix-patch" really doesn't.
You're actually changing some functions behaviour with some of those
changes. Maybe you didn't notice but there's ldap_get_values() and
ldap_get_values_len() separately. And there's ldap_bind() and
ldap_sasl_bind(),What I'm doing is driven by the fact that the ldap_*value*() family, and
the ldap_bind*() are being deprecated (that is: they're in the library,
but they're not declared in ldap.h any more, and they are implemented as
wrappers to the replacements I'm using, at the cost of extra execution
time and resources, plus decent compiler warnings).Perhaps with OpenLDAP, but what about the other implementations with
which this extension works just fine? You didn't wrap all those changes
inside the #ifdef's.ldap_*value*_len() is the safe implementation of ldap_*value*(), because
it can also handle non-null terminated values; this doesn't inhibit the
handling null-terminated ones. Moreover, PHP needs the length of the
string anyway, so... Note that this would allow PHP to use only
ldap_get_values() for both, making the API more simple and robust (I
vaguely recall the issue that brought to implementing
ldap_get_values_len() in PHP, I think it was somewhere in PHP 3 and the
patch took a while to get there).I agree it's better this way, but (even as unlikely it is) changing this
MIGHT break someone's script.

Anyway, it might be the time to cleanup the API of this extension
and make it simpler. It's pretty confusing as it is.
The returned arrays are also weird with their "count" fields and such.Anyway, none of these is an issue to me, so I'm fine with the controls
patch. A final comment: apart from some fuzziness complaints, both
patches apply also to PHP 4 without changes. This means we can get into
production immediately (well, after some testing... :)This is a new feature and new features are no longer added in PHP 4.
We only add new stuff in PHP >= 5.1.

--Jani

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit:http://www.php.net/unsub.php

Offline

#7 Nov. 9, 2005 08:37:33

Pierangelo M.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

[PHP-DEV] LDAP controls in response


> On Wed, 9 Nov 2005, Pierangelo Masarati wrote:
>
>>
>> On Wed, 2005-11-09 at 07:05 +0200, Jani Taskinen wrote:
>>> The "control-patch" looks okay. But the "warning-fix-patch" really
>>> doesn't.
>>> You're actually changing some functions behaviour with some of
>>> those
>>> changes. Maybe you didn't notice but there's ldap_get_values() and
>>> ldap_get_values_len() separately. And there's ldap_bind() and
>>> ldap_sasl_bind(),
>>
>> What I'm doing is driven by the fact that the ldap_*value*() family, and
>> the ldap_bind*() are being deprecated (that is: they're in the library,
>> but they're not declared in ldap.h any more, and they are implemented as
>> wrappers to the replacements I'm using, at the cost of extra execution
>> time and resources, plus decent compiler warnings).
>
> Perhaps with OpenLDAP, but what about the other implementations with
> which this extension works just fine? You didn't wrap all those
> changes
> inside the #ifdef's.

Right, sorry. And note that this is true only for OpenLDAP 2.3 (which is
considered stable by the OpenLDAP project but maybe not by distributors
yet...). I'm pretty confident the reworking I put in place is conformant
with most APIs, but, as I said, I likely have no chance to test it
shortly, so I wouldn't stress too much on it.

>
>> ldap_*value*_len() is the safe implementation of ldap_*value*(), because
>> it can also handle non-null terminated values; this doesn't inhibit the
>> handling null-terminated ones. Moreover, PHP needs the length of the
>> string anyway, so... Note that this would allow PHP to use only
>> ldap_get_values() for both, making the API more simple and robust (I
>> vaguely recall the issue that brought to implementing
>> ldap_get_values_len() in PHP, I think it was somewhere in PHP 3 and the
>> patch took a while to get there).
>
> I agree it's better this way, but (even as unlikely it is) changing
> this
> MIGHT break someone's script.

Well, GIGO :) If one uses ldap_get_values_len() with strings (i.e.
null-terminated arrays) the result is fine and consistent; the BER
contains the info about the value length so there's not even the
performance penalty of a strlen(). If one was relying on using
ldap_get_values() for non-null terminated strings ...

>
> Anyway, it might be the time to cleanup the API of this extension
> and make it simpler. It's pretty confusing as it is.

> The returned arrays are also weird with their "count" fields and
> such.

I added them for consistency with the rest of the data returned by PHP's
ldap_get_{entries,attributes,values}(); I'm fine if they get removed, we
also save the counter...

Should I do the cleanup? Should I simply remove the "warning" stuff and
the "count" stuff in the arrays?

>
>> Anyway, none of these is an issue to me, so I'm fine with the controls
>> patch. A final comment: apart from some fuzziness complaints, both
>> patches apply also to PHP 4 without changes. This means we can get into
>> production immediately (well, after some testing... :)
>
> This is a new feature and new features are no longer added in PHP 4.
> We only add new stuff in PHP >= 5.1.

I was speaking for our own packages; usually I don't expect anything to be
backported so far, it's fair enough to see contributed features in the
mainstream at some point.

Thanks for your time. p.

--
Pierangelo Masarati






Ing. Pierangelo Masarati

Responsabile Open Solution



SysNet s.n.c.

Via Dossi, 8 - 27100 Pavia - ITALIAhttp://www.sys-net.it------------------------------------------

Office: +39.02.23998309

Mobile: +39.333.4963172

Email:

------------------------------------------


--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit:http://www.php.net/unsub.php

Offline

#8 Nov. 10, 2005 17:54:40

Pierangelo M.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

[PHP-DEV] LDAP controls in response


On Wed, 2005-11-09 at 10:03 +0200, Jani Taskinen wrote:
> Anyway, it might be the time to cleanup the API of this extension
> and make it simpler. It's pretty confusing as it is.
> The returned arrays are also weird with their "count" fields and such.

OK, Jani.

I've removed those "count" stuff; also, I noted that I forgot things
like declaring the new arg to ldap_parse_result() to be passed by
reference, and few more details which I fixed. I also removed all the
occurrences of the ldap_*value*_len substitutions.
This is in <php-ldap-result-controls.2.txt>.

I've also added a tentative <php-ldap-known-controls.0.txt> that
partially implements encoding and decoding the pagedResults control (I
use it as a benchmark because it goes on the request and on the
response). If you find this interface useful, I'd extend it to most of
the standard track controls we support in OpenLDAP. As a C programmer,
I prefer to provide a nice and clean high level PHP interface to known
controls in addition to access to the raw encoding for skilled
developers. In my view, the API should be, for each control:

a) a ldap_ctrl_<name>() call to encode it;

b) a(n optional) ldap_ctrl_<name>_resp() call to decode the related
response, if the control requires any.

Furthermore, the (a) call:

a.1) when passed a valid LDAP handler, should set the control using the
LDAP-level ldap_set_option() API;

a.2) otherwise, it could return a PHP array containing the OID, the
value and the criticality flag, ready to be passed to the PHP-level
ldap_set_option(); this would allow to incrementally build controls
together.

The (b) call should return all the requested fields contained in the
control response.

The pagedResults calls contained in the second patch should provide a
clear example, although the second functionality of the
ldap_ctrl_paged_results() call is not implemented yet. Its usage is
exemplified in the attached <pagedResults.php> (to test it, you only
need to run OpenLDAP 2.3 test003 with "./run -k test003" from the tests/
directory; the "-k" will keep the server alive after populating it with
the right stuff).

This second patch is clearly a work in progress, I don't expect it to be
considered for inclusion in its current state; I'd rather appreciate
some feedback while I keep developing it.

p.





Ing. Pierangelo Masarati

Responsabile Open Solution



SysNet s.n.c.

Via Dossi, 8 - 27100 Pavia - ITALIAhttp://www.sys-net.it------------------------------------------

Office: +39.02.23998309

Mobile: +39.333.4963172

Email:

------------------------------------------Index: ext/ldap/ldap.c
===================================================================
RCS file: /repository/php-src/ext/ldap/ldap.c,v
retrieving revision 1.162
diff -u -r1.162 ldap.c
--- ext/ldap/ldap.c 22 Aug 2005 12:22:08 -0000 1.162
+++ ext/ldap/ldap.c 10 Nov 2005 17:25:16 -0000
@@ -80,13 +80,22 @@
ZEND_DECLARE_MODULE_GLOBALS(ldap)

static
- ZEND_BEGIN_ARG_INFO(arg3to6of6_force_ref, 0)
+ 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(arg3to7of7_force_ref, 0)
ZEND_ARG_PASS_INFO(0)
ZEND_ARG_PASS_INFO(0)
ZEND_ARG_PASS_INFO(1)
ZEND_ARG_PASS_INFO(1)
ZEND_ARG_PASS_INFO(1)
ZEND_ARG_PASS_INFO(1)
+ ZEND_ARG_PASS_INFO(1)
ZEND_END_ARG_INFO();

static int le_link, le_result, le_result_entry, le_ber_entry;
@@ -144,10 +153,10 @@
PHP_FE(ldap_first_reference, NULL)
PHP_FE(ldap_next_reference, NULL)
#ifdef HAVE_LDAP_PARSE_REFERENCE
- PHP_FE(ldap_parse_reference, third_arg_force_ref)
+ PHP_FE(ldap_parse_reference, arg3to4of4_force_ref)
#endif
#ifdef HAVE_LDAP_PARSE_RESULT
- PHP_FE(ldap_parse_result, arg3to6of6_force_ref)
+ PHP_FE(ldap_parse_result, arg3to7of7_force_ref)
#endif
#ifdef HAVE_LDAP_START_TLS_S
PHP_FE(ldap_start_tls, NULL)
@@ -191,7 +211,9 @@
{
ldap_linkdata *ld = (ldap_linkdata *)rsrc->ptr;

- ldap_unbind_s(ld->link);
+ /* ldap_unbind_s() is deprecated;
+ * the distinction between ldap_unbind() and ldap_unbind_s() is moot */
+ ldap_unbind_ext(ld->link, NULL, NULL);
#if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC)
if (ld->rebindproc != NULL) {
zval_dtor(ld->rebindproc);
@@ -215,6 +237,103 @@
efree(entry);
}

+static int _parse_referrals_resp(char ***lreferralsp, zval **referrals)
+{
+ int num_referrals = 0;
+
+ if (*lreferralsp != NULL) {
+ char **refp = *lreferralsp;
+
+ while (*refp) {
+ add_next_index_string(*referrals, *refp, 1);
+ refp++;
+ num_referrals++;
+ }
+#ifdef LDAP_API_FEATURE_X_OPENLDAP
+ ber_memvfree((void **)*lreferralsp);
+#else
+ ldap_value_free(*lreferralsp);
+#endif
+ *lreferralsp = NULL;
+ }
+
+#if ando_0
+ /* It has been suggested by Jani Taskinen to avoid the "count" entry;
+ * it was added for consistency with entry data, where attributes and
+ * attribute values have one.
+ */
+ add_assoc_long(*referrals, "count", num_referrals);
+#endif
+
+ return num_referrals;
+}
+
+static int _parse_server_controls_resp(LDAPControl ***lserverctrlsp, zval **serverctrls)
+{
+ int num_serverctrls = 0;
+
+ if (*lserverctrlsp != NULL) {
+ int error = 0;
+ LDAPControl **ctrlp = *lserverctrlsp;
+
+ while (*ctrlp) {
+ zval *ctrlval = NULL;
+
+ if ( (*ctrlp)->ldctl_oid == NULL ) {
+ error = 1;
+ break;
+ }
+
+ MAKE_STD_ZVAL(ctrlval);
+ array_init(ctrlval);
+
+ add_assoc_string(ctrlval, "oid", (*ctrlp)->ldctl_oid, 1);
+ if ( (*ctrlp)->ldctl_value.bv_len ) {
+ add_assoc_stringl(ctrlval, "value", (*ctrlp)->ldctl_value.bv_val, (*ctrlp)->ldctl_value.bv_len, 1);
+ }
+#if ando_0
+ /* As per <draft-ietf-ldapbis-protocol>:
+ *
+ * 4.1.11
+
+ The criticality field only has meaning in controls attached to
+ request messages (except UnbindRequest). For controls attached to
+ response messages and the UnbindRequest, the criticality field SHOULD
+ be FALSE, and MUST be ignored by the receiving protocol peer.
+
+ */
+ if ((*ctrlp)->ldctl_iscritical) {
+ add_assoc_bool(ctrlval, "iscritical", (*ctrlp)->ldctl_iscritical);
+ }
+#endif
+
+ add_next_index_zval(*serverctrls, ctrlval);
+
+ num_serverctrls++;
+ ctrlp++;
+ }
+ ldap_controls_free(*lserverctrlsp);
+ *lserverctrlsp = NULL;
+
+ if (error) {
+ /* ... */
+ return -1;
+ }
+ }
+
+#if ando_0
+ /* It has been suggested by Jani Taskinen to avoid the "count" entry;
+ * it was added for consistency with entry data, where attributes and
+ * attribute values have one.
+ */
+ if (num_serverctrls != -1) {
+ add_assoc_long(*serverctrls, "count", num_serverctrls);
+ }
+#endif
+
+ return num_serverctrls;
+}
+
/* {{{ PHP_INI_BEGIN
*/
PHP_INI_BEGIN()
@@ -370,7 +489,11 @@
{
char *host = NULL;
int hostlen;
+#ifdef LDAP_API_FEATURE_X_OPENLDAP
+ long port = LDAP_PORT;
+#else
long port = 389; /* Default port */
+#endif
#ifdef HAVE_ORALDAP
char *wallet, *walletpasswd;
int walletlen, walletpasswdlen;
@@ -406,17 +529,33 @@
ld = ecalloc(1, sizeof(ldap_linkdata));

#ifdef LDAP_API_FEATURE_X_OPENLDAP
- if (host != NULL && strchr(host, '/')) {
- int rc;
+ /* OpenLDAP provides a specific call to detect valid LDAP URIs */
+ {
+ int rc;
+ char *url = host;
+
+ if (!ldap_is_ldap_url(url)) {
+ int urllen = hostlen + sizeof( "ldap://:65535"; );
+
+ if (port < 0 || port > 65535) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid port number: %ld", port);
+ RETURN_FALSE;
+ }
+
+ url = emalloc(urllen);
+ snprintf( url, urllen, "ldap://%s:%ld";, host ? host : "", port ? port : LDAP_PORT );
+ }

- rc = ldap_initialize(&ldap, host);
+ rc = ldap_initialize(&ldap, url);
if (rc != LDAP_SUCCESS) {
efree(ld);
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not create session handle: %s", ldap_err2string(rc));
RETURN_FALSE;
}
- } else {
- ldap = ldap_init(host, port);
+
+ if (url != host) {
+ efree(url);
+ }
}
#else
ldap = ldap_open(host, port);
@@ -479,7 +618,21 @@

ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);

- if ((rc = ldap_bind_s(ld->link, ldap_bind_dn, ldap_bind_pw, LDAP_AUTH_SIMPLE)) != LDAP_SUCCESS) {
+#ifdef LDAP_API_FEATURE_X_OPENLDAP
+ {
+ struct berval cred;
+
+ /* ldap_bind_s() is deprecated; use ldap_sasl_bind_s() instead */
+ cred.bv_val = ldap_bind_pw;
+ cred.bv_len = ldap_bind_pw ? ldap_bind_pwlen : 0;
+ rc = ldap_sasl_bind_s(ld->link, ldap_bind_dn, LDAP_SASL_SIMPLE, &cred,
+ NULL, NULL, /* no controls right now */
+ NULL); /* we don't care about the server's credentials */
+ }
+#else
+ rc = ldap_bind_s(ld->link, ldap_bind_dn, ldap_bind_pw, LDAP_AUTH_SIMPLE);
+#endif
+ if ( rc != LDAP_SUCCESS) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to bind to server: %s", ldap_err2string(rc));
RETURN_FALSE;
} else {
@@ -1363,7 +1518,11 @@
add_index_string(return_value, i, ldap_value, 1);
}

+#ifdef LDAP_API_FEATURE_X_OPENLDAP
+ ber_memvfree((void **)ldap_value);
+#else
ldap_value_free(ldap_value);
+#endif
}
/* }}} */

@@ -1933,14 +2092,15 @@
Extract information from result */
PHP_FUNCTION(ldap_parse_result)
{
- zval **link, **result, **errcode, **matcheddn, **errmsg, **referrals;
+ zval **link, **result, **errcode, **matcheddn, **errmsg, **referrals, **serverctrls;
ldap_linkdata *ld;
LDAPMessage *ldap_result;
- char **lreferrals, **refp;
+ LDAPControl **lserverctrls;
+ char **lreferrals;
char *lmatcheddn, *lerrmsg;
int rc, lerrcode, myargcount = ZEND_NUM_ARGS();

- if (myargcount < 3 || myargcount > 6 || zend_get_parameters_ex(myargcount, &link, &result, &errcode, &matcheddn, &errmsg, &referrals) == FAILURE) {
+ if (myargcount < 3 || myargcount > 7 || zend_get_parameters_ex(myargcount, &link, &result, &errcode, &matcheddn, &errmsg, &referrals, &serverctrls) == FAILURE) {
WRONG_PARAM_COUNT;
}

@@ -1951,7 +2111,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_docref(NULL TSRMLS_CC, E_WARNING, "Unable to parse result: %s", ldap_err2string(rc));
@@ -1963,17 +2123,15 @@

/* Reverse -> fall through */
switch (myargcount) {
+ case 7:
+ /* use arg #7 as the array of controls returned by the server */
+ zval_dtor(*serverctrls);
+ array_init(*serverctrls);
+ _parse_server_controls_resp(&lserverctrls, serverctrls);
case 6:
zval_dtor(*referrals);
array_init(*referrals);
- if (lreferrals != NULL) {
- refp = lreferrals;
- while (*refp) {
- add_next_index_string(*referrals, *refp, 1);
- refp++;
- }
- ldap_value_free(lreferrals);
- }
+ _parse_referrals_resp(&lreferrals, referrals);
case 5:
zval_dtor(*errmsg);
if (lerrmsg == NULL) {
@@ -2057,32 +2215,38 @@
Extract information from reference entry */
PHP_FUNCTION(ldap_parse_reference)
{
- zval **link, **result_entry, **referrals;
+ zval **link, **result_entry, **referrals, **serverctrls;
ldap_linkdata *ld;
ldap_resultentry *resultentry;
- char **lreferrals, **refp;
+ char **lreferrals;
+ LDAPControl **lserverctrls;
+ int myargcount = ZEND_NUM_ARGS();

- if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &link, &result_entry, &referrals) == FAILURE) {
+ if (myargcount < 3 || myargcount > 4 || zend_get_parameters_ex(4, &link, &result_entry, &referrals, &serverctrls) == FAILURE) {
WRONG_PARAM_COUNT;
}

ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, link, -1, "ldap link", le_link);
ZEND_FETCH_RESOURCE(resultentry, ldap_resultentry *, result_entry, -1, "ldap result entry", le_result_entry);

- if (ldap_parse_reference(ld->link, resultentry->data, &lreferrals, NULL /* &serverctrls */, 0) != LDAP_SUCCESS) {
+ if (ldap_parse_reference(ld->link, resultentry->data, &lreferrals, &lserverctrls, 0) != LDAP_SUCCESS) {
RETURN_FALSE;
}

- zval_dtor(*referrals);
- array_init(*referrals);
- if (lreferrals != NULL) {
- refp = lreferrals;
- while (*refp) {
- add_next_index_string(*referrals, *refp, 1);
- refp++;
- }
- ldap_value_free(lreferrals);
+
+ /* Reverse -> fall through */
+ switch (myargcount) {
+ case 4:
+ /* use arg #4 as the array of controls returned by the server */
+ zval_dtor(*serverctrls);
+ array_init(*serverctrls);
+ _parse_server_controls_resp(&lserverctrls, serverctrls);
+ case 3:
+ zval_dtor(*referrals);
+ array_init(*referrals);
+ _parse_referrals_resp(&lreferrals, referrals);
}
+
RETURN_TRUE;
}
/* }}} */Index: ext/ldap/ldap.c
===================================================================
RCS file: /repository/php-src/ext/ldap/ldap.c,v
retrieving revision 1.162
diff -u -r1.162 ldap.c
--- ext/ldap/ldap.c 22 Aug 2005 12:22:08 -0000 1.162
+++ ext/ldap/ldap.c 10 Nov 2005 17:25:16 -0000
@@ -163,6 +172,17 @@
PHP_FE(ldap_8859_to_t61, NULL)
#endif

+/* routines to handle standard track controls, Pierangelo Masarati */
+#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 /* LDAP_CONTROL_PAGEDRESULTS */
+#ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
+ PHP_FE(ldap_ctrl_ppolicy, NULL)
+ PHP_FE(ldap_ctrl_ppolicy_resp, NULL)
+#endif /* LDAP_CONTROL_PASSWORDPOLICYREQUEST */
+/* end of ando */
+
{NULL, NULL, NULL}
};
/* }}} */
@@ -2297,6 +2461,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;
+ int rc, myargcount = ZEND_NUM_ARGS();
+
+ if (myargcount < 1 || 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");
+ RETURN_FALSE;
+ }
+
+ 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 */
+ case 2:
+ convert_to_long_ex(pagesize);
+ lpagesize = Z_LVAL_PP(pagesize);
+ }
+
+ ber_printf(ber, "{iO}", lpagesize, &lcookie );
+ rc = ber_flatten2( ber, &ctrl.ldctl_value, 0 );
+ if ( rc == -1 ) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to BER encode pagedResults control");
+ RETURN_FALSE;
+ }
+
+ if (ldap) {
+ /* directly set the option */
+ ctrl.ldctl_oid = LDAP_CONTROL_PAGEDRESULTS;
+
+ ctrlsp = &ctrl;
+ ctrlsp = 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 pagedResults control: %s", ldap_err2string(rc));
+ RETURN_FALSE;
+ }
+
+ } else {
+ /* TODO: return a PHP control object */
+ }
+
+ if (ber != NULL) {
+ ber_free(ber, 1);
+ }
+}
+/* }}} */
+
+/* {{{ 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;
+ BerElement *ber;
+ ber_tag_t tag;
+ int rc, i, 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", ldap_err2string(rc));
+ RETURN_FALSE;
+ }
+
+ if (lerrcode != LDAP_SUCCESS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Result is: %s", ldap_err2string(lerrcode));
+ RETURN_FALSE;
+ }
+
+ if (lserverctrls == NULL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "No server controls in result");
+ RETURN_FALSE;
+ }
+
+ for (i = 0; lserverctrls != NULL; i++) {
+ if (strcmp(lserverctrls->ldctl_oid, LDAP_CONTROL_PAGEDRESULTS) == 0) {
+ break;
+ }
+ }
+
+ if (lserverctrls == NULL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "No paged results control in result");
+ RETURN_FALSE;
+ }
+
+ ber = ber_init(&lserverctrls->ldctl_value);
+ if (ber == NULL) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to alloc BER decoding resources");
+ RETURN_FALSE;
+ }
+
+ tag = ber_scanf(ber, "{io}", &lestimated, &lcookie );
+ (void)ber_free(ber, 1);
+
+ if (tag == LBER_ERROR) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to decode paged results control response");
+ RETURN_FALSE;
+ }
+
+ if (lestimated < 0) {
+ 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
+
+#ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
+/* {{{ proto bool ldap_ctrl_ppolicy(resource link)
+ Inject password policy control */
+PHP_FUNCTION(ldap_ctrl_ppolicy)
+{
+}
+/* }}} */
+
+/* {{{ proto bool ldap_ctrl_ppolicy_resp(resource link, resource result, string cookie, int estimated)
+ Extract password policy control response */
+PHP_FUNCTION(ldap_ctrl_ppolicy_resp)
+{
+}
+/* }}} */
+#endif
+
/*
* Local variables:
* tab-width: 4
Index: ext/ldap/php_ldap.h
===================================================================
RCS file: /repository/php-src/ext/ldap/php_ldap.h,v
retrieving revision 1.32
diff -u -r1.32 php_ldap.h
--- ext/ldap/php_ldap.h 3 Aug 2005 14:07:23 -0000 1.32
+++ ext/ldap/php_ldap.h 10 Nov 2005 17:25:19 -0000
@@ -97,6 +97,15 @@
PHP_FUNCTION(ldap_8859_to_t61);
#endif

+#ifdef LDAP_CONTROL_PAGEDRESULTS
+PHP_FUNCTION(ldap_ctrl_paged_results);
+PHP_FUNCTION(ldap_ctrl_paged_results_resp);
+#endif
+#ifdef LDAP_CONTROL_PASSWORDPOLICYREQUEST
+PHP_FUNCTION(ldap_ctrl_ppolicy);
+PHP_FUNCTION(ldap_ctrl_ppolicy_resp);
+#endif
+
ZEND_BEGIN_MODULE_GLOBALS(ldap)
long num_links;
long max_links;pagedResults.phpDescription:application/php--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit:http://www.php.net/unsub.php

Attachments:
attachment pagedResults.php (1.9 KB)

Offline

#9 Nov. 14, 2005 14:33:51

Pierangelo M.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

[PHP-DEV] LDAP controls in response


On Wed, 2005-11-09 at 10:03 +0200, Jani Taskinen wrote:
> Anyway, it might be the time to cleanup the API of this extension
and make it simpler. It's pretty confusing as it is.
> The returned arrays are also weird with their "count" fields and
> such.

Jani,

sorry to bother you again. Do you think there are chances to see controls
in LDAP results in PHP 5/HEAD any soon? Another thing we'd need is LDAP
extended operations (mainly for RFC 3062 password modify exop), so I'd
like to add an API for extended operations as well.

However, as these enhancements grow bigger, I think they should be better
harmonized with the existing LDAP extension API, or even better with any
foreseen API development. If anybody is (interested in) discussing LDAP
API extension development, please let me know.

p.

--
Pierangelo Masarati









Ing. Pierangelo Masarati

Responsabile Open Solution



SysNet s.n.c.

Via Dossi, 8 - 27100 Pavia - ITALIAhttp://www.sys-net.it------------------------------------------

Office: +39.02.23998309

Mobile: +39.333.4963172

Email:

------------------------------------------


--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit:http://www.php.net/unsub.php

Offline

#10 Nov. 14, 2005 20:15:26

Jani T.
Registered: 2009-11-02
Reputation: +  0  -
Profile   Send e-mail  

[PHP-DEV] LDAP controls in response


On Mon, 14 Nov 2005, Pierangelo Masarati wrote:sorry to bother you again. Do you think there are chances to see controls
in LDAP results in PHP 5/HEAD any soon? Another thing we'd need is LDAPI'll look into it but this won't get into 5.1.0. We're gonna release
5.1.1 quite soon after and it will contain your patch. I just need to
free some time to sit down and look it over again. :)

--Jani

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit:http://www.php.net/unsub.php

Offline

  • Root
  • » PHP
  • » [PHP-DEV] LDAP controls in response [RSS Feed]

Board footer

Moderator control

Enjoy the 18th of November
PoweredBy

The Forums are managed by develissimo stuff members, if you find any issues or misplaced content please help us to fix it. Thank you! Tell us via Contact Options
Leave a Message
Welcome to Develissimo Live Support