1 /*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | https://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Authors: Rex Logan <veebert@dimensional.com> |
14 | Mark Musone <musone@afterfive.com> |
15 | Brian Wang <brian@vividnet.com> |
16 | Kaj-Michael Lang <milang@tal.org> |
17 | Antoni Pamies Olive <toni@readysoft.net> |
18 | Rasmus Lerdorf <rasmus@php.net> |
19 | Chuck Hagenbuch <chuck@horde.org> |
20 | Andrew Skalski <askalski@chekinc.com> |
21 | Hartmut Holzgraefe <hholzgra@php.net> |
22 | Jani Taskinen <jani.taskinen@iki.fi> |
23 | Daniel R. Kalowsky <kalowsky@php.net> |
24 | PHP 4.0 updates: Zeev Suraski <zeev@php.net> |
25 +----------------------------------------------------------------------+
26 */
27
28 #define IMAP41
29
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33
34 #include "php.h"
35 #include "php_ini.h"
36 #include "php_streams.h"
37 #include "Zend/zend_attributes.h"
38 #include "Zend/zend_exceptions.h"
39 #include "ext/standard/php_string.h"
40 #include "ext/standard/info.h"
41 #include "ext/standard/file.h"
42 #include "zend_smart_str.h"
43 #include "ext/pcre/php_pcre.h"
44
45 #ifdef ERROR
46 #undef ERROR
47 #endif
48 #include "php_imap.h"
49
50 #include <time.h>
51 #include <stdio.h>
52 #include <ctype.h>
53 #include <signal.h>
54
55 #ifdef PHP_WIN32
56 #include <winsock2.h>
57 #include <stdlib.h>
58 #include "win32/sendmail.h"
59 MAILSTREAM DEFAULTPROTO;
60 #endif
61
62 #define CRLF "\015\012"
63 #define CRLF_LEN sizeof("\015\012") - 1
64 #define PHP_EXPUNGE 32768
65 #define PHP_IMAP_ADDRESS_SIZE_BUF 10
66 #ifndef SENDBUFLEN
67 #define SENDBUFLEN 16385
68 #endif
69
70 #define PHP_IMAP_OPENTIMEOUT 1
71 #define PHP_IMAP_READTIMEOUT 2
72 #define PHP_IMAP_WRITETIMEOUT 3
73 #define PHP_IMAP_CLOSETIMEOUT 4
74
75 #define SA_ALL SA_MESSAGES | SA_RECENT | SA_UNSEEN | SA_UIDNEXT | SA_UIDVALIDITY
76
77 #include "php_imap_arginfo.h"
78
79 #if defined(__GNUC__) && __GNUC__ >= 4
80 # define PHP_IMAP_EXPORT __attribute__ ((visibility("default")))
81 #else
82 # define PHP_IMAP_EXPORT
83 #endif
84
85 static void _php_make_header_object(zval *myzvalue, ENVELOPE *en);
86 static void _php_imap_add_body(zval *arg, BODY *body);
87 static zend_string* _php_imap_parse_address(ADDRESS *addresslist, zval *paddress);
88 static zend_string* _php_rfc822_write_address(ADDRESS *addresslist);
89
90 /* the gets we use */
91 static char *php_mail_gets(readfn_t f, void *stream, unsigned long size, GETS_DATA *md);
92
93 /* These function declarations are missing from the IMAP header files... */
94 void rfc822_date(char *date);
95 char *cpystr(const char *str);
96 char *cpytxt(SIZEDTEXT *dst, char *text, unsigned long size);
97 #ifndef HAVE_NEW_MIME2TEXT
98 long utf8_mime2text(SIZEDTEXT *src, SIZEDTEXT *dst);
99 #else
100 long utf8_mime2text (SIZEDTEXT *src, SIZEDTEXT *dst, long flags);
101 #endif
102 unsigned long find_rightmost_bit(unsigned long *valptr);
103 void fs_give(void **block);
104 void *fs_get(size_t size);
105
106 ZEND_DECLARE_MODULE_GLOBALS(imap)
107 static PHP_GINIT_FUNCTION(imap);
108
109 /* {{{ imap dependencies */
110 static const zend_module_dep imap_deps[] = {
111 ZEND_MOD_REQUIRED("standard")
112 ZEND_MOD_END
113 };
114 /* }}} */
115
116
117 /* {{{ PHP_INI */
118 PHP_INI_BEGIN()
119 STD_PHP_INI_BOOLEAN("imap.enable_insecure_rsh", "0", PHP_INI_SYSTEM, OnUpdateBool, enable_rsh, zend_imap_globals, imap_globals)
120 PHP_INI_END()
121 /* }}} */
122
123
124 /* {{{ imap_module_entry */
125 zend_module_entry imap_module_entry = {
126 STANDARD_MODULE_HEADER_EX, NULL,
127 imap_deps,
128 "imap",
129 ext_functions,
130 PHP_MINIT(imap),
131 NULL,
132 PHP_RINIT(imap),
133 PHP_RSHUTDOWN(imap),
134 PHP_MINFO(imap),
135 PHP_IMAP_VERSION,
136 PHP_MODULE_GLOBALS(imap),
137 PHP_GINIT(imap),
138 NULL,
139 NULL,
140 STANDARD_MODULE_PROPERTIES_EX
141 };
142 /* }}} */
143
144 #ifdef COMPILE_DL_IMAP
145 #ifdef ZTS
146 ZEND_TSRMLS_CACHE_DEFINE()
147 #endif
148 ZEND_GET_MODULE(imap)
149 #endif
150
151 /* Imap class entry definition */
152 static zend_class_entry *php_imap_ce = NULL;
153 static zend_object_handlers imap_object_handlers;
154
155 typedef struct _php_imap_object {
156 MAILSTREAM *imap_stream;
157 long flags;
158 zend_object std;
159 } php_imap_object;
160
imap_object_to_zend_object(php_imap_object * obj)161 static inline zend_object *imap_object_to_zend_object(php_imap_object *obj) {
162 return ((zend_object*)(obj + 1)) - 1;
163 }
164
imap_object_from_zend_object(zend_object * zobj)165 static inline php_imap_object *imap_object_from_zend_object(zend_object *zobj) {
166 return ((php_imap_object*)(zobj + 1)) - 1;
167 }
168
imap_object_create(zend_class_entry * ce)169 static zend_object* imap_object_create(zend_class_entry* ce) {
170 php_imap_object *obj = zend_object_alloc(sizeof(php_imap_object), ce);
171 zend_object *zobj = imap_object_to_zend_object(obj);
172 obj->imap_stream = NULL;
173 obj->flags = 0;
174 zend_object_std_init(zobj, ce);
175 object_properties_init(zobj, ce);
176 zobj->handlers = &imap_object_handlers;
177
178 return zobj;
179 }
180
imap_object_get_constructor(zend_object * zobj)181 static zend_function *imap_object_get_constructor(zend_object *zobj) {
182 zend_throw_error(NULL, "Cannot directly construct IMAP\\Connection, use imap_open() instead");
183 return NULL;
184 }
185
imap_object_destroy(zend_object * zobj)186 static void imap_object_destroy(zend_object *zobj) {
187 php_imap_object *obj = imap_object_from_zend_object(zobj);
188
189 if (obj->imap_stream) {
190 /* Do not try to close prototype streams */
191 if (!(obj->flags & OP_PROTOTYPE)) {
192 mail_close_full(obj->imap_stream, obj->flags);
193 }
194 }
195
196 if (IMAPG(imap_user)) {
197 efree(IMAPG(imap_user));
198 IMAPG(imap_user) = 0;
199 }
200 if (IMAPG(imap_password)) {
201 efree(IMAPG(imap_password));
202 IMAPG(imap_password) = 0;
203 }
204
205 zend_object_std_dtor(zobj);
206 }
207
208 #define GET_IMAP_STREAM(imap_conn_struct, zval_imap_obj) \
209 imap_conn_struct = imap_object_from_zend_object(Z_OBJ_P(zval_imap_obj)); \
210 if (imap_conn_struct->imap_stream == NULL) { \
211 zend_throw_exception(zend_ce_value_error, "IMAP\\Connection is already closed", 0); \
212 RETURN_THROWS(); \
213 }
214
215 #define PHP_IMAP_CHECK_MSGNO_MAYBE_UID_PRE_FLAG_CHECKS(msgindex, arg_pos) \
216 if (msgindex < 1) { \
217 zend_argument_value_error(arg_pos, "must be greater than 0"); \
218 RETURN_THROWS(); \
219 } \
220
221 #define PHP_IMAP_CHECK_MSGNO_MAYBE_UID_POST_FLAG_CHECKS(msgindex, arg_pos, func_flags, uid_flag) \
222 if (func_flags & uid_flag) { \
223 /* This should be cached; if it causes an extra RTT to the IMAP server, */ \
224 /* then that's the price we pay for making sure we don't crash. */ \
225 unsigned int msg_no_from_uid = mail_msgno(imap_conn_struct->imap_stream, msgindex); \
226 if (msg_no_from_uid == 0) { \
227 php_error_docref(NULL, E_WARNING, "UID does not exist"); \
228 RETURN_FALSE; \
229 } \
230 } else { \
231 if (((unsigned) msgindex) > imap_conn_struct->imap_stream->nmsgs) { \
232 php_error_docref(NULL, E_WARNING, "Bad message number"); \
233 RETURN_FALSE; \
234 } \
235 } \
236
237 // TODO Promote to ValueError?
238 #define PHP_IMAP_CHECK_MSGNO(msgindex, arg_pos) \
239 if (msgindex < 1) { \
240 zend_argument_value_error(arg_pos, "must be greater than 0"); \
241 RETURN_THROWS(); \
242 } \
243 if (((unsigned) msgindex) > imap_conn_struct->imap_stream->nmsgs) { \
244 php_error_docref(NULL, E_WARNING, "Bad message number"); \
245 RETURN_FALSE; \
246 } \
247
248 /* {{{ php_imap_hash_add_object */
php_imap_hash_add_object(zval * arg,char * key,zval * tmp)249 static zval *php_imap_hash_add_object(zval *arg, char *key, zval *tmp)
250 {
251 HashTable *symtable;
252
253 if (Z_TYPE_P(arg) == IS_OBJECT) {
254 symtable = Z_OBJPROP_P(arg);
255 } else {
256 symtable = Z_ARRVAL_P(arg);
257 }
258 return zend_hash_str_update(symtable, key, strlen(key), tmp);
259 }
260 /* }}} */
261
262 /* {{{ php_imap_list_add_object */
php_imap_list_add_object(zval * arg,zval * tmp)263 static inline zval *php_imap_list_add_object(zval *arg, zval *tmp)
264 {
265 HashTable *symtable;
266
267 if (Z_TYPE_P(arg) == IS_OBJECT) {
268 symtable = Z_OBJPROP_P(arg);
269 } else {
270 symtable = Z_ARRVAL_P(arg);
271 }
272
273 return zend_hash_next_index_insert(symtable, tmp);
274 }
275 /* }}} */
276
277 /* {{{ mail_newfolderobjectlist
278 *
279 * Mail instantiate FOBJECTLIST
280 * Returns: new FOBJECTLIST list
281 * Author: CJH
282 */
mail_newfolderobjectlist(void)283 FOBJECTLIST *mail_newfolderobjectlist(void)
284 {
285 return (FOBJECTLIST *) memset(fs_get(sizeof(FOBJECTLIST)), 0, sizeof(FOBJECTLIST));
286 }
287 /* }}} */
288
289 /* {{{ mail_free_foblist
290 *
291 * Mail garbage collect FOBJECTLIST
292 * Accepts: pointer to FOBJECTLIST pointer
293 * Author: CJH
294 */
mail_free_foblist(FOBJECTLIST ** foblist,FOBJECTLIST ** tail)295 void mail_free_foblist(FOBJECTLIST **foblist, FOBJECTLIST **tail)
296 {
297 FOBJECTLIST *cur, *next;
298
299 for (cur=*foblist, next=cur->next; cur; cur=next) {
300 next = cur->next;
301
302 if(cur->text.data)
303 fs_give((void **)&(cur->text.data));
304
305 fs_give((void **)&cur);
306 }
307
308 *tail = NIL;
309 *foblist = NIL;
310 }
311 /* }}} */
312
313 /* {{{ mail_newerrorlist
314 *
315 * Mail instantiate ERRORLIST
316 * Returns: new ERRORLIST list
317 * Author: CJH
318 */
mail_newerrorlist(void)319 ERRORLIST *mail_newerrorlist(void)
320 {
321 return (ERRORLIST *) memset(fs_get(sizeof(ERRORLIST)), 0, sizeof(ERRORLIST));
322 }
323 /* }}} */
324
325 /* {{{ mail_free_errorlist
326 *
327 * Mail garbage collect FOBJECTLIST
328 * Accepts: pointer to FOBJECTLIST pointer
329 * Author: CJH
330 */
mail_free_errorlist(ERRORLIST ** errlist)331 void mail_free_errorlist(ERRORLIST **errlist)
332 {
333 if (*errlist) { /* only free if exists */
334 if ((*errlist)->text.data) {
335 fs_give((void **) &(*errlist)->text.data);
336 }
337 mail_free_errorlist (&(*errlist)->next);
338 fs_give((void **) errlist); /* return string to free storage */
339 }
340 }
341 /* }}} */
342
343 /* {{{ mail_newmessagelist
344 *
345 * Mail instantiate MESSAGELIST
346 * Returns: new MESSAGELIST list
347 * Author: CJH
348 */
mail_newmessagelist(void)349 MESSAGELIST *mail_newmessagelist(void)
350 {
351 return (MESSAGELIST *) memset(fs_get(sizeof(MESSAGELIST)), 0, sizeof(MESSAGELIST));
352 }
353 /* }}} */
354
355 /* {{{ mail_free_messagelist
356 *
357 * Mail garbage collect MESSAGELIST
358 * Accepts: pointer to MESSAGELIST pointer
359 * Author: CJH
360 */
mail_free_messagelist(MESSAGELIST ** msglist,MESSAGELIST ** tail)361 void mail_free_messagelist(MESSAGELIST **msglist, MESSAGELIST **tail)
362 {
363 MESSAGELIST *cur, *next;
364
365 for (cur = *msglist, next = cur->next; cur; cur = next) {
366 next = cur->next;
367 fs_give((void **)&cur);
368 }
369
370 *tail = NIL;
371 *msglist = NIL;
372 }
373 /* }}} */
374
375 #if defined(HAVE_IMAP2000) || defined(HAVE_IMAP2001)
376 /* {{{ mail_getquota
377 *
378 * Mail GET_QUOTA callback
379 * Called via the mail_parameter function in c-client:src/c-client/mail.c
380 * Author DRK
381 */
382
mail_getquota(MAILSTREAM * stream,char * qroot,QUOTALIST * qlist)383 void mail_getquota(MAILSTREAM *stream, char *qroot, QUOTALIST *qlist)
384 {
385 zval t_map, *return_value;
386
387 return_value = *IMAPG(quota_return);
388
389 /* put parsing code here */
390 for(; qlist; qlist = qlist->next) {
391 array_init(&t_map);
392 if (strncmp(qlist->name, "STORAGE", 7) == 0)
393 {
394 /* this is to add backwards compatibility */
395 add_assoc_long_ex(return_value, "usage", sizeof("usage") - 1, qlist->usage);
396 add_assoc_long_ex(return_value, "limit", sizeof("limit") - 1, qlist->limit);
397 }
398
399 add_assoc_long_ex(&t_map, "usage", sizeof("usage") - 1, qlist->usage);
400 add_assoc_long_ex(&t_map, "limit", sizeof("limit") - 1, qlist->limit);
401 add_assoc_zval_ex(return_value, qlist->name, strlen(qlist->name), &t_map);
402 }
403 }
404 /* }}} */
405
406 /* {{{ mail_getquota
407 *
408 * Mail GET_ACL callback
409 * Called via the mail_parameter function in c-client:src/c-client/mail.c
410 */
mail_getacl(MAILSTREAM * stream,char * mailbox,ACLLIST * alist)411 void mail_getacl(MAILSTREAM *stream, char *mailbox, ACLLIST *alist)
412 {
413
414 /* walk through the ACLLIST */
415 for(; alist; alist = alist->next) {
416 add_assoc_stringl(IMAPG(imap_acl_list), alist->identifier, alist->rights, strlen(alist->rights));
417 }
418 }
419 /* }}} */
420 #endif
421
422 /* {{{ PHP_GINIT_FUNCTION */
PHP_GINIT_FUNCTION(imap)423 static PHP_GINIT_FUNCTION(imap)
424 {
425 #if defined(COMPILE_DL_IMAP) && defined(ZTS)
426 ZEND_TSRMLS_CACHE_UPDATE();
427 #endif
428 imap_globals->imap_user = NIL;
429 imap_globals->imap_password = NIL;
430
431 imap_globals->imap_alertstack = NIL;
432 imap_globals->imap_errorstack = NIL;
433
434 imap_globals->imap_folders = NIL;
435 imap_globals->imap_folders_tail = NIL;
436 imap_globals->imap_sfolders = NIL;
437 imap_globals->imap_sfolders_tail = NIL;
438 imap_globals->imap_messages = NIL;
439 imap_globals->imap_messages_tail = NIL;
440 imap_globals->imap_folder_objects = NIL;
441 imap_globals->imap_folder_objects_tail = NIL;
442 imap_globals->imap_sfolder_objects = NIL;
443 imap_globals->imap_sfolder_objects_tail = NIL;
444
445 imap_globals->folderlist_style = FLIST_ARRAY;
446 #if defined(HAVE_IMAP2000) || defined(HAVE_IMAP2001)
447 imap_globals->quota_return = NIL;
448 imap_globals->imap_acl_list = NIL;
449 #endif
450 imap_globals->gets_stream = NIL;
451 }
452 /* }}} */
453
454 /* {{{ PHP_MINIT_FUNCTION */
PHP_MINIT_FUNCTION(imap)455 PHP_MINIT_FUNCTION(imap)
456 {
457 REGISTER_INI_ENTRIES();
458
459 #ifndef PHP_WIN32
460 mail_link(&unixdriver); /* link in the unix driver */
461 mail_link(&mhdriver); /* link in the mh driver */
462 /* mail_link(&mxdriver); */ /* According to c-client docs (internal.txt) this shouldn't be used. */
463 mail_link(&mmdfdriver); /* link in the mmdf driver */
464 mail_link(&newsdriver); /* link in the news driver */
465 mail_link(&philedriver); /* link in the phile driver */
466 #endif
467 mail_link(&imapdriver); /* link in the imap driver */
468 mail_link(&nntpdriver); /* link in the nntp driver */
469 mail_link(&pop3driver); /* link in the pop3 driver */
470 mail_link(&mbxdriver); /* link in the mbx driver */
471 mail_link(&tenexdriver); /* link in the tenex driver */
472 mail_link(&mtxdriver); /* link in the mtx driver */
473 mail_link(&dummydriver); /* link in the dummy driver */
474
475 #ifndef PHP_WIN32
476 auth_link(&auth_log); /* link in the log authenticator */
477 auth_link(&auth_md5); /* link in the cram-md5 authenticator */
478 #if defined(HAVE_IMAP_KRB) && defined(HAVE_IMAP_AUTH_GSS)
479 auth_link(&auth_gss); /* link in the gss authenticator */
480 #endif
481 auth_link(&auth_pla); /* link in the plain authenticator */
482 #endif
483
484 #ifdef HAVE_IMAP_SSL
485 ssl_onceonlyinit ();
486 #endif
487
488 php_imap_ce = register_class_IMAP_Connection();
489 php_imap_ce->create_object = imap_object_create;
490
491 memcpy(&imap_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
492 imap_object_handlers.offset = XtOffsetOf(php_imap_object, std);
493 imap_object_handlers.get_constructor = imap_object_get_constructor;
494 imap_object_handlers.free_obj = imap_object_destroy;
495 imap_object_handlers.clone_obj = NULL;
496
497 register_php_imap_symbols(module_number);
498
499 /* plug in our gets */
500 mail_parameters(NIL, SET_GETS, (void *) NIL);
501
502 /* set default timeout values */
503 mail_parameters(NIL, SET_OPENTIMEOUT, (void *) FG(default_socket_timeout));
504 mail_parameters(NIL, SET_READTIMEOUT, (void *) FG(default_socket_timeout));
505 mail_parameters(NIL, SET_WRITETIMEOUT, (void *) FG(default_socket_timeout));
506 mail_parameters(NIL, SET_CLOSETIMEOUT, (void *) FG(default_socket_timeout));
507
508 if (!IMAPG(enable_rsh)) {
509 /* disable SSH and RSH, see https://bugs.php.net/bug.php?id=77153 */
510 mail_parameters (NIL, SET_RSHTIMEOUT, 0);
511 mail_parameters (NIL, SET_SSHTIMEOUT, 0);
512 }
513
514 return SUCCESS;
515 }
516 /* }}} */
517
518 /* {{{ PHP_RINIT_FUNCTION */
PHP_RINIT_FUNCTION(imap)519 PHP_RINIT_FUNCTION(imap)
520 {
521 IMAPG(imap_errorstack) = NIL;
522 IMAPG(imap_alertstack) = NIL;
523 IMAPG(gets_stream) = NIL;
524 return SUCCESS;
525 }
526 /* }}} */
527
528 /* {{{ PHP_RSHUTDOWN_FUNCTION */
PHP_RSHUTDOWN_FUNCTION(imap)529 PHP_RSHUTDOWN_FUNCTION(imap)
530 {
531 ERRORLIST *ecur = NIL;
532 STRINGLIST *acur = NIL;
533
534 if (IMAPG(imap_errorstack) != NIL) {
535 /* output any remaining errors at their original error level */
536 if (EG(error_reporting) & E_NOTICE) {
537 zend_try {
538 ecur = IMAPG(imap_errorstack);
539 while (ecur != NIL) {
540 php_error_docref(NULL, E_NOTICE, "%s (errflg=%ld)", ecur->LTEXT, ecur->errflg);
541 ecur = ecur->next;
542 }
543 } zend_end_try();
544 }
545 mail_free_errorlist(&IMAPG(imap_errorstack));
546 IMAPG(imap_errorstack) = NIL;
547 }
548
549 if (IMAPG(imap_alertstack) != NIL) {
550 /* output any remaining alerts at E_NOTICE level */
551 if (EG(error_reporting) & E_NOTICE) {
552 zend_try {
553 acur = IMAPG(imap_alertstack);
554 while (acur != NIL) {
555 php_error_docref(NULL, E_NOTICE, "%s", acur->LTEXT);
556 acur = acur->next;
557 }
558 } zend_end_try();
559 }
560 mail_free_stringlist(&IMAPG(imap_alertstack));
561 IMAPG(imap_alertstack) = NIL;
562 }
563 return SUCCESS;
564 }
565 /* }}} */
566
567 #ifndef CCLIENTVERSION
568 # if defined(HAVE_IMAP2007e)
569 # define CCLIENTVERSION "2007e"
570 # elif defined(HAVE_IMAP2007d)
571 # define CCLIENTVERSION "2007d"
572 # elif defined(HAVE_IMAP2007b)
573 # define CCLIENTVERSION "2007b"
574 # elif defined(HAVE_IMAP2007a)
575 # define CCLIENTVERSION "2007a"
576 # elif defined(HAVE_IMAP2004)
577 # define CCLIENTVERSION "2004"
578 # elif defined(HAVE_IMAP2001)
579 # define CCLIENTVERSION "2001"
580 # elif defined(HAVE_IMAP2000)
581 # define CCLIENTVERSION "2000"
582 # elif defined(IMAP41)
583 # define CCLIENTVERSION "4.1"
584 # else
585 # define CCLIENTVERSION "4.0"
586 # endif
587 #endif
588
589 /* {{{ PHP_MINFO_FUNCTION */
PHP_MINFO_FUNCTION(imap)590 PHP_MINFO_FUNCTION(imap)
591 {
592 php_info_print_table_start();
593 php_info_print_table_row(2, "IMAP c-Client Version", CCLIENTVERSION);
594 #ifdef HAVE_IMAP_SSL
595 php_info_print_table_row(2, "SSL Support", "enabled");
596 #endif
597 #if defined(HAVE_IMAP_KRB) && defined(HAVE_IMAP_AUTH_GSS)
598 php_info_print_table_row(2, "Kerberos Support", "enabled");
599 #endif
600 php_info_print_table_end();
601
602 DISPLAY_INI_ENTRIES();
603 }
604 /* }}} */
605
606 /* {{{ Open an IMAP stream to a mailbox */
PHP_FUNCTION(imap_open)607 PHP_FUNCTION(imap_open)
608 {
609 zend_string *mailbox, *user, *passwd;
610 zend_long retries = 0, flags = 0, cl_flags = 0;
611 MAILSTREAM *imap_stream;
612 HashTable *params = NULL;
613
614 if (zend_parse_parameters(ZEND_NUM_ARGS(), "PSS|llh", &mailbox, &user, &passwd, &flags, &retries, ¶ms) == FAILURE) {
615 RETURN_THROWS();
616 }
617
618 /* Check for PHP_EXPUNGE and not CL_EXPUNGE as the user land facing CL_EXPUNGE constant is defined
619 * to something different to prevent clashes between CL_EXPUNGE and an OP_* constant allowing setting
620 * the CL_EXPUNGE flag which will expunge when the mailbox is closed (be that manually, or via the
621 * IMAP\Connection object being destroyed naturally at the end of the PHP script */
622 if (flags && ((flags & ~(OP_READONLY | OP_ANONYMOUS | OP_HALFOPEN | PHP_EXPUNGE | OP_DEBUG | OP_SHORTCACHE
623 | OP_SILENT | OP_PROTOTYPE | OP_SECURE)) != 0)) {
624 zend_argument_value_error(4, "must be a bitmask of the OP_* constants, and CL_EXPUNGE");
625 RETURN_THROWS();
626 }
627
628 if (retries < 0) {
629 zend_argument_value_error(5, "must be greater than or equal to 0");
630 RETURN_THROWS();
631 }
632
633 if (flags) {
634 if (flags & PHP_EXPUNGE) {
635 cl_flags = CL_EXPUNGE;
636 flags ^= PHP_EXPUNGE;
637 }
638 if (flags & OP_PROTOTYPE) {
639 cl_flags |= OP_PROTOTYPE;
640 }
641 }
642
643 if (params) {
644 zval *disabled_auth_method;
645
646 if ((disabled_auth_method = zend_hash_str_find(params, "DISABLE_AUTHENTICATOR", sizeof("DISABLE_AUTHENTICATOR") - 1)) != NULL) {
647 switch (Z_TYPE_P(disabled_auth_method)) {
648 case IS_STRING:
649 if (Z_STRLEN_P(disabled_auth_method) > 1) {
650 mail_parameters(NIL, DISABLE_AUTHENTICATOR, (void *)Z_STRVAL_P(disabled_auth_method));
651 }
652 break;
653 case IS_ARRAY:
654 {
655 zval *z_auth_method;
656 int i;
657 int nelems = zend_hash_num_elements(Z_ARRVAL_P(disabled_auth_method));
658
659 if (nelems == 0 ) {
660 break;
661 }
662 for (i = 0; i < nelems; i++) {
663 if ((z_auth_method = zend_hash_index_find(Z_ARRVAL_P(disabled_auth_method), i)) != NULL) {
664 if (Z_TYPE_P(z_auth_method) == IS_STRING) {
665 if (Z_STRLEN_P(z_auth_method) > 1) {
666 mail_parameters(NIL, DISABLE_AUTHENTICATOR, (void *)Z_STRVAL_P(z_auth_method));
667 }
668 } else {
669 zend_argument_type_error(6, "option \"DISABLE_AUTHENTICATOR\" must be a string or an array of strings");
670 RETURN_THROWS();
671 }
672 }
673 }
674 }
675 break;
676 default:
677 zend_argument_type_error(6, "option \"DISABLE_AUTHENTICATOR\" must be a string or an array of strings");
678 RETURN_THROWS();
679 }
680 }
681 }
682
683 if (IMAPG(imap_user)) {
684 efree(IMAPG(imap_user));
685 IMAPG(imap_user) = 0;
686 }
687
688 if (IMAPG(imap_password)) {
689 efree(IMAPG(imap_password));
690 IMAPG(imap_password) = 0;
691 }
692
693 /* local filename, need to perform open_basedir check */
694 if (ZSTR_VAL(mailbox)[0] != '{' && php_check_open_basedir(ZSTR_VAL(mailbox))) {
695 RETURN_FALSE;
696 }
697
698 IMAPG(imap_user) = estrndup(ZSTR_VAL(user), ZSTR_LEN(user));
699 IMAPG(imap_password) = estrndup(ZSTR_VAL(passwd), ZSTR_LEN(passwd));
700
701 #ifdef SET_MAXLOGINTRIALS
702 if (retries) {
703 mail_parameters(NIL, SET_MAXLOGINTRIALS, (void *) retries);
704 }
705 #endif
706
707 ZEND_IGNORE_LEAKS_BEGIN();
708 imap_stream = mail_open(NIL, ZSTR_VAL(mailbox), flags);
709 ZEND_IGNORE_LEAKS_END();
710
711 if (imap_stream == NIL) {
712 php_error_docref(NULL, E_WARNING, "Couldn't open stream %s", ZSTR_VAL(mailbox));
713 efree(IMAPG(imap_user)); IMAPG(imap_user) = 0;
714 efree(IMAPG(imap_password)); IMAPG(imap_password) = 0;
715 RETURN_FALSE;
716 }
717
718 object_init_ex(return_value, php_imap_ce);
719 imap_object_from_zend_object(Z_OBJ_P(return_value))->imap_stream = imap_stream;
720 imap_object_from_zend_object(Z_OBJ_P(return_value))->flags = cl_flags;
721 }
722 /* }}} */
723
724 /* {{{ Reopen an IMAP stream to a new mailbox */
PHP_FUNCTION(imap_reopen)725 PHP_FUNCTION(imap_reopen)
726 {
727 zval *imap_conn_obj;
728 zend_string *mailbox;
729 zend_long options = 0, retries = 0;
730 php_imap_object *imap_conn_struct;
731 long flags = 0;
732 long cl_flags = 0;
733
734 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OS|ll", &imap_conn_obj, php_imap_ce, &mailbox, &options, &retries) == FAILURE) {
735 RETURN_THROWS();
736 }
737
738 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
739
740 /* TODO Verify these are the only options available as they are pulled from the php.net documentation */
741 /* Check for PHP_EXPUNGE and not CL_EXPUNGE as the user land facing CL_EXPUNGE constant is defined
742 * to something different to prevent clashes between CL_EXPUNGE and an OP_* constant allowing setting
743 * the CL_EXPUNGE flag which will expunge when the mailbox is closed (be that manually, or via the
744 * IMAP\Connection object being destroyed naturally at the end of the PHP script */
745 if (options && ((options & ~(OP_READONLY | OP_ANONYMOUS | OP_HALFOPEN | OP_EXPUNGE | PHP_EXPUNGE)) != 0)) {
746 zend_argument_value_error(3, "must be a bitmask of OP_READONLY, OP_ANONYMOUS, OP_HALFOPEN, "
747 "OP_EXPUNGE, and CL_EXPUNGE");
748 RETURN_THROWS();
749 }
750
751 if (retries < 0) {
752 zend_argument_value_error(4, "must be greater than or equal to 0");
753 RETURN_THROWS();
754 }
755
756 if (options) {
757 flags = options;
758 if (flags & PHP_EXPUNGE) {
759 cl_flags = CL_EXPUNGE;
760 flags ^= PHP_EXPUNGE;
761 }
762 imap_conn_struct->flags = cl_flags;
763 }
764 #ifdef SET_MAXLOGINTRIALS
765 if (retries) {
766 mail_parameters(NIL, SET_MAXLOGINTRIALS, (void *) retries);
767 }
768 #endif
769 /* local filename, need to perform open_basedir check */
770 if (ZSTR_VAL(mailbox)[0] != '{' && php_check_open_basedir(ZSTR_VAL(mailbox))) {
771 RETURN_FALSE;
772 }
773
774 imap_conn_struct->imap_stream = mail_open(imap_conn_struct->imap_stream, ZSTR_VAL(mailbox), flags);
775 if (imap_conn_struct->imap_stream == NIL) {
776 /* IMAP\Connection object will release it self. */
777 php_error_docref(NULL, E_WARNING, "Couldn't re-open stream");
778 RETURN_FALSE;
779 }
780 RETURN_TRUE;
781 }
782 /* }}} */
783
PHP_FUNCTION(imap_is_open)784 PHP_FUNCTION(imap_is_open)
785 {
786 zval *imap_conn_obj;
787 php_imap_object *imap_conn_struct;
788
789 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &imap_conn_obj, php_imap_ce) == FAILURE) {
790 RETURN_THROWS();
791 }
792
793 /* Manual reimplementation of the GET_IMAP_STREAM() macro that doesn't throw */
794 imap_conn_struct = imap_object_from_zend_object(Z_OBJ_P(imap_conn_obj));
795 /* Stream was closed */
796 if (imap_conn_struct->imap_stream == NULL) {
797 RETURN_FALSE;
798 }
799 RETURN_TRUE;
800 }
801
802 /* {{{ Append a new message to a specified mailbox */
PHP_FUNCTION(imap_append)803 PHP_FUNCTION(imap_append)
804 {
805 zval *imap_conn_obj;
806 zend_string *folder, *message, *internal_date = NULL, *flags = NULL;
807 php_imap_object *imap_conn_struct;
808 STRING st;
809
810 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OSS|S!S!", &imap_conn_obj, php_imap_ce, &folder, &message, &flags, &internal_date) == FAILURE) {
811 RETURN_THROWS();
812 }
813
814 if (internal_date) {
815 zend_string *regex = zend_string_init("/[0-3][0-9]-((Jan)|(Feb)|(Mar)|(Apr)|(May)|(Jun)|(Jul)|(Aug)|(Sep)|(Oct)|(Nov)|(Dec))-[0-9]{4} [0-2][0-9]:[0-5][0-9]:[0-5][0-9] [+-][0-9]{4}/", sizeof("/[0-3][0-9]-((Jan)|(Feb)|(Mar)|(Apr)|(May)|(Jun)|(Jul)|(Aug)|(Sep)|(Oct)|(Nov)|(Dec))-[0-9]{4} [0-2][0-9]:[0-5][0-9]:[0-5][0-9] [+-][0-9]{4}/") - 1, 0);
816 pcre_cache_entry *pce; /* Compiled regex */
817 zval *subpats = NULL; /* Parts (not used) */
818 int global = 0;
819
820 /* Make sure the given internal_date string matches the RFC specifiedformat */
821 if ((pce = pcre_get_compiled_regex_cache(regex))== NULL) {
822 zend_string_release(regex);
823 RETURN_FALSE;
824 }
825
826 zend_string_release(regex);
827 php_pcre_match_impl(pce, internal_date, return_value, subpats, global,
828 0, Z_L(0), Z_L(0));
829
830 if (!Z_LVAL_P(return_value)) {
831 // TODO Promoto to error?
832 php_error_docref(NULL, E_WARNING, "Internal date not correctly formatted");
833 internal_date = NULL;
834 }
835 }
836
837 /* TODO Check if flags are valid (documentation is not present on php.net so need to check this first) */
838
839 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
840
841 INIT (&st, mail_string, (void *) ZSTR_VAL(message), ZSTR_LEN(message));
842
843 if (mail_append_full(imap_conn_struct->imap_stream, ZSTR_VAL(folder), (flags ? ZSTR_VAL(flags) : NIL), (internal_date ? ZSTR_VAL(internal_date) : NIL), &st)) {
844 RETURN_TRUE;
845 } else {
846 RETURN_FALSE;
847 }
848 }
849 /* }}} */
850
851 /* {{{ Gives the number of messages in the current mailbox */
PHP_FUNCTION(imap_num_msg)852 PHP_FUNCTION(imap_num_msg)
853 {
854 zval *imap_conn_obj;
855 php_imap_object *imap_conn_struct;
856
857 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &imap_conn_obj, php_imap_ce) == FAILURE) {
858 RETURN_THROWS();
859 }
860
861 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
862
863 RETURN_LONG(imap_conn_struct->imap_stream->nmsgs);
864 }
865 /* }}} */
866
867 /* {{{ Check if the IMAP stream is still active */
PHP_FUNCTION(imap_ping)868 PHP_FUNCTION(imap_ping)
869 {
870 zval *imap_conn_obj;
871 php_imap_object *imap_conn_struct;
872
873 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &imap_conn_obj, php_imap_ce) == FAILURE) {
874 RETURN_THROWS();
875 }
876
877 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
878
879 RETURN_BOOL(mail_ping(imap_conn_struct->imap_stream));
880 }
881 /* }}} */
882
883 /* {{{ Gives the number of recent messages in current mailbox */
PHP_FUNCTION(imap_num_recent)884 PHP_FUNCTION(imap_num_recent)
885 {
886 zval *imap_conn_obj;
887 php_imap_object *imap_conn_struct;
888
889 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &imap_conn_obj, php_imap_ce) == FAILURE) {
890 RETURN_THROWS();
891 }
892
893 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
894
895 RETURN_LONG(imap_conn_struct->imap_stream->recent);
896 }
897 /* }}} */
898
899 #if defined(HAVE_IMAP2000) || defined(HAVE_IMAP2001)
900 /* {{{ Returns the quota set to the mailbox account qroot */
PHP_FUNCTION(imap_get_quota)901 PHP_FUNCTION(imap_get_quota)
902 {
903 zval *imap_conn_obj;
904 zend_string *qroot;
905 php_imap_object *imap_conn_struct;
906
907 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OS", &imap_conn_obj, php_imap_ce, &qroot) == FAILURE) {
908 RETURN_THROWS();
909 }
910
911 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
912
913 array_init(return_value);
914 IMAPG(quota_return) = &return_value;
915
916 /* set the callback for the GET_QUOTA function */
917 mail_parameters(NIL, SET_QUOTA, (void *) mail_getquota);
918 if (!imap_getquota(imap_conn_struct->imap_stream, ZSTR_VAL(qroot))) {
919 php_error_docref(NULL, E_WARNING, "C-client imap_getquota failed");
920 zend_array_destroy(Z_ARR_P(return_value));
921 RETURN_FALSE;
922 }
923 }
924 /* }}} */
925
926 /* {{{ Returns the quota set to the mailbox account mbox */
PHP_FUNCTION(imap_get_quotaroot)927 PHP_FUNCTION(imap_get_quotaroot)
928 {
929 zval *imap_conn_obj;
930 zend_string *mbox;
931 php_imap_object *imap_conn_struct;
932
933 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OS", &imap_conn_obj, php_imap_ce, &mbox) == FAILURE) {
934 RETURN_THROWS();
935 }
936
937 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
938
939 array_init(return_value);
940 IMAPG(quota_return) = &return_value;
941
942 /* set the callback for the GET_QUOTAROOT function */
943 mail_parameters(NIL, SET_QUOTA, (void *) mail_getquota);
944 if (!imap_getquotaroot(imap_conn_struct->imap_stream, ZSTR_VAL(mbox))) {
945 php_error_docref(NULL, E_WARNING, "C-client imap_getquotaroot failed");
946 zend_array_destroy(Z_ARR_P(return_value));
947 RETURN_FALSE;
948 }
949 }
950 /* }}} */
951
952 /* {{{ Will set the quota for qroot mailbox */
PHP_FUNCTION(imap_set_quota)953 PHP_FUNCTION(imap_set_quota)
954 {
955 zval *imap_conn_obj;
956 zend_string *qroot;
957 zend_long mailbox_size;
958 php_imap_object *imap_conn_struct;
959 STRINGLIST limits;
960
961 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OSl", &imap_conn_obj, php_imap_ce, &qroot, &mailbox_size) == FAILURE) {
962 RETURN_THROWS();
963 }
964
965 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
966
967 limits.text.data = (unsigned char*)"STORAGE";
968 limits.text.size = mailbox_size;
969 limits.next = NIL;
970
971 RETURN_BOOL(imap_setquota(imap_conn_struct->imap_stream, ZSTR_VAL(qroot), &limits));
972 }
973 /* }}} */
974
975 /* {{{ Sets the ACL for a given mailbox */
PHP_FUNCTION(imap_setacl)976 PHP_FUNCTION(imap_setacl)
977 {
978 zval *imap_conn_obj;
979 zend_string *mailbox, *id, *rights;
980 php_imap_object *imap_conn_struct;
981
982 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OSSS", &imap_conn_obj, php_imap_ce, &mailbox, &id, &rights) == FAILURE) {
983 RETURN_THROWS();
984 }
985
986 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
987
988 RETURN_BOOL(imap_setacl(imap_conn_struct->imap_stream, ZSTR_VAL(mailbox), ZSTR_VAL(id), ZSTR_VAL(rights)));
989 }
990 /* }}} */
991
992 /* {{{ Gets the ACL for a given mailbox */
PHP_FUNCTION(imap_getacl)993 PHP_FUNCTION(imap_getacl)
994 {
995 zval *imap_conn_obj;
996 zend_string *mailbox;
997 php_imap_object *imap_conn_struct;
998
999 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OS", &imap_conn_obj, php_imap_ce, &mailbox) == FAILURE) {
1000 RETURN_THROWS();
1001 }
1002
1003 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
1004
1005 /* initializing the special array for the return values */
1006 array_init(return_value);
1007
1008 IMAPG(imap_acl_list) = return_value;
1009
1010 /* set the callback for the GET_ACL function */
1011 mail_parameters(NIL, SET_ACL, (void *) mail_getacl);
1012 if (!imap_getacl(imap_conn_struct->imap_stream, ZSTR_VAL(mailbox))) {
1013 php_error(E_WARNING, "c-client imap_getacl failed");
1014 zend_array_destroy(Z_ARR_P(return_value));
1015 RETURN_FALSE;
1016 }
1017
1018 IMAPG(imap_acl_list) = NIL;
1019 }
1020 /* }}} */
1021 #endif /* HAVE_IMAP2000 || HAVE_IMAP2001 */
1022
1023 /* {{{ Permanently delete all messages marked for deletion */
PHP_FUNCTION(imap_expunge)1024 PHP_FUNCTION(imap_expunge)
1025 {
1026 zval *imap_conn_obj;
1027 php_imap_object *imap_conn_struct;
1028
1029 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &imap_conn_obj, php_imap_ce) == FAILURE) {
1030 RETURN_THROWS();
1031 }
1032
1033 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
1034
1035 mail_expunge (imap_conn_struct->imap_stream);
1036
1037 RETURN_TRUE;
1038 }
1039 /* }}} */
1040
1041 /* {{{ This function garbage collects (purges) the cache of entries of a specific type. */
PHP_FUNCTION(imap_gc)1042 PHP_FUNCTION(imap_gc)
1043 {
1044 zval *imap_conn_obj;
1045 php_imap_object *imap_conn_struct;
1046 zend_long flags;
1047
1048 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ol", &imap_conn_obj, php_imap_ce, &flags) == FAILURE) {
1049 RETURN_THROWS();
1050 }
1051
1052 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
1053
1054 if (flags && ((flags & ~(GC_TEXTS | GC_ELT | GC_ENV)) != 0)) {
1055 zend_argument_value_error(2, "must be a bitmask of IMAP_GC_TEXTS, IMAP_GC_ELT, and IMAP_GC_ENV");
1056 RETURN_THROWS();
1057 }
1058
1059 mail_gc(imap_conn_struct->imap_stream, flags);
1060
1061 // TODO Return void?
1062 RETURN_TRUE;
1063 }
1064 /* }}} */
1065
1066 /* {{{ Close an IMAP stream */
PHP_FUNCTION(imap_close)1067 PHP_FUNCTION(imap_close)
1068 {
1069 zval *imap_conn_obj;
1070 php_imap_object *imap_conn_struct = NULL;
1071 zend_long options = 0;
1072
1073 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|l", &imap_conn_obj, php_imap_ce, &options) == FAILURE) {
1074 RETURN_THROWS();
1075 }
1076
1077 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
1078
1079 if (options) {
1080 /* Check that flags is exactly equal to PHP_EXPUNGE or zero */
1081 if (options && ((options & ~PHP_EXPUNGE) != 0)) {
1082 zend_argument_value_error(2, "must be CL_EXPUNGE or 0");
1083 RETURN_THROWS();
1084 }
1085
1086 /* Do the translation from PHP's internal PHP_EXPUNGE define to c-client's CL_EXPUNGE */
1087 if (options & PHP_EXPUNGE) {
1088 options ^= PHP_EXPUNGE;
1089 options |= CL_EXPUNGE;
1090 }
1091 imap_conn_struct->flags = options;
1092 }
1093
1094 /* Do not try to close prototype streams */
1095 if (!(imap_conn_struct->flags & OP_PROTOTYPE)) {
1096 mail_close_full(imap_conn_struct->imap_stream, imap_conn_struct->flags);
1097 imap_conn_struct->imap_stream = NULL;
1098 }
1099
1100 // TODO Return void?
1101 RETURN_TRUE;
1102 }
1103 /* }}} */
1104
1105 /* {{{ Returns headers for all messages in a mailbox */
PHP_FUNCTION(imap_headers)1106 PHP_FUNCTION(imap_headers)
1107 {
1108 zval *imap_conn_obj;
1109 php_imap_object *imap_conn_struct;
1110 unsigned long i;
1111 char *t;
1112 unsigned int msgno;
1113 char tmp[MAILTMPLEN];
1114
1115 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &imap_conn_obj, php_imap_ce) == FAILURE) {
1116 RETURN_THROWS();
1117 }
1118
1119 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
1120
1121 /* Initialize return array */
1122 array_init(return_value);
1123
1124 for (msgno = 1; msgno <= imap_conn_struct->imap_stream->nmsgs; msgno++) {
1125 MESSAGECACHE * cache = mail_elt (imap_conn_struct->imap_stream, msgno);
1126 mail_fetchstructure(imap_conn_struct->imap_stream, msgno, NIL);
1127 tmp[0] = cache->recent ? (cache->seen ? 'R': 'N') : ' ';
1128 tmp[1] = (cache->recent | cache->seen) ? ' ' : 'U';
1129 tmp[2] = cache->flagged ? 'F' : ' ';
1130 tmp[3] = cache->answered ? 'A' : ' ';
1131 tmp[4] = cache->deleted ? 'D' : ' ';
1132 tmp[5] = cache->draft ? 'X' : ' ';
1133 snprintf(tmp + 6, sizeof(tmp) - 6, "%4ld) ", cache->msgno);
1134 mail_date(tmp+11, cache);
1135 tmp[22] = ' ';
1136 tmp[23] = '\0';
1137 mail_fetchfrom(tmp+23, imap_conn_struct->imap_stream, msgno, (long)20);
1138 strcat(tmp, " ");
1139 if ((i = cache->user_flags)) {
1140 strcat(tmp, "{");
1141 while (i) {
1142 strlcat(tmp, imap_conn_struct->imap_stream->user_flags[find_rightmost_bit (&i)], sizeof(tmp));
1143 if (i) strlcat(tmp, " ", sizeof(tmp));
1144 }
1145 strlcat(tmp, "} ", sizeof(tmp));
1146 }
1147 mail_fetchsubject(t = tmp + strlen(tmp), imap_conn_struct->imap_stream, msgno, (long)25);
1148 snprintf(t += strlen(t), sizeof(tmp) - strlen(tmp), " (%ld chars)", cache->rfc822_size);
1149 add_next_index_string(return_value, tmp);
1150 }
1151 }
1152 /* }}} */
1153
1154 /* {{{ Read the message body */
PHP_FUNCTION(imap_body)1155 PHP_FUNCTION(imap_body)
1156 {
1157 zval *imap_conn_obj;
1158 zend_long msgno, flags = 0;
1159 php_imap_object *imap_conn_struct;
1160 char *body;
1161 unsigned long body_len = 0;
1162
1163 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ol|l", &imap_conn_obj, php_imap_ce, &msgno, &flags) == FAILURE) {
1164 RETURN_THROWS();
1165 }
1166
1167 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
1168
1169 PHP_IMAP_CHECK_MSGNO_MAYBE_UID_PRE_FLAG_CHECKS(msgno, 2);
1170
1171 if (flags && ((flags & ~(FT_UID|FT_PEEK|FT_INTERNAL)) != 0)) {
1172 zend_argument_value_error(3, "must be a bitmask of FT_UID, FT_PEEK, and FT_INTERNAL");
1173 RETURN_THROWS();
1174 }
1175
1176 PHP_IMAP_CHECK_MSGNO_MAYBE_UID_POST_FLAG_CHECKS(msgno, 2, flags, FT_UID);
1177
1178 body = mail_fetchtext_full (imap_conn_struct->imap_stream, msgno, &body_len, flags);
1179 if (body_len == 0) {
1180 RETVAL_EMPTY_STRING();
1181 } else {
1182 RETVAL_STRINGL(body, body_len);
1183 }
1184 }
1185 /* }}} */
1186
1187 /* TODO UID Tests */
1188 /* {{{ Copy specified message to a mailbox */
PHP_FUNCTION(imap_mail_copy)1189 PHP_FUNCTION(imap_mail_copy)
1190 {
1191 zval *imap_conn_obj;
1192 zend_long options = 0;
1193 zend_string *seq, *folder;
1194 php_imap_object *imap_conn_struct;
1195
1196 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OSS|l", &imap_conn_obj, php_imap_ce, &seq, &folder, &options) == FAILURE) {
1197 RETURN_THROWS();
1198 }
1199
1200 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
1201
1202 if (options && ((options & ~(CP_UID | CP_MOVE)) != 0)) {
1203 zend_argument_value_error(4, "must be a bitmask of CP_UID, and CP_MOVE");
1204 RETURN_THROWS();
1205 }
1206
1207 if (mail_copy_full(imap_conn_struct->imap_stream, ZSTR_VAL(seq), ZSTR_VAL(folder), options) == T) {
1208 RETURN_TRUE;
1209 } else {
1210 RETURN_FALSE;
1211 }
1212 }
1213 /* }}} */
1214
1215 /* TODO UID Tests */
1216 /* {{{ Move specified message to a mailbox */
PHP_FUNCTION(imap_mail_move)1217 PHP_FUNCTION(imap_mail_move)
1218 {
1219 zval *imap_conn_obj;
1220 zend_string *seq, *folder;
1221 zend_long options = 0;
1222 php_imap_object *imap_conn_struct;
1223
1224 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OSS|l", &imap_conn_obj, php_imap_ce, &seq, &folder, &options) == FAILURE) {
1225 RETURN_THROWS();
1226 }
1227
1228 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
1229
1230 if (options && ((options & ~CP_UID) != 0)) {
1231 zend_argument_value_error(4, "must be CP_UID or 0");
1232 RETURN_THROWS();
1233 }
1234
1235 /* Add CP_MOVE flag */
1236 options = (options | CP_MOVE);
1237
1238 if (mail_copy_full(imap_conn_struct->imap_stream, ZSTR_VAL(seq), ZSTR_VAL(folder), options) == T) {
1239 RETURN_TRUE;
1240 } else {
1241 RETURN_FALSE;
1242 }
1243 }
1244 /* }}} */
1245
1246 /* {{{ Create a new mailbox */
PHP_FUNCTION(imap_createmailbox)1247 PHP_FUNCTION(imap_createmailbox)
1248 {
1249 zval *imap_conn_obj;
1250 zend_string *folder;
1251 php_imap_object *imap_conn_struct;
1252
1253 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OS", &imap_conn_obj, php_imap_ce, &folder) == FAILURE) {
1254 RETURN_THROWS();
1255 }
1256
1257 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
1258
1259 if (mail_create(imap_conn_struct->imap_stream, ZSTR_VAL(folder)) == T) {
1260 RETURN_TRUE;
1261 } else {
1262 RETURN_FALSE;
1263 }
1264 }
1265 /* }}} */
1266
1267 /* {{{ Rename a mailbox */
PHP_FUNCTION(imap_renamemailbox)1268 PHP_FUNCTION(imap_renamemailbox)
1269 {
1270 zval *imap_conn_obj;
1271 zend_string *old_mailbox, *new_mailbox;
1272 php_imap_object *imap_conn_struct;
1273
1274 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OSS", &imap_conn_obj, php_imap_ce, &old_mailbox, &new_mailbox) == FAILURE) {
1275 RETURN_THROWS();
1276 }
1277
1278 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
1279
1280 if (mail_rename(imap_conn_struct->imap_stream, ZSTR_VAL(old_mailbox), ZSTR_VAL(new_mailbox)) == T) {
1281 RETURN_TRUE;
1282 } else {
1283 RETURN_FALSE;
1284 }
1285 }
1286 /* }}} */
1287
1288 /* {{{ Delete a mailbox */
PHP_FUNCTION(imap_deletemailbox)1289 PHP_FUNCTION(imap_deletemailbox)
1290 {
1291 zval *imap_conn_obj;
1292 zend_string *folder;
1293 php_imap_object *imap_conn_struct;
1294
1295 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OS", &imap_conn_obj, php_imap_ce, &folder) == FAILURE) {
1296 RETURN_THROWS();
1297 }
1298
1299 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
1300
1301 if (mail_delete(imap_conn_struct->imap_stream, ZSTR_VAL(folder)) == T) {
1302 RETURN_TRUE;
1303 } else {
1304 RETURN_FALSE;
1305 }
1306 }
1307 /* }}} */
1308
1309 /* {{{ Read the list of mailboxes */
PHP_FUNCTION(imap_list)1310 PHP_FUNCTION(imap_list)
1311 {
1312 zval *imap_conn_obj;
1313 zend_string *ref, *pat;
1314 php_imap_object *imap_conn_struct;
1315 STRINGLIST *cur=NIL;
1316
1317 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OSS", &imap_conn_obj, php_imap_ce, &ref, &pat) == FAILURE) {
1318 RETURN_THROWS();
1319 }
1320
1321 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
1322
1323 /* set flag for normal, old mailbox list */
1324 IMAPG(folderlist_style) = FLIST_ARRAY;
1325
1326 IMAPG(imap_folders) = IMAPG(imap_folders_tail) = NIL;
1327 mail_list(imap_conn_struct->imap_stream, ZSTR_VAL(ref), ZSTR_VAL(pat));
1328 if (IMAPG(imap_folders) == NIL) {
1329 RETURN_FALSE;
1330 }
1331
1332 array_init(return_value);
1333 cur=IMAPG(imap_folders);
1334 while (cur != NIL) {
1335 add_next_index_string(return_value, (char*)cur->LTEXT);
1336 cur=cur->next;
1337 }
1338 mail_free_stringlist (&IMAPG(imap_folders));
1339 IMAPG(imap_folders) = IMAPG(imap_folders_tail) = NIL;
1340 }
1341
1342 /* }}} */
1343
1344 /* {{{ Reads the list of mailboxes and returns a full array of objects containing name, attributes, and delimiter */
1345 /* Author: CJH */
PHP_FUNCTION(imap_getmailboxes)1346 PHP_FUNCTION(imap_getmailboxes)
1347 {
1348 zval *imap_conn_obj, mboxob;
1349 zend_string *ref, *pat;
1350 php_imap_object *imap_conn_struct;
1351 FOBJECTLIST *cur=NIL;
1352 char *delim=NIL;
1353
1354 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OSS", &imap_conn_obj, php_imap_ce, &ref, &pat) == FAILURE) {
1355 RETURN_THROWS();
1356 }
1357
1358 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
1359
1360 /* set flag for new, improved array of objects mailbox list */
1361 IMAPG(folderlist_style) = FLIST_OBJECT;
1362
1363 IMAPG(imap_folder_objects) = IMAPG(imap_folder_objects_tail) = NIL;
1364 mail_list(imap_conn_struct->imap_stream, ZSTR_VAL(ref), ZSTR_VAL(pat));
1365 if (IMAPG(imap_folder_objects) == NIL) {
1366 RETURN_FALSE;
1367 }
1368
1369 array_init(return_value);
1370 delim = safe_emalloc(2, sizeof(char), 0);
1371 cur=IMAPG(imap_folder_objects);
1372 while (cur != NIL) {
1373 object_init(&mboxob);
1374 add_property_string(&mboxob, "name", (char*)cur->LTEXT);
1375 add_property_long(&mboxob, "attributes", cur->attributes);
1376 #ifdef IMAP41
1377 delim[0] = (char)cur->delimiter;
1378 delim[1] = 0;
1379 add_property_string(&mboxob, "delimiter", delim);
1380 #else
1381 add_property_string(&mboxob, "delimiter", cur->delimiter);
1382 #endif
1383 php_imap_list_add_object(return_value, &mboxob);
1384 cur=cur->next;
1385 }
1386 mail_free_foblist(&IMAPG(imap_folder_objects), &IMAPG(imap_folder_objects_tail));
1387 efree(delim);
1388 IMAPG(folderlist_style) = FLIST_ARRAY; /* reset to default */
1389 }
1390 /* }}} */
1391
1392 /* {{{ Read list of mailboxes containing a certain string */
PHP_FUNCTION(imap_listscan)1393 PHP_FUNCTION(imap_listscan)
1394 {
1395 zval *imap_conn_obj;
1396 zend_string *ref, *pat, *content;
1397 php_imap_object *imap_conn_struct;
1398 STRINGLIST *cur=NIL;
1399
1400 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OSSS", &imap_conn_obj, php_imap_ce, &ref, &pat, &content) == FAILURE) {
1401 RETURN_THROWS();
1402 }
1403
1404 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
1405
1406 IMAPG(imap_folders) = NIL;
1407 mail_scan(imap_conn_struct->imap_stream, ZSTR_VAL(ref), ZSTR_VAL(pat), ZSTR_VAL(content));
1408 if (IMAPG(imap_folders) == NIL) {
1409 RETURN_FALSE;
1410 }
1411
1412 array_init(return_value);
1413 cur=IMAPG(imap_folders);
1414 while (cur != NIL) {
1415 add_next_index_string(return_value, (char*)cur->LTEXT);
1416 cur=cur->next;
1417 }
1418 mail_free_stringlist (&IMAPG(imap_folders));
1419 IMAPG(imap_folders) = IMAPG(imap_folders_tail) = NIL;
1420 }
1421
1422 /* }}} */
1423
1424 /* {{{ Get mailbox properties */
PHP_FUNCTION(imap_check)1425 PHP_FUNCTION(imap_check)
1426 {
1427 zval *imap_conn_obj;
1428 php_imap_object *imap_conn_struct;
1429 char date[100];
1430
1431 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &imap_conn_obj, php_imap_ce) == FAILURE) {
1432 RETURN_THROWS();
1433 }
1434
1435 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
1436
1437 if (mail_ping (imap_conn_struct->imap_stream) == NIL) {
1438 RETURN_FALSE;
1439 }
1440
1441 if (imap_conn_struct->imap_stream && imap_conn_struct->imap_stream->mailbox) {
1442 rfc822_date(date);
1443 object_init(return_value);
1444 add_property_string(return_value, "Date", date);
1445 add_property_string(return_value, "Driver", imap_conn_struct->imap_stream->dtb->name);
1446 add_property_string(return_value, "Mailbox", imap_conn_struct->imap_stream->mailbox);
1447 add_property_long(return_value, "Nmsgs", imap_conn_struct->imap_stream->nmsgs);
1448 add_property_long(return_value, "Recent", imap_conn_struct->imap_stream->recent);
1449 } else {
1450 RETURN_FALSE;
1451 }
1452 }
1453 /* }}} */
1454
1455 /* {{{ Mark a message for deletion */
PHP_FUNCTION(imap_delete)1456 PHP_FUNCTION(imap_delete)
1457 {
1458 zval *imap_conn_obj;
1459 php_imap_object *imap_conn_struct;
1460 zend_string *sequence;
1461 zend_long flags = 0;
1462
1463 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OS|l", &imap_conn_obj, php_imap_ce, &sequence, &flags) == FAILURE) {
1464 RETURN_THROWS();
1465 }
1466
1467 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
1468
1469 // TODO Check sequence validity?
1470
1471 if (flags && ((flags & ~FT_UID) != 0)) {
1472 zend_argument_value_error(3, "must be FT_UID or 0");
1473 RETURN_THROWS();
1474 }
1475
1476 mail_setflag_full(imap_conn_struct->imap_stream, ZSTR_VAL(sequence), "\\DELETED", flags);
1477
1478 // TODO Return void?
1479 RETURN_TRUE;
1480 }
1481 /* }}} */
1482
1483 /* {{{ Remove the delete flag from a message */
PHP_FUNCTION(imap_undelete)1484 PHP_FUNCTION(imap_undelete)
1485 {
1486 zval *imap_conn_obj;
1487 zend_string *sequence;
1488 zend_long flags = 0;
1489 php_imap_object *imap_conn_struct;
1490
1491 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OS|l", &imap_conn_obj, php_imap_ce, &sequence, &flags) == FAILURE) {
1492 RETURN_THROWS();
1493 }
1494
1495 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
1496
1497 /* TODO Check if flags are valid (documentation is not present on php.net so need to check this first) */
1498
1499 mail_clearflag_full(imap_conn_struct->imap_stream, ZSTR_VAL(sequence), "\\DELETED", flags);
1500
1501 // TODO Return void?
1502 RETURN_TRUE;
1503 }
1504 /* }}} */
1505
1506 /* {{{ Read the headers of the message */
PHP_FUNCTION(imap_headerinfo)1507 PHP_FUNCTION(imap_headerinfo)
1508 {
1509 zval *imap_conn_obj;
1510 zend_long msgno, fromlength = 0, subjectlength = 0;
1511 php_imap_object *imap_conn_struct;
1512 MESSAGECACHE *cache;
1513 ENVELOPE *en;
1514 char dummy[2000], fulladdress[MAILTMPLEN + 1];
1515
1516 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ol|ll", &imap_conn_obj, php_imap_ce, &msgno, &fromlength, &subjectlength) == FAILURE) {
1517 RETURN_THROWS();
1518 }
1519
1520 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
1521
1522 PHP_IMAP_CHECK_MSGNO(msgno, 2);
1523
1524 if (fromlength < 0 || fromlength > MAILTMPLEN) {
1525 zend_argument_value_error(3, "must be between 0 and %d", MAILTMPLEN);
1526 RETURN_THROWS();
1527 }
1528
1529 if (subjectlength < 0 || subjectlength > MAILTMPLEN) {
1530 zend_argument_value_error(4, "must be between 0 and %d", MAILTMPLEN);
1531 RETURN_THROWS();
1532 }
1533
1534 if (mail_fetchstructure(imap_conn_struct->imap_stream, msgno, NIL)) {
1535 cache = mail_elt(imap_conn_struct->imap_stream, msgno);
1536 } else {
1537 RETURN_FALSE;
1538 }
1539
1540 en = mail_fetchenvelope(imap_conn_struct->imap_stream, msgno);
1541
1542 /* call a function to parse all the text, so that we can use the
1543 same function to parse text from other sources */
1544 _php_make_header_object(return_value, en);
1545
1546 /* now run through properties that are only going to be returned
1547 from a server, not text headers */
1548 add_property_string(return_value, "Recent", cache->recent ? (cache->seen ? "R": "N") : " ");
1549 add_property_string(return_value, "Unseen", (cache->recent | cache->seen) ? " " : "U");
1550 add_property_string(return_value, "Flagged", cache->flagged ? "F" : " ");
1551 add_property_string(return_value, "Answered", cache->answered ? "A" : " ");
1552 add_property_string(return_value, "Deleted", cache->deleted ? "D" : " ");
1553 add_property_string(return_value, "Draft", cache->draft ? "X" : " ");
1554
1555 snprintf(dummy, sizeof(dummy), "%4ld", cache->msgno);
1556 add_property_string(return_value, "Msgno", dummy);
1557
1558 mail_date(dummy, cache);
1559 add_property_string(return_value, "MailDate", dummy);
1560
1561 snprintf(dummy, sizeof(dummy), "%ld", cache->rfc822_size);
1562 add_property_string(return_value, "Size", dummy);
1563
1564 add_property_long(return_value, "udate", mail_longdate(cache));
1565
1566 if (en->from && fromlength) {
1567 fulladdress[0] = 0x00;
1568 mail_fetchfrom(fulladdress, imap_conn_struct->imap_stream, msgno, fromlength);
1569 add_property_string(return_value, "fetchfrom", fulladdress);
1570 }
1571 if (en->subject && subjectlength) {
1572 fulladdress[0] = 0x00;
1573 mail_fetchsubject(fulladdress, imap_conn_struct->imap_stream, msgno, subjectlength);
1574 add_property_string(return_value, "fetchsubject", fulladdress);
1575 }
1576 }
1577 /* }}} */
1578
1579 /* {{{ Parse a set of mail headers contained in a string, and return an object similar to imap_headerinfo() */
PHP_FUNCTION(imap_rfc822_parse_headers)1580 PHP_FUNCTION(imap_rfc822_parse_headers)
1581 {
1582 zend_string *headers, *defaulthost = NULL;
1583 ENVELOPE *en;
1584
1585 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|S", &headers, &defaulthost) == FAILURE) {
1586 RETURN_THROWS();
1587 }
1588
1589 if (defaulthost) {
1590 rfc822_parse_msg(&en, NULL, ZSTR_VAL(headers), ZSTR_LEN(headers), NULL, ZSTR_VAL(defaulthost), NIL);
1591 } else {
1592 rfc822_parse_msg(&en, NULL, ZSTR_VAL(headers), ZSTR_LEN(headers), NULL, "UNKNOWN", NIL);
1593 }
1594
1595 /* call a function to parse all the text, so that we can use the
1596 same function no matter where the headers are from */
1597 _php_make_header_object(return_value, en);
1598 mail_free_envelope(&en);
1599 }
1600 /* }}} */
1601
1602 /* KMLANG */
1603 /* {{{ Return a list of subscribed mailboxes */
PHP_FUNCTION(imap_lsub)1604 PHP_FUNCTION(imap_lsub)
1605 {
1606 zval *imap_conn_obj;
1607 zend_string *ref, *pat;
1608 php_imap_object *imap_conn_struct;
1609 STRINGLIST *cur=NIL;
1610
1611 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OSS", &imap_conn_obj, php_imap_ce, &ref, &pat) == FAILURE) {
1612 RETURN_THROWS();
1613 }
1614
1615 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
1616
1617 /* set flag for normal, old mailbox list */
1618 IMAPG(folderlist_style) = FLIST_ARRAY;
1619
1620 IMAPG(imap_sfolders) = NIL;
1621 ZEND_IGNORE_LEAKS_BEGIN();
1622 mail_lsub(imap_conn_struct->imap_stream, ZSTR_VAL(ref), ZSTR_VAL(pat));
1623 ZEND_IGNORE_LEAKS_END();
1624 if (IMAPG(imap_sfolders) == NIL) {
1625 RETURN_FALSE;
1626 }
1627
1628 array_init(return_value);
1629 cur=IMAPG(imap_sfolders);
1630 while (cur != NIL) {
1631 add_next_index_string(return_value, (char*)cur->LTEXT);
1632 cur=cur->next;
1633 }
1634 mail_free_stringlist (&IMAPG(imap_sfolders));
1635 IMAPG(imap_sfolders) = IMAPG(imap_sfolders_tail) = NIL;
1636 }
1637 /* }}} */
1638
1639 /* {{{ Return a list of subscribed mailboxes, in the same format as imap_getmailboxes() */
1640 /* Author: CJH */
PHP_FUNCTION(imap_getsubscribed)1641 PHP_FUNCTION(imap_getsubscribed)
1642 {
1643 zval *imap_conn_obj, mboxob;
1644 zend_string *ref, *pat;
1645 php_imap_object *imap_conn_struct;
1646 FOBJECTLIST *cur=NIL;
1647 char *delim=NIL;
1648
1649 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OSS", &imap_conn_obj, php_imap_ce, &ref, &pat) == FAILURE) {
1650 RETURN_THROWS();
1651 }
1652
1653 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
1654
1655 /* set flag for new, improved array of objects list */
1656 IMAPG(folderlist_style) = FLIST_OBJECT;
1657
1658 IMAPG(imap_sfolder_objects) = IMAPG(imap_sfolder_objects_tail) = NIL;
1659 ZEND_IGNORE_LEAKS_BEGIN();
1660 mail_lsub(imap_conn_struct->imap_stream, ZSTR_VAL(ref), ZSTR_VAL(pat));
1661 ZEND_IGNORE_LEAKS_END();
1662 if (IMAPG(imap_sfolder_objects) == NIL) {
1663 RETURN_FALSE;
1664 }
1665
1666 array_init(return_value);
1667 delim = safe_emalloc(2, sizeof(char), 0);
1668 cur=IMAPG(imap_sfolder_objects);
1669 while (cur != NIL) {
1670 object_init(&mboxob);
1671 add_property_string(&mboxob, "name", (char*)cur->LTEXT);
1672 add_property_long(&mboxob, "attributes", cur->attributes);
1673 #ifdef IMAP41
1674 delim[0] = (char)cur->delimiter;
1675 delim[1] = 0;
1676 add_property_string(&mboxob, "delimiter", delim);
1677 #else
1678 add_property_string(&mboxob, "delimiter", cur->delimiter);
1679 #endif
1680 php_imap_list_add_object(return_value, &mboxob);
1681 cur=cur->next;
1682 }
1683 mail_free_foblist (&IMAPG(imap_sfolder_objects), &IMAPG(imap_sfolder_objects_tail));
1684 efree(delim);
1685 IMAPG(folderlist_style) = FLIST_ARRAY; /* reset to default */
1686 }
1687 /* }}} */
1688
1689 /* {{{ Subscribe to a mailbox */
PHP_FUNCTION(imap_subscribe)1690 PHP_FUNCTION(imap_subscribe)
1691 {
1692 zval *imap_conn_obj;
1693 zend_string *folder;
1694 php_imap_object *imap_conn_struct;
1695
1696 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OS", &imap_conn_obj, php_imap_ce, &folder) == FAILURE) {
1697 RETURN_THROWS();
1698 }
1699
1700 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
1701
1702 if (mail_subscribe(imap_conn_struct->imap_stream, ZSTR_VAL(folder)) == T) {
1703 RETURN_TRUE;
1704 } else {
1705 RETURN_FALSE;
1706 }
1707 }
1708 /* }}} */
1709
1710 /* {{{ Unsubscribe from a mailbox */
PHP_FUNCTION(imap_unsubscribe)1711 PHP_FUNCTION(imap_unsubscribe)
1712 {
1713 zval *imap_conn_obj;
1714 zend_string *folder;
1715 php_imap_object *imap_conn_struct;
1716
1717 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OS", &imap_conn_obj, php_imap_ce, &folder) == FAILURE) {
1718 RETURN_THROWS();
1719 }
1720
1721 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
1722
1723 if (mail_unsubscribe(imap_conn_struct->imap_stream, ZSTR_VAL(folder)) == T) {
1724 RETURN_TRUE;
1725 } else {
1726 RETURN_FALSE;
1727 }
1728 }
1729 /* }}} */
1730
1731 /* {{{ Read the full structure of a message */
PHP_FUNCTION(imap_fetchstructure)1732 PHP_FUNCTION(imap_fetchstructure)
1733 {
1734 zval *imap_conn_obj;
1735 zend_long msgno, flags = 0;
1736 php_imap_object *imap_conn_struct;
1737 BODY *body;
1738
1739 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ol|l", &imap_conn_obj, php_imap_ce, &msgno, &flags) == FAILURE) {
1740 RETURN_THROWS();
1741 }
1742
1743 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
1744
1745 PHP_IMAP_CHECK_MSGNO_MAYBE_UID_PRE_FLAG_CHECKS(msgno, 2);
1746
1747 if (flags && ((flags & ~FT_UID) != 0)) {
1748 zend_argument_value_error(3, "must be FT_UID or 0");
1749 RETURN_THROWS();
1750 }
1751
1752 PHP_IMAP_CHECK_MSGNO_MAYBE_UID_POST_FLAG_CHECKS(msgno, 2, flags, FT_UID);
1753
1754 object_init(return_value);
1755
1756 mail_fetchstructure_full(imap_conn_struct->imap_stream, msgno, &body , flags);
1757
1758 if (!body) {
1759 php_error_docref(NULL, E_WARNING, "No body information available");
1760 RETURN_FALSE;
1761 }
1762
1763 _php_imap_add_body(return_value, body);
1764 }
1765 /* }}} */
1766
1767 /* {{{ Get a specific body section */
PHP_FUNCTION(imap_fetchbody)1768 PHP_FUNCTION(imap_fetchbody)
1769 {
1770 zval *imap_conn_obj;
1771 zend_long msgno, flags = 0;
1772 php_imap_object *imap_conn_struct;
1773 char *body;
1774 zend_string *sec;
1775 unsigned long len;
1776
1777 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OlS|l", &imap_conn_obj, php_imap_ce, &msgno, &sec, &flags) == FAILURE) {
1778 RETURN_THROWS();
1779 }
1780
1781 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
1782
1783 PHP_IMAP_CHECK_MSGNO_MAYBE_UID_PRE_FLAG_CHECKS(msgno, 2);
1784
1785 if (flags && ((flags & ~(FT_UID|FT_PEEK|FT_INTERNAL)) != 0)) {
1786 zend_argument_value_error(4, "must be a bitmask of FT_UID, FT_PEEK, and FT_INTERNAL");
1787 RETURN_THROWS();
1788 }
1789
1790 PHP_IMAP_CHECK_MSGNO_MAYBE_UID_POST_FLAG_CHECKS(msgno, 2, flags, FT_UID);
1791
1792 body = mail_fetchbody_full(imap_conn_struct->imap_stream, msgno, ZSTR_VAL(sec), &len, flags);
1793
1794 if (!body) {
1795 php_error_docref(NULL, E_WARNING, "No body information available");
1796 RETURN_FALSE;
1797 }
1798 RETVAL_STRINGL(body, len);
1799 }
1800
1801 /* }}} */
1802
1803
1804 /* {{{ Get a specific body section's MIME headers */
PHP_FUNCTION(imap_fetchmime)1805 PHP_FUNCTION(imap_fetchmime)
1806 {
1807 zval *imap_conn_obj;
1808 zend_long msgno, flags = 0;
1809 php_imap_object *imap_conn_struct;
1810 char *body;
1811 zend_string *sec;
1812 unsigned long len;
1813
1814 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OlS|l", &imap_conn_obj, php_imap_ce, &msgno, &sec, &flags) == FAILURE) {
1815 RETURN_THROWS();
1816 }
1817
1818 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
1819
1820 PHP_IMAP_CHECK_MSGNO_MAYBE_UID_PRE_FLAG_CHECKS(msgno, 2);
1821
1822 if (flags && ((flags & ~(FT_UID|FT_PEEK|FT_INTERNAL)) != 0)) {
1823 zend_argument_value_error(4, "must be a bitmask of FT_UID, FT_PEEK, and FT_INTERNAL");
1824 RETURN_THROWS();
1825 }
1826
1827 PHP_IMAP_CHECK_MSGNO_MAYBE_UID_POST_FLAG_CHECKS(msgno, 2, flags, FT_UID);
1828
1829 body = mail_fetch_mime(imap_conn_struct->imap_stream, msgno, ZSTR_VAL(sec), &len, flags);
1830
1831 if (!body) {
1832 php_error_docref(NULL, E_WARNING, "No body MIME information available");
1833 RETURN_FALSE;
1834 }
1835 RETVAL_STRINGL(body, len);
1836 }
1837
1838 /* }}} */
1839
1840 /* {{{ Save a specific body section to a file */
PHP_FUNCTION(imap_savebody)1841 PHP_FUNCTION(imap_savebody)
1842 {
1843 zval *imap_conn_obj;
1844 zval *out;
1845 php_imap_object *imap_conn_struct = NULL;
1846 php_stream *writer = NULL;
1847 zend_string *section = NULL;
1848 int close_stream = 1;
1849 zend_long msgno, flags = 0;
1850
1851 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "Ozl|Sl", &imap_conn_obj, php_imap_ce, &out, &msgno, §ion, &flags)) {
1852 RETURN_THROWS();
1853 }
1854
1855 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
1856
1857 PHP_IMAP_CHECK_MSGNO_MAYBE_UID_PRE_FLAG_CHECKS(msgno, 3)
1858
1859 if (flags && ((flags & ~(FT_UID|FT_PEEK|FT_INTERNAL)) != 0)) {
1860 zend_argument_value_error(5, "must be a bitmask of FT_UID, FT_PEEK, and FT_INTERNAL");
1861 RETURN_THROWS();
1862 }
1863
1864 PHP_IMAP_CHECK_MSGNO_MAYBE_UID_POST_FLAG_CHECKS(msgno, 3, flags, FT_UID);
1865
1866 switch (Z_TYPE_P(out))
1867 {
1868 case IS_LONG:
1869 case IS_RESOURCE:
1870 close_stream = 0;
1871 php_stream_from_zval(writer, out);
1872 break;
1873
1874 default:
1875 if (!try_convert_to_string(out)) {
1876 RETURN_THROWS();
1877 }
1878 // TODO Need to check for null bytes?
1879 writer = php_stream_open_wrapper(Z_STRVAL_P(out), "wb", REPORT_ERRORS, NULL);
1880 break;
1881 }
1882
1883 if (!writer) {
1884 RETURN_FALSE;
1885 }
1886
1887 IMAPG(gets_stream) = writer;
1888 mail_parameters(NIL, SET_GETS, (void *) php_mail_gets);
1889 mail_fetchbody_full(imap_conn_struct->imap_stream, msgno, section?ZSTR_VAL(section):"", NULL, flags);
1890 mail_parameters(NIL, SET_GETS, (void *) NULL);
1891 IMAPG(gets_stream) = NULL;
1892
1893 if (close_stream) {
1894 php_stream_close(writer);
1895 }
1896
1897 RETURN_TRUE;
1898 }
1899 /* }}} */
1900
1901 /* {{{ Decode BASE64 encoded text */
PHP_FUNCTION(imap_base64)1902 PHP_FUNCTION(imap_base64)
1903 {
1904 zend_string *text;
1905 char *decode;
1906 unsigned long newlength;
1907
1908 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &text) == FAILURE) {
1909 RETURN_THROWS();
1910 }
1911
1912 decode = (char *) rfc822_base64((unsigned char *) ZSTR_VAL(text), ZSTR_LEN(text), &newlength);
1913
1914 if (decode == NULL) {
1915 RETURN_FALSE;
1916 }
1917
1918 RETVAL_STRINGL(decode, newlength);
1919 fs_give((void**) &decode);
1920 }
1921 /* }}} */
1922
1923 /* {{{ Convert a quoted-printable string to an 8-bit string */
PHP_FUNCTION(imap_qprint)1924 PHP_FUNCTION(imap_qprint)
1925 {
1926 zend_string *text;
1927 char *decode;
1928 unsigned long newlength;
1929
1930 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &text) == FAILURE) {
1931 RETURN_THROWS();
1932 }
1933
1934 decode = (char *) rfc822_qprint((unsigned char *) ZSTR_VAL(text), ZSTR_LEN(text), &newlength);
1935
1936 if (decode == NULL) {
1937 RETURN_FALSE;
1938 }
1939
1940 RETVAL_STRINGL(decode, newlength);
1941 fs_give((void**) &decode);
1942 }
1943 /* }}} */
1944
1945 /* {{{ Convert an 8-bit string to a quoted-printable string */
PHP_FUNCTION(imap_8bit)1946 PHP_FUNCTION(imap_8bit)
1947 {
1948 zend_string *text;
1949 char *decode;
1950 unsigned long newlength;
1951
1952 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &text) == FAILURE) {
1953 RETURN_THROWS();
1954 }
1955
1956 decode = (char *) rfc822_8bit((unsigned char *) ZSTR_VAL(text), ZSTR_LEN(text), &newlength);
1957
1958 if (decode == NULL) {
1959 RETURN_FALSE;
1960 }
1961
1962 RETVAL_STRINGL(decode, newlength);
1963 fs_give((void**) &decode);
1964 }
1965 /* }}} */
1966
1967 /* {{{ Convert an 8bit string to a base64 string */
PHP_FUNCTION(imap_binary)1968 PHP_FUNCTION(imap_binary)
1969 {
1970 zend_string *text;
1971 char *decode;
1972 unsigned long newlength;
1973
1974 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &text) == FAILURE) {
1975 RETURN_THROWS();
1976 }
1977
1978 decode = (char*)rfc822_binary(ZSTR_VAL(text), ZSTR_LEN(text), &newlength);
1979
1980 if (decode == NULL) {
1981 RETURN_FALSE;
1982 }
1983
1984 RETVAL_STRINGL(decode, newlength);
1985 fs_give((void**) &decode);
1986 }
1987 /* }}} */
1988
1989 /* {{{ Returns info about the current mailbox */
PHP_FUNCTION(imap_mailboxmsginfo)1990 PHP_FUNCTION(imap_mailboxmsginfo)
1991 {
1992 zval *imap_conn_obj;
1993 php_imap_object *imap_conn_struct;
1994 char date[100];
1995 unsigned long msgno;
1996 zend_ulong unreadmsg = 0, deletedmsg = 0, msize = 0;
1997
1998 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &imap_conn_obj, php_imap_ce) == FAILURE) {
1999 RETURN_THROWS();
2000 }
2001
2002 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
2003
2004 /* Initialize return object */
2005 object_init(return_value);
2006
2007 for (msgno = 1; msgno <= imap_conn_struct->imap_stream->nmsgs; msgno++) {
2008 MESSAGECACHE * cache = mail_elt (imap_conn_struct->imap_stream, msgno);
2009 mail_fetchstructure (imap_conn_struct->imap_stream, msgno, NIL);
2010
2011 if (!cache->seen || cache->recent) {
2012 unreadmsg++;
2013 }
2014
2015 if (cache->deleted) {
2016 deletedmsg++;
2017 }
2018 msize = msize + cache->rfc822_size;
2019 }
2020 add_property_long(return_value, "Unread", unreadmsg);
2021 add_property_long(return_value, "Deleted", deletedmsg);
2022 add_property_long(return_value, "Nmsgs", imap_conn_struct->imap_stream->nmsgs);
2023 add_property_long(return_value, "Size", msize);
2024 rfc822_date(date);
2025 add_property_string(return_value, "Date", date);
2026 add_property_string(return_value, "Driver", imap_conn_struct->imap_stream->dtb->name);
2027 add_property_string(return_value, "Mailbox", imap_conn_struct->imap_stream->mailbox);
2028 add_property_long(return_value, "Recent", imap_conn_struct->imap_stream->recent);
2029 }
2030 /* }}} */
2031
2032 /* {{{ Returns a properly formatted email address given the mailbox, host, and personal info */
PHP_FUNCTION(imap_rfc822_write_address)2033 PHP_FUNCTION(imap_rfc822_write_address)
2034 {
2035 zend_string *mailbox, *host, *personal;
2036 ADDRESS *addr;
2037 zend_string *string;
2038
2039 if (zend_parse_parameters(ZEND_NUM_ARGS(), "SSS", &mailbox, &host, &personal) == FAILURE) {
2040 RETURN_THROWS();
2041 }
2042
2043 addr=mail_newaddr();
2044
2045 if (mailbox) {
2046 addr->mailbox = cpystr(ZSTR_VAL(mailbox));
2047 }
2048
2049 if (host) {
2050 addr->host = cpystr(ZSTR_VAL(host));
2051 }
2052
2053 if (personal) {
2054 addr->personal = cpystr(ZSTR_VAL(personal));
2055 }
2056
2057 addr->next=NIL;
2058 addr->error=NIL;
2059 addr->adl=NIL;
2060
2061 string = _php_rfc822_write_address(addr);
2062 if (string) {
2063 RETVAL_STR(string);
2064 } else {
2065 RETVAL_FALSE;
2066 }
2067 mail_free_address(&addr);
2068 }
2069 /* }}} */
2070
2071 /* {{{ Parses an address string */
PHP_FUNCTION(imap_rfc822_parse_adrlist)2072 PHP_FUNCTION(imap_rfc822_parse_adrlist)
2073 {
2074 zval tovals;
2075 zend_string *str, *defaulthost;
2076 char *str_copy;
2077 ADDRESS *addresstmp;
2078 ENVELOPE *env;
2079
2080 if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS", &str, &defaulthost) == FAILURE) {
2081 RETURN_THROWS();
2082 }
2083
2084 env = mail_newenvelope();
2085
2086 /* rfc822_parse_adrlist() modifies passed string. Copy it. */
2087 str_copy = estrndup(ZSTR_VAL(str), ZSTR_LEN(str));
2088 rfc822_parse_adrlist(&env->to, str_copy, ZSTR_VAL(defaulthost));
2089 efree(str_copy);
2090
2091 array_init(return_value);
2092
2093 addresstmp = env->to;
2094
2095 if (addresstmp) do {
2096 object_init(&tovals);
2097 if (addresstmp->mailbox) {
2098 add_property_string(&tovals, "mailbox", addresstmp->mailbox);
2099 }
2100 if (addresstmp->host) {
2101 add_property_string(&tovals, "host", addresstmp->host);
2102 }
2103 if (addresstmp->personal) {
2104 add_property_string(&tovals, "personal", addresstmp->personal);
2105 }
2106 if (addresstmp->adl) {
2107 add_property_string(&tovals, "adl", addresstmp->adl);
2108 }
2109 php_imap_list_add_object(return_value, &tovals);
2110 } while ((addresstmp = addresstmp->next));
2111
2112 mail_free_envelope(&env);
2113 }
2114 /* }}} */
2115
2116 /* {{{ Convert a mime-encoded text to UTF-8 */
PHP_FUNCTION(imap_utf8)2117 PHP_FUNCTION(imap_utf8)
2118 {
2119 zend_string *str;
2120 SIZEDTEXT src, dest;
2121
2122 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &str) == FAILURE) {
2123 RETURN_THROWS();
2124 }
2125
2126 src.data = NULL;
2127 src.size = 0;
2128 dest.data = NULL;
2129 dest.size = 0;
2130
2131 cpytxt(&src, ZSTR_VAL(str), ZSTR_LEN(str));
2132
2133 #ifndef HAVE_NEW_MIME2TEXT
2134 utf8_mime2text(&src, &dest);
2135 #else
2136 utf8_mime2text(&src, &dest, U8T_DECOMPOSE);
2137 #endif
2138 RETVAL_STRINGL((char*)dest.data, dest.size);
2139 if (dest.data) {
2140 free(dest.data);
2141 }
2142 if (src.data && src.data != dest.data) {
2143 free(src.data);
2144 }
2145 }
2146 /* }}} */
2147
2148 /* {{{ macros for the modified utf7 conversion functions
2149 *
2150 * author: Andrew Skalski <askalski@chek.com>
2151 */
2152
2153 /* tests `c' and returns true if it is a special character */
2154 #define SPECIAL(c) ((c) <= 0x1f || (c) >= 0x7f)
2155
2156 /* validate a modified-base64 character */
2157 #define B64CHAR(c) (isalnum(c) || (c) == '+' || (c) == ',')
2158
2159 /* map the low 64 bits of `n' to the modified-base64 characters */
2160 #define B64(n) ("ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
2161 "abcdefghijklmnopqrstuvwxyz0123456789+,"[(n) & 0x3f])
2162
2163 /* map the modified-base64 character `c' to its 64 bit value */
2164 #define UNB64(c) ((c) == '+' ? 62 : (c) == ',' ? 63 : (c) >= 'a' ? \
2165 (c) - 71 : (c) >= 'A' ? (c) - 65 : (c) + 4)
2166 /* }}} */
2167
2168 /* {{{ Decode a modified UTF-7 string */
PHP_FUNCTION(imap_utf7_decode)2169 PHP_FUNCTION(imap_utf7_decode)
2170 {
2171 /* author: Andrew Skalski <askalski@chek.com> */
2172 zend_string *arg;
2173 const unsigned char *in, *inp, *endp;
2174 unsigned char *out, *outp;
2175 unsigned char c;
2176 int inlen, outlen;
2177 enum {
2178 ST_NORMAL, /* printable text */
2179 ST_DECODE0, /* encoded text rotation... */
2180 ST_DECODE1,
2181 ST_DECODE2,
2182 ST_DECODE3
2183 } state;
2184
2185 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &arg) == FAILURE) {
2186 RETURN_THROWS();
2187 }
2188
2189 in = (const unsigned char *) ZSTR_VAL(arg);
2190 inlen = ZSTR_LEN(arg);
2191
2192 /* validate and compute length of output string */
2193 outlen = 0;
2194 state = ST_NORMAL;
2195 for (endp = (inp = in) + inlen; inp < endp; inp++) {
2196 if (state == ST_NORMAL) {
2197 /* process printable character */
2198 if (SPECIAL(*inp)) {
2199 php_error_docref(NULL, E_WARNING, "Invalid modified UTF-7 character: `%c'", *inp);
2200 RETURN_FALSE;
2201 } else if (*inp != '&') {
2202 outlen++;
2203 } else if (inp + 1 == endp) {
2204 php_error_docref(NULL, E_WARNING, "Unexpected end of string");
2205 RETURN_FALSE;
2206 } else if (inp[1] != '-') {
2207 state = ST_DECODE0;
2208 } else {
2209 outlen++;
2210 inp++;
2211 }
2212 } else if (*inp == '-') {
2213 /* return to NORMAL mode */
2214 if (state == ST_DECODE1) {
2215 php_error_docref(NULL, E_WARNING, "Stray modified base64 character: `%c'", *--inp);
2216 RETURN_FALSE;
2217 }
2218 state = ST_NORMAL;
2219 } else if (!B64CHAR(*inp)) {
2220 php_error_docref(NULL, E_WARNING, "Invalid modified base64 character: `%c'", *inp);
2221 RETURN_FALSE;
2222 } else {
2223 switch (state) {
2224 case ST_DECODE3:
2225 outlen++;
2226 state = ST_DECODE0;
2227 break;
2228 case ST_DECODE2:
2229 case ST_DECODE1:
2230 outlen++;
2231 ZEND_FALLTHROUGH;
2232 case ST_DECODE0:
2233 state++;
2234 case ST_NORMAL:
2235 break;
2236 }
2237 }
2238 }
2239
2240 /* enforce end state */
2241 if (state != ST_NORMAL) {
2242 php_error_docref(NULL, E_WARNING, "Unexpected end of string");
2243 RETURN_FALSE;
2244 }
2245
2246 /* allocate output buffer */
2247 out = emalloc(outlen + 1);
2248
2249 /* decode input string */
2250 outp = out;
2251 state = ST_NORMAL;
2252 for (endp = (inp = in) + inlen; inp < endp; inp++) {
2253 if (state == ST_NORMAL) {
2254 if (*inp == '&' && inp[1] != '-') {
2255 state = ST_DECODE0;
2256 }
2257 else if ((*outp++ = *inp) == '&') {
2258 inp++;
2259 }
2260 }
2261 else if (*inp == '-') {
2262 state = ST_NORMAL;
2263 }
2264 else {
2265 /* decode input character */
2266 switch (state) {
2267 case ST_DECODE0:
2268 *outp = UNB64(*inp) << 2;
2269 state = ST_DECODE1;
2270 break;
2271 case ST_DECODE1:
2272 outp[1] = UNB64(*inp);
2273 c = outp[1] >> 4;
2274 *outp++ |= c;
2275 *outp <<= 4;
2276 state = ST_DECODE2;
2277 break;
2278 case ST_DECODE2:
2279 outp[1] = UNB64(*inp);
2280 c = outp[1] >> 2;
2281 *outp++ |= c;
2282 *outp <<= 6;
2283 state = ST_DECODE3;
2284 break;
2285 case ST_DECODE3:
2286 *outp++ |= UNB64(*inp);
2287 state = ST_DECODE0;
2288 case ST_NORMAL:
2289 break;
2290 }
2291 }
2292 }
2293
2294 *outp = 0;
2295
2296 #if PHP_DEBUG
2297 /* warn if we computed outlen incorrectly */
2298 if (outp - out != outlen) {
2299 php_error_docref(NULL, E_WARNING, "outp - out [%zd] != outlen [%d]", outp - out, outlen);
2300 }
2301 #endif
2302
2303 RETURN_STRINGL((char*)out, outlen);
2304 }
2305 /* }}} */
2306
2307 /* {{{ Encode a string in modified UTF-7 */
PHP_FUNCTION(imap_utf7_encode)2308 PHP_FUNCTION(imap_utf7_encode)
2309 {
2310 /* author: Andrew Skalski <askalski@chek.com> */
2311 zend_string *arg;
2312 const unsigned char *in, *inp, *endp;
2313 zend_string *out;
2314 unsigned char *outp;
2315 unsigned char c;
2316 int inlen, outlen;
2317 enum {
2318 ST_NORMAL, /* printable text */
2319 ST_ENCODE0, /* encoded text rotation... */
2320 ST_ENCODE1,
2321 ST_ENCODE2
2322 } state;
2323
2324 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &arg) == FAILURE) {
2325 RETURN_THROWS();
2326 }
2327
2328 in = (const unsigned char *) ZSTR_VAL(arg);
2329 inlen = ZSTR_LEN(arg);
2330
2331 /* compute the length of the result string */
2332 outlen = 0;
2333 state = ST_NORMAL;
2334 endp = (inp = in) + inlen;
2335 while (inp < endp) {
2336 if (state == ST_NORMAL) {
2337 if (SPECIAL(*inp)) {
2338 state = ST_ENCODE0;
2339 outlen++;
2340 } else if (*inp++ == '&') {
2341 outlen++;
2342 }
2343 outlen++;
2344 } else if (!SPECIAL(*inp)) {
2345 state = ST_NORMAL;
2346 } else {
2347 /* ST_ENCODE0 -> ST_ENCODE1 - two chars
2348 * ST_ENCODE1 -> ST_ENCODE2 - one char
2349 * ST_ENCODE2 -> ST_ENCODE0 - one char
2350 */
2351 if (state == ST_ENCODE2) {
2352 state = ST_ENCODE0;
2353 }
2354 else if (state++ == ST_ENCODE0) {
2355 outlen++;
2356 }
2357 outlen++;
2358 inp++;
2359 }
2360 }
2361
2362 /* allocate output buffer */
2363 out = zend_string_safe_alloc(1, outlen, 0, 0);
2364
2365 /* encode input string */
2366 outp = (unsigned char*)ZSTR_VAL(out);
2367 state = ST_NORMAL;
2368 endp = (inp = in) + inlen;
2369 while (inp < endp || state != ST_NORMAL) {
2370 if (state == ST_NORMAL) {
2371 if (SPECIAL(*inp)) {
2372 /* begin encoding */
2373 *outp++ = '&';
2374 state = ST_ENCODE0;
2375 } else if ((*outp++ = *inp++) == '&') {
2376 *outp++ = '-';
2377 }
2378 } else if (inp == endp || !SPECIAL(*inp)) {
2379 /* flush overflow and terminate region */
2380 if (state != ST_ENCODE0) {
2381 c = B64(*outp);
2382 *outp++ = c;
2383 }
2384 *outp++ = '-';
2385 state = ST_NORMAL;
2386 } else {
2387 /* encode input character */
2388 switch (state) {
2389 case ST_ENCODE0:
2390 *outp++ = B64(*inp >> 2);
2391 *outp = *inp++ << 4;
2392 state = ST_ENCODE1;
2393 break;
2394 case ST_ENCODE1:
2395 c = B64(*outp | *inp >> 4);
2396 *outp++ = c;
2397 *outp = *inp++ << 2;
2398 state = ST_ENCODE2;
2399 break;
2400 case ST_ENCODE2:
2401 c = B64(*outp | *inp >> 6);
2402 *outp++ = c;
2403 *outp++ = B64(*inp++);
2404 state = ST_ENCODE0;
2405 case ST_NORMAL:
2406 break;
2407 }
2408 }
2409 }
2410
2411 *outp = 0;
2412
2413 RETURN_STR(out);
2414 }
2415 /* }}} */
2416
2417 #undef SPECIAL
2418 #undef B64CHAR
2419 #undef B64
2420 #undef UNB64
2421
2422 #ifdef HAVE_IMAP_MUTF7
php_imap_mutf7(INTERNAL_FUNCTION_PARAMETERS,int mode)2423 static void php_imap_mutf7(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */
2424 {
2425 zend_string *in;
2426 unsigned char *out;
2427
2428 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &in) == FAILURE) {
2429 RETURN_THROWS();
2430 }
2431
2432 if (ZSTR_LEN(in) < 1) {
2433 RETURN_EMPTY_STRING();
2434 }
2435
2436 if (mode == 0) {
2437 out = utf8_to_mutf7((unsigned char *) ZSTR_VAL(in));
2438 } else {
2439 out = utf8_from_mutf7((unsigned char *) ZSTR_VAL(in));
2440 }
2441
2442 if (out == NIL) {
2443 RETURN_FALSE;
2444 } else {
2445 RETVAL_STRING((char *)out);
2446 fs_give((void**) &out);
2447 }
2448 }
2449 /* }}} */
2450
2451 /* {{{ Encode a UTF-8 string to modified UTF-7 */
PHP_FUNCTION(imap_utf8_to_mutf7)2452 PHP_FUNCTION(imap_utf8_to_mutf7)
2453 {
2454 php_imap_mutf7(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
2455 }
2456 /* }}} */
2457
2458 /* {{{ Decode a modified UTF-7 string to UTF-8 */
PHP_FUNCTION(imap_mutf7_to_utf8)2459 PHP_FUNCTION(imap_mutf7_to_utf8)
2460 {
2461 php_imap_mutf7(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
2462 }
2463 /* }}} */
2464 #endif
2465
2466 /* {{{ Sets flags on messages */
PHP_FUNCTION(imap_setflag_full)2467 PHP_FUNCTION(imap_setflag_full)
2468 {
2469 zval *imap_conn_obj;
2470 zend_string *sequence, *flag;
2471 zend_long flags = 0;
2472 php_imap_object *imap_conn_struct;
2473
2474 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OSS|l", &imap_conn_obj, php_imap_ce, &sequence, &flag, &flags) == FAILURE) {
2475 RETURN_THROWS();
2476 }
2477
2478 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
2479
2480 if (flags && ((flags & ~ST_UID) != 0)) {
2481 zend_argument_value_error(4, "must be ST_UID or 0");
2482 RETURN_THROWS();
2483 }
2484
2485 mail_setflag_full(imap_conn_struct->imap_stream, ZSTR_VAL(sequence), ZSTR_VAL(flag), (flags ? flags : NIL));
2486 RETURN_TRUE;
2487 }
2488 /* }}} */
2489
2490 /* {{{ Clears flags on messages */
PHP_FUNCTION(imap_clearflag_full)2491 PHP_FUNCTION(imap_clearflag_full)
2492 {
2493 zval *imap_conn_obj;
2494 zend_string *sequence, *flag;
2495 zend_long flags = 0;
2496 php_imap_object *imap_conn_struct;
2497
2498 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OSS|l", &imap_conn_obj, php_imap_ce, &sequence, &flag, &flags) ==FAILURE) {
2499 RETURN_THROWS();
2500 }
2501
2502 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
2503
2504 if (flags && ((flags & ~ST_UID) != 0)) {
2505 zend_argument_value_error(4, "must be ST_UID or 0");
2506 RETURN_THROWS();
2507 }
2508
2509 mail_clearflag_full(imap_conn_struct->imap_stream, ZSTR_VAL(sequence), ZSTR_VAL(flag), flags);
2510 RETURN_TRUE;
2511 }
2512 /* }}} */
2513
2514 /* {{{ Sort an array of message headers, optionally including only messages that meet specified criteria. */
PHP_FUNCTION(imap_sort)2515 PHP_FUNCTION(imap_sort)
2516 {
2517 zval *imap_conn_obj;
2518 zend_string *criteria = NULL, *charset = NULL;
2519 zend_long sort, flags = 0;
2520 bool rev;
2521 php_imap_object *imap_conn_struct;
2522 unsigned long *slst, *sl;
2523 char *search_criteria;
2524 SORTPGM *mypgm=NIL;
2525 SEARCHPGM *spg=NIL;
2526
2527 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Olb|lS!S!", &imap_conn_obj, php_imap_ce, &sort, &rev, &flags, &criteria, &charset) == FAILURE) {
2528 RETURN_THROWS();
2529 }
2530
2531 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
2532
2533 if (!(sort == SORTDATE || sort == SORTARRIVAL || sort == SORTFROM || sort == SORTSUBJECT || sort == SORTTO ||
2534 sort == SORTCC || sort == SORTSIZE) ) {
2535 zend_argument_value_error(2, "must be one of the SORT* constants");
2536 RETURN_THROWS();
2537 }
2538
2539 if (flags && ((flags & ~(SE_UID|SE_NOPREFETCH )) != 0)) {
2540 zend_argument_value_error(4, "must be a bitmask of SE_UID, and SE_NOPREFETCH");
2541 RETURN_THROWS();
2542 }
2543
2544 if (criteria) {
2545 search_criteria = estrndup(ZSTR_VAL(criteria), ZSTR_LEN(criteria));
2546 spg = mail_criteria(search_criteria);
2547 efree(search_criteria);
2548 } else {
2549 spg = mail_newsearchpgm();
2550 }
2551 if (spg == NIL) {
2552 RETURN_FALSE;
2553 }
2554
2555 mypgm = mail_newsortpgm();
2556 mypgm->reverse = rev;
2557 mypgm->function = (short) sort;
2558 mypgm->next = NIL;
2559
2560 slst = mail_sort(imap_conn_struct->imap_stream, (charset ? ZSTR_VAL(charset) : NIL), spg, mypgm, flags);
2561
2562 mail_free_sortpgm(&mypgm);
2563 if (spg && !(flags & SE_FREE)) {
2564 mail_free_searchpgm(&spg);
2565 }
2566
2567 array_init(return_value);
2568 if (slst != NULL) {
2569 for (sl = slst; *sl; sl++) {
2570 add_next_index_long(return_value, *sl);
2571 }
2572 fs_give ((void **) &slst);
2573 }
2574 }
2575 /* }}} */
2576
2577 /* {{{ Get the full unfiltered header for a message */
PHP_FUNCTION(imap_fetchheader)2578 PHP_FUNCTION(imap_fetchheader)
2579 {
2580 zval *imap_conn_obj;
2581 zend_long msgno, flags = 0;
2582 php_imap_object *imap_conn_struct;
2583
2584 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ol|l", &imap_conn_obj, php_imap_ce, &msgno, &flags) == FAILURE) {
2585 RETURN_THROWS();
2586 }
2587
2588 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
2589
2590 PHP_IMAP_CHECK_MSGNO_MAYBE_UID_PRE_FLAG_CHECKS(msgno, 2);
2591
2592 if (flags && ((flags & ~(FT_UID|FT_INTERNAL|FT_PREFETCHTEXT)) != 0)) {
2593 zend_argument_value_error(3, "must be a bitmask of FT_UID, FT_PREFETCHTEXT, and FT_INTERNAL");
2594 RETURN_THROWS();
2595 }
2596
2597 PHP_IMAP_CHECK_MSGNO_MAYBE_UID_POST_FLAG_CHECKS(msgno, 2, flags, FT_UID);
2598
2599 RETVAL_STRING(mail_fetchheader_full(imap_conn_struct->imap_stream, msgno, NIL, NIL, flags));
2600 }
2601 /* }}} */
2602
2603 /* {{{ Get the unique message id associated with a standard sequential message number */
PHP_FUNCTION(imap_uid)2604 PHP_FUNCTION(imap_uid)
2605 {
2606 zval *imap_conn_obj;
2607 zend_long msgno;
2608 php_imap_object *imap_conn_struct;
2609
2610 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ol", &imap_conn_obj, php_imap_ce, &msgno) == FAILURE) {
2611 RETURN_THROWS();
2612 }
2613
2614 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
2615
2616 PHP_IMAP_CHECK_MSGNO(msgno, 2);
2617
2618 RETURN_LONG(mail_uid(imap_conn_struct->imap_stream, msgno));
2619 }
2620 /* }}} */
2621
2622 /* {{{ Get the sequence number associated with a UID */
PHP_FUNCTION(imap_msgno)2623 PHP_FUNCTION(imap_msgno)
2624 {
2625 zval *imap_conn_obj;
2626 zend_long msg_uid;
2627 php_imap_object *imap_conn_struct;
2628
2629 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Ol", &imap_conn_obj, php_imap_ce, &msg_uid) == FAILURE) {
2630 RETURN_THROWS();
2631 }
2632
2633 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
2634
2635 /* Do NOT use the PHP_IMAP_CHECK_MSGNO() macro as UID cannot be checked for their upper bound. */
2636 if (msg_uid < 1) {
2637 zend_argument_value_error(2, "must be greater than 0");
2638 RETURN_THROWS();
2639 }
2640
2641 RETURN_LONG(mail_msgno(imap_conn_struct->imap_stream, msg_uid));
2642 }
2643 /* }}} */
2644
2645 /* {{{ Get status info from a mailbox */
PHP_FUNCTION(imap_status)2646 PHP_FUNCTION(imap_status)
2647 {
2648 zval *imap_conn_obj;
2649 zend_string *mbx;
2650 zend_long flags;
2651 php_imap_object *imap_conn_struct;
2652
2653 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OSl", &imap_conn_obj, php_imap_ce, &mbx, &flags) == FAILURE) {
2654 RETURN_THROWS();
2655 }
2656
2657 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
2658
2659 if (flags && ((flags & ~(SA_ALL)) != 0)) {
2660 zend_argument_value_error(3, "must be a bitmask of SA_* constants");
2661 RETURN_THROWS();
2662 }
2663
2664 object_init(return_value);
2665
2666 if (mail_status(imap_conn_struct->imap_stream, ZSTR_VAL(mbx), flags)) {
2667 add_property_long(return_value, "flags", IMAPG(status_flags));
2668 if (IMAPG(status_flags) & SA_MESSAGES) {
2669 add_property_long(return_value, "messages", IMAPG(status_messages));
2670 }
2671 if (IMAPG(status_flags) & SA_RECENT) {
2672 add_property_long(return_value, "recent", IMAPG(status_recent));
2673 }
2674 if (IMAPG(status_flags) & SA_UNSEEN) {
2675 add_property_long(return_value, "unseen", IMAPG(status_unseen));
2676 }
2677 if (IMAPG(status_flags) & SA_UIDNEXT) {
2678 add_property_long(return_value, "uidnext", IMAPG(status_uidnext));
2679 }
2680 if (IMAPG(status_flags) & SA_UIDVALIDITY) {
2681 add_property_long(return_value, "uidvalidity", IMAPG(status_uidvalidity));
2682 }
2683 } else {
2684 RETURN_FALSE;
2685 }
2686 }
2687 /* }}} */
2688
2689 /* {{{ Read the structure of a specified body section of a specific message */
PHP_FUNCTION(imap_bodystruct)2690 PHP_FUNCTION(imap_bodystruct)
2691 {
2692 zval *imap_conn_obj;
2693 zend_long msgno;
2694 zend_string *section;
2695 php_imap_object *imap_conn_struct;
2696 zval parametres, param, dparametres, dparam;
2697 PARAMETER *par, *dpar;
2698 BODY *body;
2699
2700 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OlS", &imap_conn_obj, php_imap_ce, &msgno, §ion) == FAILURE) {
2701 RETURN_THROWS();
2702 }
2703
2704 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
2705
2706 PHP_IMAP_CHECK_MSGNO(msgno, 2);
2707
2708 body=mail_body(imap_conn_struct->imap_stream, msgno, (unsigned char*)ZSTR_VAL(section));
2709 if (body == NULL) {
2710 RETURN_FALSE;
2711 }
2712
2713 object_init(return_value);
2714 if (body->type <= TYPEMAX) {
2715 add_property_long(return_value, "type", body->type);
2716 }
2717 if (body->encoding <= ENCMAX) {
2718 add_property_long(return_value, "encoding", body->encoding);
2719 }
2720
2721 if (body->subtype) {
2722 add_property_long(return_value, "ifsubtype", 1);
2723 add_property_string(return_value, "subtype", body->subtype);
2724 } else {
2725 add_property_long(return_value, "ifsubtype", 0);
2726 }
2727
2728 if (body->description) {
2729 add_property_long(return_value, "ifdescription", 1);
2730 add_property_string(return_value, "description", body->description);
2731 } else {
2732 add_property_long(return_value, "ifdescription", 0);
2733 }
2734 if (body->id) {
2735 add_property_long(return_value, "ifid", 1);
2736 add_property_string(return_value, "id", body->id);
2737 } else {
2738 add_property_long(return_value, "ifid", 0);
2739 }
2740
2741 if (body->size.lines) {
2742 add_property_long(return_value, "lines", body->size.lines);
2743 }
2744 if (body->size.bytes) {
2745 add_property_long(return_value, "bytes", body->size.bytes);
2746 }
2747 #ifdef IMAP41
2748 if (body->disposition.type) {
2749 add_property_long(return_value, "ifdisposition", 1);
2750 add_property_string(return_value, "disposition", body->disposition.type);
2751 } else {
2752 add_property_long(return_value, "ifdisposition", 0);
2753 }
2754
2755 if (body->disposition.parameter) {
2756 dpar = body->disposition.parameter;
2757 add_property_long(return_value, "ifdparameters", 1);
2758 array_init(&dparametres);
2759 do {
2760 object_init(&dparam);
2761 add_property_string(&dparam, "attribute", dpar->attribute);
2762 add_property_string(&dparam, "value", dpar->value);
2763 php_imap_list_add_object(&dparametres, &dparam);
2764 } while ((dpar = dpar->next));
2765 php_imap_hash_add_object(return_value, "dparameters", &dparametres);
2766 } else {
2767 add_property_long(return_value, "ifdparameters", 0);
2768 }
2769 #endif
2770
2771 if ((par = body->parameter)) {
2772 add_property_long(return_value, "ifparameters", 1);
2773
2774 array_init(¶metres);
2775 do {
2776 object_init(¶m);
2777 if (par->attribute) {
2778 add_property_string(¶m, "attribute", par->attribute);
2779 }
2780 if (par->value) {
2781 add_property_string(¶m, "value", par->value);
2782 }
2783
2784 php_imap_list_add_object(¶metres, ¶m);
2785 } while ((par = par->next));
2786 } else {
2787 object_init(¶metres);
2788 add_property_long(return_value, "ifparameters", 0);
2789 }
2790 php_imap_hash_add_object(return_value, "parameters", ¶metres);
2791 }
2792
2793 /* }}} */
2794
2795 /* {{{ Read an overview of the information in the headers of the given message sequence */
PHP_FUNCTION(imap_fetch_overview)2796 PHP_FUNCTION(imap_fetch_overview)
2797 {
2798 zval *imap_conn_obj;
2799 zend_string *sequence;
2800 php_imap_object *imap_conn_struct;
2801 zval myoverview;
2802 zend_string *address;
2803 zend_long status, flags = 0L;
2804
2805 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OS|l", &imap_conn_obj, php_imap_ce, &sequence, &flags) == FAILURE) {
2806 RETURN_THROWS();
2807 }
2808
2809 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
2810
2811 if (flags && ((flags & ~FT_UID) != 0)) {
2812 zend_argument_value_error(3, "must be FT_UID or 0");
2813 RETURN_THROWS();
2814 }
2815
2816 array_init(return_value);
2817
2818 status = (flags & FT_UID)
2819 ? mail_uid_sequence(imap_conn_struct->imap_stream, (unsigned char*)ZSTR_VAL(sequence))
2820 : mail_sequence(imap_conn_struct->imap_stream, (unsigned char*)ZSTR_VAL(sequence));
2821
2822 if (status) {
2823 MESSAGECACHE *elt;
2824 ENVELOPE *env;
2825 unsigned long i;
2826
2827 for (i = 1; i <= imap_conn_struct->imap_stream->nmsgs; i++) {
2828 if (((elt = mail_elt (imap_conn_struct->imap_stream, i))->sequence) &&
2829 (env = mail_fetch_structure (imap_conn_struct->imap_stream, i, NIL, NIL))) {
2830 object_init(&myoverview);
2831 if (env->subject) {
2832 add_property_string(&myoverview, "subject", env->subject);
2833 }
2834 if (env->from) {
2835 env->from->next=NULL;
2836 address =_php_rfc822_write_address(env->from);
2837 if (address) {
2838 add_property_str(&myoverview, "from", address);
2839 }
2840 }
2841 if (env->to) {
2842 env->to->next = NULL;
2843 address = _php_rfc822_write_address(env->to);
2844 if (address) {
2845 add_property_str(&myoverview, "to", address);
2846 }
2847 }
2848 if (env->date) {
2849 add_property_string(&myoverview, "date", (char*)env->date);
2850 }
2851 if (env->message_id) {
2852 add_property_string(&myoverview, "message_id", env->message_id);
2853 }
2854 if (env->references) {
2855 add_property_string(&myoverview, "references", env->references);
2856 }
2857 if (env->in_reply_to) {
2858 add_property_string(&myoverview, "in_reply_to", env->in_reply_to);
2859 }
2860 add_property_long(&myoverview, "size", elt->rfc822_size);
2861 add_property_long(&myoverview, "uid", mail_uid(imap_conn_struct->imap_stream, i));
2862 add_property_long(&myoverview, "msgno", i);
2863 add_property_long(&myoverview, "recent", elt->recent);
2864 add_property_long(&myoverview, "flagged", elt->flagged);
2865 add_property_long(&myoverview, "answered", elt->answered);
2866 add_property_long(&myoverview, "deleted", elt->deleted);
2867 add_property_long(&myoverview, "seen", elt->seen);
2868 add_property_long(&myoverview, "draft", elt->draft);
2869 add_property_long(&myoverview, "udate", mail_longdate(elt));
2870 php_imap_list_add_object(return_value, &myoverview);
2871 }
2872 }
2873 }
2874 }
2875 /* }}} */
2876
header_injection(zend_string * str,bool adrlist)2877 static bool header_injection(zend_string *str, bool adrlist)
2878 {
2879 char *p = ZSTR_VAL(str);
2880
2881 while ((p = strpbrk(p, "\r\n")) != NULL) {
2882 if (!(p[0] == '\r' && p[1] == '\n')
2883 /* adrlists do not support folding, but swallow trailing line breaks */
2884 && !((adrlist && p[1] == '\0')
2885 /* other headers support folding */
2886 || (!adrlist && (p[1] == ' ' || p[1] == '\t')))) {
2887 return 1;
2888 }
2889 p++;
2890 }
2891 return 0;
2892 }
2893
2894 /* {{{ Create a MIME message based on given envelope and body sections */
PHP_FUNCTION(imap_mail_compose)2895 PHP_FUNCTION(imap_mail_compose)
2896 {
2897 HashTable *envelope, *body;
2898 zend_string *key;
2899 zval *data, *pvalue, *disp_data, *env_data;
2900 char *cookie = NIL;
2901 ENVELOPE *env;
2902 BODY *bod=NULL, *topbod=NULL;
2903 PART *mypart=NULL, *part;
2904 PARAMETER *param, *disp_param = NULL, *custom_headers_param = NULL, *tmp_param = NULL;
2905 char *tmp=NULL, *mystring=NULL, *t=NULL, *tempstring=NULL, *str_copy = NULL;
2906 int toppart = 0;
2907 int first;
2908
2909 if (zend_parse_parameters(ZEND_NUM_ARGS(), "h/h/", &envelope, &body) == FAILURE) {
2910 RETURN_THROWS();
2911 }
2912
2913 if (zend_hash_num_elements(body) == 0) {
2914 zend_argument_value_error(2, "cannot be empty");
2915 }
2916
2917 #define CHECK_HEADER_INJECTION(zstr, adrlist, header) \
2918 if (header_injection(zstr, adrlist)) { \
2919 php_error_docref(NULL, E_WARNING, "header injection attempt in " header); \
2920 RETVAL_FALSE; \
2921 goto done; \
2922 }
2923
2924 #define PHP_RFC822_PARSE_ADRLIST(target, value) \
2925 str_copy = estrndup(Z_STRVAL_P(value), Z_STRLEN_P(value)); \
2926 rfc822_parse_adrlist(target, str_copy, "NO HOST"); \
2927 efree(str_copy);
2928
2929 env = mail_newenvelope();
2930 if ((pvalue = zend_hash_str_find(envelope, "remail", sizeof("remail") - 1)) != NULL) {
2931 convert_to_string(pvalue);
2932 CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "remail");
2933 env->remail = cpystr(Z_STRVAL_P(pvalue));
2934 }
2935 if ((pvalue = zend_hash_str_find(envelope, "return_path", sizeof("return_path") - 1)) != NULL) {
2936 convert_to_string(pvalue);
2937 CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 1, "return_path");
2938 PHP_RFC822_PARSE_ADRLIST(&env->return_path, pvalue);
2939 }
2940 if ((pvalue = zend_hash_str_find(envelope, "date", sizeof("date") - 1)) != NULL) {
2941 convert_to_string(pvalue);
2942 CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "date");
2943 env->date = (unsigned char*)cpystr(Z_STRVAL_P(pvalue));
2944 }
2945 if ((pvalue = zend_hash_str_find(envelope, "from", sizeof("from") - 1)) != NULL) {
2946 convert_to_string(pvalue);
2947 CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 1, "from");
2948 PHP_RFC822_PARSE_ADRLIST(&env->from, pvalue);
2949 }
2950 if ((pvalue = zend_hash_str_find(envelope, "reply_to", sizeof("reply_to") - 1)) != NULL) {
2951 convert_to_string(pvalue);
2952 CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 1, "reply_to");
2953 PHP_RFC822_PARSE_ADRLIST(&env->reply_to, pvalue);
2954 }
2955 if ((pvalue = zend_hash_str_find(envelope, "in_reply_to", sizeof("in_reply_to") - 1)) != NULL) {
2956 convert_to_string(pvalue);
2957 CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "in_reply_to");
2958 env->in_reply_to = cpystr(Z_STRVAL_P(pvalue));
2959 }
2960 if ((pvalue = zend_hash_str_find(envelope, "subject", sizeof("subject") - 1)) != NULL) {
2961 convert_to_string(pvalue);
2962 CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "subject");
2963 env->subject = cpystr(Z_STRVAL_P(pvalue));
2964 }
2965 if ((pvalue = zend_hash_str_find(envelope, "to", sizeof("to") - 1)) != NULL) {
2966 convert_to_string(pvalue);
2967 CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 1, "to");
2968 PHP_RFC822_PARSE_ADRLIST(&env->to, pvalue);
2969 }
2970 if ((pvalue = zend_hash_str_find(envelope, "cc", sizeof("cc") - 1)) != NULL) {
2971 convert_to_string(pvalue);
2972 CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 1, "cc");
2973 PHP_RFC822_PARSE_ADRLIST(&env->cc, pvalue);
2974 }
2975 if ((pvalue = zend_hash_str_find(envelope, "bcc", sizeof("bcc") - 1)) != NULL) {
2976 convert_to_string(pvalue);
2977 CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 1, "bcc");
2978 PHP_RFC822_PARSE_ADRLIST(&env->bcc, pvalue);
2979 }
2980 if ((pvalue = zend_hash_str_find(envelope, "message_id", sizeof("message_id") - 1)) != NULL) {
2981 convert_to_string(pvalue);
2982 CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "message_id");
2983 env->message_id=cpystr(Z_STRVAL_P(pvalue));
2984 }
2985
2986 if ((pvalue = zend_hash_str_find(envelope, "custom_headers", sizeof("custom_headers") - 1)) != NULL) {
2987 if (Z_TYPE_P(pvalue) == IS_ARRAY) {
2988 custom_headers_param = tmp_param = NULL;
2989 SEPARATE_ARRAY(pvalue);
2990 ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(pvalue), env_data) {
2991 custom_headers_param = mail_newbody_parameter();
2992 convert_to_string(env_data);
2993 CHECK_HEADER_INJECTION(Z_STR_P(env_data), 0, "custom_headers");
2994 custom_headers_param->value = (char *) fs_get(Z_STRLEN_P(env_data) + 1);
2995 custom_headers_param->attribute = NULL;
2996 memcpy(custom_headers_param->value, Z_STRVAL_P(env_data), Z_STRLEN_P(env_data) + 1);
2997 custom_headers_param->next = tmp_param;
2998 tmp_param = custom_headers_param;
2999 } ZEND_HASH_FOREACH_END();
3000 }
3001 }
3002
3003 first = 1;
3004 ZEND_HASH_FOREACH_VAL(body, data) {
3005 if (first) {
3006 first = 0;
3007
3008 if (Z_TYPE_P(data) != IS_ARRAY) {
3009 zend_argument_type_error(2, "individual body must be of type array, %s given",
3010 zend_zval_type_name(data));
3011 goto done;
3012 }
3013 if (zend_hash_num_elements(Z_ARRVAL_P(data)) == 0) {
3014 zend_argument_value_error(2, "individual body cannot be empty");
3015 goto done;
3016 }
3017 SEPARATE_ARRAY(data);
3018
3019 bod = mail_newbody();
3020 topbod = bod;
3021
3022 if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "type", sizeof("type") - 1)) != NULL) {
3023 zend_long type = zval_get_long(pvalue);
3024 if (type >= 0 && type <= TYPEMAX && body_types[type] != NULL) {
3025 bod->type = (short) type;
3026 }
3027 }
3028 if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "encoding", sizeof("encoding") - 1)) != NULL) {
3029 zend_long encoding = zval_get_long(pvalue);
3030 if (encoding >= 0 && encoding <= ENCMAX && body_encodings[encoding] != NULL) {
3031 bod->encoding = (short) encoding;
3032 }
3033 }
3034 if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "charset", sizeof("charset") - 1)) != NULL) {
3035 convert_to_string(pvalue);
3036 CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body charset");
3037 tmp_param = mail_newbody_parameter();
3038 tmp_param->value = cpystr(Z_STRVAL_P(pvalue));
3039 tmp_param->attribute = cpystr("CHARSET");
3040 tmp_param->next = bod->parameter;
3041 bod->parameter = tmp_param;
3042 }
3043 if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "type.parameters", sizeof("type.parameters") - 1)) != NULL) {
3044 if(Z_TYPE_P(pvalue) == IS_ARRAY && !HT_IS_PACKED(Z_ARRVAL_P(pvalue))) {
3045 disp_param = tmp_param = NULL;
3046 SEPARATE_ARRAY(pvalue);
3047 ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(pvalue), key, disp_data) {
3048 if (key == NULL) continue;
3049 CHECK_HEADER_INJECTION(key, 0, "body disposition key");
3050 disp_param = mail_newbody_parameter();
3051 disp_param->attribute = cpystr(ZSTR_VAL(key));
3052 convert_to_string(disp_data);
3053 CHECK_HEADER_INJECTION(Z_STR_P(disp_data), 0, "body disposition value");
3054 disp_param->value = (char *) fs_get(Z_STRLEN_P(disp_data) + 1);
3055 memcpy(disp_param->value, Z_STRVAL_P(disp_data), Z_STRLEN_P(disp_data) + 1);
3056 disp_param->next = tmp_param;
3057 tmp_param = disp_param;
3058 } ZEND_HASH_FOREACH_END();
3059 bod->parameter = disp_param;
3060 }
3061 }
3062 if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "subtype", sizeof("subtype") - 1)) != NULL) {
3063 convert_to_string_ex(pvalue);
3064 CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body subtype");
3065 bod->subtype = cpystr(Z_STRVAL_P(pvalue));
3066 }
3067 if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "id", sizeof("id") - 1)) != NULL) {
3068 convert_to_string(pvalue);
3069 CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body id");
3070 bod->id = cpystr(Z_STRVAL_P(pvalue));
3071 }
3072 if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "description", sizeof("description") - 1)) != NULL) {
3073 convert_to_string(pvalue);
3074 CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body description");
3075 bod->description = cpystr(Z_STRVAL_P(pvalue));
3076 }
3077 if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "disposition.type", sizeof("disposition.type") - 1)) != NULL) {
3078 convert_to_string(pvalue);
3079 CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body disposition.type");
3080 bod->disposition.type = (char *) fs_get(Z_STRLEN_P(pvalue) + 1);
3081 memcpy(bod->disposition.type, Z_STRVAL_P(pvalue), Z_STRLEN_P(pvalue)+1);
3082 }
3083 if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "disposition", sizeof("disposition") - 1)) != NULL) {
3084 if (Z_TYPE_P(pvalue) == IS_ARRAY && !HT_IS_PACKED(Z_ARRVAL_P(pvalue))) {
3085 disp_param = tmp_param = NULL;
3086 SEPARATE_ARRAY(pvalue);
3087 ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(pvalue), key, disp_data) {
3088 if (key == NULL) continue;
3089 CHECK_HEADER_INJECTION(key, 0, "body type.parameters key");
3090 disp_param = mail_newbody_parameter();
3091 disp_param->attribute = cpystr(ZSTR_VAL(key));
3092 convert_to_string(disp_data);
3093 CHECK_HEADER_INJECTION(Z_STR_P(disp_data), 0, "body type.parameters value");
3094 disp_param->value = (char *) fs_get(Z_STRLEN_P(disp_data) + 1);
3095 memcpy(disp_param->value, Z_STRVAL_P(disp_data), Z_STRLEN_P(disp_data) + 1);
3096 disp_param->next = tmp_param;
3097 tmp_param = disp_param;
3098 } ZEND_HASH_FOREACH_END();
3099 bod->disposition.parameter = disp_param;
3100 }
3101 }
3102 if (bod->type == TYPEMESSAGE && bod->subtype && !strcmp(bod->subtype, "RFC822")) {
3103 bod->nested.msg = mail_newmsg();
3104 } else {
3105 if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "contents.data", sizeof("contents.data") - 1)) != NULL) {
3106 convert_to_string(pvalue);
3107 bod->contents.text.data = fs_get(Z_STRLEN_P(pvalue) + 1);
3108 memcpy(bod->contents.text.data, Z_STRVAL_P(pvalue), Z_STRLEN_P(pvalue)+1);
3109 bod->contents.text.size = Z_STRLEN_P(pvalue);
3110 } else {
3111 bod->contents.text.data = fs_get(1);
3112 memcpy(bod->contents.text.data, "", 1);
3113 bod->contents.text.size = 0;
3114 }
3115 }
3116 if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "lines", sizeof("lines") - 1)) != NULL) {
3117 bod->size.lines = zval_get_long(pvalue);
3118 }
3119 if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "bytes", sizeof("bytes") - 1)) != NULL) {
3120 bod->size.bytes = zval_get_long(pvalue);
3121 }
3122 if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "md5", sizeof("md5") - 1)) != NULL) {
3123 convert_to_string(pvalue);
3124 CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body md5");
3125 bod->md5 = cpystr(Z_STRVAL_P(pvalue));
3126 }
3127 } else if (Z_TYPE_P(data) == IS_ARRAY && topbod->type == TYPEMULTIPART) {
3128 short type = 0;
3129 SEPARATE_ARRAY(data);
3130 if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "type", sizeof("type") - 1)) != NULL) {
3131 zend_long tmp_type = zval_get_long(pvalue);
3132 if (tmp_type >= 0 && tmp_type <= TYPEMAX && tmp_type != TYPEMULTIPART && body_types[tmp_type] != NULL) {
3133 type = (short) tmp_type;
3134 }
3135 }
3136
3137 if (!toppart) {
3138 bod->nested.part = mail_newbody_part();
3139 mypart = bod->nested.part;
3140 toppart = 1;
3141 } else {
3142 mypart->next = mail_newbody_part();
3143 mypart = mypart->next;
3144 }
3145
3146 bod = &mypart->body;
3147 bod->type = type;
3148
3149 if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "encoding", sizeof("encoding") - 1)) != NULL) {
3150 zend_long encoding = zval_get_long(pvalue);
3151 if (encoding >= 0 && encoding <= ENCMAX && body_encodings[encoding] != NULL) {
3152 bod->encoding = (short) encoding;
3153 }
3154 }
3155 if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "charset", sizeof("charset") - 1)) != NULL) {
3156 convert_to_string_ex(pvalue);
3157 CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body charset");
3158 tmp_param = mail_newbody_parameter();
3159 tmp_param->value = (char *) fs_get(Z_STRLEN_P(pvalue) + 1);
3160 memcpy(tmp_param->value, Z_STRVAL_P(pvalue), Z_STRLEN_P(pvalue) + 1);
3161 tmp_param->attribute = cpystr("CHARSET");
3162 tmp_param->next = bod->parameter;
3163 bod->parameter = tmp_param;
3164 }
3165 if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "type.parameters", sizeof("type.parameters") - 1)) != NULL) {
3166 if (Z_TYPE_P(pvalue) == IS_ARRAY && !HT_IS_PACKED(Z_ARRVAL_P(pvalue))) {
3167 disp_param = tmp_param = NULL;
3168 SEPARATE_ARRAY(pvalue);
3169 ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(pvalue), key, disp_data) {
3170 if (key == NULL) continue;
3171 CHECK_HEADER_INJECTION(key, 0, "body type.parameters key");
3172 disp_param = mail_newbody_parameter();
3173 disp_param->attribute = cpystr(ZSTR_VAL(key));
3174 convert_to_string_ex(disp_data);
3175 CHECK_HEADER_INJECTION(Z_STR_P(disp_data), 0, "body type.parameters value");
3176 disp_param->value = (char *)fs_get(Z_STRLEN_P(disp_data) + 1);
3177 memcpy(disp_param->value, Z_STRVAL_P(disp_data), Z_STRLEN_P(disp_data) + 1);
3178 disp_param->next = tmp_param;
3179 tmp_param = disp_param;
3180 } ZEND_HASH_FOREACH_END();
3181 bod->parameter = disp_param;
3182 }
3183 }
3184 if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "subtype", sizeof("subtype") - 1)) != NULL) {
3185 convert_to_string_ex(pvalue);
3186 CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body subtype");
3187 bod->subtype = cpystr(Z_STRVAL_P(pvalue));
3188 }
3189 if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "id", sizeof("id") - 1)) != NULL) {
3190 convert_to_string_ex(pvalue);
3191 CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body id");
3192 bod->id = cpystr(Z_STRVAL_P(pvalue));
3193 }
3194 if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "description", sizeof("description") - 1)) != NULL) {
3195 convert_to_string_ex(pvalue);
3196 CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body description");
3197 bod->description = cpystr(Z_STRVAL_P(pvalue));
3198 }
3199 if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "disposition.type", sizeof("disposition.type") - 1)) != NULL) {
3200 convert_to_string_ex(pvalue);
3201 CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body disposition.type");
3202 bod->disposition.type = (char *) fs_get(Z_STRLEN_P(pvalue) + 1);
3203 memcpy(bod->disposition.type, Z_STRVAL_P(pvalue), Z_STRLEN_P(pvalue)+1);
3204 }
3205 if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "disposition", sizeof("disposition") - 1)) != NULL) {
3206 if (Z_TYPE_P(pvalue) == IS_ARRAY && !HT_IS_PACKED(Z_ARRVAL_P(pvalue))) {
3207 disp_param = tmp_param = NULL;
3208 SEPARATE_ARRAY(pvalue);
3209 ZEND_HASH_MAP_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(pvalue), key, disp_data) {
3210 if (key == NULL) continue;
3211 CHECK_HEADER_INJECTION(key, 0, "body disposition key");
3212 disp_param = mail_newbody_parameter();
3213 disp_param->attribute = cpystr(ZSTR_VAL(key));
3214 convert_to_string_ex(disp_data);
3215 CHECK_HEADER_INJECTION(Z_STR_P(disp_data), 0, "body disposition value");
3216 disp_param->value = (char *) fs_get(Z_STRLEN_P(disp_data) + 1);
3217 memcpy(disp_param->value, Z_STRVAL_P(disp_data), Z_STRLEN_P(disp_data) + 1);
3218 disp_param->next = tmp_param;
3219 tmp_param = disp_param;
3220 } ZEND_HASH_FOREACH_END();
3221 bod->disposition.parameter = disp_param;
3222 }
3223 }
3224 if (bod->type == TYPEMESSAGE && bod->subtype && !strcmp(bod->subtype, "RFC822")) {
3225 bod->nested.msg = mail_newmsg();
3226 } else {
3227 if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "contents.data", sizeof("contents.data") - 1)) != NULL) {
3228 convert_to_string(pvalue);
3229 bod->contents.text.data = fs_get(Z_STRLEN_P(pvalue) + 1);
3230 memcpy(bod->contents.text.data, Z_STRVAL_P(pvalue), Z_STRLEN_P(pvalue) + 1);
3231 bod->contents.text.size = Z_STRLEN_P(pvalue);
3232 } else {
3233 bod->contents.text.data = fs_get(1);
3234 memcpy(bod->contents.text.data, "", 1);
3235 bod->contents.text.size = 0;
3236 }
3237 }
3238 if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "lines", sizeof("lines") - 1)) != NULL) {
3239 bod->size.lines = zval_get_long(pvalue);
3240 }
3241 if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "bytes", sizeof("bytes") - 1)) != NULL) {
3242 bod->size.bytes = zval_get_long(pvalue);
3243 }
3244 if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "md5", sizeof("md5") - 1)) != NULL) {
3245 convert_to_string_ex(pvalue);
3246 CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body md5");
3247 bod->md5 = cpystr(Z_STRVAL_P(pvalue));
3248 }
3249 }
3250 } ZEND_HASH_FOREACH_END();
3251
3252 if (bod && bod->type == TYPEMULTIPART && (!bod->nested.part || !bod->nested.part->next)) {
3253 php_error_docref(NULL, E_WARNING, "Cannot generate multipart e-mail without components.");
3254 RETVAL_FALSE;
3255 goto done;
3256 }
3257
3258 rfc822_encode_body_7bit(env, topbod);
3259
3260 tmp = emalloc(SENDBUFLEN + 1);
3261
3262 rfc822_header(tmp, env, topbod);
3263
3264 /* add custom envelope headers */
3265 if (custom_headers_param) {
3266 int l = strlen(tmp) - 2, l2;
3267 PARAMETER *tp = custom_headers_param;
3268
3269 /* remove last CRLF from tmp */
3270 tmp[l] = '\0';
3271 tempstring = emalloc(l);
3272 memcpy(tempstring, tmp, l);
3273
3274 do {
3275 l2 = strlen(custom_headers_param->value);
3276 tempstring = erealloc(tempstring, l + l2 + CRLF_LEN + 1);
3277 memcpy(tempstring + l, custom_headers_param->value, l2);
3278 memcpy(tempstring + l + l2, CRLF, CRLF_LEN);
3279 l += l2 + CRLF_LEN;
3280 } while ((custom_headers_param = custom_headers_param->next));
3281
3282 mail_free_body_parameter(&tp);
3283
3284 mystring = emalloc(l + CRLF_LEN + 1);
3285 memcpy(mystring, tempstring, l);
3286 memcpy(mystring + l , CRLF, CRLF_LEN);
3287 mystring[l + CRLF_LEN] = '\0';
3288
3289 efree(tempstring);
3290 } else {
3291 mystring = estrdup(tmp);
3292 }
3293
3294 bod = topbod;
3295
3296 if (bod && bod->type == TYPEMULTIPART) {
3297
3298 /* first body part */
3299 part = bod->nested.part;
3300
3301 /* find cookie */
3302 for (param = bod->parameter; param && !cookie; param = param->next) {
3303 if (!strcmp (param->attribute, "BOUNDARY")) {
3304 cookie = param->value;
3305 }
3306 }
3307
3308 /* yucky default */
3309 if (!cookie) {
3310 cookie = "-";
3311 } else if (strlen(cookie) > (SENDBUFLEN - 2 - 2 - 2)) { /* validate cookie length -- + CRLF * 2 */
3312 php_error_docref(NULL, E_WARNING, "The boundary should be no longer than 4kb");
3313 RETVAL_FALSE;
3314 goto done;
3315 }
3316
3317 /* for each part */
3318 do {
3319 t = tmp;
3320
3321 /* append mini-header */
3322 *t = '\0';
3323 rfc822_write_body_header(&t, &part->body);
3324
3325 /* output cookie, mini-header, and contents */
3326 spprintf(&tempstring, 0, "%s--%s%s%s%s", mystring, cookie, CRLF, tmp, CRLF);
3327 efree(mystring);
3328 mystring=tempstring;
3329
3330 bod=&part->body;
3331
3332 spprintf(&tempstring, 0, "%s%s%s", mystring, bod->contents.text.data ? (char *) bod->contents.text.data : "", CRLF);
3333 efree(mystring);
3334 mystring=tempstring;
3335 } while ((part = part->next)); /* until done */
3336
3337 /* output trailing cookie */
3338 spprintf(&tempstring, 0, "%s--%s--%s", mystring, cookie, CRLF);
3339 efree(mystring);
3340 mystring=tempstring;
3341 } else if (bod) {
3342 spprintf(&tempstring, 0, "%s%s%s", mystring, bod->contents.text.data ? (char *) bod->contents.text.data : "", CRLF);
3343 efree(mystring);
3344 mystring=tempstring;
3345 } else {
3346 efree(mystring);
3347 RETVAL_FALSE;
3348 goto done;
3349 }
3350
3351 RETVAL_STRING(tempstring);
3352 efree(tempstring);
3353 done:
3354 if (tmp) {
3355 efree(tmp);
3356 }
3357 mail_free_body(&topbod);
3358 mail_free_envelope(&env);
3359 }
3360 /* }}} */
3361
3362 /* {{{ _php_imap_mail */
_php_imap_mail(zend_string * to,zend_string * subject,zend_string * message,zend_string * headers,zend_string * cc,zend_string * bcc,zend_string * rpath)3363 bool _php_imap_mail(zend_string *to, zend_string *subject, zend_string *message, zend_string *headers,
3364 zend_string *cc, zend_string *bcc, zend_string* rpath)
3365 {
3366 #ifdef PHP_WIN32
3367 int tsm_err;
3368 #else
3369 FILE *sendmail;
3370 int ret;
3371 #endif
3372
3373 ZEND_ASSERT(to && ZSTR_LEN(to) != 0);
3374 ZEND_ASSERT(subject && ZSTR_LEN(subject) != 0);
3375 ZEND_ASSERT(message);
3376
3377 #ifdef PHP_WIN32
3378 char *tempMailTo;
3379 char *tsm_errmsg = NULL;
3380 ADDRESS *addr;
3381 char *bufferTo = NULL, *bufferCc = NULL, *bufferBcc = NULL, *bufferHeader = NULL;
3382 size_t offset, bufferLen = 0;
3383 size_t bt_len;
3384
3385 /* Add "To" field's necessary buffer length */
3386 bufferLen += ZSTR_LEN(to) + 6;
3387 if (headers) {
3388 bufferLen += ZSTR_LEN(headers);
3389 }
3390 if (cc) {
3391 bufferLen += ZSTR_LEN(cc) + 6;
3392 }
3393
3394 #define PHP_IMAP_CLEAN if (bufferTo) efree(bufferTo); if (bufferCc) efree(bufferCc); if (bufferBcc) efree(bufferBcc); if (bufferHeader) efree(bufferHeader);
3395 #define PHP_IMAP_BAD_DEST PHP_IMAP_CLEAN; efree(tempMailTo); return (BAD_MSG_DESTINATION);
3396
3397 bufferHeader = (char *)safe_emalloc(bufferLen, 1, 1);
3398 memset(bufferHeader, 0, bufferLen);
3399
3400 /* Handle "To" Field */
3401 strlcat(bufferHeader, "To: ", bufferLen + 1);
3402 strlcat(bufferHeader, ZSTR_VAL(to), bufferLen + 1);
3403 strlcat(bufferHeader, "\r\n", bufferLen + 1);
3404 tempMailTo = estrdup(ZSTR_VAL(to));
3405 bt_len = ZSTR_LEN(to);
3406 bufferTo = (char *)safe_emalloc(bt_len, 1, 1);
3407 bt_len++;
3408 offset = 0;
3409 addr = NULL;
3410 rfc822_parse_adrlist(&addr, tempMailTo, "NO HOST");
3411 while (addr) {
3412 if (addr->host == NULL || strcmp(addr->host, ERRHOST) == 0) {
3413 PHP_IMAP_BAD_DEST;
3414 } else {
3415 bufferTo = safe_erealloc(bufferTo, bt_len, 1, strlen(addr->mailbox));
3416 bt_len += strlen(addr->mailbox);
3417 bufferTo = safe_erealloc(bufferTo, bt_len, 1, strlen(addr->host));
3418 bt_len += strlen(addr->host);
3419 offset += slprintf(bufferTo + offset, bt_len - offset, "%s@%s,", addr->mailbox, addr->host);
3420 }
3421 addr = addr->next;
3422 }
3423 efree(tempMailTo);
3424 if (offset>0) {
3425 bufferTo[offset-1] = 0;
3426 }
3427
3428 if (cc && ZSTR_LEN(cc) != 0) {
3429 strlcat(bufferHeader, "Cc: ", bufferLen + 1);
3430 strlcat(bufferHeader, ZSTR_VAL(cc), bufferLen + 1);
3431 strlcat(bufferHeader, "\r\n", bufferLen + 1);
3432 tempMailTo = estrdup(ZSTR_VAL(cc));
3433 bt_len = ZSTR_LEN(cc);
3434 bufferCc = (char *)safe_emalloc(bt_len, 1, 1);
3435 bt_len++;
3436 offset = 0;
3437 addr = NULL;
3438 rfc822_parse_adrlist(&addr, tempMailTo, "NO HOST");
3439 while (addr) {
3440 if (addr->host == NULL || strcmp(addr->host, ERRHOST) == 0) {
3441 PHP_IMAP_BAD_DEST;
3442 } else {
3443 bufferCc = safe_erealloc(bufferCc, bt_len, 1, strlen(addr->mailbox));
3444 bt_len += strlen(addr->mailbox);
3445 bufferCc = safe_erealloc(bufferCc, bt_len, 1, strlen(addr->host));
3446 bt_len += strlen(addr->host);
3447 offset += slprintf(bufferCc + offset, bt_len - offset, "%s@%s,", addr->mailbox, addr->host);
3448 }
3449 addr = addr->next;
3450 }
3451 efree(tempMailTo);
3452 if (offset>0) {
3453 bufferCc[offset-1] = 0;
3454 }
3455 }
3456
3457 if (bcc && ZSTR_LEN(bcc)) {
3458 tempMailTo = estrdup(ZSTR_VAL(bcc));
3459 bt_len = ZSTR_LEN(bcc);
3460 bufferBcc = (char *)safe_emalloc(bt_len, 1, 1);
3461 bt_len++;
3462 offset = 0;
3463 addr = NULL;
3464 rfc822_parse_adrlist(&addr, tempMailTo, "NO HOST");
3465 while (addr) {
3466 if (addr->host == NULL || strcmp(addr->host, ERRHOST) == 0) {
3467 PHP_IMAP_BAD_DEST;
3468 } else {
3469 bufferBcc = safe_erealloc(bufferBcc, bt_len, 1, strlen(addr->mailbox));
3470 bt_len += strlen(addr->mailbox);
3471 bufferBcc = safe_erealloc(bufferBcc, bt_len, 1, strlen(addr->host));
3472 bt_len += strlen(addr->host);
3473 offset += slprintf(bufferBcc + offset, bt_len - offset, "%s@%s,", addr->mailbox, addr->host);
3474 }
3475 addr = addr->next;
3476 }
3477 efree(tempMailTo);
3478 if (offset>0) {
3479 bufferBcc[offset-1] = 0;
3480 }
3481 }
3482
3483 if (headers && ZSTR_LEN(headers)) {
3484 strlcat(bufferHeader, ZSTR_VAL(headers), bufferLen + 1);
3485 }
3486
3487 if (TSendMail(INI_STR("SMTP"), &tsm_err, &tsm_errmsg, bufferHeader, ZSTR_VAL(subject),
3488 bufferTo, ZSTR_VAL(message), bufferCc, bufferBcc, rpath ? ZSTR_VAL(rpath) : NULL) != SUCCESS) {
3489 if (tsm_errmsg) {
3490 php_error_docref(NULL, E_WARNING, "%s", tsm_errmsg);
3491 efree(tsm_errmsg);
3492 } else {
3493 php_error_docref(NULL, E_WARNING, "%s", GetSMErrorText(tsm_err));
3494 }
3495 PHP_IMAP_CLEAN;
3496 return 0;
3497 }
3498 PHP_IMAP_CLEAN;
3499 #else
3500 if (!INI_STR("sendmail_path")) {
3501 return 0;
3502 }
3503 sendmail = popen(INI_STR("sendmail_path"), "w");
3504 if (sendmail) {
3505 if (rpath && ZSTR_LEN(rpath) != 0) {
3506 fprintf(sendmail, "From: %s\n", ZSTR_VAL(rpath));
3507 }
3508 /* to cannot be a null pointer, asserted earlier on */
3509 fprintf(sendmail, "To: %s\n", ZSTR_VAL(to));
3510 if (cc && ZSTR_LEN(cc) != 0) {
3511 fprintf(sendmail, "Cc: %s\n", ZSTR_VAL(cc));
3512 }
3513 if (bcc && ZSTR_LEN(bcc) != 0) {
3514 fprintf(sendmail, "Bcc: %s\n", ZSTR_VAL(bcc));
3515 }
3516 /* subject cannot be a null pointer, asserted earlier on */
3517 fprintf(sendmail, "Subject: %s\n", ZSTR_VAL(subject));
3518 if (headers && ZSTR_LEN(headers) != 0) {
3519 fprintf(sendmail, "%s\n", ZSTR_VAL(headers));
3520 }
3521 /* message cannot be a null pointer, asserted earlier on */
3522 fprintf(sendmail, "\n%s\n", ZSTR_VAL(message));
3523 ret = pclose(sendmail);
3524
3525 return ret != -1;
3526 } else {
3527 php_error_docref(NULL, E_WARNING, "Could not execute mail delivery program");
3528 return 0;
3529 }
3530 #endif
3531 return 1;
3532 }
3533 /* }}} */
3534
3535 /* {{{ Send an email message */
PHP_FUNCTION(imap_mail)3536 PHP_FUNCTION(imap_mail)
3537 {
3538 zend_string *to=NULL, *message=NULL, *headers=NULL, *subject=NULL, *cc=NULL, *bcc=NULL, *rpath=NULL;
3539
3540 if (zend_parse_parameters(ZEND_NUM_ARGS(), "PPP|P!P!P!P!", &to, &subject, &message,
3541 &headers, &cc, &bcc, &rpath) == FAILURE) {
3542 RETURN_THROWS();
3543 }
3544
3545 /* To: */
3546 if (ZSTR_LEN(to) == 0) {
3547 zend_argument_value_error(1, "cannot be empty");
3548 RETURN_THROWS();
3549 }
3550
3551 /* Subject: */
3552 if (ZSTR_LEN(subject) == 0) {
3553 zend_argument_value_error(2, "cannot be empty");
3554 RETURN_THROWS();
3555 }
3556
3557 /* message body */
3558 if (ZSTR_LEN(message) == 0) {
3559 /* this is not really an error, so it is allowed. */
3560 // TODO Drop warning or emit ValueError?
3561 php_error_docref(NULL, E_WARNING, "No message string in mail command");
3562 }
3563
3564 if (_php_imap_mail(to, subject, message, headers, cc, bcc, rpath)) {
3565 RETURN_TRUE;
3566 } else {
3567 RETURN_FALSE;
3568 }
3569 }
3570 /* }}} */
3571
3572 /* {{{ Return a list of messages matching the given criteria */
PHP_FUNCTION(imap_search)3573 PHP_FUNCTION(imap_search)
3574 {
3575 zval *imap_conn_obj;
3576 zend_string *criteria, *charset = NULL;
3577 zend_long flags = SE_FREE;
3578 php_imap_object *imap_conn_struct;
3579 char *search_criteria;
3580 MESSAGELIST *cur;
3581 int argc = ZEND_NUM_ARGS();
3582 SEARCHPGM *pgm = NIL;
3583
3584 if (zend_parse_parameters(argc, "OS|lS", &imap_conn_obj, php_imap_ce, &criteria, &flags, &charset) == FAILURE) {
3585 RETURN_THROWS();
3586 }
3587
3588 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
3589
3590 /* TODO Update docs to allow SE_FREE as an option */
3591 if (flags && ((flags & ~(SE_FREE | SE_UID)) != 0)) {
3592 zend_argument_value_error(3, "must be a bitmask of SE_FREE, and SE_UID");
3593 RETURN_THROWS();
3594 }
3595
3596 search_criteria = estrndup(ZSTR_VAL(criteria), ZSTR_LEN(criteria));
3597
3598 IMAPG(imap_messages) = IMAPG(imap_messages_tail) = NIL;
3599 pgm = mail_criteria(search_criteria);
3600
3601 mail_search_full(imap_conn_struct->imap_stream, (argc == 4 ? ZSTR_VAL(charset) : NIL), pgm, flags);
3602
3603 if (pgm && !(flags & SE_FREE)) {
3604 mail_free_searchpgm(&pgm);
3605 }
3606
3607 if (IMAPG(imap_messages) == NIL) {
3608 efree(search_criteria);
3609 RETURN_FALSE;
3610 }
3611
3612 array_init(return_value);
3613
3614 cur = IMAPG(imap_messages);
3615 while (cur != NIL) {
3616 add_next_index_long(return_value, cur->msgid);
3617 cur = cur->next;
3618 }
3619 mail_free_messagelist(&IMAPG(imap_messages), &IMAPG(imap_messages_tail));
3620 efree(search_criteria);
3621 }
3622 /* }}} */
3623
3624 /* {{{ Returns an array of all IMAP alerts that have been generated since the last page load or since the last imap_alerts() call, whichever came last. The alert stack is cleared after imap_alerts() is called. */
3625 /* Author: CJH */
PHP_FUNCTION(imap_alerts)3626 PHP_FUNCTION(imap_alerts)
3627 {
3628 STRINGLIST *cur=NIL;
3629
3630 if (zend_parse_parameters_none() == FAILURE) {
3631 RETURN_THROWS();
3632 }
3633
3634 if (IMAPG(imap_alertstack) == NIL) {
3635 RETURN_FALSE;
3636 }
3637
3638 array_init(return_value);
3639
3640 cur = IMAPG(imap_alertstack);
3641 while (cur != NIL) {
3642 add_next_index_string(return_value, (char*)cur->LTEXT);
3643 cur = cur->next;
3644 }
3645 mail_free_stringlist(&IMAPG(imap_alertstack));
3646 IMAPG(imap_alertstack) = NIL;
3647 }
3648 /* }}} */
3649
3650 /* {{{ Returns an array of all IMAP errors generated since the last page load, or since the last imap_errors() call, whichever came last. The error stack is cleared after imap_errors() is called. */
3651 /* Author: CJH */
PHP_FUNCTION(imap_errors)3652 PHP_FUNCTION(imap_errors)
3653 {
3654 ERRORLIST *cur=NIL;
3655
3656 if (zend_parse_parameters_none() == FAILURE) {
3657 RETURN_THROWS();
3658 }
3659
3660 if (IMAPG(imap_errorstack) == NIL) {
3661 RETURN_FALSE;
3662 }
3663
3664 array_init(return_value);
3665
3666 cur = IMAPG(imap_errorstack);
3667 while (cur != NIL) {
3668 add_next_index_string(return_value, (char*)cur->LTEXT);
3669 cur = cur->next;
3670 }
3671 mail_free_errorlist(&IMAPG(imap_errorstack));
3672 IMAPG(imap_errorstack) = NIL;
3673 }
3674 /* }}} */
3675
3676 /* {{{ Returns the last error that was generated by an IMAP function. The error stack is NOT cleared after this call. */
3677 /* Author: CJH */
PHP_FUNCTION(imap_last_error)3678 PHP_FUNCTION(imap_last_error)
3679 {
3680 ERRORLIST *cur=NIL;
3681
3682 if (zend_parse_parameters_none() == FAILURE) {
3683 RETURN_THROWS();
3684 }
3685
3686 if (IMAPG(imap_errorstack) == NIL) {
3687 RETURN_FALSE;
3688 }
3689
3690 cur = IMAPG(imap_errorstack);
3691 while (cur != NIL) {
3692 if (cur->next == NIL) {
3693 RETURN_STRING((char*)cur->LTEXT);
3694 }
3695 cur = cur->next;
3696 }
3697 }
3698 /* }}} */
3699
3700 /* {{{ Decode mime header element in accordance with RFC 2047 and return array of objects containing 'charset' encoding and decoded 'text' */
PHP_FUNCTION(imap_mime_header_decode)3701 PHP_FUNCTION(imap_mime_header_decode)
3702 {
3703 /* Author: Ted Parnefors <ted@mtv.se> */
3704 zval myobject;
3705 zend_string *str;
3706 char *string, *charset, encoding, *text, *decode;
3707 zend_long charset_token, encoding_token, end_token, end, offset=0, i;
3708 unsigned long newlength;
3709
3710 if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &str) == FAILURE) {
3711 RETURN_THROWS();
3712 }
3713
3714 array_init(return_value);
3715
3716 string = ZSTR_VAL(str);
3717 end = ZSTR_LEN(str);
3718
3719 charset = (char *) safe_emalloc((end + 1), 2, 0);
3720 text = &charset[end + 1];
3721 while (offset < end) { /* Reached end of the string? */
3722 if ((charset_token = (zend_long)php_memnstr(&string[offset], "=?", 2, string + end))) { /* Is there anything encoded in the string? */
3723 charset_token -= (zend_long)string;
3724 if (offset != charset_token) { /* Is there anything before the encoded data? */
3725 /* Retrieve unencoded data that is found before encoded data */
3726 memcpy(text, &string[offset], charset_token-offset);
3727 text[charset_token - offset] = 0x00;
3728 object_init(&myobject);
3729 add_property_string(&myobject, "charset", "default");
3730 add_property_string(&myobject, "text", text);
3731 zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &myobject);
3732 }
3733 if ((encoding_token = (zend_long)php_memnstr(&string[charset_token+2], "?", 1, string+end))) { /* Find token for encoding */
3734 encoding_token -= (zend_long)string;
3735 if ((end_token = (zend_long)php_memnstr(&string[encoding_token+3], "?=", 2, string+end))) { /* Find token for end of encoded data */
3736 end_token -= (zend_long)string;
3737 memcpy(charset, &string[charset_token + 2], encoding_token - (charset_token + 2)); /* Extract charset encoding */
3738 charset[encoding_token-(charset_token + 2)] = 0x00;
3739 encoding=string[encoding_token + 1]; /* Extract encoding from string */
3740 memcpy(text, &string[encoding_token + 3], end_token - (encoding_token + 3)); /* Extract text */
3741 text[end_token - (encoding_token + 3)] = 0x00;
3742 decode = text;
3743 if (encoding == 'q' || encoding == 'Q') { /* Decode 'q' encoded data */
3744 for(i=0; text[i] != 0x00; i++) if (text[i] == '_') text[i] = ' '; /* Replace all *_' with space. */
3745 decode = (char *)rfc822_qprint((unsigned char *) text, strlen(text), &newlength);
3746 } else if (encoding == 'b' || encoding == 'B') {
3747 decode = (char *)rfc822_base64((unsigned char *) text, strlen(text), &newlength); /* Decode 'B' encoded data */
3748 }
3749 if (decode == NULL) {
3750 efree(charset);
3751 zend_array_destroy(Z_ARR_P(return_value));
3752 RETURN_FALSE;
3753 }
3754 object_init(&myobject);
3755 add_property_string(&myobject, "charset", charset);
3756 add_property_string(&myobject, "text", decode);
3757 zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &myobject);
3758
3759 /* only free decode if it was allocated by rfc822_qprint or rfc822_base64 */
3760 if (decode != text) {
3761 fs_give((void**)&decode);
3762 }
3763
3764 offset = end_token+2;
3765 for (i = 0; (string[offset + i] == ' ') || (string[offset + i] == 0x0a) || (string[offset + i] == 0x0d) || (string[offset + i] == '\t'); i++);
3766 if ((string[offset + i] == '=') && (string[offset + i + 1] == '?') && (offset + i < end)) {
3767 offset += i;
3768 }
3769 continue; /*/ Iterate the loop again please. */
3770 }
3771 }
3772 } else {
3773 /* Just some tweaking to optimize the code, and get the end statements work in a general manner.
3774 * If we end up here we didn't find a position for "charset_token",
3775 * so we need to set it to the start of the yet unextracted data.
3776 */
3777 charset_token = offset;
3778 }
3779 /* Return the rest of the data as unencoded, as it was either unencoded or was missing separators
3780 which rendered the remainder of the string impossible for us to decode. */
3781 memcpy(text, &string[charset_token], end - charset_token); /* Extract unencoded text from string */
3782 text[end - charset_token] = 0x00;
3783 object_init(&myobject);
3784 add_property_string(&myobject, "charset", "default");
3785 add_property_string(&myobject, "text", text);
3786 zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &myobject);
3787
3788 offset = end; /* We have reached the end of the string. */
3789 }
3790 efree(charset);
3791 }
3792 /* }}} */
3793
3794 /* Support Functions */
3795
3796 #ifdef HAVE_RFC822_OUTPUT_ADDRESS_LIST
3797 /* {{{ _php_rfc822_soutr */
_php_rfc822_soutr(void * stream,char * string)3798 static long _php_rfc822_soutr (void *stream, char *string)
3799 {
3800 smart_str *ret = (smart_str*)stream;
3801 int len = strlen(string);
3802
3803 smart_str_appendl(ret, string, len);
3804 return LONGT;
3805 }
3806 /* }}} */
3807
3808 /* {{{ _php_rfc822_write_address */
_php_rfc822_write_address(ADDRESS * addresslist)3809 static zend_string* _php_rfc822_write_address(ADDRESS *addresslist)
3810 {
3811 char address[MAILTMPLEN];
3812 smart_str ret = {0};
3813 RFC822BUFFER buf;
3814
3815 buf.beg = address;
3816 buf.cur = buf.beg;
3817 buf.end = buf.beg + sizeof(address) - 1;
3818 buf.s = &ret;
3819 buf.f = _php_rfc822_soutr;
3820 rfc822_output_address_list(&buf, addresslist, 0, NULL);
3821 rfc822_output_flush(&buf);
3822 smart_str_0(&ret);
3823 return ret.s;
3824 }
3825 /* }}} */
3826
3827 #else
3828
3829 /* {{{ _php_rfc822_len
3830 * Calculate string length based on imap's rfc822_cat function.
3831 */
_php_rfc822_len(char * str)3832 static int _php_rfc822_len(char *str)
3833 {
3834 int len;
3835 char *p;
3836
3837 if (!str || !*str) {
3838 return 0;
3839 }
3840
3841 /* strings with special characters will need to be quoted, as a safety measure we
3842 * add 2 bytes for the quotes just in case.
3843 */
3844 len = strlen(str) + 2;
3845 p = str;
3846 /* rfc822_cat() will escape all " and \ characters, therefore we need to increase
3847 * our buffer length to account for these characters.
3848 */
3849 while ((p = strpbrk(p, "\\\""))) {
3850 p++;
3851 len++;
3852 }
3853
3854 return len;
3855 }
3856 /* }}} */
3857
3858 /* {{{ _php_imap_get_address_size */
_php_imap_address_size(ADDRESS * addresslist)3859 static int _php_imap_address_size (ADDRESS *addresslist)
3860 {
3861 ADDRESS *tmp;
3862 int ret=0, num_ent=0;
3863
3864 tmp = addresslist;
3865
3866 if (tmp) do {
3867 ret += _php_rfc822_len(tmp->personal);
3868 ret += _php_rfc822_len(tmp->adl);
3869 ret += _php_rfc822_len(tmp->mailbox);
3870 ret += _php_rfc822_len(tmp->host);
3871 num_ent++;
3872 } while ((tmp = tmp->next));
3873
3874 /*
3875 * rfc822_write_address_full() needs some extra space for '<>,', etc.
3876 * for this perpouse we allocate additional PHP_IMAP_ADDRESS_SIZE_BUF bytes
3877 * by default this buffer is 10 bytes long
3878 */
3879 ret += (ret) ? num_ent*PHP_IMAP_ADDRESS_SIZE_BUF : 0;
3880
3881 return ret;
3882 }
3883
3884 /* }}} */
3885
3886 /* {{{ _php_rfc822_write_address */
_php_rfc822_write_address(ADDRESS * addresslist)3887 static zend_string* _php_rfc822_write_address(ADDRESS *addresslist)
3888 {
3889 char address[SENDBUFLEN];
3890
3891 if (_php_imap_address_size(addresslist) >= SENDBUFLEN) {
3892 zend_throw_error(NULL, "Address buffer overflow");
3893 return NULL;
3894 }
3895 address[0] = 0;
3896 rfc822_write_address(address, addresslist);
3897 return zend_string_init(address, strlen(address), 0);
3898 }
3899 /* }}} */
3900 #endif
3901 /* {{{ _php_imap_parse_address */
_php_imap_parse_address(ADDRESS * addresslist,zval * paddress)3902 static zend_string* _php_imap_parse_address (ADDRESS *addresslist, zval *paddress)
3903 {
3904 zend_string *fulladdress;
3905 ADDRESS *addresstmp;
3906 zval tmpvals;
3907
3908 addresstmp = addresslist;
3909
3910 fulladdress = _php_rfc822_write_address(addresstmp);
3911
3912 addresstmp = addresslist;
3913 do {
3914 object_init(&tmpvals);
3915 if (addresstmp->personal) add_property_string(&tmpvals, "personal", addresstmp->personal);
3916 if (addresstmp->adl) add_property_string(&tmpvals, "adl", addresstmp->adl);
3917 if (addresstmp->mailbox) add_property_string(&tmpvals, "mailbox", addresstmp->mailbox);
3918 if (addresstmp->host) add_property_string(&tmpvals, "host", addresstmp->host);
3919 php_imap_list_add_object(paddress, &tmpvals);
3920 } while ((addresstmp = addresstmp->next));
3921 return fulladdress;
3922 }
3923 /* }}} */
3924
3925 /* {{{ _php_make_header_object */
_php_make_header_object(zval * myzvalue,ENVELOPE * en)3926 static void _php_make_header_object(zval *myzvalue, ENVELOPE *en)
3927 {
3928 zval paddress;
3929 zend_string *fulladdress=NULL;
3930
3931 object_init(myzvalue);
3932
3933 if (en->remail) add_property_string(myzvalue, "remail", en->remail);
3934 if (en->date) add_property_string(myzvalue, "date", (char*)en->date);
3935 if (en->date) add_property_string(myzvalue, "Date", (char*)en->date);
3936 if (en->subject) add_property_string(myzvalue, "subject", en->subject);
3937 if (en->subject) add_property_string(myzvalue, "Subject", en->subject);
3938 if (en->in_reply_to) add_property_string(myzvalue, "in_reply_to", en->in_reply_to);
3939 if (en->message_id) add_property_string(myzvalue, "message_id", en->message_id);
3940 if (en->newsgroups) add_property_string(myzvalue, "newsgroups", en->newsgroups);
3941 if (en->followup_to) add_property_string(myzvalue, "followup_to", en->followup_to);
3942 if (en->references) add_property_string(myzvalue, "references", en->references);
3943
3944 if (en->to) {
3945 array_init(&paddress);
3946 fulladdress = _php_imap_parse_address(en->to, &paddress);
3947 if (fulladdress) {
3948 add_property_str(myzvalue, "toaddress", fulladdress);
3949 }
3950 php_imap_hash_add_object(myzvalue, "to", &paddress);
3951 }
3952
3953 if (en->from) {
3954 array_init(&paddress);
3955 fulladdress = _php_imap_parse_address(en->from, &paddress);
3956 if (fulladdress) {
3957 add_property_str(myzvalue, "fromaddress", fulladdress);
3958 }
3959 php_imap_hash_add_object(myzvalue, "from", &paddress);
3960 }
3961
3962 if (en->cc) {
3963 array_init(&paddress);
3964 fulladdress = _php_imap_parse_address(en->cc, &paddress);
3965 if (fulladdress) {
3966 add_property_str(myzvalue, "ccaddress", fulladdress);
3967 }
3968 php_imap_hash_add_object(myzvalue, "cc", &paddress);
3969 }
3970
3971 if (en->bcc) {
3972 array_init(&paddress);
3973 fulladdress = _php_imap_parse_address(en->bcc, &paddress);
3974 if (fulladdress) {
3975 add_property_str(myzvalue, "bccaddress", fulladdress);
3976 }
3977 php_imap_hash_add_object(myzvalue, "bcc", &paddress);
3978 }
3979
3980 if (en->reply_to) {
3981 array_init(&paddress);
3982 fulladdress = _php_imap_parse_address(en->reply_to, &paddress);
3983 if (fulladdress) {
3984 add_property_str(myzvalue, "reply_toaddress", fulladdress);
3985 }
3986 php_imap_hash_add_object(myzvalue, "reply_to", &paddress);
3987 }
3988
3989 if (en->sender) {
3990 array_init(&paddress);
3991 fulladdress = _php_imap_parse_address(en->sender, &paddress);
3992 if (fulladdress) {
3993 add_property_str(myzvalue, "senderaddress", fulladdress);
3994 }
3995 php_imap_hash_add_object(myzvalue, "sender", &paddress);
3996 }
3997
3998 if (en->return_path) {
3999 array_init(&paddress);
4000 fulladdress = _php_imap_parse_address(en->return_path, &paddress);
4001 if (fulladdress) {
4002 add_property_str(myzvalue, "return_pathaddress", fulladdress);
4003 }
4004 php_imap_hash_add_object(myzvalue, "return_path", &paddress);
4005 // From rebase might need?
4006 //add_assoc_object(myzvalue, "return_path", &paddress);
4007 }
4008 }
4009 /* }}} */
4010
4011 /* {{{ _php_imap_add_body */
_php_imap_add_body(zval * arg,BODY * body)4012 void _php_imap_add_body(zval *arg, BODY *body)
4013 {
4014 zval parametres, param, dparametres, dparam;
4015 PARAMETER *par, *dpar;
4016 PART *part;
4017
4018 if (body->type <= TYPEMAX) {
4019 add_property_long(arg, "type", body->type);
4020 }
4021
4022 if (body->encoding <= ENCMAX) {
4023 add_property_long(arg, "encoding", body->encoding);
4024 }
4025
4026 if (body->subtype) {
4027 add_property_long(arg, "ifsubtype", 1);
4028 add_property_string(arg, "subtype", body->subtype);
4029 } else {
4030 add_property_long(arg, "ifsubtype", 0);
4031 }
4032
4033 if (body->description) {
4034 add_property_long(arg, "ifdescription", 1);
4035 add_property_string(arg, "description", body->description);
4036 } else {
4037 add_property_long(arg, "ifdescription", 0);
4038 }
4039
4040 if (body->id) {
4041 add_property_long(arg, "ifid", 1);
4042 add_property_string(arg, "id", body->id);
4043 } else {
4044 add_property_long(arg, "ifid", 0);
4045 }
4046
4047 if (body->size.lines) {
4048 add_property_long(arg, "lines", body->size.lines);
4049 }
4050
4051 if (body->size.bytes) {
4052 add_property_long(arg, "bytes", body->size.bytes);
4053 }
4054
4055 #ifdef IMAP41
4056 if (body->disposition.type) {
4057 add_property_long(arg, "ifdisposition", 1);
4058 add_property_string(arg, "disposition", body->disposition.type);
4059 } else {
4060 add_property_long(arg, "ifdisposition", 0);
4061 }
4062
4063 if (body->disposition.parameter) {
4064 dpar = body->disposition.parameter;
4065 add_property_long(arg, "ifdparameters", 1);
4066 array_init(&dparametres);
4067 do {
4068 object_init(&dparam);
4069 add_property_string(&dparam, "attribute", dpar->attribute);
4070 add_property_string(&dparam, "value", dpar->value);
4071 php_imap_list_add_object(&dparametres, &dparam);
4072 } while ((dpar = dpar->next));
4073 php_imap_hash_add_object(arg, "dparameters", &dparametres);
4074 } else {
4075 add_property_long(arg, "ifdparameters", 0);
4076 }
4077 #endif
4078
4079 if ((par = body->parameter)) {
4080 add_property_long(arg, "ifparameters", 1);
4081
4082 array_init(¶metres);
4083 do {
4084 object_init(¶m);
4085 if (par->attribute) {
4086 add_property_string(¶m, "attribute", par->attribute);
4087 }
4088 if (par->value) {
4089 add_property_string(¶m, "value", par->value);
4090 }
4091
4092 php_imap_list_add_object(¶metres, ¶m);
4093 } while ((par = par->next));
4094 } else {
4095 object_init(¶metres);
4096 add_property_long(arg, "ifparameters", 0);
4097 }
4098 php_imap_hash_add_object(arg, "parameters", ¶metres);
4099
4100 /* multipart message ? */
4101 if (body->type == TYPEMULTIPART) {
4102 array_init(¶metres);
4103 for (part = body->CONTENT_PART; part; part = part->next) {
4104 object_init(¶m);
4105 _php_imap_add_body(¶m, &part->body);
4106 php_imap_list_add_object(¶metres, ¶m);
4107 }
4108 php_imap_hash_add_object(arg, "parts", ¶metres);
4109 }
4110
4111 /* encapsulated message ? */
4112 if ((body->type == TYPEMESSAGE) && (!strcasecmp(body->subtype, "rfc822"))) {
4113 body = body->CONTENT_MSG_BODY;
4114 array_init(¶metres);
4115 object_init(¶m);
4116 _php_imap_add_body(¶m, body);
4117 php_imap_list_add_object(¶metres, ¶m);
4118 php_imap_hash_add_object(arg, "parts", ¶metres);
4119 }
4120 }
4121 /* }}} */
4122
4123 /* imap_thread, stealing this from header cclient -rjs3 */
4124 /* {{{ build_thread_tree_helper */
build_thread_tree_helper(THREADNODE * cur,zval * tree,long * numNodes,char * buf)4125 static void build_thread_tree_helper(THREADNODE *cur, zval *tree, long *numNodes, char *buf)
4126 {
4127 unsigned long thisNode = *numNodes;
4128
4129 /* define "#.num" */
4130 snprintf(buf, 25, "%ld.num", thisNode);
4131
4132 add_assoc_long(tree, buf, cur->num);
4133
4134 snprintf(buf, 25, "%ld.next", thisNode);
4135 if(cur->next) {
4136 (*numNodes)++;
4137 add_assoc_long(tree, buf, *numNodes);
4138 build_thread_tree_helper(cur->next, tree, numNodes, buf);
4139 } else { /* "null pointer" */
4140 add_assoc_long(tree, buf, 0);
4141 }
4142
4143 snprintf(buf, 25, "%ld.branch", thisNode);
4144 if(cur->branch) {
4145 (*numNodes)++;
4146 add_assoc_long(tree, buf, *numNodes);
4147 build_thread_tree_helper(cur->branch, tree, numNodes, buf);
4148 } else { /* "null pointer" */
4149 add_assoc_long(tree, buf, 0);
4150 }
4151 }
4152 /* }}} */
4153
4154 /* {{{ build_thread_tree */
build_thread_tree(THREADNODE * top,zval ** tree)4155 static int build_thread_tree(THREADNODE *top, zval **tree)
4156 {
4157 long numNodes = 0;
4158 char buf[25];
4159
4160 array_init(*tree);
4161
4162 build_thread_tree_helper(top, *tree, &numNodes, buf);
4163
4164 return SUCCESS;
4165 }
4166 /* }}} */
4167
4168 /* {{{ Return threaded by REFERENCES tree */
PHP_FUNCTION(imap_thread)4169 PHP_FUNCTION(imap_thread)
4170 {
4171 zval *imap_conn_obj;
4172 php_imap_object *imap_conn_struct;
4173 zend_long flags = SE_FREE;
4174 char criteria[] = "ALL";
4175 THREADNODE *top;
4176 SEARCHPGM *pgm = NIL;
4177
4178 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|l", &imap_conn_obj, php_imap_ce, &flags) == FAILURE) {
4179 RETURN_THROWS();
4180 }
4181
4182 GET_IMAP_STREAM(imap_conn_struct, imap_conn_obj);
4183
4184 /* TODO Check if flags are valid (documentation is not present on php.net so need to check this first) */
4185
4186 pgm = mail_criteria(criteria);
4187 top = mail_thread(imap_conn_struct->imap_stream, "REFERENCES", NIL, pgm, flags);
4188 if (pgm && !(flags & SE_FREE)) {
4189 mail_free_searchpgm(&pgm);
4190 }
4191
4192 if (top == NIL) {
4193 php_error_docref(NULL, E_WARNING, "Function returned an empty tree");
4194 RETURN_FALSE;
4195 }
4196
4197 /* Populate our return value data structure here. */
4198 if (build_thread_tree(top, &return_value) == FAILURE) {
4199 mail_free_threadnode(&top);
4200 RETURN_FALSE;
4201 }
4202 mail_free_threadnode(&top);
4203 }
4204 /* }}} */
4205
4206 /* {{{ Set or fetch imap timeout */
PHP_FUNCTION(imap_timeout)4207 PHP_FUNCTION(imap_timeout)
4208 {
4209 zend_long ttype, timeout=-1;
4210 int timeout_type;
4211
4212 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|l", &ttype, &timeout) == FAILURE) {
4213 RETURN_THROWS();
4214 }
4215
4216 if (timeout == -1) {
4217 switch (ttype) {
4218 case 1:
4219 timeout_type = GET_OPENTIMEOUT;
4220 break;
4221 case 2:
4222 timeout_type = GET_READTIMEOUT;
4223 break;
4224 case 3:
4225 timeout_type = GET_WRITETIMEOUT;
4226 break;
4227 case 4:
4228 timeout_type = GET_CLOSETIMEOUT;
4229 break;
4230 default:
4231 RETURN_FALSE;
4232 break;
4233 }
4234
4235 timeout = (zend_long) mail_parameters(NIL, timeout_type, NIL);
4236 RETURN_LONG(timeout);
4237 } else if (timeout >= 0) {
4238 switch (ttype) {
4239 case 1:
4240 timeout_type = SET_OPENTIMEOUT;
4241 break;
4242 case 2:
4243 timeout_type = SET_READTIMEOUT;
4244 break;
4245 case 3:
4246 timeout_type = SET_WRITETIMEOUT;
4247 break;
4248 case 4:
4249 timeout_type = SET_CLOSETIMEOUT;
4250 break;
4251 default:
4252 RETURN_FALSE;
4253 break;
4254 }
4255
4256 timeout = (zend_long) mail_parameters(NIL, timeout_type, (void *) timeout);
4257 RETURN_TRUE;
4258 } else {
4259 RETURN_FALSE;
4260 }
4261 }
4262 /* }}} */
4263
4264 #define GETS_FETCH_SIZE 8196LU
php_mail_gets(readfn_t f,void * stream,unsigned long size,GETS_DATA * md)4265 static char *php_mail_gets(readfn_t f, void *stream, unsigned long size, GETS_DATA *md) /* {{{ */
4266 {
4267
4268 /* write to the gets stream if it is set,
4269 otherwise forward to c-clients gets */
4270 if (IMAPG(gets_stream)) {
4271 char buf[GETS_FETCH_SIZE];
4272
4273 while (size) {
4274 unsigned long read;
4275
4276 if (size > GETS_FETCH_SIZE) {
4277 read = GETS_FETCH_SIZE;
4278 size -=GETS_FETCH_SIZE;
4279 } else {
4280 read = size;
4281 size = 0;
4282 }
4283
4284 if (!f(stream, read, buf)) {
4285 php_error_docref(NULL, E_WARNING, "Failed to read from socket");
4286 break;
4287 } else if (read != php_stream_write(IMAPG(gets_stream), buf, read)) {
4288 php_error_docref(NULL, E_WARNING, "Failed to write to stream");
4289 break;
4290 }
4291 }
4292 return NULL;
4293 } else {
4294 char *buf = pemalloc(size + 1, 1);
4295
4296 if (f(stream, size, buf)) {
4297 buf[size] = '\0';
4298 } else {
4299 php_error_docref(NULL, E_WARNING, "Failed to read from socket");
4300 free(buf);
4301 buf = NULL;
4302 }
4303 return buf;
4304 }
4305 }
4306 /* }}} */
4307
4308 /* {{{ Interfaces to C-client */
mm_searched(MAILSTREAM * stream,unsigned long number)4309 PHP_IMAP_EXPORT void mm_searched(MAILSTREAM *stream, unsigned long number)
4310 {
4311 MESSAGELIST *cur = NIL;
4312
4313 if (IMAPG(imap_messages) == NIL) {
4314 IMAPG(imap_messages) = mail_newmessagelist();
4315 IMAPG(imap_messages)->msgid = number;
4316 IMAPG(imap_messages)->next = NIL;
4317 IMAPG(imap_messages_tail) = IMAPG(imap_messages);
4318 } else {
4319 cur = IMAPG(imap_messages_tail);
4320 cur->next = mail_newmessagelist();
4321 cur = cur->next;
4322 cur->msgid = number;
4323 cur->next = NIL;
4324 IMAPG(imap_messages_tail) = cur;
4325 }
4326 }
4327
mm_exists(MAILSTREAM * stream,unsigned long number)4328 PHP_IMAP_EXPORT void mm_exists(MAILSTREAM *stream, unsigned long number)
4329 {
4330 }
4331
mm_expunged(MAILSTREAM * stream,unsigned long number)4332 PHP_IMAP_EXPORT void mm_expunged(MAILSTREAM *stream, unsigned long number)
4333 {
4334 }
4335
mm_flags(MAILSTREAM * stream,unsigned long number)4336 PHP_IMAP_EXPORT void mm_flags(MAILSTREAM *stream, unsigned long number)
4337 {
4338 }
4339
4340 /* Author: CJH */
mm_notify(MAILSTREAM * stream,char * str,long errflg)4341 PHP_IMAP_EXPORT void mm_notify(MAILSTREAM *stream, char *str, long errflg)
4342 {
4343 STRINGLIST *cur = NIL;
4344
4345 if (strncmp(str, "[ALERT] ", 8) == 0) {
4346 if (IMAPG(imap_alertstack) == NIL) {
4347 IMAPG(imap_alertstack) = mail_newstringlist();
4348 IMAPG(imap_alertstack)->LSIZE = strlen((char*)(IMAPG(imap_alertstack)->LTEXT = (unsigned char*)cpystr(str)));
4349 IMAPG(imap_alertstack)->next = NIL;
4350 } else {
4351 cur = IMAPG(imap_alertstack);
4352 while (cur->next != NIL) {
4353 cur = cur->next;
4354 }
4355 cur->next = mail_newstringlist ();
4356 cur = cur->next;
4357 cur->LSIZE = strlen((char*)(cur->LTEXT = (unsigned char*)cpystr(str)));
4358 cur->next = NIL;
4359 }
4360 }
4361 }
4362
mm_list(MAILSTREAM * stream,DTYPE delimiter,char * mailbox,long attributes)4363 PHP_IMAP_EXPORT void mm_list(MAILSTREAM *stream, DTYPE delimiter, char *mailbox, long attributes)
4364 {
4365 STRINGLIST *cur=NIL;
4366 FOBJECTLIST *ocur=NIL;
4367
4368 if (IMAPG(folderlist_style) == FLIST_OBJECT) {
4369 /* build up a the new array of objects */
4370 /* Author: CJH */
4371 if (IMAPG(imap_folder_objects) == NIL) {
4372 IMAPG(imap_folder_objects) = mail_newfolderobjectlist();
4373 IMAPG(imap_folder_objects)->LSIZE=strlen((char*)(IMAPG(imap_folder_objects)->LTEXT = (unsigned char*)cpystr(mailbox)));
4374 IMAPG(imap_folder_objects)->delimiter = delimiter;
4375 IMAPG(imap_folder_objects)->attributes = attributes;
4376 IMAPG(imap_folder_objects)->next = NIL;
4377 IMAPG(imap_folder_objects_tail) = IMAPG(imap_folder_objects);
4378 } else {
4379 ocur=IMAPG(imap_folder_objects_tail);
4380 ocur->next=mail_newfolderobjectlist();
4381 ocur=ocur->next;
4382 ocur->LSIZE = strlen((char*)(ocur->LTEXT = (unsigned char*)cpystr(mailbox)));
4383 ocur->delimiter = delimiter;
4384 ocur->attributes = attributes;
4385 ocur->next = NIL;
4386 IMAPG(imap_folder_objects_tail) = ocur;
4387 }
4388
4389 } else {
4390 /* build the old IMAPG(imap_folders) variable to allow old imap_listmailbox() to work */
4391 if (!(attributes & LATT_NOSELECT)) {
4392 if (IMAPG(imap_folders) == NIL) {
4393 IMAPG(imap_folders)=mail_newstringlist();
4394 IMAPG(imap_folders)->LSIZE=strlen((char*)(IMAPG(imap_folders)->LTEXT = (unsigned char*)cpystr(mailbox)));
4395 IMAPG(imap_folders)->next=NIL;
4396 IMAPG(imap_folders_tail) = IMAPG(imap_folders);
4397 } else {
4398 cur=IMAPG(imap_folders_tail);
4399 cur->next=mail_newstringlist ();
4400 cur=cur->next;
4401 cur->LSIZE = strlen((char*)(cur->LTEXT = (unsigned char*)cpystr(mailbox)));
4402 cur->next = NIL;
4403 IMAPG(imap_folders_tail) = cur;
4404 }
4405 }
4406 }
4407 }
4408
mm_lsub(MAILSTREAM * stream,DTYPE delimiter,char * mailbox,long attributes)4409 PHP_IMAP_EXPORT void mm_lsub(MAILSTREAM *stream, DTYPE delimiter, char *mailbox, long attributes)
4410 {
4411 STRINGLIST *cur=NIL;
4412 FOBJECTLIST *ocur=NIL;
4413
4414 if (IMAPG(folderlist_style) == FLIST_OBJECT) {
4415 /* build the array of objects */
4416 /* Author: CJH */
4417 if (IMAPG(imap_sfolder_objects) == NIL) {
4418 IMAPG(imap_sfolder_objects) = mail_newfolderobjectlist();
4419 IMAPG(imap_sfolder_objects)->LSIZE = strlen((char*)(IMAPG(imap_sfolder_objects)->LTEXT = (unsigned char*)cpystr(mailbox)));
4420 IMAPG(imap_sfolder_objects)->delimiter = delimiter;
4421 IMAPG(imap_sfolder_objects)->attributes = attributes;
4422 IMAPG(imap_sfolder_objects)->next = NIL;
4423 IMAPG(imap_sfolder_objects_tail) = IMAPG(imap_sfolder_objects);
4424 } else {
4425 ocur=IMAPG(imap_sfolder_objects_tail);
4426 ocur->next=mail_newfolderobjectlist();
4427 ocur=ocur->next;
4428 ocur->LSIZE=strlen((char*)(ocur->LTEXT = (unsigned char*)cpystr(mailbox)));
4429 ocur->delimiter = delimiter;
4430 ocur->attributes = attributes;
4431 ocur->next = NIL;
4432 IMAPG(imap_sfolder_objects_tail) = ocur;
4433 }
4434 } else {
4435 /* build the old simple array for imap_listsubscribed() */
4436 if (IMAPG(imap_sfolders) == NIL) {
4437 IMAPG(imap_sfolders)=mail_newstringlist();
4438 IMAPG(imap_sfolders)->LSIZE=strlen((char*)(IMAPG(imap_sfolders)->LTEXT = (unsigned char*)cpystr(mailbox)));
4439 IMAPG(imap_sfolders)->next=NIL;
4440 IMAPG(imap_sfolders_tail) = IMAPG(imap_sfolders);
4441 } else {
4442 cur=IMAPG(imap_sfolders_tail);
4443 cur->next=mail_newstringlist ();
4444 cur=cur->next;
4445 cur->LSIZE = strlen((char*)(cur->LTEXT = (unsigned char*)cpystr(mailbox)));
4446 cur->next = NIL;
4447 IMAPG(imap_sfolders_tail) = cur;
4448 }
4449 }
4450 }
4451
mm_status(MAILSTREAM * stream,char * mailbox,MAILSTATUS * status)4452 PHP_IMAP_EXPORT void mm_status(MAILSTREAM *stream, char *mailbox, MAILSTATUS *status)
4453 {
4454
4455 IMAPG(status_flags)=status->flags;
4456 if (IMAPG(status_flags) & SA_MESSAGES) {
4457 IMAPG(status_messages)=status->messages;
4458 }
4459 if (IMAPG(status_flags) & SA_RECENT) {
4460 IMAPG(status_recent)=status->recent;
4461 }
4462 if (IMAPG(status_flags) & SA_UNSEEN) {
4463 IMAPG(status_unseen)=status->unseen;
4464 }
4465 if (IMAPG(status_flags) & SA_UIDNEXT) {
4466 IMAPG(status_uidnext)=status->uidnext;
4467 }
4468 if (IMAPG(status_flags) & SA_UIDVALIDITY) {
4469 IMAPG(status_uidvalidity)=status->uidvalidity;
4470 }
4471 }
4472
mm_log(char * str,long errflg)4473 PHP_IMAP_EXPORT void mm_log(char *str, long errflg)
4474 {
4475 ERRORLIST *cur = NIL;
4476
4477 /* Author: CJH */
4478 if (errflg != NIL) { /* CJH: maybe put these into a more comprehensive log for debugging purposes? */
4479 if (IMAPG(imap_errorstack) == NIL) {
4480 IMAPG(imap_errorstack) = mail_newerrorlist();
4481 IMAPG(imap_errorstack)->LSIZE = strlen((char*)(IMAPG(imap_errorstack)->LTEXT = (unsigned char*)cpystr(str)));
4482 IMAPG(imap_errorstack)->errflg = errflg;
4483 IMAPG(imap_errorstack)->next = NIL;
4484 } else {
4485 cur = IMAPG(imap_errorstack);
4486 while (cur->next != NIL) {
4487 cur = cur->next;
4488 }
4489 cur->next = mail_newerrorlist();
4490 cur = cur->next;
4491 cur->LSIZE = strlen((char*)(cur->LTEXT = (unsigned char*)cpystr(str)));
4492 cur->errflg = errflg;
4493 cur->next = NIL;
4494 }
4495 }
4496 }
4497
mm_dlog(char * str)4498 PHP_IMAP_EXPORT void mm_dlog(char *str)
4499 {
4500 /* CJH: this is for debugging; it might be useful to allow setting
4501 the stream to debug mode and capturing this somewhere - syslog?
4502 php debugger? */
4503 }
4504
mm_login(NETMBX * mb,char * user,char * pwd,long trial)4505 PHP_IMAP_EXPORT void mm_login(NETMBX *mb, char *user, char *pwd, long trial)
4506 {
4507
4508 if (*mb->user) {
4509 strlcpy (user, mb->user, MAILTMPLEN);
4510 } else {
4511 strlcpy (user, IMAPG(imap_user), MAILTMPLEN);
4512 }
4513 strlcpy (pwd, IMAPG(imap_password), MAILTMPLEN);
4514 }
4515
mm_critical(MAILSTREAM * stream)4516 PHP_IMAP_EXPORT void mm_critical(MAILSTREAM *stream)
4517 {
4518 }
4519
mm_nocritical(MAILSTREAM * stream)4520 PHP_IMAP_EXPORT void mm_nocritical(MAILSTREAM *stream)
4521 {
4522 }
4523
mm_diskerror(MAILSTREAM * stream,long errcode,long serious)4524 PHP_IMAP_EXPORT long mm_diskerror(MAILSTREAM *stream, long errcode, long serious)
4525 {
4526 return 1;
4527 }
4528
mm_fatal(char * str)4529 PHP_IMAP_EXPORT void mm_fatal(char *str)
4530 {
4531 }
4532 /* }}} */
4533