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