Annotation of embedaddon/php/ext/ldap/ldap.c, revision 1.1.1.4
1.1 misho 1: /*
2: +----------------------------------------------------------------------+
3: | PHP Version 5 |
4: +----------------------------------------------------------------------+
1.1.1.4 ! misho 5: | Copyright (c) 1997-2014 The PHP Group |
1.1 misho 6: +----------------------------------------------------------------------+
7: | This source file is subject to version 3.01 of the PHP license, |
8: | that is bundled with this package in the file LICENSE, and is |
9: | available through the world-wide-web at the following url: |
10: | http://www.php.net/license/3_01.txt |
11: | If you did not receive a copy of the PHP license and are unable to |
12: | obtain it through the world-wide-web, please send a note to |
13: | license@php.net so we can mail you a copy immediately. |
14: +----------------------------------------------------------------------+
15: | Authors: Amitay Isaacs <amitay@w-o-i.com> |
16: | Eric Warnke <ericw@albany.edu> |
17: | Rasmus Lerdorf <rasmus@php.net> |
18: | Gerrit Thomson <334647@swin.edu.au> |
19: | Jani Taskinen <sniper@iki.fi> |
20: | Stig Venaas <venaas@uninett.no> |
21: | Doug Goldstein <cardoe@cardoe.com> |
22: | PHP 4.0 updates: Zeev Suraski <zeev@zend.com> |
23: +----------------------------------------------------------------------+
24: */
25:
1.1.1.2 misho 26: /* $Id$ */
1.1 misho 27: #define IS_EXT_MODULE
28:
29: #ifdef HAVE_CONFIG_H
30: #include "config.h"
31: #endif
32:
33: /* Additional headers for NetWare */
34: #if defined(NETWARE) && (NEW_LIBC)
35: #include <sys/select.h>
36: #include <sys/timeval.h>
37: #endif
38:
39: #include "php.h"
40: #include "php_ini.h"
41:
42: #include <stddef.h>
43:
44: #include "ext/standard/dl.h"
45: #include "php_ldap.h"
46:
47: #ifdef PHP_WIN32
48: #include <string.h>
49: #include "config.w32.h"
50: #if HAVE_NSLDAP
51: #include <winsock2.h>
52: #endif
53: #define strdup _strdup
54: #undef WINDOWS
55: #undef strcasecmp
56: #undef strncasecmp
57: #define WINSOCK 1
58: #define __STDC__ 1
59: #endif
60:
61: #include "ext/standard/php_string.h"
62: #include "ext/standard/info.h"
63:
64: #ifdef HAVE_LDAP_SASL_H
65: #include <sasl.h>
66: #elif defined(HAVE_LDAP_SASL_SASL_H)
67: #include <sasl/sasl.h>
68: #endif
69:
70: typedef struct {
71: LDAP *link;
72: #if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC)
73: zval *rebindproc;
74: #endif
75: } ldap_linkdata;
76:
77: typedef struct {
78: LDAPMessage *data;
79: BerElement *ber;
80: int id;
81: } ldap_resultentry;
82:
83: ZEND_DECLARE_MODULE_GLOBALS(ldap)
84: static PHP_GINIT_FUNCTION(ldap);
85:
86: static int le_link, le_result, le_result_entry;
87:
88: #ifdef COMPILE_DL_LDAP
89: ZEND_GET_MODULE(ldap)
90: #endif
91:
92: static void _close_ldap_link(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
93: {
94: ldap_linkdata *ld = (ldap_linkdata *)rsrc->ptr;
95:
96: ldap_unbind_s(ld->link);
97: #if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC)
98: if (ld->rebindproc != NULL) {
99: zval_dtor(ld->rebindproc);
100: FREE_ZVAL(ld->rebindproc);
101: }
102: #endif
103: efree(ld);
104: LDAPG(num_links)--;
105: }
106: /* }}} */
107:
108: static void _free_ldap_result(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
109: {
110: LDAPMessage *result = (LDAPMessage *)rsrc->ptr;
111: ldap_msgfree(result);
112: }
113: /* }}} */
114:
115: static void _free_ldap_result_entry(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
116: {
117: ldap_resultentry *entry = (ldap_resultentry *)rsrc->ptr;
118:
119: if (entry->ber != NULL) {
120: ber_free(entry->ber, 0);
121: entry->ber = NULL;
122: }
123: zend_list_delete(entry->id);
124: efree(entry);
125: }
126: /* }}} */
127:
128: /* {{{ PHP_INI_BEGIN
129: */
130: PHP_INI_BEGIN()
131: STD_PHP_INI_ENTRY_EX("ldap.max_links", "-1", PHP_INI_SYSTEM, OnUpdateLong, max_links, zend_ldap_globals, ldap_globals, display_link_numbers)
132: PHP_INI_END()
133: /* }}} */
134:
135: /* {{{ PHP_GINIT_FUNCTION
136: */
137: static PHP_GINIT_FUNCTION(ldap)
138: {
139: ldap_globals->num_links = 0;
140: }
141: /* }}} */
142:
143: /* {{{ PHP_MINIT_FUNCTION
144: */
145: PHP_MINIT_FUNCTION(ldap)
146: {
147: REGISTER_INI_ENTRIES();
148:
149: /* Constants to be used with deref-parameter in php_ldap_do_search() */
150: REGISTER_LONG_CONSTANT("LDAP_DEREF_NEVER", LDAP_DEREF_NEVER, CONST_PERSISTENT | CONST_CS);
151: REGISTER_LONG_CONSTANT("LDAP_DEREF_SEARCHING", LDAP_DEREF_SEARCHING, CONST_PERSISTENT | CONST_CS);
152: REGISTER_LONG_CONSTANT("LDAP_DEREF_FINDING", LDAP_DEREF_FINDING, CONST_PERSISTENT | CONST_CS);
153: REGISTER_LONG_CONSTANT("LDAP_DEREF_ALWAYS", LDAP_DEREF_ALWAYS, CONST_PERSISTENT | CONST_CS);
154:
1.1.1.4 ! misho 155: /* Constants to be used with ldap_modify_batch() */
! 156: REGISTER_LONG_CONSTANT("LDAP_MODIFY_BATCH_ADD", LDAP_MODIFY_BATCH_ADD, CONST_PERSISTENT | CONST_CS);
! 157: REGISTER_LONG_CONSTANT("LDAP_MODIFY_BATCH_REMOVE", LDAP_MODIFY_BATCH_REMOVE, CONST_PERSISTENT | CONST_CS);
! 158: REGISTER_LONG_CONSTANT("LDAP_MODIFY_BATCH_REMOVE_ALL", LDAP_MODIFY_BATCH_REMOVE_ALL, CONST_PERSISTENT | CONST_CS);
! 159: REGISTER_LONG_CONSTANT("LDAP_MODIFY_BATCH_REPLACE", LDAP_MODIFY_BATCH_REPLACE, CONST_PERSISTENT | CONST_CS);
! 160: REGISTER_STRING_CONSTANT("LDAP_MODIFY_BATCH_ATTRIB", LDAP_MODIFY_BATCH_ATTRIB, CONST_PERSISTENT | CONST_CS);
! 161: REGISTER_STRING_CONSTANT("LDAP_MODIFY_BATCH_MODTYPE", LDAP_MODIFY_BATCH_MODTYPE, CONST_PERSISTENT | CONST_CS);
! 162: REGISTER_STRING_CONSTANT("LDAP_MODIFY_BATCH_VALUES", LDAP_MODIFY_BATCH_VALUES, CONST_PERSISTENT | CONST_CS);
! 163:
1.1 misho 164: #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10
165: /* LDAP options */
166: REGISTER_LONG_CONSTANT("LDAP_OPT_DEREF", LDAP_OPT_DEREF, CONST_PERSISTENT | CONST_CS);
167: REGISTER_LONG_CONSTANT("LDAP_OPT_SIZELIMIT", LDAP_OPT_SIZELIMIT, CONST_PERSISTENT | CONST_CS);
168: REGISTER_LONG_CONSTANT("LDAP_OPT_TIMELIMIT", LDAP_OPT_TIMELIMIT, CONST_PERSISTENT | CONST_CS);
169: #ifdef LDAP_OPT_NETWORK_TIMEOUT
170: REGISTER_LONG_CONSTANT("LDAP_OPT_NETWORK_TIMEOUT", LDAP_OPT_NETWORK_TIMEOUT, CONST_PERSISTENT | CONST_CS);
171: #elif defined (LDAP_X_OPT_CONNECT_TIMEOUT)
172: REGISTER_LONG_CONSTANT("LDAP_OPT_NETWORK_TIMEOUT", LDAP_X_OPT_CONNECT_TIMEOUT, CONST_PERSISTENT | CONST_CS);
173: #endif
174: REGISTER_LONG_CONSTANT("LDAP_OPT_PROTOCOL_VERSION", LDAP_OPT_PROTOCOL_VERSION, CONST_PERSISTENT | CONST_CS);
175: REGISTER_LONG_CONSTANT("LDAP_OPT_ERROR_NUMBER", LDAP_OPT_ERROR_NUMBER, CONST_PERSISTENT | CONST_CS);
176: REGISTER_LONG_CONSTANT("LDAP_OPT_REFERRALS", LDAP_OPT_REFERRALS, CONST_PERSISTENT | CONST_CS);
177: #ifdef LDAP_OPT_RESTART
178: REGISTER_LONG_CONSTANT("LDAP_OPT_RESTART", LDAP_OPT_RESTART, CONST_PERSISTENT | CONST_CS);
179: #endif
180: #ifdef LDAP_OPT_HOST_NAME
181: REGISTER_LONG_CONSTANT("LDAP_OPT_HOST_NAME", LDAP_OPT_HOST_NAME, CONST_PERSISTENT | CONST_CS);
182: #endif
183: REGISTER_LONG_CONSTANT("LDAP_OPT_ERROR_STRING", LDAP_OPT_ERROR_STRING, CONST_PERSISTENT | CONST_CS);
184: #ifdef LDAP_OPT_MATCHED_DN
185: REGISTER_LONG_CONSTANT("LDAP_OPT_MATCHED_DN", LDAP_OPT_MATCHED_DN, CONST_PERSISTENT | CONST_CS);
186: #endif
187: REGISTER_LONG_CONSTANT("LDAP_OPT_SERVER_CONTROLS", LDAP_OPT_SERVER_CONTROLS, CONST_PERSISTENT | CONST_CS);
188: REGISTER_LONG_CONSTANT("LDAP_OPT_CLIENT_CONTROLS", LDAP_OPT_CLIENT_CONTROLS, CONST_PERSISTENT | CONST_CS);
189: #endif
190: #ifdef LDAP_OPT_DEBUG_LEVEL
191: REGISTER_LONG_CONSTANT("LDAP_OPT_DEBUG_LEVEL", LDAP_OPT_DEBUG_LEVEL, CONST_PERSISTENT | CONST_CS);
192: #endif
193:
194: #ifdef HAVE_LDAP_SASL
195: REGISTER_LONG_CONSTANT("LDAP_OPT_X_SASL_MECH", LDAP_OPT_X_SASL_MECH, CONST_PERSISTENT | CONST_CS);
196: REGISTER_LONG_CONSTANT("LDAP_OPT_X_SASL_REALM", LDAP_OPT_X_SASL_REALM, CONST_PERSISTENT | CONST_CS);
197: REGISTER_LONG_CONSTANT("LDAP_OPT_X_SASL_AUTHCID", LDAP_OPT_X_SASL_AUTHCID, CONST_PERSISTENT | CONST_CS);
198: REGISTER_LONG_CONSTANT("LDAP_OPT_X_SASL_AUTHZID", LDAP_OPT_X_SASL_AUTHZID, CONST_PERSISTENT | CONST_CS);
199: #endif
200:
201: #ifdef ORALDAP
202: REGISTER_LONG_CONSTANT("GSLC_SSL_NO_AUTH", GSLC_SSL_NO_AUTH, CONST_PERSISTENT | CONST_CS);
203: REGISTER_LONG_CONSTANT("GSLC_SSL_ONEWAY_AUTH", GSLC_SSL_ONEWAY_AUTH, CONST_PERSISTENT | CONST_CS);
204: REGISTER_LONG_CONSTANT("GSLC_SSL_TWOWAY_AUTH", GSLC_SSL_TWOWAY_AUTH, CONST_PERSISTENT | CONST_CS);
205: #endif
206:
207: le_link = zend_register_list_destructors_ex(_close_ldap_link, NULL, "ldap link", module_number);
208: le_result = zend_register_list_destructors_ex(_free_ldap_result, NULL, "ldap result", module_number);
209: le_result_entry = zend_register_list_destructors_ex(_free_ldap_result_entry, NULL, "ldap result entry", module_number);
210:
211: Z_TYPE(ldap_module_entry) = type;
212:
213: return SUCCESS;
214: }
215: /* }}} */
216:
217: /* {{{ PHP_MSHUTDOWN_FUNCTION
218: */
219: PHP_MSHUTDOWN_FUNCTION(ldap)
220: {
221: UNREGISTER_INI_ENTRIES();
222: return SUCCESS;
223: }
224: /* }}} */
225:
226: /* {{{ PHP_MINFO_FUNCTION
227: */
228: PHP_MINFO_FUNCTION(ldap)
229: {
230: char tmp[32];
231: #if HAVE_NSLDAP
232: LDAPVersion ver;
233: double SDKVersion;
234: #endif
235:
236: php_info_print_table_start();
237: php_info_print_table_row(2, "LDAP Support", "enabled");
1.1.1.2 misho 238: php_info_print_table_row(2, "RCS Version", "$Id$");
1.1 misho 239:
240: if (LDAPG(max_links) == -1) {
241: snprintf(tmp, 31, "%ld/unlimited", LDAPG(num_links));
242: } else {
243: snprintf(tmp, 31, "%ld/%ld", LDAPG(num_links), LDAPG(max_links));
244: }
245: php_info_print_table_row(2, "Total Links", tmp);
246:
247: #ifdef LDAP_API_VERSION
248: snprintf(tmp, 31, "%d", LDAP_API_VERSION);
249: php_info_print_table_row(2, "API Version", tmp);
250: #endif
251:
252: #ifdef LDAP_VENDOR_NAME
253: php_info_print_table_row(2, "Vendor Name", LDAP_VENDOR_NAME);
254: #endif
255:
256: #ifdef LDAP_VENDOR_VERSION
257: snprintf(tmp, 31, "%d", LDAP_VENDOR_VERSION);
258: php_info_print_table_row(2, "Vendor Version", tmp);
259: #endif
260:
261: #if HAVE_NSLDAP
262: SDKVersion = ldap_version(&ver);
263: snprintf(tmp, 31, "%F", SDKVersion/100.0);
264: php_info_print_table_row(2, "SDK Version", tmp);
265:
266: snprintf(tmp, 31, "%F", ver.protocol_version/100.0);
267: php_info_print_table_row(2, "Highest LDAP Protocol Supported", tmp);
268:
269: snprintf(tmp, 31, "%F", ver.SSL_version/100.0);
270: php_info_print_table_row(2, "SSL Level Supported", tmp);
271:
272: if (ver.security_level != LDAP_SECURITY_NONE) {
273: snprintf(tmp, 31, "%d", ver.security_level);
274: } else {
275: strcpy(tmp, "SSL not enabled");
276: }
277: php_info_print_table_row(2, "Level of Encryption", tmp);
278: #endif
279:
280: #ifdef HAVE_LDAP_SASL
281: php_info_print_table_row(2, "SASL Support", "Enabled");
282: #endif
283:
284: php_info_print_table_end();
285: DISPLAY_INI_ENTRIES();
286: }
287: /* }}} */
288:
289: /* {{{ proto resource ldap_connect([string host [, int port [, string wallet [, string wallet_passwd [, int authmode]]]]])
290: Connect to an LDAP server */
291: PHP_FUNCTION(ldap_connect)
292: {
293: char *host = NULL;
294: int hostlen;
295: long port = 389; /* Default port */
296: #ifdef HAVE_ORALDAP
297: char *wallet = NULL, *walletpasswd = NULL;
298: int walletlen = 0, walletpasswdlen = 0;
299: long authmode = GSLC_SSL_NO_AUTH;
300: int ssl=0;
301: #endif
302: ldap_linkdata *ld;
303: LDAP *ldap;
304:
305: #ifdef HAVE_ORALDAP
306: if (ZEND_NUM_ARGS() == 3 || ZEND_NUM_ARGS() == 4) {
307: WRONG_PARAM_COUNT;
308: }
309:
310: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|slssl", &host, &hostlen, &port, &wallet, &walletlen, &walletpasswd, &walletpasswdlen, &authmode) != SUCCESS) {
311: RETURN_FALSE;
312: }
313:
314: if (ZEND_NUM_ARGS() == 5) {
315: ssl = 1;
316: }
317: #else
318: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sl", &host, &hostlen, &port) != SUCCESS) {
319: RETURN_FALSE;
320: }
321: #endif
322:
323: if (LDAPG(max_links) != -1 && LDAPG(num_links) >= LDAPG(max_links)) {
324: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Too many open links (%ld)", LDAPG(num_links));
325: RETURN_FALSE;
326: }
327:
328: ld = ecalloc(1, sizeof(ldap_linkdata));
329:
330: #ifdef LDAP_API_FEATURE_X_OPENLDAP
331: if (host != NULL && strchr(host, '/')) {
332: int rc;
333:
334: rc = ldap_initialize(&ldap, host);
335: if (rc != LDAP_SUCCESS) {
336: efree(ld);
337: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not create session handle: %s", ldap_err2string(rc));
338: RETURN_FALSE;
339: }
340: } else {
341: ldap = ldap_init(host, port);
342: }
343: #else
344: ldap = ldap_open(host, port);
345: #endif
346:
347: if (ldap == NULL) {
348: efree(ld);
349: RETURN_FALSE;
350: } else {
351: #ifdef HAVE_ORALDAP
352: if (ssl) {
353: if (ldap_init_SSL(&ldap->ld_sb, wallet, walletpasswd, authmode)) {
354: efree(ld);
355: php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSL init failed");
356: RETURN_FALSE;
357: }
358: }
359: #endif
360: LDAPG(num_links)++;
361: ld->link = ldap;
362: ZEND_REGISTER_RESOURCE(return_value, ld, le_link);
363: }
364:
365: }
366: /* }}} */
367:
368: /* {{{ _get_lderrno
369: */
370: static int _get_lderrno(LDAP *ldap)
371: {
372: #if !HAVE_NSLDAP
373: #if LDAP_API_VERSION > 2000 || HAVE_ORALDAP_10
374: int lderr;
375:
376: /* New versions of OpenLDAP do it this way */
377: ldap_get_option(ldap, LDAP_OPT_ERROR_NUMBER, &lderr);
378: return lderr;
379: #else
380: return ldap->ld_errno;
381: #endif
382: #else
383: return ldap_get_lderrno(ldap, NULL, NULL);
384: #endif
385: }
386: /* }}} */
387:
388: /* {{{ proto bool ldap_bind(resource link [, string dn [, string password]])
389: Bind to LDAP directory */
390: PHP_FUNCTION(ldap_bind)
391: {
392: zval *link;
393: char *ldap_bind_dn = NULL, *ldap_bind_pw = NULL;
394: int ldap_bind_dnlen, ldap_bind_pwlen;
395: ldap_linkdata *ld;
396: int rc;
397:
398: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|ss", &link, &ldap_bind_dn, &ldap_bind_dnlen, &ldap_bind_pw, &ldap_bind_pwlen) != SUCCESS) {
399: RETURN_FALSE;
400: }
401:
1.1.1.4 ! misho 402: if (ldap_bind_dn != NULL && memchr(ldap_bind_dn, '\0', ldap_bind_dnlen) != NULL) {
! 403: php_error_docref(NULL TSRMLS_CC, E_WARNING, "DN contains a null byte");
! 404: RETURN_FALSE;
! 405: }
! 406:
! 407: if (ldap_bind_pw != NULL && memchr(ldap_bind_pw, '\0', ldap_bind_pwlen) != NULL) {
! 408: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Password contains a null byte");
! 409: RETURN_FALSE;
! 410: }
! 411:
1.1 misho 412: ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
413:
414: if ((rc = ldap_bind_s(ld->link, ldap_bind_dn, ldap_bind_pw, LDAP_AUTH_SIMPLE)) != LDAP_SUCCESS) {
415: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to bind to server: %s", ldap_err2string(rc));
416: RETURN_FALSE;
417: } else {
418: RETURN_TRUE;
419: }
420: }
421: /* }}} */
422:
423: #ifdef HAVE_LDAP_SASL
424: typedef struct {
425: char *mech;
426: char *realm;
427: char *authcid;
428: char *passwd;
429: char *authzid;
430: } php_ldap_bictx;
431:
432: /* {{{ _php_sasl_setdefs
433: */
434: static php_ldap_bictx *_php_sasl_setdefs(LDAP *ld, char *sasl_mech, char *sasl_realm, char *sasl_authc_id, char *passwd, char *sasl_authz_id)
435: {
436: php_ldap_bictx *ctx;
437:
438: ctx = ber_memalloc(sizeof(php_ldap_bictx));
439: ctx->mech = (sasl_mech) ? ber_strdup(sasl_mech) : NULL;
440: ctx->realm = (sasl_realm) ? ber_strdup(sasl_realm) : NULL;
441: ctx->authcid = (sasl_authc_id) ? ber_strdup(sasl_authc_id) : NULL;
442: ctx->passwd = (passwd) ? ber_strdup(passwd) : NULL;
443: ctx->authzid = (sasl_authz_id) ? ber_strdup(sasl_authz_id) : NULL;
444:
445: if (ctx->mech == NULL) {
446: ldap_get_option(ld, LDAP_OPT_X_SASL_MECH, &ctx->mech);
447: }
448: if (ctx->realm == NULL) {
449: ldap_get_option(ld, LDAP_OPT_X_SASL_REALM, &ctx->realm);
450: }
451: if (ctx->authcid == NULL) {
452: ldap_get_option(ld, LDAP_OPT_X_SASL_AUTHCID, &ctx->authcid);
453: }
454: if (ctx->authzid == NULL) {
455: ldap_get_option(ld, LDAP_OPT_X_SASL_AUTHZID, &ctx->authzid);
456: }
457:
458: return ctx;
459: }
460: /* }}} */
461:
462: /* {{{ _php_sasl_freedefs
463: */
464: static void _php_sasl_freedefs(php_ldap_bictx *ctx)
465: {
466: if (ctx->mech) ber_memfree(ctx->mech);
467: if (ctx->realm) ber_memfree(ctx->realm);
468: if (ctx->authcid) ber_memfree(ctx->authcid);
469: if (ctx->passwd) ber_memfree(ctx->passwd);
470: if (ctx->authzid) ber_memfree(ctx->authzid);
471: ber_memfree(ctx);
472: }
473: /* }}} */
474:
475: /* {{{ _php_sasl_interact
476: Internal interact function for SASL */
477: static int _php_sasl_interact(LDAP *ld, unsigned flags, void *defaults, void *in)
478: {
479: sasl_interact_t *interact = in;
480: const char *p;
481: php_ldap_bictx *ctx = defaults;
482:
483: for (;interact->id != SASL_CB_LIST_END;interact++) {
484: p = NULL;
485: switch(interact->id) {
486: case SASL_CB_GETREALM:
487: p = ctx->realm;
488: break;
489: case SASL_CB_AUTHNAME:
490: p = ctx->authcid;
491: break;
492: case SASL_CB_USER:
493: p = ctx->authzid;
494: break;
495: case SASL_CB_PASS:
496: p = ctx->passwd;
497: break;
498: }
499: if (p) {
500: interact->result = p;
501: interact->len = strlen(interact->result);
502: }
503: }
504: return LDAP_SUCCESS;
505: }
506: /* }}} */
507:
508: /* {{{ proto bool ldap_sasl_bind(resource link [, string binddn [, string password [, string sasl_mech [, string sasl_realm [, string sasl_authc_id [, string sasl_authz_id [, string props]]]]]]])
509: Bind to LDAP directory using SASL */
510: PHP_FUNCTION(ldap_sasl_bind)
511: {
512: zval *link;
513: ldap_linkdata *ld;
514: char *binddn = NULL;
515: char *passwd = NULL;
516: char *sasl_mech = NULL;
517: char *sasl_realm = NULL;
518: char *sasl_authz_id = NULL;
519: char *sasl_authc_id = NULL;
520: char *props = NULL;
521: int rc, dn_len, passwd_len, mech_len, realm_len, authc_id_len, authz_id_len, props_len;
522: php_ldap_bictx *ctx;
523:
524: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|sssssss", &link, &binddn, &dn_len, &passwd, &passwd_len, &sasl_mech, &mech_len, &sasl_realm, &realm_len, &sasl_authc_id, &authc_id_len, &sasl_authz_id, &authz_id_len, &props, &props_len) != SUCCESS) {
525: RETURN_FALSE;
526: }
527:
528: ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
529:
530: ctx = _php_sasl_setdefs(ld->link, sasl_mech, sasl_realm, sasl_authc_id, passwd, sasl_authz_id);
531:
532: if (props) {
533: ldap_set_option(ld->link, LDAP_OPT_X_SASL_SECPROPS, props);
534: }
535:
536: rc = ldap_sasl_interactive_bind_s(ld->link, binddn, ctx->mech, NULL, NULL, LDAP_SASL_QUIET, _php_sasl_interact, ctx);
537: if (rc != LDAP_SUCCESS) {
538: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to bind to server: %s", ldap_err2string(rc));
539: RETVAL_FALSE;
540: } else {
541: RETVAL_TRUE;
542: }
543: _php_sasl_freedefs(ctx);
544: }
545: /* }}} */
546: #endif /* HAVE_LDAP_SASL */
547:
548: /* {{{ proto bool ldap_unbind(resource link)
549: Unbind from LDAP directory */
550: PHP_FUNCTION(ldap_unbind)
551: {
552: zval *link;
553: ldap_linkdata *ld;
554:
555: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &link) != SUCCESS) {
556: RETURN_FALSE;
557: }
558:
559: ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
560:
561: zend_list_delete(Z_LVAL_P(link));
562: RETURN_TRUE;
563: }
564: /* }}} */
565:
566: /* {{{ php_set_opts
567: */
568: static void php_set_opts(LDAP *ldap, int sizelimit, int timelimit, int deref, int *old_sizelimit, int *old_timelimit, int *old_deref)
569: {
570: /* sizelimit */
571: if (sizelimit > -1) {
572: #if (LDAP_API_VERSION >= 2004) || HAVE_NSLDAP || HAVE_ORALDAP_10
573: ldap_get_option(ldap, LDAP_OPT_SIZELIMIT, old_sizelimit);
574: ldap_set_option(ldap, LDAP_OPT_SIZELIMIT, &sizelimit);
575: #else
576: *old_sizelimit = ldap->ld_sizelimit;
577: ldap->ld_sizelimit = sizelimit;
578: #endif
579: }
580:
581: /* timelimit */
582: if (timelimit > -1) {
583: #if (LDAP_API_VERSION >= 2004) || HAVE_NSLDAP || HAVE_ORALDAP_10
584: ldap_get_option(ldap, LDAP_OPT_SIZELIMIT, old_timelimit);
585: ldap_set_option(ldap, LDAP_OPT_TIMELIMIT, &timelimit);
586: #else
587: *old_timelimit = ldap->ld_timelimit;
588: ldap->ld_timelimit = timelimit;
589: #endif
590: }
591:
592: /* deref */
593: if (deref > -1) {
594: #if (LDAP_API_VERSION >= 2004) || HAVE_NSLDAP || HAVE_ORALDAP_10
595: ldap_get_option(ldap, LDAP_OPT_SIZELIMIT, old_deref);
596: ldap_set_option(ldap, LDAP_OPT_DEREF, &deref);
597: #else
598: *old_deref = ldap->ld_deref;
599: ldap->ld_deref = deref;
600: #endif
601: }
602: }
603: /* }}} */
604:
605: /* {{{ php_ldap_do_search
606: */
607: static void php_ldap_do_search(INTERNAL_FUNCTION_PARAMETERS, int scope)
608: {
1.1.1.2 misho 609: zval *link, *base_dn, **filter, *attrs = NULL, **attr;
1.1 misho 610: long attrsonly, sizelimit, timelimit, deref;
611: char *ldap_base_dn = NULL, *ldap_filter = NULL, **ldap_attrs = NULL;
612: ldap_linkdata *ld = NULL;
613: LDAPMessage *ldap_res;
614: int ldap_attrsonly = 0, ldap_sizelimit = -1, ldap_timelimit = -1, ldap_deref = -1;
615: int old_ldap_sizelimit = -1, old_ldap_timelimit = -1, old_ldap_deref = -1;
616: int num_attribs = 0, ret = 1, i, errno, argcount = ZEND_NUM_ARGS();
617:
618: if (zend_parse_parameters(argcount TSRMLS_CC, "zzZ|allll", &link, &base_dn, &filter, &attrs, &attrsonly,
619: &sizelimit, &timelimit, &deref) == FAILURE) {
620: return;
621: }
622:
623: /* Reverse -> fall through */
624: switch (argcount) {
625: case 8:
626: ldap_deref = deref;
627: case 7:
628: ldap_timelimit = timelimit;
629: case 6:
630: ldap_sizelimit = sizelimit;
631: case 5:
632: ldap_attrsonly = attrsonly;
633: case 4:
634: num_attribs = zend_hash_num_elements(Z_ARRVAL_P(attrs));
635: ldap_attrs = safe_emalloc((num_attribs+1), sizeof(char *), 0);
636:
637: for (i = 0; i<num_attribs; i++) {
638: if (zend_hash_index_find(Z_ARRVAL_P(attrs), i, (void **) &attr) != SUCCESS) {
639: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Array initialization wrong");
640: ret = 0;
641: goto cleanup;
642: }
643:
644: SEPARATE_ZVAL(attr);
645: convert_to_string_ex(attr);
646: ldap_attrs[i] = Z_STRVAL_PP(attr);
647: }
648: ldap_attrs[num_attribs] = NULL;
649: default:
650: break;
651: }
652:
653: /* parallel search? */
654: if (Z_TYPE_P(link) == IS_ARRAY) {
655: int i, nlinks, nbases, nfilters, *rcs;
656: ldap_linkdata **lds;
657: zval **entry, *resource;
658:
659: nlinks = zend_hash_num_elements(Z_ARRVAL_P(link));
660: if (nlinks == 0) {
661: php_error_docref(NULL TSRMLS_CC, E_WARNING, "No links in link array");
662: ret = 0;
663: goto cleanup;
664: }
665:
666: if (Z_TYPE_P(base_dn) == IS_ARRAY) {
667: nbases = zend_hash_num_elements(Z_ARRVAL_P(base_dn));
668: if (nbases != nlinks) {
669: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Base must either be a string, or an array with the same number of elements as the links array");
670: ret = 0;
671: goto cleanup;
672: }
673: zend_hash_internal_pointer_reset(Z_ARRVAL_P(base_dn));
674: } else {
675: nbases = 0; /* this means string, not array */
676: /* If anything else than string is passed, ldap_base_dn = NULL */
677: if (Z_TYPE_P(base_dn) == IS_STRING) {
678: ldap_base_dn = Z_STRVAL_P(base_dn);
679: } else {
680: ldap_base_dn = NULL;
681: }
682: }
683:
684: if (Z_TYPE_PP(filter) == IS_ARRAY) {
685: nfilters = zend_hash_num_elements(Z_ARRVAL_PP(filter));
686: if (nfilters != nlinks) {
687: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Filter must either be a string, or an array with the same number of elements as the links array");
688: ret = 0;
689: goto cleanup;
690: }
691: zend_hash_internal_pointer_reset(Z_ARRVAL_PP(filter));
692: } else {
693: nfilters = 0; /* this means string, not array */
694: convert_to_string_ex(filter);
695: ldap_filter = Z_STRVAL_PP(filter);
696: }
697:
698: lds = safe_emalloc(nlinks, sizeof(ldap_linkdata), 0);
699: rcs = safe_emalloc(nlinks, sizeof(*rcs), 0);
700:
701: zend_hash_internal_pointer_reset(Z_ARRVAL_P(link));
702: for (i=0; i<nlinks; i++) {
703: zend_hash_get_current_data(Z_ARRVAL_P(link), (void **)&entry);
704:
705: ld = (ldap_linkdata *) zend_fetch_resource(entry TSRMLS_CC, -1, "ldap link", NULL, 1, le_link);
706: if (ld == NULL) {
707: ret = 0;
708: goto cleanup_parallel;
709: }
710: if (nbases != 0) { /* base_dn an array? */
711: zend_hash_get_current_data(Z_ARRVAL_P(base_dn), (void **)&entry);
712: zend_hash_move_forward(Z_ARRVAL_P(base_dn));
713:
714: /* If anything else than string is passed, ldap_base_dn = NULL */
715: if (Z_TYPE_PP(entry) == IS_STRING) {
716: ldap_base_dn = Z_STRVAL_PP(entry);
717: } else {
718: ldap_base_dn = NULL;
719: }
720: }
721: if (nfilters != 0) { /* filter an array? */
722: zend_hash_get_current_data(Z_ARRVAL_PP(filter), (void **)&entry);
723: zend_hash_move_forward(Z_ARRVAL_PP(filter));
724: convert_to_string_ex(entry);
725: ldap_filter = Z_STRVAL_PP(entry);
726: }
727:
728: php_set_opts(ld->link, ldap_sizelimit, ldap_timelimit, ldap_deref, &old_ldap_sizelimit, &old_ldap_timelimit, &old_ldap_deref);
729:
730: /* Run the actual search */
731: rcs[i] = ldap_search(ld->link, ldap_base_dn, scope, ldap_filter, ldap_attrs, ldap_attrsonly);
732: lds[i] = ld;
733: zend_hash_move_forward(Z_ARRVAL_P(link));
734: }
735:
736: array_init(return_value);
737:
738: /* Collect results from the searches */
739: for (i=0; i<nlinks; i++) {
740: MAKE_STD_ZVAL(resource);
741: if (rcs[i] != -1) {
742: rcs[i] = ldap_result(lds[i]->link, LDAP_RES_ANY, 1 /* LDAP_MSG_ALL */, NULL, &ldap_res);
743: }
744: if (rcs[i] != -1) {
745: ZEND_REGISTER_RESOURCE(resource, ldap_res, le_result);
746: add_next_index_zval(return_value, resource);
747: } else {
748: add_next_index_bool(return_value, 0);
749: }
750: }
751:
752: cleanup_parallel:
753: efree(lds);
754: efree(rcs);
755: } else {
756: convert_to_string_ex(filter);
757: ldap_filter = Z_STRVAL_PP(filter);
758:
759: /* If anything else than string is passed, ldap_base_dn = NULL */
760: if (Z_TYPE_P(base_dn) == IS_STRING) {
761: ldap_base_dn = Z_STRVAL_P(base_dn);
762: }
763:
764: ld = (ldap_linkdata *) zend_fetch_resource(&link TSRMLS_CC, -1, "ldap link", NULL, 1, le_link);
765: if (ld == NULL) {
766: ret = 0;
767: goto cleanup;
768: }
769:
770: php_set_opts(ld->link, ldap_sizelimit, ldap_timelimit, ldap_deref, &old_ldap_sizelimit, &old_ldap_timelimit, &old_ldap_deref);
771:
772: /* Run the actual search */
773: errno = ldap_search_s(ld->link, ldap_base_dn, scope, ldap_filter, ldap_attrs, ldap_attrsonly, &ldap_res);
774:
775: if (errno != LDAP_SUCCESS
776: && errno != LDAP_SIZELIMIT_EXCEEDED
777: #ifdef LDAP_ADMINLIMIT_EXCEEDED
778: && errno != LDAP_ADMINLIMIT_EXCEEDED
779: #endif
780: #ifdef LDAP_REFERRAL
781: && errno != LDAP_REFERRAL
782: #endif
783: ) {
784: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Search: %s", ldap_err2string(errno));
785: ret = 0;
786: } else {
787: if (errno == LDAP_SIZELIMIT_EXCEEDED) {
788: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Partial search results returned: Sizelimit exceeded");
789: }
790: #ifdef LDAP_ADMINLIMIT_EXCEEDED
791: else if (errno == LDAP_ADMINLIMIT_EXCEEDED) {
792: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Partial search results returned: Adminlimit exceeded");
793: }
794: #endif
795:
796: ZEND_REGISTER_RESOURCE(return_value, ldap_res, le_result);
797: }
798: }
799:
800: cleanup:
801: if (ld) {
802: /* Restoring previous options */
803: php_set_opts(ld->link, old_ldap_sizelimit, old_ldap_timelimit, old_ldap_deref, &ldap_sizelimit, &ldap_timelimit, &ldap_deref);
804: }
805: if (ldap_attrs != NULL) {
806: efree(ldap_attrs);
807: }
808: if (!ret) {
809: RETVAL_BOOL(ret);
810: }
811: }
812: /* }}} */
813:
814: /* {{{ proto resource ldap_read(resource|array link, string base_dn, string filter [, array attrs [, int attrsonly [, int sizelimit [, int timelimit [, int deref]]]]])
815: Read an entry */
816: PHP_FUNCTION(ldap_read)
817: {
818: php_ldap_do_search(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_SCOPE_BASE);
819: }
820: /* }}} */
821:
822: /* {{{ proto resource ldap_list(resource|array link, string base_dn, string filter [, array attrs [, int attrsonly [, int sizelimit [, int timelimit [, int deref]]]]])
823: Single-level search */
824: PHP_FUNCTION(ldap_list)
825: {
826: php_ldap_do_search(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_SCOPE_ONELEVEL);
827: }
828: /* }}} */
829:
830: /* {{{ proto resource ldap_search(resource|array link, string base_dn, string filter [, array attrs [, int attrsonly [, int sizelimit [, int timelimit [, int deref]]]]])
831: Search LDAP tree under base_dn */
832: PHP_FUNCTION(ldap_search)
833: {
834: php_ldap_do_search(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_SCOPE_SUBTREE);
835: }
836: /* }}} */
837:
838: /* {{{ proto bool ldap_free_result(resource result)
839: Free result memory */
840: PHP_FUNCTION(ldap_free_result)
841: {
842: zval *result;
843: LDAPMessage *ldap_result;
844:
845: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &result) != SUCCESS) {
846: return;
847: }
848:
849: ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, &result, -1, "ldap result", le_result);
850:
851: zend_list_delete(Z_LVAL_P(result)); /* Delete list entry */
852: RETVAL_TRUE;
853: }
854: /* }}} */
855:
856: /* {{{ proto int ldap_count_entries(resource link, resource result)
857: Count the number of entries in a search result */
858: PHP_FUNCTION(ldap_count_entries)
859: {
860: zval *link, *result;
861: ldap_linkdata *ld;
862: LDAPMessage *ldap_result;
863:
864: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr", &link, &result) != SUCCESS) {
865: return;
866: }
867:
868: ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
869: ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, &result, -1, "ldap result", le_result);
870:
871: RETURN_LONG(ldap_count_entries(ld->link, ldap_result));
872: }
873: /* }}} */
874:
875: /* {{{ proto resource ldap_first_entry(resource link, resource result)
876: Return first result id */
877: PHP_FUNCTION(ldap_first_entry)
878: {
879: zval *link, *result;
880: ldap_linkdata *ld;
881: ldap_resultentry *resultentry;
882: LDAPMessage *ldap_result, *entry;
883:
884: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr", &link, &result) != SUCCESS) {
885: return;
886: }
887:
888: ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
889: ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, &result, -1, "ldap result", le_result);
890:
891: if ((entry = ldap_first_entry(ld->link, ldap_result)) == NULL) {
892: RETVAL_FALSE;
893: } else {
894: resultentry = emalloc(sizeof(ldap_resultentry));
895: ZEND_REGISTER_RESOURCE(return_value, resultentry, le_result_entry);
896: resultentry->id = Z_LVAL_P(result);
897: zend_list_addref(resultentry->id);
898: resultentry->data = entry;
899: resultentry->ber = NULL;
900: }
901: }
902: /* }}} */
903:
904: /* {{{ proto resource ldap_next_entry(resource link, resource result_entry)
905: Get next result entry */
906: PHP_FUNCTION(ldap_next_entry)
907: {
908: zval *link, *result_entry;
909: ldap_linkdata *ld;
910: ldap_resultentry *resultentry, *resultentry_next;
911: LDAPMessage *entry_next;
912:
913: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr", &link, &result_entry) != SUCCESS) {
914: return;
915: }
916:
917: ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
918: ZEND_FETCH_RESOURCE(resultentry, ldap_resultentry *, &result_entry, -1, "ldap result entry", le_result_entry);
919:
920: if ((entry_next = ldap_next_entry(ld->link, resultentry->data)) == NULL) {
921: RETVAL_FALSE;
922: } else {
923: resultentry_next = emalloc(sizeof(ldap_resultentry));
924: ZEND_REGISTER_RESOURCE(return_value, resultentry_next, le_result_entry);
925: resultentry_next->id = resultentry->id;
926: zend_list_addref(resultentry->id);
927: resultentry_next->data = entry_next;
928: resultentry_next->ber = NULL;
929: }
930: }
931: /* }}} */
932:
933: /* {{{ proto array ldap_get_entries(resource link, resource result)
934: Get all result entries */
935: PHP_FUNCTION(ldap_get_entries)
936: {
937: zval *link, *result;
938: LDAPMessage *ldap_result, *ldap_result_entry;
939: zval *tmp1, *tmp2;
940: ldap_linkdata *ld;
941: LDAP *ldap;
942: int num_entries, num_attrib, num_values, i;
943: BerElement *ber;
944: char *attribute;
945: size_t attr_len;
946: struct berval **ldap_value;
947: char *dn;
948:
949: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr", &link, &result) != SUCCESS) {
950: return;
951: }
952:
953: ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
954: ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, &result, -1, "ldap result", le_result);
955:
956: ldap = ld->link;
957: num_entries = ldap_count_entries(ldap, ldap_result);
958:
959: array_init(return_value);
960: add_assoc_long(return_value, "count", num_entries);
961:
962: if (num_entries == 0) {
963: return;
964: }
965:
966: ldap_result_entry = ldap_first_entry(ldap, ldap_result);
967: if (ldap_result_entry == NULL) {
968: zval_dtor(return_value);
969: RETURN_FALSE;
970: }
971:
972: num_entries = 0;
973: while (ldap_result_entry != NULL) {
974: MAKE_STD_ZVAL(tmp1);
975: array_init(tmp1);
976:
977: num_attrib = 0;
978: attribute = ldap_first_attribute(ldap, ldap_result_entry, &ber);
979:
980: while (attribute != NULL) {
981: ldap_value = ldap_get_values_len(ldap, ldap_result_entry, attribute);
982: num_values = ldap_count_values_len(ldap_value);
983:
984: MAKE_STD_ZVAL(tmp2);
985: array_init(tmp2);
986: add_assoc_long(tmp2, "count", num_values);
987: for (i = 0; i < num_values; i++) {
988: add_index_stringl(tmp2, i, ldap_value[i]->bv_val, ldap_value[i]->bv_len, 1);
989: }
990: ldap_value_free_len(ldap_value);
991:
992: attr_len = strlen(attribute);
993: zend_hash_update(Z_ARRVAL_P(tmp1), php_strtolower(attribute, attr_len), attr_len+1, (void *) &tmp2, sizeof(zval *), NULL);
994: add_index_string(tmp1, num_attrib, attribute, 1);
995:
996: num_attrib++;
997: #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS
998: ldap_memfree(attribute);
999: #endif
1000: attribute = ldap_next_attribute(ldap, ldap_result_entry, ber);
1001: }
1002: #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS
1003: if (ber != NULL) {
1004: ber_free(ber, 0);
1005: }
1006: #endif
1007:
1008: add_assoc_long(tmp1, "count", num_attrib);
1009: dn = ldap_get_dn(ldap, ldap_result_entry);
1010: add_assoc_string(tmp1, "dn", dn, 1);
1011: #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS
1012: ldap_memfree(dn);
1013: #else
1014: free(dn);
1015: #endif
1016:
1017: zend_hash_index_update(Z_ARRVAL_P(return_value), num_entries, (void *) &tmp1, sizeof(zval *), NULL);
1018:
1019: num_entries++;
1020: ldap_result_entry = ldap_next_entry(ldap, ldap_result_entry);
1021: }
1022:
1023: add_assoc_long(return_value, "count", num_entries);
1024:
1025: }
1026: /* }}} */
1027:
1028: /* {{{ proto string ldap_first_attribute(resource link, resource result_entry)
1029: Return first attribute */
1030: PHP_FUNCTION(ldap_first_attribute)
1031: {
1032: zval *link, *result_entry;
1033: ldap_linkdata *ld;
1034: ldap_resultentry *resultentry;
1035: char *attribute;
1036: long dummy_ber;
1037:
1038: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr|l", &link, &result_entry, &dummy_ber) != SUCCESS) {
1039: return;
1040: }
1041:
1042: ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
1043: ZEND_FETCH_RESOURCE(resultentry, ldap_resultentry *, &result_entry, -1, "ldap result entry", le_result_entry);
1044:
1045: if ((attribute = ldap_first_attribute(ld->link, resultentry->data, &resultentry->ber)) == NULL) {
1046: RETURN_FALSE;
1047: } else {
1048: RETVAL_STRING(attribute, 1);
1049: #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS
1050: ldap_memfree(attribute);
1051: #endif
1052: }
1053: }
1054: /* }}} */
1055:
1056: /* {{{ proto string ldap_next_attribute(resource link, resource result_entry)
1057: Get the next attribute in result */
1058: PHP_FUNCTION(ldap_next_attribute)
1059: {
1060: zval *link, *result_entry;
1061: ldap_linkdata *ld;
1062: ldap_resultentry *resultentry;
1063: char *attribute;
1064: long dummy_ber;
1065:
1066: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr|l", &link, &result_entry, &dummy_ber) != SUCCESS) {
1067: return;
1068: }
1069:
1070: ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
1071: ZEND_FETCH_RESOURCE(resultentry, ldap_resultentry *, &result_entry, -1, "ldap result entry", le_result_entry);
1072:
1073: if (resultentry->ber == NULL) {
1074: php_error_docref(NULL TSRMLS_CC, E_WARNING, "called before calling ldap_first_attribute() or no attributes found in result entry");
1075: RETURN_FALSE;
1076: }
1077:
1078: if ((attribute = ldap_next_attribute(ld->link, resultentry->data, resultentry->ber)) == NULL) {
1079: #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS
1080: if (resultentry->ber != NULL) {
1081: ber_free(resultentry->ber, 0);
1082: resultentry->ber = NULL;
1083: }
1084: #endif
1085: RETURN_FALSE;
1086: } else {
1087: RETVAL_STRING(attribute, 1);
1088: #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS
1089: ldap_memfree(attribute);
1090: #endif
1091: }
1092: }
1093: /* }}} */
1094:
1095: /* {{{ proto array ldap_get_attributes(resource link, resource result_entry)
1096: Get attributes from a search result entry */
1097: PHP_FUNCTION(ldap_get_attributes)
1098: {
1099: zval *link, *result_entry;
1100: zval *tmp;
1101: ldap_linkdata *ld;
1102: ldap_resultentry *resultentry;
1103: char *attribute;
1104: struct berval **ldap_value;
1105: int i, num_values, num_attrib;
1106: BerElement *ber;
1107:
1108: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr", &link, &result_entry) != SUCCESS) {
1109: return;
1110: }
1111:
1112: ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
1113: ZEND_FETCH_RESOURCE(resultentry, ldap_resultentry *, &result_entry, -1, "ldap result entry", le_result_entry);
1114:
1115: array_init(return_value);
1116: num_attrib = 0;
1117:
1118: attribute = ldap_first_attribute(ld->link, resultentry->data, &ber);
1119: while (attribute != NULL) {
1120: ldap_value = ldap_get_values_len(ld->link, resultentry->data, attribute);
1121: num_values = ldap_count_values_len(ldap_value);
1122:
1123: MAKE_STD_ZVAL(tmp);
1124: array_init(tmp);
1125: add_assoc_long(tmp, "count", num_values);
1126: for (i = 0; i < num_values; i++) {
1127: add_index_stringl(tmp, i, ldap_value[i]->bv_val, ldap_value[i]->bv_len, 1);
1128: }
1129: ldap_value_free_len(ldap_value);
1130:
1131: zend_hash_update(Z_ARRVAL_P(return_value), attribute, strlen(attribute)+1, (void *) &tmp, sizeof(zval *), NULL);
1132: add_index_string(return_value, num_attrib, attribute, 1);
1133:
1134: num_attrib++;
1135: #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS
1136: ldap_memfree(attribute);
1137: #endif
1138: attribute = ldap_next_attribute(ld->link, resultentry->data, ber);
1139: }
1140: #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS
1141: if (ber != NULL) {
1142: ber_free(ber, 0);
1143: }
1144: #endif
1145:
1146: add_assoc_long(return_value, "count", num_attrib);
1147: }
1148: /* }}} */
1149:
1150: /* {{{ proto array ldap_get_values_len(resource link, resource result_entry, string attribute)
1151: Get all values with lengths from a result entry */
1152: PHP_FUNCTION(ldap_get_values_len)
1153: {
1154: zval *link, *result_entry;
1155: ldap_linkdata *ld;
1156: ldap_resultentry *resultentry;
1157: char *attr;
1158: struct berval **ldap_value_len;
1159: int i, num_values, attr_len;
1160:
1161: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rrs", &link, &result_entry, &attr, &attr_len) != SUCCESS) {
1162: return;
1163: }
1164:
1165: ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
1166: ZEND_FETCH_RESOURCE(resultentry, ldap_resultentry *, &result_entry, -1, "ldap result entry", le_result_entry);
1167:
1168: if ((ldap_value_len = ldap_get_values_len(ld->link, resultentry->data, attr)) == NULL) {
1169: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot get the value(s) of attribute %s", ldap_err2string(_get_lderrno(ld->link)));
1170: RETURN_FALSE;
1171: }
1172:
1173: num_values = ldap_count_values_len(ldap_value_len);
1174: array_init(return_value);
1175:
1176: for (i=0; i<num_values; i++) {
1177: add_next_index_stringl(return_value, ldap_value_len[i]->bv_val, ldap_value_len[i]->bv_len, 1);
1178: }
1179:
1180: add_assoc_long(return_value, "count", num_values);
1181: ldap_value_free_len(ldap_value_len);
1182:
1183: }
1184: /* }}} */
1185:
1186: /* {{{ proto string ldap_get_dn(resource link, resource result_entry)
1187: Get the DN of a result entry */
1188: PHP_FUNCTION(ldap_get_dn)
1189: {
1190: zval *link, *result_entry;
1191: ldap_linkdata *ld;
1192: ldap_resultentry *resultentry;
1193: char *text;
1194:
1195: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr", &link, &result_entry) != SUCCESS) {
1196: return;
1197: }
1198:
1199: ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
1200: ZEND_FETCH_RESOURCE(resultentry, ldap_resultentry *, &result_entry, -1, "ldap result entry", le_result_entry);
1201:
1202: text = ldap_get_dn(ld->link, resultentry->data);
1203: if (text != NULL) {
1204: RETVAL_STRING(text, 1);
1205: #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS
1206: ldap_memfree(text);
1207: #else
1208: free(text);
1209: #endif
1210: } else {
1211: RETURN_FALSE;
1212: }
1213: }
1214: /* }}} */
1215:
1216: /* {{{ proto array ldap_explode_dn(string dn, int with_attrib)
1217: Splits DN into its component parts */
1218: PHP_FUNCTION(ldap_explode_dn)
1219: {
1220: long with_attrib;
1221: char *dn, **ldap_value;
1222: int i, count, dn_len;
1223:
1224: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &dn, &dn_len, &with_attrib) != SUCCESS) {
1225: return;
1226: }
1227:
1228: if (!(ldap_value = ldap_explode_dn(dn, with_attrib))) {
1229: /* Invalid parameters were passed to ldap_explode_dn */
1230: RETURN_FALSE;
1231: }
1232:
1233: i=0;
1234: while (ldap_value[i] != NULL) i++;
1235: count = i;
1236:
1237: array_init(return_value);
1238:
1239: add_assoc_long(return_value, "count", count);
1240: for (i = 0; i<count; i++) {
1241: add_index_string(return_value, i, ldap_value[i], 1);
1242: }
1243:
1244: ldap_value_free(ldap_value);
1245: }
1246: /* }}} */
1247:
1248: /* {{{ proto string ldap_dn2ufn(string dn)
1249: Convert DN to User Friendly Naming format */
1250: PHP_FUNCTION(ldap_dn2ufn)
1251: {
1252: char *dn, *ufn;
1253: int dn_len;
1254:
1255: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &dn, &dn_len) != SUCCESS) {
1256: return;
1257: }
1258:
1259: ufn = ldap_dn2ufn(dn);
1260:
1261: if (ufn != NULL) {
1262: RETVAL_STRING(ufn, 1);
1263: #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 || WINDOWS
1264: ldap_memfree(ufn);
1265: #endif
1266: } else {
1267: RETURN_FALSE;
1268: }
1269: }
1270: /* }}} */
1271:
1272:
1273: /* added to fix use of ldap_modify_add for doing an ldap_add, gerrit thomson. */
1274: #define PHP_LD_FULL_ADD 0xff
1275: /* {{{ php_ldap_do_modify
1276: */
1277: static void php_ldap_do_modify(INTERNAL_FUNCTION_PARAMETERS, int oper)
1278: {
1279: zval *link, *entry, **value, **ivalue;
1280: ldap_linkdata *ld;
1281: char *dn;
1282: LDAPMod **ldap_mods;
1283: int i, j, num_attribs, num_values, dn_len;
1284: int *num_berval;
1285: char *attribute;
1286: ulong index;
1287: int is_full_add=0; /* flag for full add operation so ldap_mod_add can be put back into oper, gerrit THomson */
1288:
1289: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsa", &link, &dn, &dn_len, &entry) != SUCCESS) {
1290: return;
1291: }
1292:
1293: ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
1294:
1295: num_attribs = zend_hash_num_elements(Z_ARRVAL_P(entry));
1296: ldap_mods = safe_emalloc((num_attribs+1), sizeof(LDAPMod *), 0);
1297: num_berval = safe_emalloc(num_attribs, sizeof(int), 0);
1298: zend_hash_internal_pointer_reset(Z_ARRVAL_P(entry));
1299:
1300: /* added by gerrit thomson to fix ldap_add using ldap_mod_add */
1301: if (oper == PHP_LD_FULL_ADD) {
1302: oper = LDAP_MOD_ADD;
1303: is_full_add = 1;
1304: }
1305: /* end additional , gerrit thomson */
1306:
1307: for (i = 0; i < num_attribs; i++) {
1308: ldap_mods[i] = emalloc(sizeof(LDAPMod));
1309: ldap_mods[i]->mod_op = oper | LDAP_MOD_BVALUES;
1310: ldap_mods[i]->mod_type = NULL;
1311:
1312: if (zend_hash_get_current_key(Z_ARRVAL_P(entry), &attribute, &index, 0) == HASH_KEY_IS_STRING) {
1313: ldap_mods[i]->mod_type = estrdup(attribute);
1314: } else {
1315: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown attribute in the data");
1316: /* Free allocated memory */
1317: while (i >= 0) {
1318: if (ldap_mods[i]->mod_type) {
1319: efree(ldap_mods[i]->mod_type);
1320: }
1321: efree(ldap_mods[i]);
1322: i--;
1323: }
1324: efree(num_berval);
1325: efree(ldap_mods);
1326: RETURN_FALSE;
1327: }
1328:
1329: zend_hash_get_current_data(Z_ARRVAL_P(entry), (void **)&value);
1330:
1331: if (Z_TYPE_PP(value) != IS_ARRAY) {
1332: num_values = 1;
1333: } else {
1334: num_values = zend_hash_num_elements(Z_ARRVAL_PP(value));
1335: }
1336:
1337: num_berval[i] = num_values;
1338: ldap_mods[i]->mod_bvalues = safe_emalloc((num_values + 1), sizeof(struct berval *), 0);
1339:
1340: /* allow for arrays with one element, no allowance for arrays with none but probably not required, gerrit thomson. */
1341: if ((num_values == 1) && (Z_TYPE_PP(value) != IS_ARRAY)) {
1342: convert_to_string_ex(value);
1343: ldap_mods[i]->mod_bvalues[0] = (struct berval *) emalloc (sizeof(struct berval));
1344: ldap_mods[i]->mod_bvalues[0]->bv_len = Z_STRLEN_PP(value);
1345: ldap_mods[i]->mod_bvalues[0]->bv_val = Z_STRVAL_PP(value);
1346: } else {
1347: for (j = 0; j < num_values; j++) {
1348: if (zend_hash_index_find(Z_ARRVAL_PP(value), j, (void **) &ivalue) != SUCCESS) {
1349: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Value array must have consecutive indices 0, 1, ...");
1350: num_berval[i] = j;
1351: num_attribs = i + 1;
1352: RETVAL_FALSE;
1353: goto errexit;
1354: }
1355: convert_to_string_ex(ivalue);
1356: ldap_mods[i]->mod_bvalues[j] = (struct berval *) emalloc (sizeof(struct berval));
1357: ldap_mods[i]->mod_bvalues[j]->bv_len = Z_STRLEN_PP(ivalue);
1358: ldap_mods[i]->mod_bvalues[j]->bv_val = Z_STRVAL_PP(ivalue);
1359: }
1360: }
1361: ldap_mods[i]->mod_bvalues[num_values] = NULL;
1362: zend_hash_move_forward(Z_ARRVAL_P(entry));
1363: }
1364: ldap_mods[num_attribs] = NULL;
1365:
1366: /* check flag to see if do_mod was called to perform full add , gerrit thomson */
1367: if (is_full_add == 1) {
1368: if ((i = ldap_add_s(ld->link, dn, ldap_mods)) != LDAP_SUCCESS) {
1369: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Add: %s", ldap_err2string(i));
1370: RETVAL_FALSE;
1371: } else RETVAL_TRUE;
1372: } else {
1373: if ((i = ldap_modify_ext_s(ld->link, dn, ldap_mods, NULL, NULL)) != LDAP_SUCCESS) {
1374: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Modify: %s", ldap_err2string(i));
1375: RETVAL_FALSE;
1376: } else RETVAL_TRUE;
1377: }
1378:
1379: errexit:
1380: for (i = 0; i < num_attribs; i++) {
1381: efree(ldap_mods[i]->mod_type);
1382: for (j = 0; j < num_berval[i]; j++) {
1383: efree(ldap_mods[i]->mod_bvalues[j]);
1384: }
1385: efree(ldap_mods[i]->mod_bvalues);
1386: efree(ldap_mods[i]);
1387: }
1388: efree(num_berval);
1389: efree(ldap_mods);
1390:
1391: return;
1392: }
1393: /* }}} */
1394:
1395: /* {{{ proto bool ldap_add(resource link, string dn, array entry)
1396: Add entries to LDAP directory */
1397: PHP_FUNCTION(ldap_add)
1398: {
1399: /* use a newly define parameter into the do_modify so ldap_mod_add can be used the way it is supposed to be used , Gerrit THomson */
1400: php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_LD_FULL_ADD);
1401: }
1402: /* }}} */
1403:
1404: /* three functions for attribute base modifications, gerrit Thomson */
1405:
1406: /* {{{ proto bool ldap_mod_replace(resource link, string dn, array entry)
1407: Replace attribute values with new ones */
1408: PHP_FUNCTION(ldap_mod_replace)
1409: {
1410: php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_REPLACE);
1411: }
1412: /* }}} */
1413:
1414: /* {{{ proto bool ldap_mod_add(resource link, string dn, array entry)
1415: Add attribute values to current */
1416: PHP_FUNCTION(ldap_mod_add)
1417: {
1418: php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_ADD);
1419: }
1420: /* }}} */
1421:
1422: /* {{{ proto bool ldap_mod_del(resource link, string dn, array entry)
1423: Delete attribute values */
1424: PHP_FUNCTION(ldap_mod_del)
1425: {
1426: php_ldap_do_modify(INTERNAL_FUNCTION_PARAM_PASSTHRU, LDAP_MOD_DELETE);
1427: }
1428: /* }}} */
1429:
1430: /* {{{ proto bool ldap_delete(resource link, string dn)
1431: Delete an entry from a directory */
1432: PHP_FUNCTION(ldap_delete)
1433: {
1434: zval *link;
1435: ldap_linkdata *ld;
1436: char *dn;
1437: int rc, dn_len;
1438:
1439: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &link, &dn, &dn_len) != SUCCESS) {
1440: return;
1441: }
1442:
1443: ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
1444:
1445: if ((rc = ldap_delete_s(ld->link, dn)) != LDAP_SUCCESS) {
1446: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Delete: %s", ldap_err2string(rc));
1447: RETURN_FALSE;
1448: }
1449:
1450: RETURN_TRUE;
1451: }
1452: /* }}} */
1453:
1.1.1.4 ! misho 1454: /* {{{ _ldap_str_equal_to_const
! 1455: */
! 1456: static int _ldap_str_equal_to_const(const char *str, uint str_len, const char *cstr)
! 1457: {
! 1458: int i;
! 1459:
! 1460: if (strlen(cstr) != str_len)
! 1461: return 0;
! 1462:
! 1463: for (i = 0; i < str_len; ++i) {
! 1464: if (str[i] != cstr[i]) {
! 1465: return 0;
! 1466: }
! 1467: }
! 1468:
! 1469: return 1;
! 1470: }
! 1471: /* }}} */
! 1472:
! 1473: /* {{{ _ldap_strlen_max
! 1474: */
! 1475: static int _ldap_strlen_max(const char *str, uint max_len)
! 1476: {
! 1477: int i;
! 1478:
! 1479: for (i = 0; i < max_len; ++i) {
! 1480: if (str[i] == '\0') {
! 1481: return i;
! 1482: }
! 1483: }
! 1484:
! 1485: return max_len;
! 1486: }
! 1487: /* }}} */
! 1488:
! 1489: /* {{{ _ldap_hash_fetch
! 1490: */
! 1491: static void _ldap_hash_fetch(zval *hashTbl, const char *key, zval **out)
! 1492: {
! 1493: zval **fetched;
! 1494: if (zend_hash_find(Z_ARRVAL_P(hashTbl), key, strlen(key)+1, (void **) &fetched) == SUCCESS) {
! 1495: *out = *fetched;
! 1496: }
! 1497: else {
! 1498: *out = NULL;
! 1499: }
! 1500: }
! 1501: /* }}} */
! 1502:
! 1503: /* {{{ proto bool ldap_modify_batch(resource link, string dn, array modifs)
! 1504: Perform multiple modifications as part of one operation */
! 1505: PHP_FUNCTION(ldap_modify_batch)
! 1506: {
! 1507: ldap_linkdata *ld;
! 1508: zval *link, *mods, *mod, *modinfo, *modval;
! 1509: zval *attrib, *modtype, *vals;
! 1510: zval **fetched;
! 1511: char *dn;
! 1512: int dn_len;
! 1513: int i, j, k;
! 1514: int num_mods, num_modprops, num_modvals;
! 1515: LDAPMod **ldap_mods;
! 1516: uint oper;
! 1517:
! 1518: /*
! 1519: $mods = array(
! 1520: array(
! 1521: "attrib" => "unicodePwd",
! 1522: "modtype" => LDAP_MODIFY_BATCH_REMOVE,
! 1523: "values" => array($oldpw)
! 1524: ),
! 1525: array(
! 1526: "attrib" => "unicodePwd",
! 1527: "modtype" => LDAP_MODIFY_BATCH_ADD,
! 1528: "values" => array($newpw)
! 1529: ),
! 1530: array(
! 1531: "attrib" => "userPrincipalName",
! 1532: "modtype" => LDAP_MODIFY_BATCH_REPLACE,
! 1533: "values" => array("janitor@corp.contoso.com")
! 1534: ),
! 1535: array(
! 1536: "attrib" => "userCert",
! 1537: "modtype" => LDAP_MODIFY_BATCH_REMOVE_ALL
! 1538: )
! 1539: );
! 1540: */
! 1541:
! 1542: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsa", &link, &dn, &dn_len, &mods) != SUCCESS) {
! 1543: return;
! 1544: }
! 1545:
! 1546: ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
! 1547:
! 1548: /* perform validation */
! 1549: {
! 1550: char *modkey;
! 1551: uint modkeylen;
! 1552: long modtype;
! 1553:
! 1554: /* to store the wrongly-typed keys */
! 1555: ulong tmpUlong;
! 1556:
! 1557: /* make sure the DN contains no NUL bytes */
! 1558: if (_ldap_strlen_max(dn, dn_len) != dn_len) {
! 1559: php_error_docref(NULL TSRMLS_CC, E_WARNING, "DN must not contain NUL bytes");
! 1560: RETURN_FALSE;
! 1561: }
! 1562:
! 1563: /* make sure the top level is a normal array */
! 1564: zend_hash_internal_pointer_reset(Z_ARRVAL_P(mods));
! 1565: if (zend_hash_get_current_key_type(Z_ARRVAL_P(mods)) != HASH_KEY_IS_LONG) {
! 1566: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Modifications array must not be string-indexed");
! 1567: RETURN_FALSE;
! 1568: }
! 1569:
! 1570: num_mods = zend_hash_num_elements(Z_ARRVAL_P(mods));
! 1571:
! 1572: for (i = 0; i < num_mods; i++) {
! 1573: /* is the numbering consecutive? */
! 1574: if (zend_hash_index_find(Z_ARRVAL_P(mods), i, (void **) &fetched) != SUCCESS) {
! 1575: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Modifications array must have consecutive indices 0, 1, ...");
! 1576: RETURN_FALSE;
! 1577: }
! 1578: mod = *fetched;
! 1579:
! 1580: /* is it an array? */
! 1581: if (Z_TYPE_P(mod) != IS_ARRAY) {
! 1582: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Each entry of modifications array must be an array itself");
! 1583: RETURN_FALSE;
! 1584: }
! 1585:
! 1586: /* for the modification hashtable... */
! 1587: zend_hash_internal_pointer_reset(Z_ARRVAL_P(mod));
! 1588: num_modprops = zend_hash_num_elements(Z_ARRVAL_P(mod));
! 1589:
! 1590: for (j = 0; j < num_modprops; j++) {
! 1591: /* are the keys strings? */
! 1592: if (zend_hash_get_current_key_ex(Z_ARRVAL_P(mod), &modkey, &modkeylen, &tmpUlong, 0, NULL) != HASH_KEY_IS_STRING) {
! 1593: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Each entry of modifications array must be string-indexed");
! 1594: RETURN_FALSE;
! 1595: }
! 1596:
! 1597: /* modkeylen includes the terminating NUL byte; remove that */
! 1598: --modkeylen;
! 1599:
! 1600: /* is this a valid entry? */
! 1601: if (
! 1602: !_ldap_str_equal_to_const(modkey, modkeylen, LDAP_MODIFY_BATCH_ATTRIB) &&
! 1603: !_ldap_str_equal_to_const(modkey, modkeylen, LDAP_MODIFY_BATCH_MODTYPE) &&
! 1604: !_ldap_str_equal_to_const(modkey, modkeylen, LDAP_MODIFY_BATCH_VALUES)
! 1605: ) {
! 1606: php_error_docref(NULL TSRMLS_CC, E_WARNING, "The only allowed keys in entries of the modifications array are '" LDAP_MODIFY_BATCH_ATTRIB "', '" LDAP_MODIFY_BATCH_MODTYPE "' and '" LDAP_MODIFY_BATCH_VALUES "'");
! 1607: RETURN_FALSE;
! 1608: }
! 1609:
! 1610: zend_hash_get_current_data(Z_ARRVAL_P(mod), (void **) &fetched);
! 1611: modinfo = *fetched;
! 1612:
! 1613: /* does the value type match the key? */
! 1614: if (_ldap_str_equal_to_const(modkey, modkeylen, LDAP_MODIFY_BATCH_ATTRIB)) {
! 1615: if (Z_TYPE_P(modinfo) != IS_STRING) {
! 1616: php_error_docref(NULL TSRMLS_CC, E_WARNING, "A '" LDAP_MODIFY_BATCH_ATTRIB "' value must be a string");
! 1617: RETURN_FALSE;
! 1618: }
! 1619:
! 1620: if (Z_STRLEN_P(modinfo) != _ldap_strlen_max(Z_STRVAL_P(modinfo), Z_STRLEN_P(modinfo))) {
! 1621: php_error_docref(NULL TSRMLS_CC, E_WARNING, "A '" LDAP_MODIFY_BATCH_ATTRIB "' value must not contain NUL bytes");
! 1622: RETURN_FALSE;
! 1623: }
! 1624: }
! 1625: else if (_ldap_str_equal_to_const(modkey, modkeylen, LDAP_MODIFY_BATCH_MODTYPE)) {
! 1626: if (Z_TYPE_P(modinfo) != IS_LONG) {
! 1627: php_error_docref(NULL TSRMLS_CC, E_WARNING, "A '" LDAP_MODIFY_BATCH_MODTYPE "' value must be a long");
! 1628: RETURN_FALSE;
! 1629: }
! 1630:
! 1631: /* is the value in range? */
! 1632: modtype = Z_LVAL_P(modinfo);
! 1633: if (
! 1634: modtype != LDAP_MODIFY_BATCH_ADD &&
! 1635: modtype != LDAP_MODIFY_BATCH_REMOVE &&
! 1636: modtype != LDAP_MODIFY_BATCH_REPLACE &&
! 1637: modtype != LDAP_MODIFY_BATCH_REMOVE_ALL
! 1638: ) {
! 1639: php_error_docref(NULL TSRMLS_CC, E_WARNING, "The '" LDAP_MODIFY_BATCH_MODTYPE "' value must match one of the LDAP_MODIFY_BATCH_* constants");
! 1640: RETURN_FALSE;
! 1641: }
! 1642:
! 1643: /* if it's REMOVE_ALL, there must not be a values array; otherwise, there must */
! 1644: if (modtype == LDAP_MODIFY_BATCH_REMOVE_ALL) {
! 1645: if (zend_hash_exists(Z_ARRVAL_P(mod), LDAP_MODIFY_BATCH_VALUES, strlen(LDAP_MODIFY_BATCH_VALUES) + 1)) {
! 1646: php_error_docref(NULL TSRMLS_CC, E_WARNING, "If '" LDAP_MODIFY_BATCH_MODTYPE "' is LDAP_MODIFY_BATCH_REMOVE_ALL, a '" LDAP_MODIFY_BATCH_VALUES "' array must not be provided");
! 1647: RETURN_FALSE;
! 1648: }
! 1649: }
! 1650: else {
! 1651: if (!zend_hash_exists(Z_ARRVAL_P(mod), LDAP_MODIFY_BATCH_VALUES, strlen(LDAP_MODIFY_BATCH_VALUES) + 1)) {
! 1652: php_error_docref(NULL TSRMLS_CC, E_WARNING, "If '" LDAP_MODIFY_BATCH_MODTYPE "' is not LDAP_MODIFY_BATCH_REMOVE_ALL, a '" LDAP_MODIFY_BATCH_VALUES "' array must be provided");
! 1653: RETURN_FALSE;
! 1654: }
! 1655: }
! 1656: }
! 1657: else if (_ldap_str_equal_to_const(modkey, modkeylen, LDAP_MODIFY_BATCH_VALUES)) {
! 1658: if (Z_TYPE_P(modinfo) != IS_ARRAY) {
! 1659: php_error_docref(NULL TSRMLS_CC, E_WARNING, "A '" LDAP_MODIFY_BATCH_VALUES "' value must be an array");
! 1660: RETURN_FALSE;
! 1661: }
! 1662:
! 1663: /* is the array not empty? */
! 1664: zend_hash_internal_pointer_reset(Z_ARRVAL_P(modinfo));
! 1665: num_modvals = zend_hash_num_elements(Z_ARRVAL_P(modinfo));
! 1666: if (num_modvals == 0) {
! 1667: php_error_docref(NULL TSRMLS_CC, E_WARNING, "A '" LDAP_MODIFY_BATCH_VALUES "' array must have at least one element");
! 1668: RETURN_FALSE;
! 1669: }
! 1670:
! 1671: /* are its keys integers? */
! 1672: if (zend_hash_get_current_key_type(Z_ARRVAL_P(modinfo)) != HASH_KEY_IS_LONG) {
! 1673: php_error_docref(NULL TSRMLS_CC, E_WARNING, "A '" LDAP_MODIFY_BATCH_VALUES "' array must not be string-indexed");
! 1674: RETURN_FALSE;
! 1675: }
! 1676:
! 1677: /* are the keys consecutive? */
! 1678: for (k = 0; k < num_modvals; k++) {
! 1679: if (zend_hash_index_find(Z_ARRVAL_P(modinfo), k, (void **) &fetched) != SUCCESS) {
! 1680: php_error_docref(NULL TSRMLS_CC, E_WARNING, "A '" LDAP_MODIFY_BATCH_VALUES "' array must have consecutive indices 0, 1, ...");
! 1681: RETURN_FALSE;
! 1682: }
! 1683: modval = *fetched;
! 1684:
! 1685: /* is the data element a string? */
! 1686: if (Z_TYPE_P(modval) != IS_STRING) {
! 1687: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Each element of a '" LDAP_MODIFY_BATCH_VALUES "' array must be a string");
! 1688: RETURN_FALSE;
! 1689: }
! 1690: }
! 1691: }
! 1692:
! 1693: zend_hash_move_forward(Z_ARRVAL_P(mod));
! 1694: }
! 1695: }
! 1696: }
! 1697: /* validation was successful */
! 1698:
! 1699: /* allocate array of modifications */
! 1700: ldap_mods = safe_emalloc((num_mods+1), sizeof(LDAPMod *), 0);
! 1701:
! 1702: /* for each modification */
! 1703: for (i = 0; i < num_mods; i++) {
! 1704: /* allocate the modification struct */
! 1705: ldap_mods[i] = safe_emalloc(1, sizeof(LDAPMod), 0);
! 1706:
! 1707: /* fetch the relevant data */
! 1708: zend_hash_index_find(Z_ARRVAL_P(mods), i, (void **) &fetched);
! 1709: mod = *fetched;
! 1710:
! 1711: _ldap_hash_fetch(mod, LDAP_MODIFY_BATCH_ATTRIB, &attrib);
! 1712: _ldap_hash_fetch(mod, LDAP_MODIFY_BATCH_MODTYPE, &modtype);
! 1713: _ldap_hash_fetch(mod, LDAP_MODIFY_BATCH_VALUES, &vals);
! 1714:
! 1715: /* map the modification type */
! 1716: switch (Z_LVAL_P(modtype)) {
! 1717: case LDAP_MODIFY_BATCH_ADD:
! 1718: oper = LDAP_MOD_ADD;
! 1719: break;
! 1720: case LDAP_MODIFY_BATCH_REMOVE:
! 1721: case LDAP_MODIFY_BATCH_REMOVE_ALL:
! 1722: oper = LDAP_MOD_DELETE;
! 1723: break;
! 1724: case LDAP_MODIFY_BATCH_REPLACE:
! 1725: oper = LDAP_MOD_REPLACE;
! 1726: break;
! 1727: default:
! 1728: php_error_docref(NULL TSRMLS_CC, E_ERROR, "Unknown and uncaught modification type.");
! 1729: RETURN_FALSE;
! 1730: }
! 1731:
! 1732: /* fill in the basic info */
! 1733: ldap_mods[i]->mod_op = oper | LDAP_MOD_BVALUES;
! 1734: ldap_mods[i]->mod_type = estrndup(Z_STRVAL_P(attrib), Z_STRLEN_P(attrib));
! 1735:
! 1736: if (Z_LVAL_P(modtype) == LDAP_MODIFY_BATCH_REMOVE_ALL) {
! 1737: /* no values */
! 1738: ldap_mods[i]->mod_bvalues = NULL;
! 1739: }
! 1740: else {
! 1741: /* allocate space for the values as part of this modification */
! 1742: num_modvals = zend_hash_num_elements(Z_ARRVAL_P(vals));
! 1743: ldap_mods[i]->mod_bvalues = safe_emalloc((num_modvals+1), sizeof(struct berval *), 0);
! 1744:
! 1745: /* for each value */
! 1746: for (j = 0; j < num_modvals; j++) {
! 1747: /* fetch it */
! 1748: zend_hash_index_find(Z_ARRVAL_P(vals), j, (void **) &fetched);
! 1749: modval = *fetched;
! 1750:
! 1751: /* allocate the data struct */
! 1752: ldap_mods[i]->mod_bvalues[j] = safe_emalloc(1, sizeof(struct berval), 0);
! 1753:
! 1754: /* fill it */
! 1755: ldap_mods[i]->mod_bvalues[j]->bv_len = Z_STRLEN_P(modval);
! 1756: ldap_mods[i]->mod_bvalues[j]->bv_val = estrndup(Z_STRVAL_P(modval), Z_STRLEN_P(modval));
! 1757: }
! 1758:
! 1759: /* NULL-terminate values */
! 1760: ldap_mods[i]->mod_bvalues[num_modvals] = NULL;
! 1761: }
! 1762: }
! 1763:
! 1764: /* NULL-terminate modifications */
! 1765: ldap_mods[num_mods] = NULL;
! 1766:
! 1767: /* perform (finally) */
! 1768: if ((i = ldap_modify_ext_s(ld->link, dn, ldap_mods, NULL, NULL)) != LDAP_SUCCESS) {
! 1769: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Batch Modify: %s", ldap_err2string(i));
! 1770: RETVAL_FALSE;
! 1771: } else RETVAL_TRUE;
! 1772:
! 1773: /* clean up */
! 1774: {
! 1775: for (i = 0; i < num_mods; i++) {
! 1776: /* attribute */
! 1777: efree(ldap_mods[i]->mod_type);
! 1778:
! 1779: if (ldap_mods[i]->mod_bvalues != NULL) {
! 1780: /* each BER value */
! 1781: for (j = 0; ldap_mods[i]->mod_bvalues[j] != NULL; j++) {
! 1782: /* free the data bytes */
! 1783: efree(ldap_mods[i]->mod_bvalues[j]->bv_val);
! 1784:
! 1785: /* free the bvalue struct */
! 1786: efree(ldap_mods[i]->mod_bvalues[j]);
! 1787: }
! 1788:
! 1789: /* the BER value array */
! 1790: efree(ldap_mods[i]->mod_bvalues);
! 1791: }
! 1792:
! 1793: /* the modification */
! 1794: efree(ldap_mods[i]);
! 1795: }
! 1796:
! 1797: /* the modifications array */
! 1798: efree(ldap_mods);
! 1799: }
! 1800: }
! 1801: /* }}} */
! 1802:
1.1 misho 1803: /* {{{ proto int ldap_errno(resource link)
1804: Get the current ldap error number */
1805: PHP_FUNCTION(ldap_errno)
1806: {
1807: zval *link;
1808: ldap_linkdata *ld;
1809:
1810: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &link) != SUCCESS) {
1811: return;
1812: }
1813:
1814: ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
1815:
1816: RETURN_LONG(_get_lderrno(ld->link));
1817: }
1818: /* }}} */
1819:
1820: /* {{{ proto string ldap_err2str(int errno)
1821: Convert error number to error string */
1822: PHP_FUNCTION(ldap_err2str)
1823: {
1824: long perrno;
1825:
1826: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &perrno) != SUCCESS) {
1827: return;
1828: }
1829:
1830: RETURN_STRING(ldap_err2string(perrno), 1);
1831: }
1832: /* }}} */
1833:
1834: /* {{{ proto string ldap_error(resource link)
1835: Get the current ldap error string */
1836: PHP_FUNCTION(ldap_error)
1837: {
1838: zval *link;
1839: ldap_linkdata *ld;
1840: int ld_errno;
1841:
1842: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &link) != SUCCESS) {
1843: return;
1844: }
1845:
1846: ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
1847:
1848: ld_errno = _get_lderrno(ld->link);
1849:
1850: RETURN_STRING(ldap_err2string(ld_errno), 1);
1851: }
1852: /* }}} */
1853:
1854: /* {{{ proto bool ldap_compare(resource link, string dn, string attr, string value)
1855: Determine if an entry has a specific value for one of its attributes */
1856: PHP_FUNCTION(ldap_compare)
1857: {
1858: zval *link;
1859: char *dn, *attr, *value;
1860: int dn_len, attr_len, value_len;
1861: ldap_linkdata *ld;
1862: int errno;
1863:
1864: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsss", &link, &dn, &dn_len, &attr, &attr_len, &value, &value_len) != SUCCESS) {
1865: return;
1866: }
1867:
1868: ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
1869:
1870: errno = ldap_compare_s(ld->link, dn, attr, value);
1871:
1872: switch (errno) {
1873: case LDAP_COMPARE_TRUE:
1874: RETURN_TRUE;
1875: break;
1876:
1877: case LDAP_COMPARE_FALSE:
1878: RETURN_FALSE;
1879: break;
1880: }
1881:
1882: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Compare: %s", ldap_err2string(errno));
1883: RETURN_LONG(-1);
1884: }
1885: /* }}} */
1886:
1887: /* {{{ proto bool ldap_sort(resource link, resource result, string sortfilter)
1888: Sort LDAP result entries */
1889: PHP_FUNCTION(ldap_sort)
1890: {
1891: zval *link, *result;
1892: ldap_linkdata *ld;
1893: char *sortfilter;
1894: int sflen;
1895: zend_rsrc_list_entry *le;
1896:
1897: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rrs", &link, &result, &sortfilter, &sflen) != SUCCESS) {
1898: RETURN_FALSE;
1899: }
1900:
1901: ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
1902:
1903: if (zend_hash_index_find(&EG(regular_list), Z_LVAL_P(result), (void **) &le) != SUCCESS || le->type != le_result) {
1904: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Supplied resource is not a valid ldap result resource");
1905: RETURN_FALSE;
1906: }
1907:
1908: if (ldap_sort_entries(ld->link, (LDAPMessage **) &le->ptr, sflen ? sortfilter : NULL, strcmp) != LDAP_SUCCESS) {
1909: php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", ldap_err2string(errno));
1910: RETURN_FALSE;
1911: }
1912:
1913: RETURN_TRUE;
1914: }
1915: /* }}} */
1916:
1917: #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10
1918: /* {{{ proto bool ldap_get_option(resource link, int option, mixed retval)
1919: Get the current value of various session-wide parameters */
1920: PHP_FUNCTION(ldap_get_option)
1921: {
1922: zval *link, *retval;
1923: ldap_linkdata *ld;
1924: long option;
1925:
1926: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rlz", &link, &option, &retval) != SUCCESS) {
1927: return;
1928: }
1929:
1930: ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
1931:
1932: switch (option) {
1933: /* options with int value */
1934: case LDAP_OPT_DEREF:
1935: case LDAP_OPT_SIZELIMIT:
1936: case LDAP_OPT_TIMELIMIT:
1937: case LDAP_OPT_PROTOCOL_VERSION:
1938: case LDAP_OPT_ERROR_NUMBER:
1939: case LDAP_OPT_REFERRALS:
1940: #ifdef LDAP_OPT_RESTART
1941: case LDAP_OPT_RESTART:
1942: #endif
1943: {
1944: int val;
1945:
1946: if (ldap_get_option(ld->link, option, &val)) {
1947: RETURN_FALSE;
1948: }
1949: zval_dtor(retval);
1950: ZVAL_LONG(retval, val);
1951: } break;
1952: #ifdef LDAP_OPT_NETWORK_TIMEOUT
1953: case LDAP_OPT_NETWORK_TIMEOUT:
1954: {
1955: struct timeval *timeout = NULL;
1956:
1957: if (ldap_get_option(ld->link, LDAP_OPT_NETWORK_TIMEOUT, (void *) &timeout)) {
1958: if (timeout) {
1959: ldap_memfree(timeout);
1960: }
1961: RETURN_FALSE;
1962: }
1963: if (!timeout) {
1964: RETURN_FALSE;
1965: }
1966: zval_dtor(retval);
1967: ZVAL_LONG(retval, timeout->tv_sec);
1968: ldap_memfree(timeout);
1969: } break;
1970: #elif defined(LDAP_X_OPT_CONNECT_TIMEOUT)
1971: case LDAP_X_OPT_CONNECT_TIMEOUT:
1972: {
1973: int timeout;
1974:
1975: if (ldap_get_option(ld->link, LDAP_X_OPT_CONNECT_TIMEOUT, &timeout)) {
1976: RETURN_FALSE;
1977: }
1978: zval_dtor(retval);
1979: ZVAL_LONG(retval, (timeout / 1000));
1980: } break;
1981: #endif
1982: /* options with string value */
1983: case LDAP_OPT_ERROR_STRING:
1984: #ifdef LDAP_OPT_HOST_NAME
1985: case LDAP_OPT_HOST_NAME:
1986: #endif
1987: #ifdef HAVE_LDAP_SASL
1988: case LDAP_OPT_X_SASL_MECH:
1989: case LDAP_OPT_X_SASL_REALM:
1990: case LDAP_OPT_X_SASL_AUTHCID:
1991: case LDAP_OPT_X_SASL_AUTHZID:
1992: #endif
1993: #ifdef LDAP_OPT_MATCHED_DN
1994: case LDAP_OPT_MATCHED_DN:
1995: #endif
1996: {
1997: char *val = NULL;
1998:
1999: if (ldap_get_option(ld->link, option, &val) || val == NULL || *val == '\0') {
2000: if (val) {
2001: ldap_memfree(val);
2002: }
2003: RETURN_FALSE;
2004: }
2005: zval_dtor(retval);
2006: ZVAL_STRING(retval, val, 1);
2007: ldap_memfree(val);
2008: } break;
2009: /* options not implemented
2010: case LDAP_OPT_SERVER_CONTROLS:
2011: case LDAP_OPT_CLIENT_CONTROLS:
2012: case LDAP_OPT_API_INFO:
2013: case LDAP_OPT_API_FEATURE_INFO:
2014: */
2015: default:
2016: RETURN_FALSE;
2017: }
2018: RETURN_TRUE;
2019: }
2020: /* }}} */
2021:
2022: /* {{{ proto bool ldap_set_option(resource link, int option, mixed newval)
2023: Set the value of various session-wide parameters */
2024: PHP_FUNCTION(ldap_set_option)
2025: {
2026: zval *link, **newval;
2027: ldap_linkdata *ld;
2028: LDAP *ldap;
2029: long option;
2030:
2031: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zlZ", &link, &option, &newval) != SUCCESS) {
2032: return;
2033: }
2034:
2035: if (Z_TYPE_P(link) == IS_NULL) {
2036: ldap = NULL;
2037: } else {
2038: ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
2039: ldap = ld->link;
2040: }
2041:
2042: switch (option) {
2043: /* options with int value */
2044: case LDAP_OPT_DEREF:
2045: case LDAP_OPT_SIZELIMIT:
2046: case LDAP_OPT_TIMELIMIT:
2047: case LDAP_OPT_PROTOCOL_VERSION:
2048: case LDAP_OPT_ERROR_NUMBER:
2049: #ifdef LDAP_OPT_DEBUG_LEVEL
2050: case LDAP_OPT_DEBUG_LEVEL:
2051: #endif
2052: {
2053: int val;
2054:
2055: convert_to_long_ex(newval);
2056: val = Z_LVAL_PP(newval);
2057: if (ldap_set_option(ldap, option, &val)) {
2058: RETURN_FALSE;
2059: }
2060: } break;
2061: #ifdef LDAP_OPT_NETWORK_TIMEOUT
2062: case LDAP_OPT_NETWORK_TIMEOUT:
2063: {
2064: struct timeval timeout;
2065:
2066: convert_to_long_ex(newval);
2067: timeout.tv_sec = Z_LVAL_PP(newval);
2068: timeout.tv_usec = 0;
2069: if (ldap_set_option(ldap, LDAP_OPT_NETWORK_TIMEOUT, (void *) &timeout)) {
2070: RETURN_FALSE;
2071: }
2072: } break;
2073: #elif defined(LDAP_X_OPT_CONNECT_TIMEOUT)
2074: case LDAP_X_OPT_CONNECT_TIMEOUT:
2075: {
2076: int timeout;
2077:
2078: convert_to_long_ex(newval);
2079: timeout = 1000 * Z_LVAL_PP(newval); /* Convert to milliseconds */
2080: if (ldap_set_option(ldap, LDAP_X_OPT_CONNECT_TIMEOUT, &timeout)) {
2081: RETURN_FALSE;
2082: }
2083: } break;
2084: #endif
2085: /* options with string value */
2086: case LDAP_OPT_ERROR_STRING:
2087: #ifdef LDAP_OPT_HOST_NAME
2088: case LDAP_OPT_HOST_NAME:
2089: #endif
2090: #ifdef HAVE_LDAP_SASL
2091: case LDAP_OPT_X_SASL_MECH:
2092: case LDAP_OPT_X_SASL_REALM:
2093: case LDAP_OPT_X_SASL_AUTHCID:
2094: case LDAP_OPT_X_SASL_AUTHZID:
2095: #endif
2096: #ifdef LDAP_OPT_MATCHED_DN
2097: case LDAP_OPT_MATCHED_DN:
2098: #endif
2099: {
2100: char *val;
2101: convert_to_string_ex(newval);
2102: val = Z_STRVAL_PP(newval);
2103: if (ldap_set_option(ldap, option, val)) {
2104: RETURN_FALSE;
2105: }
2106: } break;
2107: /* options with boolean value */
2108: case LDAP_OPT_REFERRALS:
2109: #ifdef LDAP_OPT_RESTART
2110: case LDAP_OPT_RESTART:
2111: #endif
2112: {
2113: void *val;
2114: convert_to_boolean_ex(newval);
2115: val = Z_LVAL_PP(newval)
2116: ? LDAP_OPT_ON : LDAP_OPT_OFF;
2117: if (ldap_set_option(ldap, option, val)) {
2118: RETURN_FALSE;
2119: }
2120: } break;
2121: /* options with control list value */
2122: case LDAP_OPT_SERVER_CONTROLS:
2123: case LDAP_OPT_CLIENT_CONTROLS:
2124: {
2125: LDAPControl *ctrl, **ctrls, **ctrlp;
2126: zval **ctrlval, **val;
2127: int ncontrols;
2128: char error=0;
2129:
2130: if ((Z_TYPE_PP(newval) != IS_ARRAY) || !(ncontrols = zend_hash_num_elements(Z_ARRVAL_PP(newval)))) {
2131: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Expected non-empty array value for this option");
2132: RETURN_FALSE;
2133: }
2134: ctrls = safe_emalloc((1 + ncontrols), sizeof(*ctrls), 0);
2135: *ctrls = NULL;
2136: ctrlp = ctrls;
2137: zend_hash_internal_pointer_reset(Z_ARRVAL_PP(newval));
2138: while (zend_hash_get_current_data(Z_ARRVAL_PP(newval), (void**)&ctrlval) == SUCCESS) {
2139: if (Z_TYPE_PP(ctrlval) != IS_ARRAY) {
2140: php_error_docref(NULL TSRMLS_CC, E_WARNING, "The array value must contain only arrays, where each array is a control");
2141: error = 1;
2142: break;
2143: }
2144: if (zend_hash_find(Z_ARRVAL_PP(ctrlval), "oid", sizeof("oid"), (void **) &val) != SUCCESS) {
2145: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Control must have an oid key");
2146: error = 1;
2147: break;
2148: }
2149: ctrl = *ctrlp = emalloc(sizeof(**ctrlp));
2150: convert_to_string_ex(val);
2151: ctrl->ldctl_oid = Z_STRVAL_PP(val);
2152: if (zend_hash_find(Z_ARRVAL_PP(ctrlval), "value", sizeof("value"), (void **) &val) == SUCCESS) {
2153: convert_to_string_ex(val);
2154: ctrl->ldctl_value.bv_val = Z_STRVAL_PP(val);
2155: ctrl->ldctl_value.bv_len = Z_STRLEN_PP(val);
2156: } else {
2157: ctrl->ldctl_value.bv_val = NULL;
2158: ctrl->ldctl_value.bv_len = 0;
2159: }
2160: if (zend_hash_find(Z_ARRVAL_PP(ctrlval), "iscritical", sizeof("iscritical"), (void **) &val) == SUCCESS) {
2161: convert_to_boolean_ex(val);
2162: ctrl->ldctl_iscritical = Z_BVAL_PP(val);
2163: } else {
2164: ctrl->ldctl_iscritical = 0;
2165: }
2166:
2167: ++ctrlp;
2168: *ctrlp = NULL;
2169: zend_hash_move_forward(Z_ARRVAL_PP(newval));
2170: }
2171: if (!error) {
2172: error = ldap_set_option(ldap, option, ctrls);
2173: }
2174: ctrlp = ctrls;
2175: while (*ctrlp) {
2176: efree(*ctrlp);
2177: ctrlp++;
2178: }
2179: efree(ctrls);
2180: if (error) {
2181: RETURN_FALSE;
2182: }
2183: } break;
2184: default:
2185: RETURN_FALSE;
2186: }
2187: RETURN_TRUE;
2188: }
2189: /* }}} */
2190:
2191: #ifdef HAVE_LDAP_PARSE_RESULT
2192: /* {{{ proto bool ldap_parse_result(resource link, resource result, int errcode, string matcheddn, string errmsg, array referrals)
2193: Extract information from result */
2194: PHP_FUNCTION(ldap_parse_result)
2195: {
2196: zval *link, *result, *errcode, *matcheddn, *errmsg, *referrals;
2197: ldap_linkdata *ld;
2198: LDAPMessage *ldap_result;
2199: char **lreferrals, **refp;
2200: char *lmatcheddn, *lerrmsg;
2201: int rc, lerrcode, myargcount = ZEND_NUM_ARGS();
2202:
2203: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rrz|zzz", &link, &result, &errcode, &matcheddn, &errmsg, &referrals) != SUCCESS) {
2204: return;
2205: }
2206:
2207: ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
2208: ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, &result, -1, "ldap result", le_result);
2209:
2210: rc = ldap_parse_result(ld->link, ldap_result, &lerrcode,
2211: myargcount > 3 ? &lmatcheddn : NULL,
2212: myargcount > 4 ? &lerrmsg : NULL,
2213: myargcount > 5 ? &lreferrals : NULL,
2214: NULL /* &serverctrls */,
2215: 0);
2216: if (rc != LDAP_SUCCESS) {
2217: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to parse result: %s", ldap_err2string(rc));
2218: RETURN_FALSE;
2219: }
2220:
2221: zval_dtor(errcode);
2222: ZVAL_LONG(errcode, lerrcode);
2223:
2224: /* Reverse -> fall through */
2225: switch (myargcount) {
2226: case 6:
2227: zval_dtor(referrals);
2228: array_init(referrals);
2229: if (lreferrals != NULL) {
2230: refp = lreferrals;
2231: while (*refp) {
2232: add_next_index_string(referrals, *refp, 1);
2233: refp++;
2234: }
2235: ldap_value_free(lreferrals);
2236: }
2237: case 5:
2238: zval_dtor(errmsg);
2239: if (lerrmsg == NULL) {
2240: ZVAL_EMPTY_STRING(errmsg);
2241: } else {
2242: ZVAL_STRING(errmsg, lerrmsg, 1);
2243: ldap_memfree(lerrmsg);
2244: }
2245: case 4:
2246: zval_dtor(matcheddn);
2247: if (lmatcheddn == NULL) {
2248: ZVAL_EMPTY_STRING(matcheddn);
2249: } else {
2250: ZVAL_STRING(matcheddn, lmatcheddn, 1);
2251: ldap_memfree(lmatcheddn);
2252: }
2253: }
2254: RETURN_TRUE;
2255: }
2256: /* }}} */
2257: #endif
2258:
2259: /* {{{ proto resource ldap_first_reference(resource link, resource result)
2260: Return first reference */
2261: PHP_FUNCTION(ldap_first_reference)
2262: {
2263: zval *link, *result;
2264: ldap_linkdata *ld;
2265: ldap_resultentry *resultentry;
2266: LDAPMessage *ldap_result, *entry;
2267:
2268: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr", &link, &result) != SUCCESS) {
2269: return;
2270: }
2271:
2272: ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
2273: ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, &result, -1, "ldap result", le_result);
2274:
2275: if ((entry = ldap_first_reference(ld->link, ldap_result)) == NULL) {
2276: RETVAL_FALSE;
2277: } else {
2278: resultentry = emalloc(sizeof(ldap_resultentry));
2279: ZEND_REGISTER_RESOURCE(return_value, resultentry, le_result_entry);
2280: resultentry->id = Z_LVAL_P(result);
2281: zend_list_addref(resultentry->id);
2282: resultentry->data = entry;
2283: resultentry->ber = NULL;
2284: }
2285: }
2286: /* }}} */
2287:
2288: /* {{{ proto resource ldap_next_reference(resource link, resource reference_entry)
2289: Get next reference */
2290: PHP_FUNCTION(ldap_next_reference)
2291: {
2292: zval *link, *result_entry;
2293: ldap_linkdata *ld;
2294: ldap_resultentry *resultentry, *resultentry_next;
2295: LDAPMessage *entry_next;
2296:
2297: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr", &link, &result_entry) != SUCCESS) {
2298: return;
2299: }
2300:
2301: ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
2302: ZEND_FETCH_RESOURCE(resultentry, ldap_resultentry *, &result_entry, -1, "ldap result entry", le_result_entry);
2303:
2304: if ((entry_next = ldap_next_reference(ld->link, resultentry->data)) == NULL) {
2305: RETVAL_FALSE;
2306: } else {
2307: resultentry_next = emalloc(sizeof(ldap_resultentry));
2308: ZEND_REGISTER_RESOURCE(return_value, resultentry_next, le_result_entry);
2309: resultentry_next->id = resultentry->id;
2310: zend_list_addref(resultentry->id);
2311: resultentry_next->data = entry_next;
2312: resultentry_next->ber = NULL;
2313: }
2314: }
2315: /* }}} */
2316:
2317: #ifdef HAVE_LDAP_PARSE_REFERENCE
2318: /* {{{ proto bool ldap_parse_reference(resource link, resource reference_entry, array referrals)
2319: Extract information from reference entry */
2320: PHP_FUNCTION(ldap_parse_reference)
2321: {
2322: zval *link, *result_entry, *referrals;
2323: ldap_linkdata *ld;
2324: ldap_resultentry *resultentry;
2325: char **lreferrals, **refp;
2326:
2327: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rrz", &link, &result_entry, &referrals) != SUCCESS) {
2328: return;
2329: }
2330:
2331: ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
2332: ZEND_FETCH_RESOURCE(resultentry, ldap_resultentry *, &result_entry, -1, "ldap result entry", le_result_entry);
2333:
2334: if (ldap_parse_reference(ld->link, resultentry->data, &lreferrals, NULL /* &serverctrls */, 0) != LDAP_SUCCESS) {
2335: RETURN_FALSE;
2336: }
2337:
2338: zval_dtor(referrals);
2339: array_init(referrals);
2340: if (lreferrals != NULL) {
2341: refp = lreferrals;
2342: while (*refp) {
2343: add_next_index_string(referrals, *refp, 1);
2344: refp++;
2345: }
2346: ldap_value_free(lreferrals);
2347: }
2348: RETURN_TRUE;
2349: }
2350: /* }}} */
2351: #endif
2352:
2353: /* {{{ proto bool ldap_rename(resource link, string dn, string newrdn, string newparent, bool deleteoldrdn);
2354: Modify the name of an entry */
2355: PHP_FUNCTION(ldap_rename)
2356: {
2357: zval *link;
2358: ldap_linkdata *ld;
2359: int rc;
2360: char *dn, *newrdn, *newparent;
2361: int dn_len, newrdn_len, newparent_len;
2362: zend_bool deleteoldrdn;
2363:
2364: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsssb", &link, &dn, &dn_len, &newrdn, &newrdn_len, &newparent, &newparent_len, &deleteoldrdn) != SUCCESS) {
2365: return;
2366: }
2367:
2368: ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
2369:
2370: if (newparent_len == 0) {
2371: newparent = NULL;
2372: }
2373:
2374: #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10
2375: rc = ldap_rename_s(ld->link, dn, newrdn, newparent, deleteoldrdn, NULL, NULL);
2376: #else
2377: if (newparent_len != 0) {
2378: php_error_docref(NULL TSRMLS_CC, E_WARNING, "You are using old LDAP API, newparent must be the empty string, can only modify RDN");
2379: RETURN_FALSE;
2380: }
2381: /* could support old APIs but need check for ldap_modrdn2()/ldap_modrdn() */
2382: rc = ldap_modrdn2_s(ld->link, dn, newrdn, deleteoldrdn);
2383: #endif
2384:
2385: if (rc == LDAP_SUCCESS) {
2386: RETURN_TRUE;
2387: }
2388: RETURN_FALSE;
2389: }
2390: /* }}} */
2391:
2392: #ifdef HAVE_LDAP_START_TLS_S
2393: /* {{{ proto bool ldap_start_tls(resource link)
2394: Start TLS */
2395: PHP_FUNCTION(ldap_start_tls)
2396: {
2397: zval *link;
2398: ldap_linkdata *ld;
2399: int rc, protocol = LDAP_VERSION3;
2400:
2401: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &link) != SUCCESS) {
2402: return;
2403: }
2404:
2405: ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
2406:
2407: if (((rc = ldap_set_option(ld->link, LDAP_OPT_PROTOCOL_VERSION, &protocol)) != LDAP_SUCCESS) ||
2408: ((rc = ldap_start_tls_s(ld->link, NULL, NULL)) != LDAP_SUCCESS)
2409: ) {
2410: php_error_docref(NULL TSRMLS_CC, E_WARNING,"Unable to start TLS: %s", ldap_err2string(rc));
2411: RETURN_FALSE;
2412: } else {
2413: RETURN_TRUE;
2414: }
2415: }
2416: /* }}} */
2417: #endif
2418: #endif /* (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10 */
2419:
2420: #if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC)
2421: /* {{{ _ldap_rebind_proc()
2422: */
2423: int _ldap_rebind_proc(LDAP *ldap, const char *url, ber_tag_t req, ber_int_t msgid, void *params)
2424: {
2425: ldap_linkdata *ld;
2426: int retval;
2427: zval *cb_url;
2428: zval **cb_args[2];
2429: zval *cb_retval;
2430: zval *cb_link = (zval *) params;
2431: TSRMLS_FETCH();
2432:
2433: ld = (ldap_linkdata *) zend_fetch_resource(&cb_link TSRMLS_CC, -1, "ldap link", NULL, 1, le_link);
2434:
2435: /* link exists and callback set? */
2436: if (ld == NULL || ld->rebindproc == NULL) {
2437: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Link not found or no callback set");
2438: return LDAP_OTHER;
2439: }
2440:
2441: /* callback */
2442: MAKE_STD_ZVAL(cb_url);
2443: ZVAL_STRING(cb_url, estrdup(url), 0);
2444: cb_args[0] = &cb_link;
2445: cb_args[1] = &cb_url;
2446: if (call_user_function_ex(EG(function_table), NULL, ld->rebindproc, &cb_retval, 2, cb_args, 0, NULL TSRMLS_CC) == SUCCESS && cb_retval) {
2447: convert_to_long_ex(&cb_retval);
2448: retval = Z_LVAL_P(cb_retval);
2449: zval_ptr_dtor(&cb_retval);
2450: } else {
2451: php_error_docref(NULL TSRMLS_CC, E_WARNING, "rebind_proc PHP callback failed");
2452: retval = LDAP_OTHER;
2453: }
2454: zval_dtor(cb_url);
2455: FREE_ZVAL(cb_url);
2456: return retval;
2457: }
2458: /* }}} */
2459:
2460: /* {{{ proto bool ldap_set_rebind_proc(resource link, string callback)
2461: Set a callback function to do re-binds on referral chasing. */
2462: PHP_FUNCTION(ldap_set_rebind_proc)
2463: {
2464: zval *link, *callback;
2465: ldap_linkdata *ld;
2466: char *callback_name;
2467:
2468: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz", &link, &callback) != SUCCESS) {
2469: RETURN_FALSE;
2470: }
2471:
2472: ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
2473:
2474: if (Z_TYPE_P(callback) == IS_STRING && Z_STRLEN_P(callback) == 0) {
2475: /* unregister rebind procedure */
2476: if (ld->rebindproc != NULL) {
2477: zval_dtor(ld->rebindproc);
1.1.1.4 ! misho 2478: FREE_ZVAL(ld->rebindproc);
1.1 misho 2479: ld->rebindproc = NULL;
2480: ldap_set_rebind_proc(ld->link, NULL, NULL);
2481: }
2482: RETURN_TRUE;
2483: }
2484:
2485: /* callable? */
2486: if (!zend_is_callable(callback, 0, &callback_name TSRMLS_CC)) {
2487: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Two arguments expected for '%s' to be a valid callback", callback_name);
2488: efree(callback_name);
2489: RETURN_FALSE;
2490: }
2491: efree(callback_name);
2492:
2493: /* register rebind procedure */
2494: if (ld->rebindproc == NULL) {
2495: ldap_set_rebind_proc(ld->link, _ldap_rebind_proc, (void *) link);
2496: } else {
2497: zval_dtor(ld->rebindproc);
2498: }
2499:
2500: ALLOC_ZVAL(ld->rebindproc);
2501: *ld->rebindproc = *callback;
2502: zval_copy_ctor(ld->rebindproc);
2503: RETURN_TRUE;
2504: }
2505: /* }}} */
2506: #endif
2507:
2508: #ifdef STR_TRANSLATION
2509: /* {{{ php_ldap_do_translate
2510: */
2511: static void php_ldap_do_translate(INTERNAL_FUNCTION_PARAMETERS, int way)
2512: {
2513: char *value;
2514: int result, ldap_len;
2515:
2516: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &value, &value_len) != SUCCESS) {
2517: return;
2518: }
2519:
2520: if (value_len == 0) {
2521: RETURN_FALSE;
2522: }
2523:
2524: if (way == 1) {
2525: result = ldap_8859_to_t61(&value, &value_len, 0);
2526: } else {
2527: result = ldap_t61_to_8859(&value, &value_len, 0);
2528: }
2529:
2530: if (result == LDAP_SUCCESS) {
2531: RETVAL_STRINGL(value, value_len, 1);
2532: free(value);
2533: } else {
2534: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Conversion from iso-8859-1 to t61 failed: %s", ldap_err2string(result));
2535: RETVAL_FALSE;
2536: }
2537: }
2538: /* }}} */
2539:
2540: /* {{{ proto string ldap_t61_to_8859(string value)
2541: Translate t61 characters to 8859 characters */
2542: PHP_FUNCTION(ldap_t61_to_8859)
2543: {
2544: php_ldap_do_translate(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
2545: }
2546: /* }}} */
2547:
2548: /* {{{ proto string ldap_8859_to_t61(string value)
2549: Translate 8859 characters to t61 characters */
2550: PHP_FUNCTION(ldap_8859_to_t61)
2551: {
2552: php_ldap_do_translate(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
2553: }
2554: /* }}} */
2555: #endif
2556:
1.1.1.2 misho 2557: #ifdef LDAP_CONTROL_PAGEDRESULTS
2558: /* {{{ proto mixed ldap_control_paged_result(resource link, int pagesize [, bool iscritical [, string cookie]])
2559: Inject paged results control*/
2560: PHP_FUNCTION(ldap_control_paged_result)
2561: {
2562: long pagesize;
2563: zend_bool iscritical;
2564: zval *link;
2565: char *cookie = NULL;
2566: int cookie_len = 0;
2567: struct berval lcookie = { 0, NULL };
2568: ldap_linkdata *ld;
2569: LDAP *ldap;
2570: BerElement *ber = NULL;
2571: LDAPControl ctrl, *ctrlsp[2];
2572: int rc, myargcount = ZEND_NUM_ARGS();
2573:
2574: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl|bs", &link, &pagesize, &iscritical, &cookie, &cookie_len) != SUCCESS) {
2575: return;
2576: }
2577:
2578: if (Z_TYPE_P(link) == IS_NULL) {
2579: ldap = NULL;
2580: } else {
2581: ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
2582: ldap = ld->link;
2583: }
2584:
2585: ber = ber_alloc_t(LBER_USE_DER);
2586: if (ber == NULL) {
2587: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to alloc BER encoding resources for paged results control");
2588: RETURN_FALSE;
2589: }
2590:
2591: ctrl.ldctl_iscritical = 0;
2592:
2593: switch (myargcount) {
2594: case 4:
2595: lcookie.bv_val = cookie;
2596: lcookie.bv_len = cookie_len;
2597: /* fallthru */
2598: case 3:
2599: ctrl.ldctl_iscritical = (int)iscritical;
2600: /* fallthru */
2601: }
2602:
2603: if (ber_printf(ber, "{iO}", (int)pagesize, &lcookie) == LBER_ERROR) {
2604: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to BER printf paged results control");
2605: RETVAL_FALSE;
2606: goto lcpr_error_out;
2607: }
2608: rc = ber_flatten2(ber, &ctrl.ldctl_value, 0);
2609: if (rc == LBER_ERROR) {
2610: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to BER encode paged results control");
2611: RETVAL_FALSE;
2612: goto lcpr_error_out;
2613: }
2614:
2615: ctrl.ldctl_oid = LDAP_CONTROL_PAGEDRESULTS;
2616:
2617: if (ldap) {
2618: /* directly set the option */
2619: ctrlsp[0] = &ctrl;
2620: ctrlsp[1] = NULL;
2621:
2622: rc = ldap_set_option(ldap, LDAP_OPT_SERVER_CONTROLS, ctrlsp);
2623: if (rc != LDAP_SUCCESS) {
2624: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set paged results control: %s (%d)", ldap_err2string(rc), rc);
2625: RETVAL_FALSE;
2626: goto lcpr_error_out;
2627: }
2628: RETVAL_TRUE;
2629: } else {
2630: /* return a PHP control object */
2631: array_init(return_value);
2632:
2633: add_assoc_string(return_value, "oid", ctrl.ldctl_oid, 1);
2634: if (ctrl.ldctl_value.bv_len) {
2635: add_assoc_stringl(return_value, "value", ctrl.ldctl_value.bv_val, ctrl.ldctl_value.bv_len, 1);
2636: }
2637: if (ctrl.ldctl_iscritical) {
2638: add_assoc_bool(return_value, "iscritical", ctrl.ldctl_iscritical);
2639: }
2640: }
2641:
2642: lcpr_error_out:
2643: if (ber != NULL) {
2644: ber_free(ber, 1);
2645: }
2646: return;
2647: }
2648: /* }}} */
2649:
2650: /* {{{ proto bool ldap_control_paged_result_response(resource link, resource result [, string &cookie [, int &estimated]])
2651: Extract paged results control response */
2652: PHP_FUNCTION(ldap_control_paged_result_response)
2653: {
2654: zval *link, *result, *cookie, *estimated;
2655: struct berval lcookie;
2656: int lestimated;
2657: ldap_linkdata *ld;
2658: LDAPMessage *ldap_result;
2659: LDAPControl **lserverctrls, *lctrl;
2660: BerElement *ber;
2661: ber_tag_t tag;
2662: int rc, lerrcode, myargcount = ZEND_NUM_ARGS();
2663:
2664: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr|zz", &link, &result, &cookie, &estimated) != SUCCESS) {
2665: return;
2666: }
2667:
2668: ZEND_FETCH_RESOURCE(ld, ldap_linkdata *, &link, -1, "ldap link", le_link);
2669: ZEND_FETCH_RESOURCE(ldap_result, LDAPMessage *, &result, -1, "ldap result", le_result);
2670:
2671: rc = ldap_parse_result(ld->link,
2672: ldap_result,
2673: &lerrcode,
2674: NULL, /* matcheddn */
2675: NULL, /* errmsg */
2676: NULL, /* referrals */
2677: &lserverctrls,
2678: 0);
2679:
2680: if (rc != LDAP_SUCCESS) {
2681: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to parse result: %s (%d)", ldap_err2string(rc), rc);
2682: RETURN_FALSE;
2683: }
2684:
2685: if (lerrcode != LDAP_SUCCESS) {
2686: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Result is: %s (%d)", ldap_err2string(lerrcode), lerrcode);
2687: RETURN_FALSE;
2688: }
2689:
2690: if (lserverctrls == NULL) {
2691: php_error_docref(NULL TSRMLS_CC, E_WARNING, "No server controls in result");
2692: RETURN_FALSE;
2693: }
2694:
2695: lctrl = ldap_find_control(LDAP_CONTROL_PAGEDRESULTS, lserverctrls);
2696: if (lctrl == NULL) {
2697: ldap_controls_free(lserverctrls);
2698: php_error_docref(NULL TSRMLS_CC, E_WARNING, "No paged results control response in result");
2699: RETURN_FALSE;
2700: }
2701:
2702: ber = ber_init(&lctrl->ldctl_value);
2703: if (ber == NULL) {
2704: ldap_controls_free(lserverctrls);
2705: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to alloc BER decoding resources for paged results control response");
2706: RETURN_FALSE;
2707: }
2708:
2709: tag = ber_scanf(ber, "{io}", &lestimated, &lcookie);
2710: (void)ber_free(ber, 1);
2711:
2712: if (tag == LBER_ERROR) {
2713: ldap_controls_free(lserverctrls);
2714: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to decode paged results control response");
2715: RETURN_FALSE;
2716: }
2717:
2718: if (lestimated < 0) {
2719: ldap_controls_free(lserverctrls);
2720: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid paged results control response value");
2721: RETURN_FALSE;
2722: }
2723:
2724: ldap_controls_free(lserverctrls);
2725: if (myargcount == 4) {
2726: zval_dtor(estimated);
2727: ZVAL_LONG(estimated, lestimated);
2728: }
2729:
2730: zval_dtor(cookie);
2731: if (lcookie.bv_len == 0) {
2732: ZVAL_EMPTY_STRING(cookie);
2733: } else {
2734: ZVAL_STRINGL(cookie, lcookie.bv_val, lcookie.bv_len, 1);
2735: }
2736: ldap_memfree(lcookie.bv_val);
2737:
2738: RETURN_TRUE;
2739: }
2740: /* }}} */
2741: #endif
2742:
1.1 misho 2743: /* {{{ arginfo */
2744: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_connect, 0, 0, 0)
2745: ZEND_ARG_INFO(0, hostname)
2746: ZEND_ARG_INFO(0, port)
2747: #ifdef HAVE_ORALDAP
2748: ZEND_ARG_INFO(0, wallet)
2749: ZEND_ARG_INFO(0, wallet_passwd)
2750: ZEND_ARG_INFO(0, authmode)
2751: #endif
2752: ZEND_END_ARG_INFO()
2753:
2754: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_resource, 0, 0, 1)
2755: ZEND_ARG_INFO(0, link_identifier)
2756: ZEND_END_ARG_INFO()
2757:
2758: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_bind, 0, 0, 1)
2759: ZEND_ARG_INFO(0, link_identifier)
2760: ZEND_ARG_INFO(0, bind_rdn)
2761: ZEND_ARG_INFO(0, bind_password)
2762: ZEND_END_ARG_INFO()
2763:
2764: #ifdef HAVE_LDAP_SASL
2765: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_sasl_bind, 0, 0, 1)
2766: ZEND_ARG_INFO(0, link)
2767: ZEND_ARG_INFO(0, binddn)
2768: ZEND_ARG_INFO(0, password)
2769: ZEND_ARG_INFO(0, sasl_mech)
2770: ZEND_ARG_INFO(0, sasl_realm)
2771: ZEND_ARG_INFO(0, sasl_authz_id)
2772: ZEND_ARG_INFO(0, props)
2773: ZEND_END_ARG_INFO()
2774: #endif
2775:
2776: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_read, 0, 0, 3)
2777: ZEND_ARG_INFO(0, link_identifier)
2778: ZEND_ARG_INFO(0, base_dn)
2779: ZEND_ARG_INFO(0, filter)
2780: ZEND_ARG_INFO(0, attributes)
2781: ZEND_ARG_INFO(0, attrsonly)
2782: ZEND_ARG_INFO(0, sizelimit)
2783: ZEND_ARG_INFO(0, timelimit)
2784: ZEND_ARG_INFO(0, deref)
2785: ZEND_END_ARG_INFO()
2786:
2787: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_list, 0, 0, 3)
2788: ZEND_ARG_INFO(0, link_identifier)
2789: ZEND_ARG_INFO(0, base_dn)
2790: ZEND_ARG_INFO(0, filter)
2791: ZEND_ARG_INFO(0, attributes)
2792: ZEND_ARG_INFO(0, attrsonly)
2793: ZEND_ARG_INFO(0, sizelimit)
2794: ZEND_ARG_INFO(0, timelimit)
2795: ZEND_ARG_INFO(0, deref)
2796: ZEND_END_ARG_INFO()
2797:
2798: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_search, 0, 0, 3)
2799: ZEND_ARG_INFO(0, link_identifier)
2800: ZEND_ARG_INFO(0, base_dn)
2801: ZEND_ARG_INFO(0, filter)
2802: ZEND_ARG_INFO(0, attributes)
2803: ZEND_ARG_INFO(0, attrsonly)
2804: ZEND_ARG_INFO(0, sizelimit)
2805: ZEND_ARG_INFO(0, timelimit)
2806: ZEND_ARG_INFO(0, deref)
2807: ZEND_END_ARG_INFO()
2808:
2809: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_count_entries, 0, 0, 2)
2810: ZEND_ARG_INFO(0, link_identifier)
2811: ZEND_ARG_INFO(0, result_identifier)
2812: ZEND_END_ARG_INFO()
2813:
2814: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_first_entry, 0, 0, 2)
2815: ZEND_ARG_INFO(0, link_identifier)
2816: ZEND_ARG_INFO(0, result_identifier)
2817: ZEND_END_ARG_INFO()
2818:
2819: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_next_entry, 0, 0, 2)
2820: ZEND_ARG_INFO(0, link_identifier)
2821: ZEND_ARG_INFO(0, result_identifier)
2822: ZEND_END_ARG_INFO()
2823:
2824: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_get_entries, 0, 0, 2)
2825: ZEND_ARG_INFO(0, link_identifier)
2826: ZEND_ARG_INFO(0, result_identifier)
2827: ZEND_END_ARG_INFO()
2828:
2829: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_first_attribute, 0, 0, 2)
2830: ZEND_ARG_INFO(0, link_identifier)
2831: ZEND_ARG_INFO(0, result_entry_identifier)
2832: ZEND_END_ARG_INFO()
2833:
2834: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_next_attribute, 0, 0, 2)
2835: ZEND_ARG_INFO(0, link_identifier)
2836: ZEND_ARG_INFO(0, result_entry_identifier)
2837: ZEND_END_ARG_INFO()
2838:
2839: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_get_attributes, 0, 0, 2)
2840: ZEND_ARG_INFO(0, link_identifier)
2841: ZEND_ARG_INFO(0, result_entry_identifier)
2842: ZEND_END_ARG_INFO()
2843:
2844: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_get_values, 0, 0, 3)
2845: ZEND_ARG_INFO(0, link_identifier)
2846: ZEND_ARG_INFO(0, result_entry_identifier)
2847: ZEND_ARG_INFO(0, attribute)
2848: ZEND_END_ARG_INFO()
2849:
2850: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_get_values_len, 0, 0, 3)
2851: ZEND_ARG_INFO(0, link_identifier)
2852: ZEND_ARG_INFO(0, result_entry_identifier)
2853: ZEND_ARG_INFO(0, attribute)
2854: ZEND_END_ARG_INFO()
2855:
2856: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_get_dn, 0, 0, 2)
2857: ZEND_ARG_INFO(0, link_identifier)
2858: ZEND_ARG_INFO(0, result_entry_identifier)
2859: ZEND_END_ARG_INFO()
2860:
2861: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_explode_dn, 0, 0, 2)
2862: ZEND_ARG_INFO(0, dn)
2863: ZEND_ARG_INFO(0, with_attrib)
2864: ZEND_END_ARG_INFO()
2865:
2866: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_dn2ufn, 0, 0, 1)
2867: ZEND_ARG_INFO(0, dn)
2868: ZEND_END_ARG_INFO()
2869:
2870: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_add, 0, 0, 3)
2871: ZEND_ARG_INFO(0, link_identifier)
2872: ZEND_ARG_INFO(0, dn)
2873: ZEND_ARG_INFO(0, entry)
2874: ZEND_END_ARG_INFO()
2875:
2876: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_delete, 0, 0, 2)
2877: ZEND_ARG_INFO(0, link_identifier)
2878: ZEND_ARG_INFO(0, dn)
2879: ZEND_END_ARG_INFO()
2880:
2881: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_modify, 0, 0, 3)
2882: ZEND_ARG_INFO(0, link_identifier)
2883: ZEND_ARG_INFO(0, dn)
2884: ZEND_ARG_INFO(0, entry)
2885: ZEND_END_ARG_INFO()
2886:
1.1.1.4 ! misho 2887: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_modify_batch, 0, 0, 3)
! 2888: ZEND_ARG_INFO(0, link_identifier)
! 2889: ZEND_ARG_INFO(0, dn)
! 2890: ZEND_ARG_ARRAY_INFO(0, modifications_info, 0)
! 2891: ZEND_END_ARG_INFO()
! 2892:
1.1 misho 2893: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_mod_add, 0, 0, 3)
2894: ZEND_ARG_INFO(0, link_identifier)
2895: ZEND_ARG_INFO(0, dn)
2896: ZEND_ARG_INFO(0, entry)
2897: ZEND_END_ARG_INFO()
2898:
2899: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_mod_replace, 0, 0, 3)
2900: ZEND_ARG_INFO(0, link_identifier)
2901: ZEND_ARG_INFO(0, dn)
2902: ZEND_ARG_INFO(0, entry)
2903: ZEND_END_ARG_INFO()
2904:
2905: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_mod_del, 0, 0, 3)
2906: ZEND_ARG_INFO(0, link_identifier)
2907: ZEND_ARG_INFO(0, dn)
2908: ZEND_ARG_INFO(0, entry)
2909: ZEND_END_ARG_INFO()
2910:
2911: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_err2str, 0, 0, 1)
2912: ZEND_ARG_INFO(0, errno)
2913: ZEND_END_ARG_INFO()
2914:
2915: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_compare, 0, 0, 4)
2916: ZEND_ARG_INFO(0, link_identifier)
2917: ZEND_ARG_INFO(0, dn)
2918: ZEND_ARG_INFO(0, attribute)
2919: ZEND_ARG_INFO(0, value)
2920: ZEND_END_ARG_INFO()
2921:
2922: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_sort, 0, 0, 3)
2923: ZEND_ARG_INFO(0, link)
2924: ZEND_ARG_INFO(0, result)
2925: ZEND_ARG_INFO(0, sortfilter)
2926: ZEND_END_ARG_INFO()
2927:
1.1.1.2 misho 2928: #ifdef LDAP_CONTROL_PAGEDRESULTS
2929: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_control_paged_result, 0, 0, 2)
2930: ZEND_ARG_INFO(0, link)
2931: ZEND_ARG_INFO(0, pagesize)
2932: ZEND_ARG_INFO(0, iscritical)
2933: ZEND_ARG_INFO(0, cookie)
2934: ZEND_END_ARG_INFO();
2935:
2936: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_control_paged_result_response, 0, 0, 2)
2937: ZEND_ARG_INFO(0, link)
2938: ZEND_ARG_INFO(0, result)
2939: ZEND_ARG_INFO(1, cookie)
2940: ZEND_ARG_INFO(1, estimated)
2941: ZEND_END_ARG_INFO();
2942: #endif
2943:
1.1 misho 2944: #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10
2945: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_rename, 0, 0, 5)
2946: ZEND_ARG_INFO(0, link_identifier)
2947: ZEND_ARG_INFO(0, dn)
2948: ZEND_ARG_INFO(0, newrdn)
2949: ZEND_ARG_INFO(0, newparent)
2950: ZEND_ARG_INFO(0, deleteoldrdn)
2951: ZEND_END_ARG_INFO()
2952:
2953: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_get_option, 0, 0, 3)
2954: ZEND_ARG_INFO(0, link_identifier)
2955: ZEND_ARG_INFO(0, option)
2956: ZEND_ARG_INFO(1, retval)
2957: ZEND_END_ARG_INFO()
2958:
2959: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_set_option, 0, 0, 3)
2960: ZEND_ARG_INFO(0, link_identifier)
2961: ZEND_ARG_INFO(0, option)
2962: ZEND_ARG_INFO(0, newval)
2963: ZEND_END_ARG_INFO()
2964:
2965: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_first_reference, 0, 0, 2)
2966: ZEND_ARG_INFO(0, link)
2967: ZEND_ARG_INFO(0, result)
2968: ZEND_END_ARG_INFO()
2969:
2970: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_next_reference, 0, 0, 2)
2971: ZEND_ARG_INFO(0, link)
2972: ZEND_ARG_INFO(0, entry)
2973: ZEND_END_ARG_INFO()
2974:
2975: #ifdef HAVE_LDAP_PARSE_REFERENCE
2976: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_parse_reference, 0, 0, 3)
2977: ZEND_ARG_INFO(0, link)
2978: ZEND_ARG_INFO(0, entry)
2979: ZEND_ARG_INFO(1, referrals)
2980: ZEND_END_ARG_INFO()
2981: #endif
2982:
2983:
2984: #ifdef HAVE_LDAP_PARSE_RESULT
2985: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_parse_result, 0, 0, 3)
2986: ZEND_ARG_INFO(0, link)
2987: ZEND_ARG_INFO(0, result)
2988: ZEND_ARG_INFO(1, errcode)
2989: ZEND_ARG_INFO(1, matcheddn)
2990: ZEND_ARG_INFO(1, errmsg)
2991: ZEND_ARG_INFO(1, referrals)
2992: ZEND_END_ARG_INFO()
2993: #endif
2994: #endif
2995:
2996: #if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC)
2997: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_set_rebind_proc, 0, 0, 2)
2998: ZEND_ARG_INFO(0, link)
2999: ZEND_ARG_INFO(0, callback)
3000: ZEND_END_ARG_INFO()
3001: #endif
3002:
3003: #ifdef STR_TRANSLATION
3004: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_t61_to_8859, 0, 0, 1)
3005: ZEND_ARG_INFO(0, value)
3006: ZEND_END_ARG_INFO()
3007:
3008: ZEND_BEGIN_ARG_INFO_EX(arginfo_ldap_8859_to_t61, 0, 0, 1)
3009: ZEND_ARG_INFO(0, value)
3010: ZEND_END_ARG_INFO()
3011: #endif
3012: /* }}} */
3013:
3014: /*
3015: This is just a small subset of the functionality provided by the LDAP library. All the
3016: operations are synchronous. Referrals are not handled automatically.
3017: */
3018: /* {{{ ldap_functions[]
3019: */
3020: const zend_function_entry ldap_functions[] = {
3021: PHP_FE(ldap_connect, arginfo_ldap_connect)
3022: PHP_FALIAS(ldap_close, ldap_unbind, arginfo_ldap_resource)
3023: PHP_FE(ldap_bind, arginfo_ldap_bind)
3024: #ifdef HAVE_LDAP_SASL
3025: PHP_FE(ldap_sasl_bind, arginfo_ldap_sasl_bind)
3026: #endif
3027: PHP_FE(ldap_unbind, arginfo_ldap_resource)
3028: PHP_FE(ldap_read, arginfo_ldap_read)
3029: PHP_FE(ldap_list, arginfo_ldap_list)
3030: PHP_FE(ldap_search, arginfo_ldap_search)
3031: PHP_FE(ldap_free_result, arginfo_ldap_resource)
3032: PHP_FE(ldap_count_entries, arginfo_ldap_count_entries)
3033: PHP_FE(ldap_first_entry, arginfo_ldap_first_entry)
3034: PHP_FE(ldap_next_entry, arginfo_ldap_next_entry)
3035: PHP_FE(ldap_get_entries, arginfo_ldap_get_entries)
3036: PHP_FE(ldap_first_attribute, arginfo_ldap_first_attribute)
3037: PHP_FE(ldap_next_attribute, arginfo_ldap_next_attribute)
3038: PHP_FE(ldap_get_attributes, arginfo_ldap_get_attributes)
3039: PHP_FALIAS(ldap_get_values, ldap_get_values_len, arginfo_ldap_get_values)
3040: PHP_FE(ldap_get_values_len, arginfo_ldap_get_values_len)
3041: PHP_FE(ldap_get_dn, arginfo_ldap_get_dn)
3042: PHP_FE(ldap_explode_dn, arginfo_ldap_explode_dn)
3043: PHP_FE(ldap_dn2ufn, arginfo_ldap_dn2ufn)
3044: PHP_FE(ldap_add, arginfo_ldap_add)
3045: PHP_FE(ldap_delete, arginfo_ldap_delete)
1.1.1.4 ! misho 3046: PHP_FE(ldap_modify_batch, arginfo_ldap_modify_batch)
1.1 misho 3047: PHP_FALIAS(ldap_modify, ldap_mod_replace, arginfo_ldap_modify)
3048:
3049: /* additional functions for attribute based modifications, Gerrit Thomson */
3050: PHP_FE(ldap_mod_add, arginfo_ldap_mod_add)
3051: PHP_FE(ldap_mod_replace, arginfo_ldap_mod_replace)
3052: PHP_FE(ldap_mod_del, arginfo_ldap_mod_del)
3053: /* end gjt mod */
3054:
3055: PHP_FE(ldap_errno, arginfo_ldap_resource)
3056: PHP_FE(ldap_err2str, arginfo_ldap_err2str)
3057: PHP_FE(ldap_error, arginfo_ldap_resource)
3058: PHP_FE(ldap_compare, arginfo_ldap_compare)
3059: PHP_FE(ldap_sort, arginfo_ldap_sort)
3060:
3061: #if (LDAP_API_VERSION > 2000) || HAVE_NSLDAP || HAVE_ORALDAP_10
3062: PHP_FE(ldap_rename, arginfo_ldap_rename)
3063: PHP_FE(ldap_get_option, arginfo_ldap_get_option)
3064: PHP_FE(ldap_set_option, arginfo_ldap_set_option)
3065: PHP_FE(ldap_first_reference, arginfo_ldap_first_reference)
3066: PHP_FE(ldap_next_reference, arginfo_ldap_next_reference)
3067: #ifdef HAVE_LDAP_PARSE_REFERENCE
3068: PHP_FE(ldap_parse_reference, arginfo_ldap_parse_reference)
3069: #endif
3070: #ifdef HAVE_LDAP_PARSE_RESULT
3071: PHP_FE(ldap_parse_result, arginfo_ldap_parse_result)
3072: #endif
3073: #ifdef HAVE_LDAP_START_TLS_S
3074: PHP_FE(ldap_start_tls, arginfo_ldap_resource)
3075: #endif
3076: #endif
3077:
3078: #if defined(LDAP_API_FEATURE_X_OPENLDAP) && defined(HAVE_3ARG_SETREBINDPROC)
3079: PHP_FE(ldap_set_rebind_proc, arginfo_ldap_set_rebind_proc)
3080: #endif
3081:
3082: #ifdef STR_TRANSLATION
3083: PHP_FE(ldap_t61_to_8859, arginfo_ldap_t61_to_8859)
3084: PHP_FE(ldap_8859_to_t61, arginfo_ldap_8859_to_t61)
3085: #endif
3086:
1.1.1.2 misho 3087: #ifdef LDAP_CONTROL_PAGEDRESULTS
3088: PHP_FE(ldap_control_paged_result, arginfo_ldap_control_paged_result)
3089: PHP_FE(ldap_control_paged_result_response, arginfo_ldap_control_paged_result_response)
3090: #endif
1.1 misho 3091: PHP_FE_END
3092: };
3093: /* }}} */
3094:
3095: zend_module_entry ldap_module_entry = { /* {{{ */
3096: STANDARD_MODULE_HEADER,
3097: "ldap",
3098: ldap_functions,
3099: PHP_MINIT(ldap),
3100: PHP_MSHUTDOWN(ldap),
3101: NULL,
3102: NULL,
3103: PHP_MINFO(ldap),
3104: NO_VERSION_YET,
3105: PHP_MODULE_GLOBALS(ldap),
3106: PHP_GINIT(ldap),
3107: NULL,
3108: NULL,
3109: STANDARD_MODULE_PROPERTIES_EX
3110: };
3111: /* }}} */
3112:
3113: /*
3114: * Local variables:
3115: * tab-width: 4
3116: * c-basic-offset: 4
3117: * End:
3118: * vim600: sw=4 ts=4 fdm=marker
3119: * vim<600: sw=4 ts=4
3120: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>