[PATCH] LDAP module patch (adding new functionality).

php.internals

Ignacio Arenaza

20 years ago
Hi, I have modified the ldap module to be able to use Paged Results (see RFC 2696). In order to do that, I have modified ldap_parse_result to provide the server controls to the user. This is where paged results control returned from the server are, specifically the cookie value. Without this value you can't do paged results at all. The values returned in this extension control are BER-encoded (see ITU's X.690 recommendation) so I have created two new functions that wrap around ber_printf() and ber_scanf(), to allow for the encodig/decoding of these values. I have tested these modifications with W2003 AD and OpenLDAP 2.1.x servers, using a linux PHP client linked with OpenLDAP libraries (I don't have access to neither Netscape's nor Oracle's libraries to test them). I have made diffs against current CVS versions as of today, 2006.04.09, 23:15 CET DST) for PHP_4_3, PHP_4_4, PHP_5_0, PHP_5_1 and HEAD branches. I'm sending them attached. I hope this could be added to the standard version of PHP in the near future. Thanks in advance for your time. Saludos. Iñaki.
-- School of Management Mondragon University 20560 Oñati - Spain +34 943 718009 (ext. 225) GPG Key available at public keyservers Index: ext/ldap/ldap.c =================================================================== RCS file: /repository/php-src/ext/ldap/ldap.c,v retrieving revision 1.130.2.13 diff -u -r1.130.2.13 ldap.c --- ext/ldap/ldap.c 8 May 2005 16:06:24 -0000 1.130.2.13 +++ ext/ldap/ldap.c 9 Apr 2006 20:46:51 -0000 @@ -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; @@ -131,8 +131,10 @@ PHP_FE(ldap_parse_reference, third_argument_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 + PHP_FE(ldap_ber_printf, NULL) + PHP_FE(ldap_ber_scanf, NULL) #ifdef HAVE_LDAP_START_TLS_S PHP_FE(ldap_start_tls, NULL) #endif @@ -1759,18 +1761,19 @@ /* }}} */ #ifdef HAVE_LDAP_PARSE_RESULT -/* {{{ proto bool ldap_parse_result(resource link, resource result, int errcode, string matcheddn, string errmsg, array referrals) +/* {{{ proto bool ldap_parse_result(resource link, resource result, int errcode, string matcheddn, string errmsg, array referrals, array serverctrls) 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; + LDAPControl **lserverctrls, **ctrlp, *ctrl; char **lreferrals, **refp; 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; } @@ -1781,7 +1784,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)); @@ -1793,6 +1796,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); array_init(*referrals); @@ -1826,6 +1852,303 @@ /* }}} */ #endif +/* {{{ proto string ldap_ber_printf(string format [, mixed arg1 [, mixed ...]]) + Creates a BER encoded string of the values/types specified in the format string. Returns the BER encoded string, or 'false' if the enconding failed */ +PHP_FUNCTION(ldap_ber_printf) +{ + zval ***args; + int argc, curarg, rc; + char *format; + char fmt_buf[5], *err_msg; + unsigned int format_length, pos; + BerElement *ber; + struct berval bv_str, *bv_retval; + + argc = ZEND_NUM_ARGS(); + + if (argc < 1) { + WRONG_PARAM_COUNT; + } + + args = (zval ***)safe_emalloc(argc, sizeof(zval *), 0); + + if (zend_get_parameters_array_ex(argc, args) == FAILURE) { + efree(args); + WRONG_PARAM_COUNT; + } + + convert_to_string_ex(args[0]); + format = Z_STRVAL_PP(args[0]); + format_length = Z_STRLEN_PP(args[0]); + + ber = ber_alloc_t(LBER_USE_DER); + if (ber == NULL) { + efree(args); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to allocate enough memory"); + RETURN_FALSE; + } + + err_msg = NULL; + pos = 0; + curarg = 1; + while (pos < format_length) { + switch(format[pos]) { + case '{' : + case '}' : + case '[' : + case ']' : + case 'n' : + snprintf (fmt_buf, sizeof(fmt_buf), "%c", format[pos]); + rc = ber_printf(ber, fmt_buf); + break; + default: + if (curarg >= argc) { + err_msg = "Too few arguments"; + goto ber_printf_errexit; + } + else { + switch(format[pos]) { + case 'b' : + convert_to_boolean_ex(args[curarg]); + rc = ber_printf(ber, "b", Z_LVAL_PP(args[curarg])); + curarg++; + break; + case 'e' : + case 'i' : + case 't' : + snprintf (fmt_buf, sizeof(fmt_buf), "%c", format[pos]); + convert_to_long_ex(args[curarg]); + rc = ber_printf(ber, fmt_buf, Z_LVAL_PP(args[curarg])); + curarg++; + break; + case 'B' : + convert_to_string_ex(args[curarg]); + rc = ber_printf(ber, "B", Z_STRVAL_PP(args[curarg]), + 8 * Z_STRLEN_PP(args[curarg])); + curarg++; + break; + case 's' : + convert_to_string_ex(args[curarg]); + rc = ber_printf(ber, "s", Z_STRVAL_PP(args[curarg])); + curarg++; + break; + case 'o' : + convert_to_string_ex(args[curarg]); + rc = ber_printf(ber, "o", Z_STRVAL_PP(args[curarg]), + Z_STRLEN_PP(args[curarg])); + curarg++; + break; + case 'O' : + convert_to_string_ex(args[curarg]); + bv_str.bv_val = Z_STRVAL_PP(args[curarg]); + bv_str.bv_len = Z_STRLEN_PP(args[curarg]); + rc = ber_printf(ber, "O", &bv_str); + curarg++; + break; + case 'v' : + case 'V' : + err_msg = "Unsupported format specifier by now: '%c'"; + goto ber_printf_errexit; + break; + case 'W' : /* This is an OpenLDAP extension only + * not present on draft-ietf-ldapext-ldap-c-api-*.txt + */ + default: + err_msg = "Unkown format specifier: '%c'"; + goto ber_printf_errexit; + } /* switch */ + } /* else */ + } /* switch */ + if (rc == -1) { + err_msg = "Unable to process some values. Check you format string and values"; + goto ber_printf_errexit; + } + pos++; + } + + if (ber_flatten (ber, &bv_retval) == -1) { + goto ber_printf_errexit; + } + + RETVAL_STRINGL(bv_retval->bv_val, bv_retval->bv_len, 1); + ber_bvfree(bv_retval); + ber_free(ber,0); + efree(args); + return; + +ber_printf_errexit: + ber_free(ber,0); + efree(args); + php_error_docref(NULL TSRMLS_CC, E_WARNING, err_msg, format[pos] ); + RETURN_FALSE; +} +/* }}} */ + +/* {{{ proto int ldap_ber_scanf(string berval, string format [, mixed arg1 [, mixed ...]]) + The complimentary function to ber_printf */ +PHP_FUNCTION(ldap_ber_scanf) +{ + zval ***args; + int argc, i, curarg, int_val; + char *format, *err_msg, *string; + char fmt_buf[5]; + unsigned int format_length, pos; + BerElement *ber; + ber_tag_t rc, tag; + ber_len_t ber_len; + struct berval bv_str, *bv_ptr; + + + argc = ZEND_NUM_ARGS(); + if (argc < 2) { + WRONG_PARAM_COUNT; + } + + args = (zval ***) safe_emalloc(sizeof(zval **), argc, 0); + if (zend_get_parameters_array_ex(argc, args) == FAILURE) { + efree(args); + WRONG_PARAM_COUNT; + } + + /* If any variables are passed, make sure they are all passed by reference */ + if ((argc - 2) > 0) { + for (i = 2; i < argc; i++){ + if ( ! PZVAL_IS_REF(*args[i])) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "Parameter %d must be passed by reference", i); + RETURN_LONG(0); + } + } + } + + err_msg = NULL; + + convert_to_string_ex(args[0]); + convert_to_string_ex(args[1]); + + bv_str.bv_val = Z_STRVAL_PP(args[0]); + bv_str.bv_len = Z_STRLEN_PP(args[0]); + ber = ber_init(&bv_str); + if (ber == NULL) { + efree(args); + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "Unable to allocate enough memory or invalid BER data"); + RETURN_LONG(0); + } + + format=Z_STRVAL_PP(args[1]); + format_length=Z_STRLEN_PP(args[1]); + + pos = 0; + curarg = 2; + while (pos < format_length) { + switch(format[pos]) { + case '{' : + case '}' : + case '[' : + case ']' : + case 'n' : + snprintf (fmt_buf, sizeof(fmt_buf), "%c", format[pos]); + rc = ber_scanf(ber, fmt_buf); + break; + default: + if (curarg >= argc) { + err_msg = "Too few arguments"; + goto ber_scanf_errexit; + } + else { + switch(format[pos]) { + case 'a' : + rc = ber_scanf(ber, "a", &string); + if (rc != LBER_ERROR) { + zval_dtor(*args[curarg]); + ZVAL_STRING(*args[curarg], string, 1); + ber_memfree(string); + curarg++; + } + break; + case 'O' : + rc = ber_scanf(ber, "O", &bv_ptr); + if (rc != LBER_ERROR) { + zval_dtor(*args[curarg]); + ZVAL_STRINGL(*args[curarg], bv_ptr->bv_val, + bv_ptr->bv_len, 1); + ber_bvfree(bv_ptr); + curarg++; + } + break; + case 'b' : + rc = ber_scanf(ber, "b", &int_val); + if (rc != LBER_ERROR) { + zval_dtor(*args[curarg]); + ZVAL_BOOL(*args[curarg], int_val); + curarg++; + } + break; + case 'e' : + case 'i' : + snprintf (fmt_buf, sizeof(fmt_buf), "%c", format[pos]); + rc = ber_scanf(ber, fmt_buf, &int_val); + if (rc != LBER_ERROR) { + zval_dtor(*args[curarg]); + ZVAL_LONG(*args[curarg], int_val); + curarg++; + } + break; + case 'B' : + rc = ber_scanf(ber, "B", &string, &ber_len); + if (rc != LBER_ERROR) { + /* ber_len is in bits, _not_ in bytes, so beware! + */ + zval_dtor(*args[curarg]); + ZVAL_STRINGL(*args[curarg], string, (ber_len+7)/8, 1); + ber_memfree(string); + curarg++; + } + break; + case 't' : + rc = ber_scanf(ber, "t", &tag); + if (rc != LBER_ERROR) { + zval_dtor(*args[curarg]); + ZVAL_LONG(*args[curarg], tag); + curarg++; + } + break; + case 'x' : + rc = ber_scanf(ber, "x"); + break; + case 'v' : + case 'V' : + err_msg = "Unsupported format specifier by now: '%c'"; + goto ber_scanf_errexit; + break; + case 'l' : + case 's' : /* This is an OpenLDAP extension only + * not present on draft-ietf-ldapext-ldap-c-api-*.txt + */ + default: + err_msg = "Unkown format specifier: '%c'"; + goto ber_scanf_errexit; + } + } + } + if (rc == LBER_ERROR) { + err_msg = "Unable to process some values. Check you format string and values"; + goto ber_scanf_errexit; + } + pos++; + } + RETURN_LONG(curarg - 2); + +ber_scanf_errexit: + ber_free(ber,0); + efree(args); + php_error_docref(NULL TSRMLS_CC, E_WARNING, err_msg, format[pos] ); + RETURN_LONG(0); +} +/* }}} */ + + /* {{{ proto resource ldap_first_reference(resource link, resource result) Return first reference */ PHP_FUNCTION(ldap_first_reference) Index: ext/ldap/php_ldap.h =================================================================== RCS file: /repository/php-src/ext/ldap/php_ldap.h,v retrieving revision 1.25.8.2 diff -u -r1.25.8.2 php_ldap.h --- ext/ldap/php_ldap.h 8 May 2005 16:06:25 -0000 1.25.8.2 +++ ext/ldap/php_ldap.h 9 Apr 2006 20:46:51 -0000 @@ -53,6 +53,8 @@ PHP_FUNCTION(ldap_get_values); PHP_FUNCTION(ldap_get_values_len); PHP_FUNCTION(ber_free); +PHP_FUNCTION(ldap_ber_printf); +PHP_FUNCTION(ldap_ber_scanf); PHP_FUNCTION(ldap_get_dn); PHP_FUNCTION(ldap_explode_dn); PHP_FUNCTION(ldap_dn2ufn); Index: ext/ldap/ldap.c =================================================================== RCS file: /repository/php-src/ext/ldap/ldap.c,v retrieving revision 1.130.2.13.2.1 diff -u -r1.130.2.13.2.1 ldap.c --- ext/ldap/ldap.c 1 Jan 2006 13:46:54 -0000 1.130.2.13.2.1 +++ ext/ldap/ldap.c 9 Apr 2006 20:45:37 -0000 @@ -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; @@ -131,8 +131,10 @@ PHP_FE(ldap_parse_reference, third_argument_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 + PHP_FE(ldap_ber_printf, NULL) + PHP_FE(ldap_ber_scanf, NULL) #ifdef HAVE_LDAP_START_TLS_S PHP_FE(ldap_start_tls, NULL) #endif @@ -1759,18 +1761,19 @@ /* }}} */ #ifdef HAVE_LDAP_PARSE_RESULT -/* {{{ proto bool ldap_parse_result(resource link, resource result, int errcode, string matcheddn, string errmsg, array referrals) +/* {{{ proto bool ldap_parse_result(resource link, resource result, int errcode, string matcheddn, string errmsg, array referrals, array serverctrls) 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; + LDAPControl **lserverctrls, **ctrlp, *ctrl; char **lreferrals, **refp; 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; } @@ -1781,7 +1784,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)); @@ -1793,6 +1796,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); array_init(*referrals); @@ -1826,6 +1852,303 @@ /* }}} */ #endif +/* {{{ proto string ldap_ber_printf(string format [, mixed arg1 [, mixed ...]]) + Creates a BER encoded string of the values/types specified in the format string. Returns the BER encoded string, or 'false' if the enconding failed */ +PHP_FUNCTION(ldap_ber_printf) +{ + zval ***args; + int argc, curarg, rc; + char *format; + char fmt_buf[5], *err_msg; + unsigned int format_length, pos; + BerElement *ber; + struct berval bv_str, *bv_retval; + + argc = ZEND_NUM_ARGS(); + + if (argc < 1) { + WRONG_PARAM_COUNT; + } + + args = (zval ***)safe_emalloc(argc, sizeof(zval *), 0); + + if (zend_get_parameters_array_ex(argc, args) == FAILURE) { + efree(args); + WRONG_PARAM_COUNT; + } + + convert_to_string_ex(args[0]); + format = Z_STRVAL_PP(args[0]); + format_length = Z_STRLEN_PP(args[0]); + + ber = ber_alloc_t(LBER_USE_DER); + if (ber == NULL) { + efree(args); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to allocate enough memory"); + RETURN_FALSE; + } + + err_msg = NULL; + pos = 0; + curarg = 1; + while (pos < format_length) { + switch(format[pos]) { + case '{' : + case '}' : + case '[' : + case ']' : + case 'n' : + snprintf (fmt_buf, sizeof(fmt_buf), "%c", format[pos]); + rc = ber_printf(ber, fmt_buf); + break; + default: + if (curarg >= argc) { + err_msg = "Too few arguments"; + goto ber_printf_errexit; + } + else { + switch(format[pos]) { + case 'b' : + convert_to_boolean_ex(args[curarg]); + rc = ber_printf(ber, "b", Z_LVAL_PP(args[curarg])); + curarg++; + break; + case 'e' : + case 'i' : + case 't' : + snprintf (fmt_buf, sizeof(fmt_buf), "%c", format[pos]); + convert_to_long_ex(args[curarg]); + rc = ber_printf(ber, fmt_buf, Z_LVAL_PP(args[curarg])); + curarg++; + break; + case 'B' : + convert_to_string_ex(args[curarg]); + rc = ber_printf(ber, "B", Z_STRVAL_PP(args[curarg]), + 8 * Z_STRLEN_PP(args[curarg])); + curarg++; + break; + case 's' : + convert_to_string_ex(args[curarg]); + rc = ber_printf(ber, "s", Z_STRVAL_PP(args[curarg])); + curarg++; + break; + case 'o' : + convert_to_string_ex(args[curarg]); + rc = ber_printf(ber, "o", Z_STRVAL_PP(args[curarg]), + Z_STRLEN_PP(args[curarg])); + curarg++; + break; + case 'O' : + convert_to_string_ex(args[curarg]); + bv_str.bv_val = Z_STRVAL_PP(args[curarg]); + bv_str.bv_len = Z_STRLEN_PP(args[curarg]); + rc = ber_printf(ber, "O", &bv_str); + curarg++; + break; + case 'v' : + case 'V' : + err_msg = "Unsupported format specifier by now: '%c'"; + goto ber_printf_errexit; + break; + case 'W' : /* This is an OpenLDAP extension only + * not present on draft-ietf-ldapext-ldap-c-api-*.txt + */ + default: + err_msg = "Unkown format specifier: '%c'"; + goto ber_printf_errexit; + } /* switch */ + } /* else */ + } /* switch */ + if (rc == -1) { + err_msg = "Unable to process some values. Check you format string and values"; + goto ber_printf_errexit; + } + pos++; + } + + if (ber_flatten (ber, &bv_retval) == -1) { + goto ber_printf_errexit; + } + + RETVAL_STRINGL(bv_retval->bv_val, bv_retval->bv_len, 1); + ber_bvfree(bv_retval); + ber_free(ber,0); + efree(args); + return; + +ber_printf_errexit: + ber_free(ber,0); + efree(args); + php_error_docref(NULL TSRMLS_CC, E_WARNING, err_msg, format[pos] ); + RETURN_FALSE; +} +/* }}} */ + +/* {{{ proto int ldap_ber_scanf(string berval, string format [, mixed arg1 [, mixed ...]]) + The complimentary function to ber_printf */ +PHP_FUNCTION(ldap_ber_scanf) +{ + zval ***args; + int argc, i, curarg, int_val; + char *format, *err_msg, *string; + char fmt_buf[5]; + unsigned int format_length, pos; + BerElement *ber; + ber_tag_t rc, tag; + ber_len_t ber_len; + struct berval bv_str, *bv_ptr; + + + argc = ZEND_NUM_ARGS(); + if (argc < 2) { + WRONG_PARAM_COUNT; + } + + args = (zval ***) safe_emalloc(sizeof(zval **), argc, 0); + if (zend_get_parameters_array_ex(argc, args) == FAILURE) { + efree(args); + WRONG_PARAM_COUNT; + } + + /* If any variables are passed, make sure they are all passed by reference */ + if ((argc - 2) > 0) { + for (i = 2; i < argc; i++){ + if ( ! PZVAL_IS_REF(*args[i])) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "Parameter %d must be passed by reference", i); + RETURN_LONG(0); + } + } + } + + err_msg = NULL; + + convert_to_string_ex(args[0]); + convert_to_string_ex(args[1]); + + bv_str.bv_val = Z_STRVAL_PP(args[0]); + bv_str.bv_len = Z_STRLEN_PP(args[0]); + ber = ber_init(&bv_str); + if (ber == NULL) { + efree(args); + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "Unable to allocate enough memory or invalid BER data"); + RETURN_LONG(0); + } + + format=Z_STRVAL_PP(args[1]); + format_length=Z_STRLEN_PP(args[1]); + + pos = 0; + curarg = 2; + while (pos < format_length) { + switch(format[pos]) { + case '{' : + case '}' : + case '[' : + case ']' : + case 'n' : + snprintf (fmt_buf, sizeof(fmt_buf), "%c", format[pos]); + rc = ber_scanf(ber, fmt_buf); + break; + default: + if (curarg >= argc) { + err_msg = "Too few arguments"; + goto ber_scanf_errexit; + } + else { + switch(format[pos]) { + case 'a' : + rc = ber_scanf(ber, "a", &string); + if (rc != LBER_ERROR) { + zval_dtor(*args[curarg]); + ZVAL_STRING(*args[curarg], string, 1); + ber_memfree(string); + curarg++; + } + break; + case 'O' : + rc = ber_scanf(ber, "O", &bv_ptr); + if (rc != LBER_ERROR) { + zval_dtor(*args[curarg]); + ZVAL_STRINGL(*args[curarg], bv_ptr->bv_val, + bv_ptr->bv_len, 1); + ber_bvfree(bv_ptr); + curarg++; + } + break; + case 'b' : + rc = ber_scanf(ber, "b", &int_val); + if (rc != LBER_ERROR) { + zval_dtor(*args[curarg]); + ZVAL_BOOL(*args[curarg], int_val); + curarg++; + } + break; + case 'e' : + case 'i' : + snprintf (fmt_buf, sizeof(fmt_buf), "%c", format[pos]); + rc = ber_scanf(ber, fmt_buf, &int_val); + if (rc != LBER_ERROR) { + zval_dtor(*args[curarg]); + ZVAL_LONG(*args[curarg], int_val); + curarg++; + } + break; + case 'B' : + rc = ber_scanf(ber, "B", &string, &ber_len); + if (rc != LBER_ERROR) { + /* ber_len is in bits, _not_ in bytes, so beware! + */ + zval_dtor(*args[curarg]); + ZVAL_STRINGL(*args[curarg], string, (ber_len+7)/8, 1); + ber_memfree(string); + curarg++; + } + break; + case 't' : + rc = ber_scanf(ber, "t", &tag); + if (rc != LBER_ERROR) { + zval_dtor(*args[curarg]); + ZVAL_LONG(*args[curarg], tag); + curarg++; + } + break; + case 'x' : + rc = ber_scanf(ber, "x"); + break; + case 'v' : + case 'V' : + err_msg = "Unsupported format specifier by now: '%c'"; + goto ber_scanf_errexit; + break; + case 'l' : + case 's' : /* This is an OpenLDAP extension only + * not present on draft-ietf-ldapext-ldap-c-api-*.txt + */ + default: + err_msg = "Unkown format specifier: '%c'"; + goto ber_scanf_errexit; + } + } + } + if (rc == LBER_ERROR) { + err_msg = "Unable to process some values. Check you format string and values"; + goto ber_scanf_errexit; + } + pos++; + } + RETURN_LONG(curarg - 2); + +ber_scanf_errexit: + ber_free(ber,0); + efree(args); + php_error_docref(NULL TSRMLS_CC, E_WARNING, err_msg, format[pos] ); + RETURN_LONG(0); +} +/* }}} */ + + /* {{{ proto resource ldap_first_reference(resource link, resource result) Return first reference */ PHP_FUNCTION(ldap_first_reference) Index: ext/ldap/php_ldap.h =================================================================== RCS file: /repository/php-src/ext/ldap/php_ldap.h,v retrieving revision 1.25.8.2.2.1 diff -u -r1.25.8.2.2.1 php_ldap.h --- ext/ldap/php_ldap.h 1 Jan 2006 13:46:54 -0000 1.25.8.2.2.1 +++ ext/ldap/php_ldap.h 9 Apr 2006 20:45:37 -0000 @@ -53,6 +53,8 @@ PHP_FUNCTION(ldap_get_values); PHP_FUNCTION(ldap_get_values_len); PHP_FUNCTION(ber_free); +PHP_FUNCTION(ldap_ber_printf); +PHP_FUNCTION(ldap_ber_scanf); PHP_FUNCTION(ldap_get_dn); PHP_FUNCTION(ldap_explode_dn); PHP_FUNCTION(ldap_dn2ufn); Index: ext/ldap/ldap.c =================================================================== RCS file: /repository/php-src/ext/ldap/ldap.c,v retrieving revision 1.154.2.7 diff -u -r1.154.2.7 ldap.c --- ext/ldap/ldap.c 9 Jul 2005 01:00:11 -0000 1.154.2.7 +++ ext/ldap/ldap.c 9 Apr 2006 20:43:52 -0000 @@ -80,7 +80,7 @@ ZEND_DECLARE_MODULE_GLOBALS(ldap) static - ZEND_BEGIN_ARG_INFO(arg3to6of6_force_ref, 0) + ZEND_BEGIN_ARG_INFO(arg3to7of7_force_ref, 0) ZEND_ARG_PASS_INFO(0) ZEND_ARG_PASS_INFO(0) ZEND_ARG_PASS_INFO(1) @@ -147,8 +147,10 @@ PHP_FE(ldap_parse_reference, third_arg_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 + PHP_FE(ldap_ber_printf, NULL) + PHP_FE(ldap_ber_scanf, NULL) #ifdef HAVE_LDAP_START_TLS_S PHP_FE(ldap_start_tls, NULL) #endif @@ -1929,18 +1931,19 @@ /* }}} */ #ifdef HAVE_LDAP_PARSE_RESULT -/* {{{ proto bool ldap_parse_result(resource link, resource result, int errcode, string matcheddn, string errmsg, array referrals) +/* {{{ proto bool ldap_parse_result(resource link, resource result, int errcode, string matcheddn, string errmsg, array referrals, array serverctrls) 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; + LDAPControl **lserverctrls, **ctrlp, *ctrl; char **lreferrals, **refp; 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 +1954,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,6 +1966,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); array_init(*referrals); @@ -1996,6 +2022,303 @@ /* }}} */ #endif +/* {{{ proto string ldap_ber_printf(string format [, mixed arg1 [, mixed ...]]) + Creates a BER encoded string of the values/types specified in the format string. Returns the BER encoded string, or 'false' if the enconding failed */ +PHP_FUNCTION(ldap_ber_printf) +{ + zval ***args; + int argc, curarg, rc; + char *format; + char fmt_buf[5], *err_msg; + unsigned int format_length, pos; + BerElement *ber; + struct berval bv_str, *bv_retval; + + argc = ZEND_NUM_ARGS(); + + if (argc < 1) { + WRONG_PARAM_COUNT; + } + + args = (zval ***)safe_emalloc(argc, sizeof(zval *), 0); + + if (zend_get_parameters_array_ex(argc, args) == FAILURE) { + efree(args); + WRONG_PARAM_COUNT; + } + + convert_to_string_ex(args[0]); + format = Z_STRVAL_PP(args[0]); + format_length = Z_STRLEN_PP(args[0]); + + ber = ber_alloc_t(LBER_USE_DER); + if (ber == NULL) { + efree(args); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to allocate enough memory"); + RETURN_FALSE; + } + + err_msg = NULL; + pos = 0; + curarg = 1; + while (pos < format_length) { + switch(format[pos]) { + case '{' : + case '}' : + case '[' : + case ']' : + case 'n' : + snprintf (fmt_buf, sizeof(fmt_buf), "%c", format[pos]); + rc = ber_printf(ber, fmt_buf); + break; + default: + if (curarg >= argc) { + err_msg = "Too few arguments"; + goto ber_printf_errexit; + } + else { + switch(format[pos]) { + case 'b' : + convert_to_boolean_ex(args[curarg]); + rc = ber_printf(ber, "b", Z_LVAL_PP(args[curarg])); + curarg++; + break; + case 'e' : + case 'i' : + case 't' : + snprintf (fmt_buf, sizeof(fmt_buf), "%c", format[pos]); + convert_to_long_ex(args[curarg]); + rc = ber_printf(ber, fmt_buf, Z_LVAL_PP(args[curarg])); + curarg++; + break; + case 'B' : + convert_to_string_ex(args[curarg]); + rc = ber_printf(ber, "B", Z_STRVAL_PP(args[curarg]), + 8 * Z_STRLEN_PP(args[curarg])); + curarg++; + break; + case 's' : + convert_to_string_ex(args[curarg]); + rc = ber_printf(ber, "s", Z_STRVAL_PP(args[curarg])); + curarg++; + break; + case 'o' : + convert_to_string_ex(args[curarg]); + rc = ber_printf(ber, "o", Z_STRVAL_PP(args[curarg]), + Z_STRLEN_PP(args[curarg])); + curarg++; + break; + case 'O' : + convert_to_string_ex(args[curarg]); + bv_str.bv_val = Z_STRVAL_PP(args[curarg]); + bv_str.bv_len = Z_STRLEN_PP(args[curarg]); + rc = ber_printf(ber, "O", &bv_str); + curarg++; + break; + case 'v' : + case 'V' : + err_msg = "Unsupported format specifier by now: '%c'"; + goto ber_printf_errexit; + break; + case 'W' : /* This is an OpenLDAP extension only + * not present on draft-ietf-ldapext-ldap-c-api-*.txt + */ + default: + err_msg = "Unkown format specifier: '%c'"; + goto ber_printf_errexit; + } /* switch */ + } /* else */ + } /* switch */ + if (rc == -1) { + err_msg = "Unable to process some values. Check you format string and values"; + goto ber_printf_errexit; + } + pos++; + } + + if (ber_flatten (ber, &bv_retval) == -1) { + goto ber_printf_errexit; + } + + RETVAL_STRINGL(bv_retval->bv_val, bv_retval->bv_len, 1); + ber_bvfree(bv_retval); + ber_free(ber,0); + efree(args); + return; + +ber_printf_errexit: + ber_free(ber,0); + efree(args); + php_error_docref(NULL TSRMLS_CC, E_WARNING, err_msg, format[pos] ); + RETURN_FALSE; +} +/* }}} */ + +/* {{{ proto int ldap_ber_scanf(string berval, string format [, mixed arg1 [, mixed ...]]) + The complimentary function to ber_printf */ +PHP_FUNCTION(ldap_ber_scanf) +{ + zval ***args; + int argc, i, curarg, int_val; + char *format, *err_msg, *string; + char fmt_buf[5]; + unsigned int format_length, pos; + BerElement *ber; + ber_tag_t rc, tag; + ber_len_t ber_len; + struct berval bv_str, *bv_ptr; + + + argc = ZEND_NUM_ARGS(); + if (argc < 2) { + WRONG_PARAM_COUNT; + } + + args = (zval ***) safe_emalloc(sizeof(zval **), argc, 0); + if (zend_get_parameters_array_ex(argc, args) == FAILURE) { + efree(args); + WRONG_PARAM_COUNT; + } + + /* If any variables are passed, make sure they are all passed by reference */ + if ((argc - 2) > 0) { + for (i = 2; i < argc; i++){ + if ( ! PZVAL_IS_REF(*args[i])) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "Parameter %d must be passed by reference", i); + RETURN_LONG(0); + } + } + } + + err_msg = NULL; + + convert_to_string_ex(args[0]); + convert_to_string_ex(args[1]); + + bv_str.bv_val = Z_STRVAL_PP(args[0]); + bv_str.bv_len = Z_STRLEN_PP(args[0]); + ber = ber_init(&bv_str); + if (ber == NULL) { + efree(args); + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "Unable to allocate enough memory or invalid BER data"); + RETURN_LONG(0); + } + + format=Z_STRVAL_PP(args[1]); + format_length=Z_STRLEN_PP(args[1]); + + pos = 0; + curarg = 2; + while (pos < format_length) { + switch(format[pos]) { + case '{' : + case '}' : + case '[' : + case ']' : + case 'n' : + snprintf (fmt_buf, sizeof(fmt_buf), "%c", format[pos]); + rc = ber_scanf(ber, fmt_buf); + break; + default: + if (curarg >= argc) { + err_msg = "Too few arguments"; + goto ber_scanf_errexit; + } + else { + switch(format[pos]) { + case 'a' : + rc = ber_scanf(ber, "a", &string); + if (rc != LBER_ERROR) { + zval_dtor(*args[curarg]); + ZVAL_STRING(*args[curarg], string, 1); + ber_memfree(string); + curarg++; + } + break; + case 'O' : + rc = ber_scanf(ber, "O", &bv_ptr); + if (rc != LBER_ERROR) { + zval_dtor(*args[curarg]); + ZVAL_STRINGL(*args[curarg], bv_ptr->bv_val, + bv_ptr->bv_len, 1); + ber_bvfree(bv_ptr); + curarg++; + } + break; + case 'b' : + rc = ber_scanf(ber, "b", &int_val); + if (rc != LBER_ERROR) { + zval_dtor(*args[curarg]); + ZVAL_BOOL(*args[curarg], int_val); + curarg++; + } + break; + case 'e' : + case 'i' : + snprintf (fmt_buf, sizeof(fmt_buf), "%c", format[pos]); + rc = ber_scanf(ber, fmt_buf, &int_val); + if (rc != LBER_ERROR) { + zval_dtor(*args[curarg]); + ZVAL_LONG(*args[curarg], int_val); + curarg++; + } + break; + case 'B' : + rc = ber_scanf(ber, "B", &string, &ber_len); + if (rc != LBER_ERROR) { + /* ber_len is in bits, _not_ in bytes, so beware! + */ + zval_dtor(*args[curarg]); + ZVAL_STRINGL(*args[curarg], string, (ber_len+7)/8, 1); + ber_memfree(string); + curarg++; + } + break; + case 't' : + rc = ber_scanf(ber, "t", &tag); + if (rc != LBER_ERROR) { + zval_dtor(*args[curarg]); + ZVAL_LONG(*args[curarg], tag); + curarg++; + } + break; + case 'x' : + rc = ber_scanf(ber, "x"); + break; + case 'v' : + case 'V' : + err_msg = "Unsupported format specifier by now: '%c'"; + goto ber_scanf_errexit; + break; + case 'l' : + case 's' : /* This is an OpenLDAP extension only + * not present on draft-ietf-ldapext-ldap-c-api-*.txt + */ + default: + err_msg = "Unkown format specifier: '%c'"; + goto ber_scanf_errexit; + } + } + } + if (rc == LBER_ERROR) { + err_msg = "Unable to process some values. Check you format string and values"; + goto ber_scanf_errexit; + } + pos++; + } + RETURN_LONG(curarg - 2); + +ber_scanf_errexit: + ber_free(ber,0); + efree(args); + php_error_docref(NULL TSRMLS_CC, E_WARNING, err_msg, format[pos] ); + RETURN_LONG(0); +} +/* }}} */ + + /* {{{ proto resource ldap_first_reference(resource link, resource result) Return first reference */ PHP_FUNCTION(ldap_first_reference) Index: ext/ldap/php_ldap.h =================================================================== RCS file: /repository/php-src/ext/ldap/php_ldap.h,v retrieving revision 1.30.2.1 diff -u -r1.30.2.1 php_ldap.h --- ext/ldap/php_ldap.h 8 May 2005 15:44:15 -0000 1.30.2.1 +++ ext/ldap/php_ldap.h 9 Apr 2006 20:43:53 -0000 @@ -56,6 +56,8 @@ PHP_FUNCTION(ldap_get_values); PHP_FUNCTION(ldap_get_values_len); PHP_FUNCTION(ber_free); +PHP_FUNCTION(ldap_ber_printf); +PHP_FUNCTION(ldap_ber_scanf); PHP_FUNCTION(ldap_get_dn); PHP_FUNCTION(ldap_explode_dn); PHP_FUNCTION(ldap_dn2ufn); Index: ext/ldap/ldap.c =================================================================== RCS file: /repository/php-src/ext/ldap/ldap.c,v retrieving revision 1.161.2.3 diff -u -r1.161.2.3 ldap.c --- ext/ldap/ldap.c 1 Jan 2006 12:50:08 -0000 1.161.2.3 +++ ext/ldap/ldap.c 9 Apr 2006 20:40:07 -0000 @@ -80,7 +80,7 @@ ZEND_DECLARE_MODULE_GLOBALS(ldap) static - ZEND_BEGIN_ARG_INFO(arg3to6of6_force_ref, 0) + ZEND_BEGIN_ARG_INFO(arg3to7of7_force_ref, 0) ZEND_ARG_PASS_INFO(0) ZEND_ARG_PASS_INFO(0) ZEND_ARG_PASS_INFO(1) @@ -147,8 +147,10 @@ PHP_FE(ldap_parse_reference, third_arg_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 + PHP_FE(ldap_ber_printf, NULL) + PHP_FE(ldap_ber_scanf, NULL) #ifdef HAVE_LDAP_START_TLS_S PHP_FE(ldap_start_tls, NULL) #endif @@ -1932,18 +1934,19 @@ /* }}} */ #ifdef HAVE_LDAP_PARSE_RESULT -/* {{{ proto bool ldap_parse_result(resource link, resource result, int errcode, string matcheddn, string errmsg, array referrals) +/* {{{ proto bool ldap_parse_result(resource link, resource result, int errcode, string matcheddn, string errmsg, array referrals, array serverctrls) 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; + LDAPControl **lserverctrls, **ctrlp, *ctrl; char **lreferrals, **refp; 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; } @@ -1954,7 +1957,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)); @@ -1966,6 +1969,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); array_init(*referrals); @@ -1999,6 +2025,303 @@ /* }}} */ #endif +/* {{{ proto string ldap_ber_printf(string format [, mixed arg1 [, mixed ...]]) + Creates a BER encoded string of the values/types specified in the format string. Returns the BER encoded string, or 'false' if the enconding failed */ +PHP_FUNCTION(ldap_ber_printf) +{ + zval ***args; + int argc, curarg, rc; + char *format; + char fmt_buf[5], *err_msg; + unsigned int format_length, pos; + BerElement *ber; + struct berval bv_str, *bv_retval; + + argc = ZEND_NUM_ARGS(); + + if (argc < 1) { + WRONG_PARAM_COUNT; + } + + args = (zval ***)safe_emalloc(argc, sizeof(zval *), 0); + + if (zend_get_parameters_array_ex(argc, args) == FAILURE) { + efree(args); + WRONG_PARAM_COUNT; + } + + convert_to_string_ex(args[0]); + format = Z_STRVAL_PP(args[0]); + format_length = Z_STRLEN_PP(args[0]); + + ber = ber_alloc_t(LBER_USE_DER); + if (ber == NULL) { + efree(args); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to allocate enough memory"); + RETURN_FALSE; + } + + err_msg = NULL; + pos = 0; + curarg = 1; + while (pos < format_length) { + switch(format[pos]) { + case '{' : + case '}' : + case '[' : + case ']' : + case 'n' : + snprintf (fmt_buf, sizeof(fmt_buf), "%c", format[pos]); + rc = ber_printf(ber, fmt_buf); + break; + default: + if (curarg >= argc) { + err_msg = "Too few arguments"; + goto ber_printf_errexit; + } + else { + switch(format[pos]) { + case 'b' : + convert_to_boolean_ex(args[curarg]); + rc = ber_printf(ber, "b", Z_LVAL_PP(args[curarg])); + curarg++; + break; + case 'e' : + case 'i' : + case 't' : + snprintf (fmt_buf, sizeof(fmt_buf), "%c", format[pos]); + convert_to_long_ex(args[curarg]); + rc = ber_printf(ber, fmt_buf, Z_LVAL_PP(args[curarg])); + curarg++; + break; + case 'B' : + convert_to_string_ex(args[curarg]); + rc = ber_printf(ber, "B", Z_STRVAL_PP(args[curarg]), + 8 * Z_STRLEN_PP(args[curarg])); + curarg++; + break; + case 's' : + convert_to_string_ex(args[curarg]); + rc = ber_printf(ber, "s", Z_STRVAL_PP(args[curarg])); + curarg++; + break; + case 'o' : + convert_to_string_ex(args[curarg]); + rc = ber_printf(ber, "o", Z_STRVAL_PP(args[curarg]), + Z_STRLEN_PP(args[curarg])); + curarg++; + break; + case 'O' : + convert_to_string_ex(args[curarg]); + bv_str.bv_val = Z_STRVAL_PP(args[curarg]); + bv_str.bv_len = Z_STRLEN_PP(args[curarg]); + rc = ber_printf(ber, "O", &bv_str); + curarg++; + break; + case 'v' : + case 'V' : + err_msg = "Unsupported format specifier by now: '%c'"; + goto ber_printf_errexit; + break; + case 'W' : /* This is an OpenLDAP extension only + * not present on draft-ietf-ldapext-ldap-c-api-*.txt + */ + default: + err_msg = "Unkown format specifier: '%c'"; + goto ber_printf_errexit; + } /* switch */ + } /* else */ + } /* switch */ + if (rc == -1) { + err_msg = "Unable to process some values. Check you format string and values"; + goto ber_printf_errexit; + } + pos++; + } + + if (ber_flatten (ber, &bv_retval) == -1) { + goto ber_printf_errexit; + } + + RETVAL_STRINGL(bv_retval->bv_val, bv_retval->bv_len, 1); + ber_bvfree(bv_retval); + ber_free(ber,0); + efree(args); + return; + +ber_printf_errexit: + ber_free(ber,0); + efree(args); + php_error_docref(NULL TSRMLS_CC, E_WARNING, err_msg, format[pos] ); + RETURN_FALSE; +} +/* }}} */ + +/* {{{ proto int ldap_ber_scanf(string berval, string format [, mixed arg1 [, mixed ...]]) + The complimentary function to ber_printf */ +PHP_FUNCTION(ldap_ber_scanf) +{ + zval ***args; + int argc, i, curarg, int_val; + char *format, *err_msg, *string; + char fmt_buf[5]; + unsigned int format_length, pos; + BerElement *ber; + ber_tag_t rc, tag; + ber_len_t ber_len; + struct berval bv_str, *bv_ptr; + + + argc = ZEND_NUM_ARGS(); + if (argc < 2) { + WRONG_PARAM_COUNT; + } + + args = (zval ***) safe_emalloc(sizeof(zval **), argc, 0); + if (zend_get_parameters_array_ex(argc, args) == FAILURE) { + efree(args); + WRONG_PARAM_COUNT; + } + + /* If any variables are passed, make sure they are all passed by reference */ + if ((argc - 2) > 0) { + for (i = 2; i < argc; i++){ + if ( ! PZVAL_IS_REF(*args[i])) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "Parameter %d must be passed by reference", i); + RETURN_LONG(0); + } + } + } + + err_msg = NULL; + + convert_to_string_ex(args[0]); + convert_to_string_ex(args[1]); + + bv_str.bv_val = Z_STRVAL_PP(args[0]); + bv_str.bv_len = Z_STRLEN_PP(args[0]); + ber = ber_init(&bv_str); + if (ber == NULL) { + efree(args); + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "Unable to allocate enough memory or invalid BER data"); + RETURN_LONG(0); + } + + format=Z_STRVAL_PP(args[1]); + format_length=Z_STRLEN_PP(args[1]); + + pos = 0; + curarg = 2; + while (pos < format_length) { + switch(format[pos]) { + case '{' : + case '}' : + case '[' : + case ']' : + case 'n' : + snprintf (fmt_buf, sizeof(fmt_buf), "%c", format[pos]); + rc = ber_scanf(ber, fmt_buf); + break; + default: + if (curarg >= argc) { + err_msg = "Too few arguments"; + goto ber_scanf_errexit; + } + else { + switch(format[pos]) { + case 'a' : + rc = ber_scanf(ber, "a", &string); + if (rc != LBER_ERROR) { + zval_dtor(*args[curarg]); + ZVAL_STRING(*args[curarg], string, 1); + ber_memfree(string); + curarg++; + } + break; + case 'O' : + rc = ber_scanf(ber, "O", &bv_ptr); + if (rc != LBER_ERROR) { + zval_dtor(*args[curarg]); + ZVAL_STRINGL(*args[curarg], bv_ptr->bv_val, + bv_ptr->bv_len, 1); + ber_bvfree(bv_ptr); + curarg++; + } + break; + case 'b' : + rc = ber_scanf(ber, "b", &int_val); + if (rc != LBER_ERROR) { + zval_dtor(*args[curarg]); + ZVAL_BOOL(*args[curarg], int_val); + curarg++; + } + break; + case 'e' : + case 'i' : + snprintf (fmt_buf, sizeof(fmt_buf), "%c", format[pos]); + rc = ber_scanf(ber, fmt_buf, &int_val); + if (rc != LBER_ERROR) { + zval_dtor(*args[curarg]); + ZVAL_LONG(*args[curarg], int_val); + curarg++; + } + break; + case 'B' : + rc = ber_scanf(ber, "B", &string, &ber_len); + if (rc != LBER_ERROR) { + /* ber_len is in bits, _not_ in bytes, so beware! + */ + zval_dtor(*args[curarg]); + ZVAL_STRINGL(*args[curarg], string, (ber_len+7)/8, 1); + ber_memfree(string); + curarg++; + } + break; + case 't' : + rc = ber_scanf(ber, "t", &tag); + if (rc != LBER_ERROR) { + zval_dtor(*args[curarg]); + ZVAL_LONG(*args[curarg], tag); + curarg++; + } + break; + case 'x' : + rc = ber_scanf(ber, "x"); + break; + case 'v' : + case 'V' : + err_msg = "Unsupported format specifier by now: '%c'"; + goto ber_scanf_errexit; + break; + case 'l' : + case 's' : /* This is an OpenLDAP extension only + * not present on draft-ietf-ldapext-ldap-c-api-*.txt + */ + default: + err_msg = "Unkown format specifier: '%c'"; + goto ber_scanf_errexit; + } + } + } + if (rc == LBER_ERROR) { + err_msg = "Unable to process some values. Check you format string and values"; + goto ber_scanf_errexit; + } + pos++; + } + RETURN_LONG(curarg - 2); + +ber_scanf_errexit: + ber_free(ber,0); + efree(args); + php_error_docref(NULL TSRMLS_CC, E_WARNING, err_msg, format[pos] ); + RETURN_LONG(0); +} +/* }}} */ + + /* {{{ proto resource ldap_first_reference(resource link, resource result) Return first reference */ PHP_FUNCTION(ldap_first_reference) Index: ext/ldap/php_ldap.h =================================================================== RCS file: /repository/php-src/ext/ldap/php_ldap.h,v retrieving revision 1.32.2.1 diff -u -r1.32.2.1 php_ldap.h --- ext/ldap/php_ldap.h 1 Jan 2006 12:50:08 -0000 1.32.2.1 +++ ext/ldap/php_ldap.h 9 Apr 2006 20:40:07 -0000 @@ -56,6 +56,8 @@ PHP_FUNCTION(ldap_get_values); PHP_FUNCTION(ldap_get_values_len); PHP_FUNCTION(ber_free); +PHP_FUNCTION(ldap_ber_printf); +PHP_FUNCTION(ldap_ber_scanf); PHP_FUNCTION(ldap_get_dn); PHP_FUNCTION(ldap_explode_dn); PHP_FUNCTION(ldap_dn2ufn); Index: ext/ldap/ldap.c =================================================================== RCS file: /repository/php-src/ext/ldap/ldap.c,v retrieving revision 1.165 diff -u -r1.165 ldap.c --- ext/ldap/ldap.c 1 Jan 2006 13:09:51 -0000 1.165 +++ ext/ldap/ldap.c 9 Apr 2006 21:15:38 -0000 @@ -80,7 +80,7 @@ ZEND_DECLARE_MODULE_GLOBALS(ldap) static - ZEND_BEGIN_ARG_INFO(arg3to6of6_force_ref, 0) + ZEND_BEGIN_ARG_INFO(arg3to7of7_force_ref, 0) ZEND_ARG_PASS_INFO(0) ZEND_ARG_PASS_INFO(0) ZEND_ARG_PASS_INFO(1) @@ -147,8 +147,10 @@ PHP_FE(ldap_parse_reference, third_arg_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 + PHP_FE(ldap_ber_printf, NULL) + PHP_FE(ldap_ber_scanf, NULL) #ifdef HAVE_LDAP_START_TLS_S PHP_FE(ldap_start_tls, NULL) #endif @@ -1932,18 +1934,19 @@ /* }}} */ #ifdef HAVE_LDAP_PARSE_RESULT -/* {{{ proto bool ldap_parse_result(resource link, resource result, int errcode, string matcheddn, string errmsg, array referrals) +/* {{{ proto bool ldap_parse_result(resource link, resource result, int errcode, string matcheddn, string errmsg, array referrals, array serverctrls) 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; + LDAPControl **lserverctrls, **ctrlp, *ctrl; char **lreferrals, **refp; 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; } @@ -1954,7 +1957,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)); @@ -1966,6 +1969,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); array_init(*referrals); @@ -1999,6 +2025,303 @@ /* }}} */ #endif +/* {{{ proto string ldap_ber_printf(string format [, mixed arg1 [, mixed ...]]) + Creates a BER encoded string of the values/types specified in the format string. Returns the BER encoded string, or 'false' if the enconding failed */ +PHP_FUNCTION(ldap_ber_printf) +{ + zval ***args; + int argc, curarg, rc; + char *format; + char fmt_buf[5], *err_msg; + unsigned int format_length, pos; + BerElement *ber; + struct berval bv_str, *bv_retval; + + argc = ZEND_NUM_ARGS(); + + if (argc < 1) { + WRONG_PARAM_COUNT; + } + + args = (zval ***)safe_emalloc(argc, sizeof(zval *), 0); + + if (zend_get_parameters_array_ex(argc, args) == FAILURE) { + efree(args); + WRONG_PARAM_COUNT; + } + + convert_to_string_ex(args[0]); + format = Z_STRVAL_PP(args[0]); + format_length = Z_STRLEN_PP(args[0]); + + ber = ber_alloc_t(LBER_USE_DER); + if (ber == NULL) { + efree(args); + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to allocate enough memory"); + RETURN_FALSE; + } + + err_msg = NULL; + pos = 0; + curarg = 1; + while (pos < format_length) { + switch(format[pos]) { + case '{' : + case '}' : + case '[' : + case ']' : + case 'n' : + snprintf (fmt_buf, sizeof(fmt_buf), "%c", format[pos]); + rc = ber_printf(ber, fmt_buf); + break; + default: + if (curarg >= argc) { + err_msg = "Too few arguments"; + goto ber_printf_errexit; + } + else { + switch(format[pos]) { + case 'b' : + convert_to_boolean_ex(args[curarg]); + rc = ber_printf(ber, "b", Z_LVAL_PP(args[curarg])); + curarg++; + break; + case 'e' : + case 'i' : + case 't' : + snprintf (fmt_buf, sizeof(fmt_buf), "%c", format[pos]); + convert_to_long_ex(args[curarg]); + rc = ber_printf(ber, fmt_buf, Z_LVAL_PP(args[curarg])); + curarg++; + break; + case 'B' : + convert_to_string_ex(args[curarg]); + rc = ber_printf(ber, "B", Z_STRVAL_PP(args[curarg]), + 8 * Z_STRLEN_PP(args[curarg])); + curarg++; + break; + case 's' : + convert_to_string_ex(args[curarg]); + rc = ber_printf(ber, "s", Z_STRVAL_PP(args[curarg])); + curarg++; + break; + case 'o' : + convert_to_string_ex(args[curarg]); + rc = ber_printf(ber, "o", Z_STRVAL_PP(args[curarg]), + Z_STRLEN_PP(args[curarg])); + curarg++; + break; + case 'O' : + convert_to_string_ex(args[curarg]); + bv_str.bv_val = Z_STRVAL_PP(args[curarg]); + bv_str.bv_len = Z_STRLEN_PP(args[curarg]); + rc = ber_printf(ber, "O", &bv_str); + curarg++; + break; + case 'v' : + case 'V' : + err_msg = "Unsupported format specifier by now: '%c'"; + goto ber_printf_errexit; + break; + case 'W' : /* This is an OpenLDAP extension only + * not present on draft-ietf-ldapext-ldap-c-api-*.txt + */ + default: + err_msg = "Unkown format specifier: '%c'"; + goto ber_printf_errexit; + } /* switch */ + } /* else */ + } /* switch */ + if (rc == -1) { + err_msg = "Unable to process some values. Check you format string and values"; + goto ber_printf_errexit; + } + pos++; + } + + if (ber_flatten (ber, &bv_retval) == -1) { + goto ber_printf_errexit; + } + + RETVAL_STRINGL(bv_retval->bv_val, bv_retval->bv_len, 1); + ber_bvfree(bv_retval); + ber_free(ber,0); + efree(args); + return; + +ber_printf_errexit: + ber_free(ber,0); + efree(args); + php_error_docref(NULL TSRMLS_CC, E_WARNING, err_msg, format[pos] ); + RETURN_FALSE; +} +/* }}} */ + +/* {{{ proto int ldap_ber_scanf(string berval, string format [, mixed arg1 [, mixed ...]]) + The complimentary function to ber_printf */ +PHP_FUNCTION(ldap_ber_scanf) +{ + zval ***args; + int argc, i, curarg, int_val; + char *format, *err_msg, *string; + char fmt_buf[5]; + unsigned int format_length, pos; + BerElement *ber; + ber_tag_t rc, tag; + ber_len_t ber_len; + struct berval bv_str, *bv_ptr; + + + argc = ZEND_NUM_ARGS(); + if (argc < 2) { + WRONG_PARAM_COUNT; + } + + args = (zval ***) safe_emalloc(sizeof(zval **), argc, 0); + if (zend_get_parameters_array_ex(argc, args) == FAILURE) { + efree(args); + WRONG_PARAM_COUNT; + } + + /* If any variables are passed, make sure they are all passed by reference */ + if ((argc - 2) > 0) { + for (i = 2; i < argc; i++){ + if ( ! PZVAL_IS_REF(*args[i])) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "Parameter %d must be passed by reference", i); + RETURN_LONG(0); + } + } + } + + err_msg = NULL; + + convert_to_string_ex(args[0]); + convert_to_string_ex(args[1]); + + bv_str.bv_val = Z_STRVAL_PP(args[0]); + bv_str.bv_len = Z_STRLEN_PP(args[0]); + ber = ber_init(&bv_str); + if (ber == NULL) { + efree(args); + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "Unable to allocate enough memory or invalid BER data"); + RETURN_LONG(0); + } + + format=Z_STRVAL_PP(args[1]); + format_length=Z_STRLEN_PP(args[1]); + + pos = 0; + curarg = 2; + while (pos < format_length) { + switch(format[pos]) { + case '{' : + case '}' : + case '[' : + case ']' : + case 'n' : + snprintf (fmt_buf, sizeof(fmt_buf), "%c", format[pos]); + rc = ber_scanf(ber, fmt_buf); + break; + default: + if (curarg >= argc) { + err_msg = "Too few arguments"; + goto ber_scanf_errexit; + } + else { + switch(format[pos]) { + case 'a' : + rc = ber_scanf(ber, "a", &string); + if (rc != LBER_ERROR) { + zval_dtor(*args[curarg]); + ZVAL_STRING(*args[curarg], string, 1); + ber_memfree(string); + curarg++; + } + break; + case 'O' : + rc = ber_scanf(ber, "O", &bv_ptr); + if (rc != LBER_ERROR) { + zval_dtor(*args[curarg]); + ZVAL_STRINGL(*args[curarg], bv_ptr->bv_val, + bv_ptr->bv_len, 1); + ber_bvfree(bv_ptr); + curarg++; + } + break; + case 'b' : + rc = ber_scanf(ber, "b", &int_val); + if (rc != LBER_ERROR) { + zval_dtor(*args[curarg]); + ZVAL_BOOL(*args[curarg], int_val); + curarg++; + } + break; + case 'e' : + case 'i' : + snprintf (fmt_buf, sizeof(fmt_buf), "%c", format[pos]); + rc = ber_scanf(ber, fmt_buf, &int_val); + if (rc != LBER_ERROR) { + zval_dtor(*args[curarg]); + ZVAL_LONG(*args[curarg], int_val); + curarg++; + } + break; + case 'B' : + rc = ber_scanf(ber, "B", &string, &ber_len); + if (rc != LBER_ERROR) { + /* ber_len is in bits, _not_ in bytes, so beware! + */ + zval_dtor(*args[curarg]); + ZVAL_STRINGL(*args[curarg], string, (ber_len+7)/8, 1); + ber_memfree(string); + curarg++; + } + break; + case 't' : + rc = ber_scanf(ber, "t", &tag); + if (rc != LBER_ERROR) { + zval_dtor(*args[curarg]); + ZVAL_LONG(*args[curarg], tag); + curarg++; + } + break; + case 'x' : + rc = ber_scanf(ber, "x"); + break; + case 'v' : + case 'V' : + err_msg = "Unsupported format specifier by now: '%c'"; + goto ber_scanf_errexit; + break; + case 'l' : + case 's' : /* This is an OpenLDAP extension only + * not present on draft-ietf-ldapext-ldap-c-api-*.txt + */ + default: + err_msg = "Unkown format specifier: '%c'"; + goto ber_scanf_errexit; + } + } + } + if (rc == LBER_ERROR) { + err_msg = "Unable to process some values. Check you format string and values"; + goto ber_scanf_errexit; + } + pos++; + } + RETURN_LONG(curarg - 2); + +ber_scanf_errexit: + ber_free(ber,0); + efree(args); + php_error_docref(NULL TSRMLS_CC, E_WARNING, err_msg, format[pos] ); + RETURN_LONG(0); +} +/* }}} */ + + /* {{{ proto resource ldap_first_reference(resource link, resource result) Return first reference */ PHP_FUNCTION(ldap_first_reference) Index: ext/ldap/php_ldap.h =================================================================== RCS file: /repository/php-src/ext/ldap/php_ldap.h,v retrieving revision 1.33 diff -u -r1.33 php_ldap.h --- ext/ldap/php_ldap.h 1 Jan 2006 13:09:51 -0000 1.33 +++ ext/ldap/php_ldap.h 9 Apr 2006 21:15:39 -0000 @@ -56,6 +56,8 @@ PHP_FUNCTION(ldap_get_values); PHP_FUNCTION(ldap_get_values_len); PHP_FUNCTION(ber_free); +PHP_FUNCTION(ldap_ber_printf); +PHP_FUNCTION(ldap_ber_scanf); PHP_FUNCTION(ldap_get_dn); PHP_FUNCTION(ldap_explode_dn); PHP_FUNCTION(ldap_dn2ufn);

Marcus Börger

20 years ago
Hello Ignacio, first thanks for doing the work and providing the results. but your attachments didn't make it to the list most likely because you used non text/plain encoding or strange file endings. The list only accepts .txt as text/plain. So instead of .diff send .diff.txt and avoid zip or other packed archives. If the patch sets are to big you should provide them online via link. Regarding the branches. There won't be any new features in 4.3, 4.4 or 5.0. In 5.1 there might be additions but we will soon release 5.1.3 and then head towards 5.2 by branching after the release. That said patches are only of interest for 5.1 and HEAD right now. You also spoke of tests. Care to write some .phpt tests? best regards marcus Sunday, April 9, 2006, 11:19:05 PM, you wrote:
> Hi,
> I have modified the ldap module to be able to use Paged Results (see > RFC 2696).
> In order to do that, I have modified ldap_parse_result to provide the > server controls to the user. This is where paged results control > returned from the server are, specifically the cookie value. Without > this value you can't do paged results at all.
> The values returned in this extension control are BER-encoded (see > ITU's X.690 recommendation) so I have created two new functions that > wrap around ber_printf() and ber_scanf(), to allow for the > encodig/decoding of these values.
> I have tested these modifications with W2003 AD and OpenLDAP 2.1.x > servers, using a linux PHP client linked with OpenLDAP libraries (I > don't have access to neither Netscape's nor Oracle's libraries to test > them).
> I have made diffs against current CVS versions as of today, > 2006.04.09, 23:15 CET DST) for PHP_4_3, PHP_4_4, PHP_5_0, PHP_5_1 > and HEAD branches. I'm sending them attached.
> I hope this could be added to the standard version of PHP in the near > future.
> Thanks in advance for your time.
> Saludos. Iñaki.
Best regards, Marcus

Marcus Börger

20 years ago
Hello Ignacio, ups - forget the part with the attachements. I was only looking for attachments and my mailer hid them since they are inlined....still care for writing .phpt tests? best regards marcus Monday, April 10, 2006, 12:51:10 AM, you wrote:

Ignacio Arenaza

20 years ago
Marcus Boerger <helly@php.net> writes:
> Hello Ignacio,
Hello,
> ups - forget the part with the attachements. I was only looking for > attachments and my mailer hid them since they are inlined....still > care for writing .phpt tests?
Ok, I'll code one, althout testing this is configuration intensive on the part of the tester (you need a LDAP server, a binding account, several objects created in the LDAP tree to be able to make queries, need to know the distinguished name of the "root" of the tree you are going to query, etc.). I don't really mind doing it, as I already have all this setup, but I'm not so sure this will be so much useful as a .phpt test for others to use. I'll send you the .phpt test as soon as I have it ready. Saludos. Iñaki.
-- School of Management Mondragon University 20560 Oñati - Spain +34 943 718009 (ext. 225) GPG Key available at public keyservers

Marcus Börger

20 years ago
Hello Ignacio, thanks, i konw about the limitations of course. But i'll try to do my best to get it running on our side to have the ext tested to soem extend et least. best regards marcus Monday, April 10, 2006, 9:42:42 PM, you wrote:
> Marcus Boerger <helly@php.net> writes:
>> Hello Ignacio,
> Hello,
>> ups - forget the part with the attachements. I was only looking for >> attachments and my mailer hid them since they are inlined....still >> care for writing .phpt tests?
> Ok, I'll code one, althout testing this is configuration intensive on > the part of the tester (you need a LDAP server, a binding account, > several objects created in the LDAP tree to be able to make queries, > need to know the distinguished name of the "root" of the tree you are > going to query, etc.).
> I don't really mind doing it, as I already have all this setup, but > I'm not so sure this will be so much useful as a .phpt test for others > to use.
> I'll send you the .phpt test as soon as I have it ready.
> Saludos. Iñaki.
> -- > School of Management > Mondragon University > 20560 Oñati - Spain > +34 943 718009 (ext. 225)
> GPG Key available at public keyservers
Best regards, Marcus

Ignacio Arenaza

20 years ago
Marcus Boerger <helly@php.net> writes:
> thanks, i konw about the limitations of course. But i'll try to do my best > to get it running on our side to have the ext tested to soem extend et > least.
Hello Marcus, it took me longer than expected due to work pressure, but here is a .phpt script to test this patch. I have tested it with MS Active Directory (w2003) and OpenLDAP 2.2.23 on a Debian Sarge Box, and is working perfectly with both of them. I haven't been able to test the patch with neither Netscape's nor Oracle's LDAP libraries, as I don't have access to them. Saludos. Iñaki.
-- School of Management Mondragon University 20560 Oñati - Spain +34 943 718009 (ext. 225) GPG Key available at public keyservers --TEST-- ldap paged results control extension (RFC2606) --SKIPIF-- <?php if (!extension_loaded('ldap')) die("skip no ldap extension"); ?> --FILE-- <?php define ('PAGED_CONTROL_OID', '1.2.840.113556.1.4.319'); define ('PAGE_SIZE', 5); $ldap_host = 'ldap://172.31.3.4'; $ldap_user = 'cn=admin,dc=eteo,dc=edu'; $ldap_pwd = 'ldap-user'; $query = 'dc=eteo,dc=edu'; $query_filter = 'objectClass=*'; $query_attribs = array('cn'); $cookie = ''; $l = ldap_connect($ldap_host); if (!$l) { echo "Not OK: ldap_connect \n"; exit; } if (!ldap_set_option($l, LDAP_OPT_PROTOCOL_VERSION, 3)) { echo "Not OK: ldap_set_option (v3)\n"; exit; } if (!ldap_bind($l, $ldap_user, $ldap_pwd)) { echo "Not OK: ldap_bind\n"; exit; } $continue = true; while ($continue) { $paged_control = array( array( 'oid' => PAGED_CONTROL_OID, 'iscritical' => true, 'value' => ldap_ber_printf ('{iO}', PAGE_SIZE, $cookie) ) ); if (!ldap_set_option($l, LDAP_OPT_SERVER_CONTROLS, $paged_control)) { echo "Not OK: ldap_set_option (controls)\n"; exit; } $sr = ldap_search($l, $query, $query_filter, $query_attribs, 0, 0, 0, LDAP_DEREF_NEVER); if ($sr === FALSE) { echo "Not OK: ldap_search\n"; exit; } if (!ldap_parse_result ($l, $sr, &$errcode, &$matcheddn, &$errmsg, &$referrals, &$serverctrls)) { echo "Not OK: ldap_parse_result\n"; exit; } $paged_control_found = FALSE; if (isset($serverctrls)) { foreach ($serverctrls as $i) { if ($i['oid'] == PAGED_CONTROL_OID) { ldap_ber_scanf($i['value'], '{iO}', &$pagesize, &$cookie); $paged_control_found = TRUE; break; } } } if (!$paged_control_found) { echo "Not OK: paged control not found in response \n"; exit; } if (FALSE === ($num_entries = ldap_count_entries ($l, $sr))) { echo "Not OK: ldap_count_entries\n"; exit; } echo "$num_entries \n"; if ($num_entries > PAGE_SIZE) { echo 'Not OK: received more than '. PAGE_SIZE . " entries\n"; exit; } if (($num_entries != PAGE_SIZE) && ($cookie != '')) { echo 'Not OK: received less than '. PAGE_SIZE . " entries\n"; exit; } if ($cookie == '') { $continue = false; } } echo "OK\n"; ?> --EXPECT OK

Ignacio Arenaza

20 years ago
Marcus Boerger <helly@php.net> writes: Hello again Marcus, forget about the previous email, I forgot to remove a debugging echo statement and the test will always fail. I'm attaching the right test script in this mail. Saludos. Iñaki.
-- School of Management Mondragon University 20560 Oñati - Spain +34 943 718009 (ext. 225) GPG Key available at public keyservers --TEST-- ldap paged results control extension (RFC2606) --SKIPIF-- <?php if (!extension_loaded('ldap')) die("skip no ldap extension"); ?> --FILE-- <?php define ('PAGED_CONTROL_OID', '1.2.840.113556.1.4.319'); define ('PAGE_SIZE', 5); $ldap_host = 'ldap://172.31.3.4'; $ldap_user = 'cn=admin,dc=eteo,dc=edu'; $ldap_pwd = 'ldap-user'; $query = 'dc=eteo,dc=edu'; $query_filter = 'objectClass=*'; $query_attribs = array('cn'); $cookie = ''; $l = ldap_connect($ldap_host); if (!$l) { echo "Not OK: ldap_connect \n"; exit; } if (!ldap_set_option($l, LDAP_OPT_PROTOCOL_VERSION, 3)) { echo "Not OK: ldap_set_option (v3)\n"; exit; } if (!ldap_bind($l, $ldap_user, $ldap_pwd)) { echo "Not OK: ldap_bind\n"; exit; } $continue = true; while ($continue) { $paged_control = array( array( 'oid' => PAGED_CONTROL_OID, 'iscritical' => true, 'value' => ldap_ber_printf ('{iO}', PAGE_SIZE, $cookie) ) ); if (!ldap_set_option($l, LDAP_OPT_SERVER_CONTROLS, $paged_control)) { echo "Not OK: ldap_set_option (controls)\n"; exit; } $sr = ldap_search($l, $query, $query_filter, $query_attribs, 0, 0, 0, LDAP_DEREF_NEVER); if ($sr === FALSE) { echo "Not OK: ldap_search\n"; exit; } if (!ldap_parse_result ($l, $sr, &$errcode, &$matcheddn, &$errmsg, &$referrals, &$serverctrls)) { echo "Not OK: ldap_parse_result\n"; exit; } $paged_control_found = FALSE; if (isset($serverctrls)) { foreach ($serverctrls as $i) { if ($i['oid'] == PAGED_CONTROL_OID) { ldap_ber_scanf($i['value'], '{iO}', &$pagesize, &$cookie); $paged_control_found = TRUE; break; } } } if (!$paged_control_found) { echo "Not OK: paged control not found in response \n"; exit; } if (FALSE === ($num_entries = ldap_count_entries ($l, $sr))) { echo "Not OK: ldap_count_entries\n"; exit; } if ($num_entries > PAGE_SIZE) { echo 'Not OK: received more than '. PAGE_SIZE . " entries\n"; exit; } if (($num_entries != PAGE_SIZE) && ($cookie != '')) { echo 'Not OK: received less than '. PAGE_SIZE . " entries\n"; exit; } if ($cookie == '') { $continue = false; } } echo "OK\n"; ?> --EXPECT OK

Marcus Börger

20 years ago
Hello Ignacio, thanks for your efforts so far. What the test is missing now is that skipif doesn't detect whether an ldap server can be connected after all, just like the database test's skipif try to connect the database. Maybe you need some settings, prefereable in environment variables for that. Anyway skipif should prevent the test from running when there is no setup to test against. As soon as i have that addition i can test it on our gcov machine and commit the test. best regards marcus Friday, April 28, 2006, 3:56:35 PM, you wrote:
> Marcus Boerger <helly@php.net> writes:
> Hello again Marcus,
> forget about the previous email, I forgot to remove a debugging echo > statement and the test will always fail.
> I'm attaching the right test script in this mail.
> Saludos. Iñaki.
Best regards, Marcus

Ignacio Arenaza

20 years ago
Marcus Boerger <helly@php.net> writes: [ I'm resending this, as I haven't seen it ] [ in the internals list :-? ]
> thanks for your efforts so far. What the test is missing now is that > skipif doesn't detect whether an ldap server can be connected after all, > just like the database test's skipif try to connect the database. Maybe > you need some settings, prefereable in environment variables for that. > Anyway skipif should prevent the test from running when there is no > setup to test against. As soon as i have that addition i can test it > on our gcov machine and commit the test.
Ok, here it is a second cut at it. I hope this is what you are looking for. Saludos. Iñaki.
-- School of Management Mondragon University 20560 Oñati - Spain +34 943 718009 (ext. 225) GPG Key available at public keyservers <?php /* Change the values to reflect your LDAP environment */ $ldap_host = '127.0.0.1'; $ldap_user = 'cn=ldap-user,dc=my,dc=domain,dc=com'; $ldap_password = 'ldap-user'; ?> <?php /* Change the values to reflect your LDAP environment */ $query_base_dn = 'dc=my,dc=domain,dc=com'; $query_filter = 'objectClass=*'; $query_attribs = array('cn'); ?> <?php if (!extension_loaded('ldap')) { die ("skip no ldap extension\n"); } include ('connect.inc'); $link = @ldap_connect ($ldap_host); if (!$link) { die ("skip cannot connect\n"); } if (!@ldap_set_option ($link, LDAP_OPT_PROTOCOL_VERSION, 3)) { die ("skip cannot set LDAP protocol version to 3\n"); } if (!@ldap_bind ($link, $ldap_user, $ldap_password)) { die ("skip cannot bind\n"); } @ldap_close ($link); ?> --TEST-- ldap paged results control extension (RFC2606) --SKIPIF-- <?php include('skipif.inc'); ?> --FILE-- <?php define ('PAGED_CONTROL_OID', '1.2.840.113556.1.4.319'); define ('PAGE_SIZE', 5); include ('query.inc'); $cookie = ''; $link = ldap_connect ($ldap_host); if (!$link) { exit ("Not OK: ldap_connect\n"); } if (!ldap_set_option ($link, LDAP_OPT_PROTOCOL_VERSION, 3)) { exit ("Not OK: ldap_set_option (v3)\n"); } if (!ldap_bind ($link, $ldap_user, $ldap_password)) { exit ("Not OK: ldap_bind\n"); } $continue = true; while ($continue) { $paged_control = array( array( 'oid' => PAGED_CONTROL_OID, 'iscritical' => true, 'value' => ldap_ber_printf ('{iO}', PAGE_SIZE, $cookie) ) ); if (!@ldap_set_option ($link, LDAP_OPT_SERVER_CONTROLS, $paged_control)) { exit ("Not OK: ldap_set_option (controls)\n"); } $sr = @ldap_search ($link, $query_base_dn, $query_filter, $query_attribs, 0, 0, 0, LDAP_DEREF_NEVER); if ($sr === FALSE) { exit ("Not OK: ldap_search\n"); exit; } if (!@ldap_parse_result ($link, $sr, &$errcode, &$matcheddn, &$errmsg, &$referrals, &$serverctrls)) { exit ("Not OK: ldap_parse_result\n"); exit; } $paged_control_found = FALSE; if (isset($serverctrls)) { foreach ($serverctrls as $i) { if ($i['oid'] == PAGED_CONTROL_OID) { ldap_ber_scanf ($i['value'], '{iO}', &$pagesize, &$cookie); $paged_control_found = TRUE; break; } } } if (!$paged_control_found) { exit ("Not OK: paged control not found in response \n"); exit; } if (FALSE === ($num_entries = @ldap_count_entries ($link, $sr))) { exit ("Not OK: ldap_count_entries\n"); exit; } if ($num_entries > PAGE_SIZE) { exit ('Not OK: received more than '. PAGE_SIZE . " entries\n"); exit; } if (($num_entries != PAGE_SIZE) && ($cookie != '')) { exit ('Not OK: received less than '. PAGE_SIZE . " entries\n"); exit; } if ($cookie == '') { $continue = false; } } exit ("OK\n"); ?> --EXPECT OK

Marcus Börger

20 years ago
Hello Ignacio, thanks again - now i only need time to bring it on the testing server and once it is running there i'll commit. Maybe Nuno can do it earlier as he is working on the gcov testing server anyway with the SoC student? best regards marcus Tuesday, May 9, 2006, 7:04:37 PM, you wrote:
> Marcus Boerger <helly@php.net> writes:
> [ I'm resending this, as I haven't seen it ] > [ in the internals list :-? ]
>> thanks for your efforts so far. What the test is missing now is that >> skipif doesn't detect whether an ldap server can be connected after all, >> just like the database test's skipif try to connect the database. Maybe >> you need some settings, prefereable in environment variables for that. >> Anyway skipif should prevent the test from running when there is no >> setup to test against. As soon as i have that addition i can test it >> on our gcov machine and commit the test.
> Ok, here it is a second cut at it. I hope this is what you are looking > for.
> Saludos. Iñaki.
Best regards, Marcus