1/*
2   +----------------------------------------------------------------------+
3   | PHP Version 5                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1997-2014 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    long flags=NIL;
1274    long cl_flags=NIL;
1275
1276    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|ll", &streamind, &mailbox, &mailbox_len, &options, &retries) == FAILURE) {
1277        return;
1278    }
1279
1280    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
1281
1282    if (options) {
1283        flags = options;
1284        if (flags & PHP_EXPUNGE) {
1285            cl_flags = CL_EXPUNGE;
1286            flags ^= PHP_EXPUNGE;
1287        }
1288        imap_le_struct->flags = cl_flags;
1289    }
1290#ifdef SET_MAXLOGINTRIALS
1291    if (retries) {
1292        mail_parameters(NIL, SET_MAXLOGINTRIALS, (void *) retries);
1293    }
1294#endif
1295    /* local filename, need to perform open_basedir check */
1296    if (mailbox[0] != '{' && php_check_open_basedir(mailbox TSRMLS_CC)) {
1297        RETURN_FALSE;
1298    }
1299
1300    imap_le_struct->imap_stream = mail_open(imap_le_struct->imap_stream, mailbox, flags);
1301    if (imap_le_struct->imap_stream == NIL) {
1302        zend_list_delete(Z_RESVAL_P(streamind));
1303        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't re-open stream");
1304        RETURN_FALSE;
1305    }
1306    RETURN_TRUE;
1307}
1308/* }}} */
1309
1310/* {{{ proto bool imap_append(resource stream_id, string folder, string message [, string options [, string internal_date]])
1311   Append a new message to a specified mailbox */
1312PHP_FUNCTION(imap_append)
1313{
1314    zval *streamind;
1315    char *folder, *message, *internal_date = NULL, *flags = NULL;
1316    int folder_len, message_len, internal_date_len = 0, flags_len = 0;
1317    pils *imap_le_struct;
1318    STRING st;
1319    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}/";
1320    const int regex_len = strlen(regex);
1321    pcre_cache_entry *pce;              /* Compiled regex */
1322    zval *subpats = NULL;               /* Parts (not used) */
1323    long regex_flags = 0;               /* Flags (not used) */
1324    long start_offset = 0;              /* Start offset (not used) */
1325    int global = 0;
1326
1327    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) {
1328        return;
1329    }
1330
1331    if (internal_date) {
1332        /* Make sure the given internal_date string matches the RFC specifiedformat */
1333        if ((pce = pcre_get_compiled_regex_cache(regex, regex_len TSRMLS_CC))== NULL) {
1334            RETURN_FALSE;
1335        }
1336
1337        php_pcre_match_impl(pce, internal_date, internal_date_len, return_value, subpats, global,
1338            0, regex_flags, start_offset TSRMLS_CC);
1339
1340        if (!Z_LVAL_P(return_value)) {
1341            php_error_docref(NULL TSRMLS_CC, E_WARNING, "internal date not correctly formatted");
1342            internal_date = NULL;
1343        }
1344    }
1345
1346    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
1347
1348    INIT (&st, mail_string, (void *) message, message_len);
1349
1350    if (mail_append_full(imap_le_struct->imap_stream, folder, (flags ? flags : NIL), (internal_date ? internal_date : NIL), &st)) {
1351        RETURN_TRUE;
1352    } else {
1353        RETURN_FALSE;
1354    }
1355}
1356/* }}} */
1357
1358/* {{{ proto int imap_num_msg(resource stream_id)
1359   Gives the number of messages in the current mailbox */
1360PHP_FUNCTION(imap_num_msg)
1361{
1362    zval *streamind;
1363    pils *imap_le_struct;
1364
1365    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &streamind) == FAILURE) {
1366        return;
1367    }
1368
1369    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
1370
1371    RETURN_LONG(imap_le_struct->imap_stream->nmsgs);
1372}
1373/* }}} */
1374
1375/* {{{ proto bool imap_ping(resource stream_id)
1376   Check if the IMAP stream is still active */
1377PHP_FUNCTION(imap_ping)
1378{
1379    zval *streamind;
1380    pils *imap_le_struct;
1381
1382    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &streamind) == FAILURE) {
1383        return;
1384    }
1385
1386    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
1387
1388    RETURN_BOOL(mail_ping(imap_le_struct->imap_stream));
1389}
1390/* }}} */
1391
1392/* {{{ proto int imap_num_recent(resource stream_id)
1393   Gives the number of recent messages in current mailbox */
1394PHP_FUNCTION(imap_num_recent)
1395{
1396    zval *streamind;
1397    pils *imap_le_struct;
1398
1399    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &streamind) == FAILURE) {
1400        return;
1401    }
1402
1403    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
1404
1405    RETURN_LONG(imap_le_struct->imap_stream->recent);
1406}
1407/* }}} */
1408
1409#if defined(HAVE_IMAP2000) || defined(HAVE_IMAP2001)
1410/* {{{ proto array imap_get_quota(resource stream_id, string qroot)
1411    Returns the quota set to the mailbox account qroot */
1412PHP_FUNCTION(imap_get_quota)
1413{
1414    zval *streamind;
1415    char *qroot;
1416    int qroot_len;
1417    pils *imap_le_struct;
1418
1419    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &streamind, &qroot, &qroot_len) == FAILURE) {
1420        return;
1421    }
1422
1423    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
1424
1425    array_init(return_value);
1426    IMAPG(quota_return) = &return_value;
1427
1428    /* set the callback for the GET_QUOTA function */
1429    mail_parameters(NIL, SET_QUOTA, (void *) mail_getquota);
1430    if (!imap_getquota(imap_le_struct->imap_stream, qroot)) {
1431        php_error_docref(NULL TSRMLS_CC, E_WARNING, "c-client imap_getquota failed");
1432        zval_dtor(return_value);
1433        RETURN_FALSE;
1434    }
1435}
1436/* }}} */
1437
1438/* {{{ proto array imap_get_quotaroot(resource stream_id, string mbox)
1439    Returns the quota set to the mailbox account mbox */
1440PHP_FUNCTION(imap_get_quotaroot)
1441{
1442    zval *streamind;
1443    char *mbox;
1444    int mbox_len;
1445    pils *imap_le_struct;
1446
1447    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &streamind, &mbox, &mbox_len) == FAILURE) {
1448        return;
1449    }
1450
1451    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
1452
1453    array_init(return_value);
1454    IMAPG(quota_return) = &return_value;
1455
1456    /* set the callback for the GET_QUOTAROOT function */
1457    mail_parameters(NIL, SET_QUOTA, (void *) mail_getquota);
1458    if (!imap_getquotaroot(imap_le_struct->imap_stream, mbox)) {
1459        php_error_docref(NULL TSRMLS_CC, E_WARNING, "c-client imap_getquotaroot failed");
1460        zval_dtor(return_value);
1461        RETURN_FALSE;
1462    }
1463}
1464/* }}} */
1465
1466/* {{{ proto bool imap_set_quota(resource stream_id, string qroot, int mailbox_size)
1467   Will set the quota for qroot mailbox */
1468PHP_FUNCTION(imap_set_quota)
1469{
1470    zval *streamind;
1471    char *qroot;
1472    int qroot_len;
1473    long mailbox_size;
1474    pils *imap_le_struct;
1475    STRINGLIST  limits;
1476
1477    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsl", &streamind, &qroot, &qroot_len, &mailbox_size) == FAILURE) {
1478        return;
1479    }
1480
1481    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
1482
1483    limits.text.data = "STORAGE";
1484    limits.text.size = mailbox_size;
1485    limits.next = NIL;
1486
1487    RETURN_BOOL(imap_setquota(imap_le_struct->imap_stream, qroot, &limits));
1488}
1489/* }}} */
1490
1491/* {{{ proto bool imap_setacl(resource stream_id, string mailbox, string id, string rights)
1492    Sets the ACL for a given mailbox */
1493PHP_FUNCTION(imap_setacl)
1494{
1495    zval *streamind;
1496    char *mailbox, *id, *rights;
1497    int mailbox_len, id_len, rights_len;
1498    pils *imap_le_struct;
1499
1500    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsss", &streamind, &mailbox, &mailbox_len, &id, &id_len, &rights, &rights_len) == FAILURE) {
1501        return;
1502    }
1503
1504    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
1505
1506    RETURN_BOOL(imap_setacl(imap_le_struct->imap_stream, mailbox, id, rights));
1507}
1508/* }}} */
1509
1510/* {{{ proto array imap_getacl(resource stream_id, string mailbox)
1511    Gets the ACL for a given mailbox */
1512PHP_FUNCTION(imap_getacl)
1513{
1514    zval *streamind;
1515    char *mailbox;
1516    int mailbox_len;
1517    pils *imap_le_struct;
1518
1519    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &streamind, &mailbox, &mailbox_len) == FAILURE) {
1520        return;
1521    }
1522
1523    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
1524
1525    /* initializing the special array for the return values */
1526    array_init(return_value);
1527
1528    IMAPG(imap_acl_list) = return_value;
1529
1530    /* set the callback for the GET_ACL function */
1531    mail_parameters(NIL, SET_ACL, (void *) mail_getacl);
1532    if (!imap_getacl(imap_le_struct->imap_stream, mailbox)) {
1533        php_error(E_WARNING, "c-client imap_getacl failed");
1534        zval_dtor(return_value);
1535        RETURN_FALSE;
1536    }
1537
1538    IMAPG(imap_acl_list) = NIL;
1539}
1540/* }}} */
1541#endif /* HAVE_IMAP2000 || HAVE_IMAP2001 */
1542
1543/* {{{ proto bool imap_expunge(resource stream_id)
1544   Permanently delete all messages marked for deletion */
1545PHP_FUNCTION(imap_expunge)
1546{
1547    zval *streamind;
1548    pils *imap_le_struct;
1549
1550    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &streamind) == FAILURE) {
1551        return;
1552    }
1553
1554    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
1555
1556    mail_expunge (imap_le_struct->imap_stream);
1557
1558    RETURN_TRUE;
1559}
1560/* }}} */
1561
1562/* {{{ proto bool imap_gc(resource stream_id, int flags)
1563   This function garbage collects (purges) the cache of entries of a specific type. */
1564PHP_FUNCTION(imap_gc)
1565{
1566    zval *streamind;
1567    pils *imap_le_struct;
1568    long flags;
1569
1570    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &streamind, &flags) == FAILURE) {
1571        return;
1572    }
1573
1574    if (flags && ((flags & ~(GC_TEXTS | GC_ELT | GC_ENV)) != 0)) {
1575        php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid value for the flags parameter");
1576        RETURN_FALSE;
1577    }
1578
1579    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
1580
1581    mail_gc(imap_le_struct->imap_stream, flags);
1582
1583    RETURN_TRUE;
1584}
1585/* }}} */
1586
1587/* {{{ proto bool imap_close(resource stream_id [, int options])
1588   Close an IMAP stream */
1589PHP_FUNCTION(imap_close)
1590{
1591    zval *streamind;
1592    pils *imap_le_struct=NULL;
1593    long options = 0, flags = NIL;
1594    int argc = ZEND_NUM_ARGS();
1595
1596    if (zend_parse_parameters(argc TSRMLS_CC, "r|l", &streamind, &options) == FAILURE) {
1597        return;
1598    }
1599
1600    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
1601
1602    if (argc == 2) {
1603        flags = options;
1604
1605        /* Check that flags is exactly equal to PHP_EXPUNGE or zero */
1606        if (flags && ((flags & ~PHP_EXPUNGE) != 0)) {
1607            php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid value for the flags parameter");
1608            RETURN_FALSE;
1609        }
1610
1611        /* Do the translation from PHP's internal PHP_EXPUNGE define to c-client's CL_EXPUNGE */
1612        if (flags & PHP_EXPUNGE) {
1613            flags ^= PHP_EXPUNGE;
1614            flags |= CL_EXPUNGE;
1615        }
1616        imap_le_struct->flags = flags;
1617    }
1618
1619    zend_list_delete(Z_RESVAL_P(streamind));
1620
1621    RETURN_TRUE;
1622}
1623/* }}} */
1624
1625/* {{{ proto array imap_headers(resource stream_id)
1626   Returns headers for all messages in a mailbox */
1627PHP_FUNCTION(imap_headers)
1628{
1629    zval *streamind;
1630    pils *imap_le_struct;
1631    unsigned long i;
1632    char *t;
1633    unsigned int msgno;
1634    char tmp[MAILTMPLEN];
1635
1636    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &streamind) == FAILURE) {
1637        return;
1638    }
1639
1640    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
1641
1642    /* Initialize return array */
1643    array_init(return_value);
1644
1645    for (msgno = 1; msgno <= imap_le_struct->imap_stream->nmsgs; msgno++) {
1646        MESSAGECACHE * cache = mail_elt (imap_le_struct->imap_stream, msgno);
1647        mail_fetchstructure(imap_le_struct->imap_stream, msgno, NIL);
1648        tmp[0] = cache->recent ? (cache->seen ? 'R': 'N') : ' ';
1649        tmp[1] = (cache->recent | cache->seen) ? ' ' : 'U';
1650        tmp[2] = cache->flagged ? 'F' : ' ';
1651        tmp[3] = cache->answered ? 'A' : ' ';
1652        tmp[4] = cache->deleted ? 'D' : ' ';
1653        tmp[5] = cache->draft ? 'X' : ' ';
1654        snprintf(tmp + 6, sizeof(tmp) - 6, "%4ld) ", cache->msgno);
1655        mail_date(tmp+11, cache);
1656        tmp[22] = ' ';
1657        tmp[23] = '\0';
1658        mail_fetchfrom(tmp+23, imap_le_struct->imap_stream, msgno, (long)20);
1659        strcat(tmp, " ");
1660        if ((i = cache->user_flags)) {
1661            strcat(tmp, "{");
1662            while (i) {
1663                strlcat(tmp, imap_le_struct->imap_stream->user_flags[find_rightmost_bit (&i)], sizeof(tmp));
1664                if (i) strlcat(tmp, " ", sizeof(tmp));
1665            }
1666            strlcat(tmp, "} ", sizeof(tmp));
1667        }
1668        mail_fetchsubject(t = tmp + strlen(tmp), imap_le_struct->imap_stream, msgno, (long)25);
1669        snprintf(t += strlen(t), sizeof(tmp) - strlen(tmp), " (%ld chars)", cache->rfc822_size);
1670        add_next_index_string(return_value, tmp, 1);
1671    }
1672}
1673/* }}} */
1674
1675/* {{{ proto string imap_body(resource stream_id, int msg_no [, int options])
1676   Read the message body */
1677PHP_FUNCTION(imap_body)
1678{
1679    zval *streamind;
1680    long msgno, flags = 0;
1681    pils *imap_le_struct;
1682    int msgindex, argc = ZEND_NUM_ARGS();
1683    char *body;
1684    unsigned long body_len = 0;
1685
1686    if (zend_parse_parameters(argc TSRMLS_CC, "rl|l", &streamind, &msgno, &flags) == FAILURE) {
1687        return;
1688    }
1689
1690    if (flags && ((flags & ~(FT_UID|FT_PEEK|FT_INTERNAL)) != 0)) {
1691        php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid value for the options parameter");
1692        RETURN_FALSE;
1693    }
1694
1695    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
1696
1697    if ((argc == 3) && (flags & FT_UID)) {
1698        /* This should be cached; if it causes an extra RTT to the
1699           IMAP server, then that's the price we pay for making
1700           sure we don't crash. */
1701        msgindex = mail_msgno(imap_le_struct->imap_stream, msgno);
1702    } else {
1703        msgindex = msgno;
1704    }
1705    if ((msgindex < 1) || ((unsigned) msgindex > imap_le_struct->imap_stream->nmsgs)) {
1706        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad message number");
1707        RETURN_FALSE;
1708    }
1709
1710    body = mail_fetchtext_full (imap_le_struct->imap_stream, msgno, &body_len, (argc == 3 ? flags : NIL));
1711    if (body_len == 0) {
1712        RETVAL_EMPTY_STRING();
1713    } else {
1714        RETVAL_STRINGL(body, body_len, 1);
1715    }
1716}
1717/* }}} */
1718
1719/* {{{ proto bool imap_mail_copy(resource stream_id, string msglist, string mailbox [, int options])
1720   Copy specified message to a mailbox */
1721PHP_FUNCTION(imap_mail_copy)
1722{
1723    zval *streamind;
1724    long options = 0;
1725    char *seq, *folder;
1726    int seq_len, folder_len, argc = ZEND_NUM_ARGS();
1727    pils *imap_le_struct;
1728
1729    if (zend_parse_parameters(argc TSRMLS_CC, "rss|l", &streamind, &seq, &seq_len, &folder, &folder_len, &options) == FAILURE) {
1730        return;
1731    }
1732
1733    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
1734
1735    if (mail_copy_full(imap_le_struct->imap_stream, seq, folder, (argc == 4 ? options : NIL)) == T) {
1736        RETURN_TRUE;
1737    } else {
1738        RETURN_FALSE;
1739    }
1740}
1741/* }}} */
1742
1743/* {{{ proto bool imap_mail_move(resource stream_id, string sequence, string mailbox [, int options])
1744   Move specified message to a mailbox */
1745PHP_FUNCTION(imap_mail_move)
1746{
1747    zval *streamind;
1748    char *seq, *folder;
1749    int seq_len, folder_len;
1750    long options = 0;
1751    pils *imap_le_struct;
1752    int argc = ZEND_NUM_ARGS();
1753
1754    if (zend_parse_parameters(argc TSRMLS_CC, "rss|l", &streamind, &seq, &seq_len, &folder, &folder_len, &options) == FAILURE) {
1755        return;
1756    }
1757
1758    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
1759
1760    if (mail_copy_full(imap_le_struct->imap_stream, seq, folder, (argc == 4 ? (options | CP_MOVE) : CP_MOVE)) == T) {
1761        RETURN_TRUE;
1762    } else {
1763        RETURN_FALSE;
1764    }
1765}
1766/* }}} */
1767
1768/* {{{ proto bool imap_createmailbox(resource stream_id, string mailbox)
1769   Create a new mailbox */
1770PHP_FUNCTION(imap_createmailbox)
1771{
1772    zval *streamind;
1773    char *folder;
1774    int folder_len;
1775    pils *imap_le_struct;
1776
1777    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &streamind, &folder, &folder_len) == FAILURE) {
1778        return;
1779    }
1780
1781    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
1782
1783    if (mail_create(imap_le_struct->imap_stream, folder) == T) {
1784        RETURN_TRUE;
1785    } else {
1786        RETURN_FALSE;
1787    }
1788}
1789/* }}} */
1790
1791/* {{{ proto bool imap_renamemailbox(resource stream_id, string old_name, string new_name)
1792   Rename a mailbox */
1793PHP_FUNCTION(imap_renamemailbox)
1794{
1795    zval *streamind;
1796    char *old_mailbox, *new_mailbox;
1797    int old_mailbox_len, new_mailbox_len;
1798    pils *imap_le_struct;
1799
1800    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &streamind, &old_mailbox, &old_mailbox_len, &new_mailbox, &new_mailbox_len) == FAILURE) {
1801        return;
1802    }
1803
1804    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
1805
1806    if (mail_rename(imap_le_struct->imap_stream, old_mailbox, new_mailbox) == T) {
1807        RETURN_TRUE;
1808    } else {
1809        RETURN_FALSE;
1810    }
1811}
1812/* }}} */
1813
1814/* {{{ proto bool imap_deletemailbox(resource stream_id, string mailbox)
1815   Delete a mailbox */
1816PHP_FUNCTION(imap_deletemailbox)
1817{
1818    zval *streamind;
1819    char *folder;
1820    int folder_len;
1821    pils *imap_le_struct;
1822
1823    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &streamind, &folder, &folder_len) == FAILURE) {
1824        return;
1825    }
1826
1827    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
1828
1829    if (mail_delete(imap_le_struct->imap_stream, folder) == T) {
1830        RETURN_TRUE;
1831    } else {
1832        RETURN_FALSE;
1833    }
1834}
1835/* }}} */
1836
1837/* {{{ proto array imap_list(resource stream_id, string ref, string pattern)
1838   Read the list of mailboxes */
1839PHP_FUNCTION(imap_list)
1840{
1841    zval *streamind;
1842    char *ref, *pat;
1843    int ref_len, pat_len;
1844    pils *imap_le_struct;
1845    STRINGLIST *cur=NIL;
1846
1847    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &streamind, &ref, &ref_len, &pat, &pat_len) == FAILURE) {
1848        return;
1849    }
1850
1851    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
1852
1853    /* set flag for normal, old mailbox list */
1854    IMAPG(folderlist_style) = FLIST_ARRAY;
1855
1856    IMAPG(imap_folders) = IMAPG(imap_folders_tail) = NIL;
1857    mail_list(imap_le_struct->imap_stream, ref, pat);
1858    if (IMAPG(imap_folders) == NIL) {
1859        RETURN_FALSE;
1860    }
1861
1862    array_init(return_value);
1863    cur=IMAPG(imap_folders);
1864    while (cur != NIL) {
1865        add_next_index_string(return_value, cur->LTEXT, 1);
1866        cur=cur->next;
1867    }
1868    mail_free_stringlist (&IMAPG(imap_folders));
1869    IMAPG(imap_folders) = IMAPG(imap_folders_tail) = NIL;
1870}
1871
1872/* }}} */
1873
1874/* {{{ proto array imap_getmailboxes(resource stream_id, string ref, string pattern)
1875   Reads the list of mailboxes and returns a full array of objects containing name, attributes, and delimiter */
1876/* Author: CJH */
1877PHP_FUNCTION(imap_list_full)
1878{
1879    zval *streamind, *mboxob;
1880    char *ref, *pat;
1881    int ref_len, pat_len;
1882    pils *imap_le_struct;
1883    FOBJECTLIST *cur=NIL;
1884    char *delim=NIL;
1885
1886    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &streamind, &ref, &ref_len, &pat, &pat_len) == FAILURE) {
1887        return;
1888    }
1889
1890    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
1891
1892    /* set flag for new, improved array of objects mailbox list */
1893    IMAPG(folderlist_style) = FLIST_OBJECT;
1894
1895    IMAPG(imap_folder_objects) = IMAPG(imap_folder_objects_tail) = NIL;
1896    mail_list(imap_le_struct->imap_stream, ref, pat);
1897    if (IMAPG(imap_folder_objects) == NIL) {
1898        RETURN_FALSE;
1899    }
1900
1901    array_init(return_value);
1902    delim = safe_emalloc(2, sizeof(char), 0);
1903    cur=IMAPG(imap_folder_objects);
1904    while (cur != NIL) {
1905        MAKE_STD_ZVAL(mboxob);
1906        object_init(mboxob);
1907        add_property_string(mboxob, "name", cur->LTEXT, 1);
1908        add_property_long(mboxob, "attributes", cur->attributes);
1909#ifdef IMAP41
1910        delim[0] = (char)cur->delimiter;
1911        delim[1] = 0;
1912        add_property_string(mboxob, "delimiter", delim, 1);
1913#else
1914        add_property_string(mboxob, "delimiter", cur->delimiter, 1);
1915#endif
1916        add_next_index_object(return_value, mboxob TSRMLS_CC);
1917        cur=cur->next;
1918    }
1919    mail_free_foblist(&IMAPG(imap_folder_objects), &IMAPG(imap_folder_objects_tail));
1920    efree(delim);
1921    IMAPG(folderlist_style) = FLIST_ARRAY;      /* reset to default */
1922}
1923/* }}} */
1924
1925/* {{{ proto array imap_listscan(resource stream_id, string ref, string pattern, string content)
1926   Read list of mailboxes containing a certain string */
1927PHP_FUNCTION(imap_listscan)
1928{
1929    zval *streamind;
1930    char *ref, *pat, *content;
1931    int ref_len, pat_len, content_len;
1932    pils *imap_le_struct;
1933    STRINGLIST *cur=NIL;
1934
1935    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsss", &streamind, &ref, &ref_len, &pat, &pat_len, &content, &content_len) == FAILURE) {
1936        return;
1937    }
1938
1939    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
1940
1941    IMAPG(imap_folders) = NIL;
1942    mail_scan(imap_le_struct->imap_stream, ref, pat, content);
1943    if (IMAPG(imap_folders) == NIL) {
1944        RETURN_FALSE;
1945    }
1946
1947    array_init(return_value);
1948    cur=IMAPG(imap_folders);
1949    while (cur != NIL) {
1950        add_next_index_string(return_value, cur->LTEXT, 1);
1951        cur=cur->next;
1952    }
1953    mail_free_stringlist (&IMAPG(imap_folders));
1954    IMAPG(imap_folders) = IMAPG(imap_folders_tail) = NIL;
1955}
1956
1957/* }}} */
1958
1959/* {{{ proto object imap_check(resource stream_id)
1960   Get mailbox properties */
1961PHP_FUNCTION(imap_check)
1962{
1963    zval *streamind;
1964    pils *imap_le_struct;
1965    char date[100];
1966
1967    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &streamind) == FAILURE) {
1968        return;
1969    }
1970
1971    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
1972
1973    if (mail_ping (imap_le_struct->imap_stream) == NIL) {
1974        RETURN_FALSE;
1975    }
1976
1977    if (imap_le_struct->imap_stream && imap_le_struct->imap_stream->mailbox) {
1978        rfc822_date(date);
1979        object_init(return_value);
1980        add_property_string(return_value, "Date", date, 1);
1981        add_property_string(return_value, "Driver", imap_le_struct->imap_stream->dtb->name, 1);
1982        add_property_string(return_value, "Mailbox", imap_le_struct->imap_stream->mailbox, 1);
1983        add_property_long(return_value, "Nmsgs", imap_le_struct->imap_stream->nmsgs);
1984        add_property_long(return_value, "Recent", imap_le_struct->imap_stream->recent);
1985    } else {
1986        RETURN_FALSE;
1987    }
1988}
1989/* }}} */
1990
1991/* {{{ proto bool imap_delete(resource stream_id, int msg_no [, int options])
1992   Mark a message for deletion */
1993PHP_FUNCTION(imap_delete)
1994{
1995    zval *streamind, **sequence;
1996    pils *imap_le_struct;
1997    long flags = 0;
1998    int argc = ZEND_NUM_ARGS();
1999
2000    if (zend_parse_parameters(argc TSRMLS_CC, "rZ|l", &streamind, &sequence, &flags) == FAILURE) {
2001        return;
2002    }
2003
2004    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
2005
2006    convert_to_string_ex(sequence);
2007
2008    mail_setflag_full(imap_le_struct->imap_stream, Z_STRVAL_PP(sequence), "\\DELETED", (argc == 3 ? flags : NIL));
2009    RETVAL_TRUE;
2010}
2011/* }}} */
2012
2013/* {{{ proto bool imap_undelete(resource stream_id, int msg_no [, int flags])
2014   Remove the delete flag from a message */
2015PHP_FUNCTION(imap_undelete)
2016{
2017    zval *streamind, **sequence;
2018    long flags = 0;
2019    pils *imap_le_struct;
2020    int argc = ZEND_NUM_ARGS();
2021
2022    if (zend_parse_parameters(argc TSRMLS_CC, "rZ|l", &streamind, &sequence, &flags) == FAILURE) {
2023        return;
2024    }
2025
2026    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
2027
2028    convert_to_string_ex(sequence);
2029
2030    mail_clearflag_full(imap_le_struct->imap_stream, Z_STRVAL_PP(sequence), "\\DELETED", (argc == 3 ? flags : NIL));
2031    RETVAL_TRUE;
2032}
2033/* }}} */
2034
2035/* {{{ proto object imap_headerinfo(resource stream_id, int msg_no [, int from_length [, int subject_length [, string default_host]]])
2036   Read the headers of the message */
2037PHP_FUNCTION(imap_headerinfo)
2038{
2039    zval *streamind;
2040    char *defaulthost = NULL;
2041    int defaulthost_len = 0, argc = ZEND_NUM_ARGS();
2042    long msgno, fromlength, subjectlength;
2043    pils *imap_le_struct;
2044    MESSAGECACHE *cache;
2045    ENVELOPE *en;
2046    char dummy[2000], fulladdress[MAILTMPLEN + 1];
2047
2048    if (zend_parse_parameters(argc TSRMLS_CC, "rl|lls", &streamind, &msgno, &fromlength, &subjectlength, &defaulthost, &defaulthost_len) == FAILURE) {
2049        return;
2050    }
2051
2052    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
2053
2054    if (argc >= 3) {
2055        if (fromlength < 0 || fromlength > MAILTMPLEN) {
2056            php_error_docref(NULL TSRMLS_CC, E_WARNING, "From length has to be between 0 and %d", MAILTMPLEN);
2057            RETURN_FALSE;
2058        }
2059    } else {
2060        fromlength = 0x00;
2061    }
2062    if (argc >= 4) {
2063        if (subjectlength < 0 || subjectlength > MAILTMPLEN) {
2064            php_error_docref(NULL TSRMLS_CC, E_WARNING, "Subject length has to be between 0 and %d", MAILTMPLEN);
2065            RETURN_FALSE;
2066        }
2067    } else {
2068        subjectlength = 0x00;
2069    }
2070
2071    PHP_IMAP_CHECK_MSGNO(msgno);
2072
2073    if (mail_fetchstructure(imap_le_struct->imap_stream, msgno, NIL)) {
2074        cache = mail_elt(imap_le_struct->imap_stream, msgno);
2075    } else {
2076        RETURN_FALSE;
2077    }
2078
2079    en = mail_fetchenvelope(imap_le_struct->imap_stream, msgno);
2080
2081    /* call a function to parse all the text, so that we can use the
2082       same function to parse text from other sources */
2083    _php_make_header_object(return_value, en TSRMLS_CC);
2084
2085    /* now run through properties that are only going to be returned
2086       from a server, not text headers */
2087    add_property_string(return_value, "Recent", cache->recent ? (cache->seen ? "R": "N") : " ", 1);
2088    add_property_string(return_value, "Unseen", (cache->recent | cache->seen) ? " " : "U", 1);
2089    add_property_string(return_value, "Flagged", cache->flagged ? "F" : " ", 1);
2090    add_property_string(return_value, "Answered", cache->answered ? "A" : " ", 1);
2091    add_property_string(return_value, "Deleted", cache->deleted ? "D" : " ", 1);
2092    add_property_string(return_value, "Draft", cache->draft ? "X" : " ", 1);
2093
2094    snprintf(dummy, sizeof(dummy), "%4ld", cache->msgno);
2095    add_property_string(return_value, "Msgno", dummy, 1);
2096
2097    mail_date(dummy, cache);
2098    add_property_string(return_value, "MailDate", dummy, 1);
2099
2100    snprintf(dummy, sizeof(dummy), "%ld", cache->rfc822_size);
2101    add_property_string(return_value, "Size", dummy, 1);
2102
2103    add_property_long(return_value, "udate", mail_longdate(cache));
2104
2105    if (en->from && fromlength) {
2106        fulladdress[0] = 0x00;
2107        mail_fetchfrom(fulladdress, imap_le_struct->imap_stream, msgno, fromlength);
2108        add_property_string(return_value, "fetchfrom", fulladdress, 1);
2109    }
2110    if (en->subject && subjectlength) {
2111        fulladdress[0] = 0x00;
2112        mail_fetchsubject(fulladdress, imap_le_struct->imap_stream, msgno, subjectlength);
2113        add_property_string(return_value, "fetchsubject", fulladdress, 1);
2114    }
2115}
2116/* }}} */
2117
2118/* {{{ proto object imap_rfc822_parse_headers(string headers [, string default_host])
2119   Parse a set of mail headers contained in a string, and return an object similar to imap_headerinfo() */
2120PHP_FUNCTION(imap_rfc822_parse_headers)
2121{
2122    char *headers, *defaulthost = NULL;
2123    ENVELOPE *en;
2124    int headers_len, defaulthost_len = 0, argc = ZEND_NUM_ARGS();
2125
2126    if (zend_parse_parameters(argc TSRMLS_CC, "s|s", &headers, &headers_len, &defaulthost, &defaulthost_len) == FAILURE) {
2127        return;
2128    }
2129
2130    if (argc == 2) {
2131        rfc822_parse_msg(&en, NULL, headers, headers_len, NULL, defaulthost, NIL);
2132    } else {
2133        rfc822_parse_msg(&en, NULL, headers, headers_len, NULL, "UNKNOWN", NIL);
2134    }
2135
2136    /* call a function to parse all the text, so that we can use the
2137       same function no matter where the headers are from */
2138    _php_make_header_object(return_value, en TSRMLS_CC);
2139    mail_free_envelope(&en);
2140}
2141/* }}} */
2142
2143/* KMLANG */
2144/* {{{ proto array imap_lsub(resource stream_id, string ref, string pattern)
2145   Return a list of subscribed mailboxes */
2146PHP_FUNCTION(imap_lsub)
2147{
2148    zval *streamind;
2149    char *ref, *pat;
2150    int ref_len, pat_len;
2151    pils *imap_le_struct;
2152    STRINGLIST *cur=NIL;
2153
2154    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &streamind, &ref, &ref_len, &pat, &pat_len) == FAILURE) {
2155        return;
2156    }
2157
2158    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
2159
2160    /* set flag for normal, old mailbox list */
2161    IMAPG(folderlist_style) = FLIST_ARRAY;
2162
2163    IMAPG(imap_sfolders) = NIL;
2164    mail_lsub(imap_le_struct->imap_stream, ref, pat);
2165    if (IMAPG(imap_sfolders) == NIL) {
2166        RETURN_FALSE;
2167    }
2168
2169    array_init(return_value);
2170    cur=IMAPG(imap_sfolders);
2171    while (cur != NIL) {
2172        add_next_index_string(return_value, cur->LTEXT, 1);
2173        cur=cur->next;
2174    }
2175    mail_free_stringlist (&IMAPG(imap_sfolders));
2176    IMAPG(imap_sfolders) = IMAPG(imap_sfolders_tail) = NIL;
2177}
2178/* }}} */
2179
2180/* {{{ proto array imap_getsubscribed(resource stream_id, string ref, string pattern)
2181   Return a list of subscribed mailboxes, in the same format as imap_getmailboxes() */
2182/* Author: CJH */
2183PHP_FUNCTION(imap_lsub_full)
2184{
2185    zval *streamind, *mboxob;
2186    char *ref, *pat;
2187    int ref_len, pat_len;
2188    pils *imap_le_struct;
2189    FOBJECTLIST *cur=NIL;
2190    char *delim=NIL;
2191
2192    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &streamind, &ref, &ref_len, &pat, &pat_len) == FAILURE) {
2193        return;
2194    }
2195
2196    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
2197
2198    /* set flag for new, improved array of objects list */
2199    IMAPG(folderlist_style) = FLIST_OBJECT;
2200
2201    IMAPG(imap_sfolder_objects) = IMAPG(imap_sfolder_objects_tail) = NIL;
2202    mail_lsub(imap_le_struct->imap_stream, ref, pat);
2203    if (IMAPG(imap_sfolder_objects) == NIL) {
2204        RETURN_FALSE;
2205    }
2206
2207    array_init(return_value);
2208    delim = safe_emalloc(2, sizeof(char), 0);
2209    cur=IMAPG(imap_sfolder_objects);
2210    while (cur != NIL) {
2211        MAKE_STD_ZVAL(mboxob);
2212        object_init(mboxob);
2213        add_property_string(mboxob, "name", cur->LTEXT, 1);
2214        add_property_long(mboxob, "attributes", cur->attributes);
2215#ifdef IMAP41
2216        delim[0] = (char)cur->delimiter;
2217        delim[1] = 0;
2218        add_property_string(mboxob, "delimiter", delim, 1);
2219#else
2220        add_property_string(mboxob, "delimiter", cur->delimiter, 1);
2221#endif
2222        add_next_index_object(return_value, mboxob TSRMLS_CC);
2223        cur=cur->next;
2224    }
2225    mail_free_foblist (&IMAPG(imap_sfolder_objects), &IMAPG(imap_sfolder_objects_tail));
2226    efree(delim);
2227    IMAPG(folderlist_style) = FLIST_ARRAY; /* reset to default */
2228}
2229/* }}} */
2230
2231/* {{{ proto bool imap_subscribe(resource stream_id, string mailbox)
2232   Subscribe to a mailbox */
2233PHP_FUNCTION(imap_subscribe)
2234{
2235    zval *streamind;
2236    char *folder;
2237    int folder_len;
2238    pils *imap_le_struct;
2239
2240    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &streamind, &folder, &folder_len) == FAILURE) {
2241        return;
2242    }
2243
2244    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
2245
2246    if (mail_subscribe(imap_le_struct->imap_stream, folder) == T) {
2247        RETURN_TRUE;
2248    } else {
2249        RETURN_FALSE;
2250    }
2251}
2252/* }}} */
2253
2254/* {{{ proto bool imap_unsubscribe(resource stream_id, string mailbox)
2255   Unsubscribe from a mailbox */
2256PHP_FUNCTION(imap_unsubscribe)
2257{
2258    zval *streamind;
2259    char *folder;
2260    int folder_len;
2261    pils *imap_le_struct;
2262
2263    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &streamind, &folder, &folder_len) == FAILURE) {
2264        return;
2265    }
2266
2267    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
2268
2269    if (mail_unsubscribe(imap_le_struct->imap_stream, folder) == T) {
2270        RETURN_TRUE;
2271    } else {
2272        RETURN_FALSE;
2273    }
2274}
2275/* }}} */
2276
2277/* {{{ proto object imap_fetchstructure(resource stream_id, int msg_no [, int options])
2278   Read the full structure of a message */
2279PHP_FUNCTION(imap_fetchstructure)
2280{
2281    zval *streamind;
2282    long msgno, flags = 0;
2283    pils *imap_le_struct;
2284    BODY *body;
2285    int msgindex, argc = ZEND_NUM_ARGS();
2286
2287    if (zend_parse_parameters(argc TSRMLS_CC, "rl|l", &streamind, &msgno, &flags) == FAILURE) {
2288        return;
2289    }
2290
2291    if (flags && ((flags & ~FT_UID) != 0)) {
2292        php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid value for the options parameter");
2293        RETURN_FALSE;
2294    }
2295
2296    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
2297
2298    if (msgno < 1) {
2299        RETURN_FALSE;
2300    }
2301
2302    object_init(return_value);
2303
2304    if ((argc == 3) && (flags & FT_UID)) {
2305        /* This should be cached; if it causes an extra RTT to the
2306           IMAP server, then that's the price we pay for making
2307           sure we don't crash. */
2308        msgindex = mail_msgno(imap_le_struct->imap_stream, msgno);
2309    } else {
2310        msgindex = msgno;
2311    }
2312    PHP_IMAP_CHECK_MSGNO(msgindex);
2313
2314    mail_fetchstructure_full(imap_le_struct->imap_stream, msgno, &body , (argc == 3 ? flags : NIL));
2315
2316    if (!body) {
2317        php_error_docref(NULL TSRMLS_CC, E_WARNING, "No body information available");
2318        RETURN_FALSE;
2319    }
2320
2321    _php_imap_add_body(return_value, body TSRMLS_CC);
2322}
2323/* }}} */
2324
2325/* {{{ proto string imap_fetchbody(resource stream_id, int msg_no, string section [, int options])
2326   Get a specific body section */
2327PHP_FUNCTION(imap_fetchbody)
2328{
2329    zval *streamind;
2330    long msgno, flags = 0;
2331    pils *imap_le_struct;
2332    char *body, *sec;
2333    int sec_len;
2334    unsigned long len;
2335    int argc = ZEND_NUM_ARGS();
2336
2337    if (zend_parse_parameters(argc TSRMLS_CC, "rls|l", &streamind, &msgno, &sec, &sec_len, &flags) == FAILURE) {
2338        return;
2339    }
2340
2341    if (flags && ((flags & ~(FT_UID|FT_PEEK|FT_INTERNAL)) != 0)) {
2342        php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid value for the options parameter");
2343        RETURN_FALSE;
2344    }
2345
2346    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
2347
2348    if (argc < 4 || !(flags & FT_UID)) {
2349        /* only perform the check if the msgno is a message number and not a UID */
2350        PHP_IMAP_CHECK_MSGNO(msgno);
2351    }
2352
2353    body = mail_fetchbody_full(imap_le_struct->imap_stream, msgno, sec, &len, (argc == 4 ? flags : NIL));
2354
2355    if (!body) {
2356        php_error_docref(NULL TSRMLS_CC, E_WARNING, "No body information available");
2357        RETURN_FALSE;
2358    }
2359    RETVAL_STRINGL(body, len, 1);
2360}
2361
2362/* }}} */
2363
2364
2365/* {{{ proto string imap_fetchmime(resource stream_id, int msg_no, string section [, int options])
2366   Get a specific body section's MIME headers */
2367PHP_FUNCTION(imap_fetchmime)
2368{
2369    zval *streamind;
2370    long msgno, flags = 0;
2371    pils *imap_le_struct;
2372    char *body, *sec;
2373    int sec_len;
2374    unsigned long len;
2375    int argc = ZEND_NUM_ARGS();
2376
2377    if (zend_parse_parameters(argc TSRMLS_CC, "rls|l", &streamind, &msgno, &sec, &sec_len, &flags) == FAILURE) {
2378        return;
2379    }
2380
2381    if (flags && ((flags & ~(FT_UID|FT_PEEK|FT_INTERNAL)) != 0)) {
2382        php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid value for the options parameter");
2383        RETURN_FALSE;
2384    }
2385
2386    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
2387
2388    if (argc < 4 || !(flags & FT_UID)) {
2389        /* only perform the check if the msgno is a message number and not a UID */
2390        PHP_IMAP_CHECK_MSGNO(msgno);
2391    }
2392
2393    body = mail_fetch_mime(imap_le_struct->imap_stream, msgno, sec, &len, (argc == 4 ? flags : NIL));
2394
2395    if (!body) {
2396        php_error_docref(NULL TSRMLS_CC, E_WARNING, "No body MIME information available");
2397        RETURN_FALSE;
2398    }
2399    RETVAL_STRINGL(body, len, 1);
2400}
2401
2402/* }}} */
2403
2404/* {{{ proto bool imap_savebody(resource stream_id, string|resource file, int msg_no[, string section = ""[, int options = 0]])
2405    Save a specific body section to a file */
2406PHP_FUNCTION(imap_savebody)
2407{
2408    zval *stream, **out;
2409    pils *imap_ptr = NULL;
2410    php_stream *writer = NULL;
2411    char *section = "";
2412    int section_len = 0, close_stream = 1;
2413    long msgno, flags = 0;
2414
2415    if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rZl|sl", &stream, &out, &msgno, &section, &section_len, &flags)) {
2416        RETURN_FALSE;
2417    }
2418
2419    ZEND_FETCH_RESOURCE(imap_ptr, pils *, &stream, -1, "imap", le_imap);
2420
2421    if (!imap_ptr) {
2422        RETURN_FALSE;
2423    }
2424
2425    switch (Z_TYPE_PP(out))
2426    {
2427        case IS_LONG:
2428        case IS_RESOURCE:
2429            close_stream = 0;
2430            php_stream_from_zval(writer, out);
2431        break;
2432
2433        default:
2434            convert_to_string_ex(out);
2435            writer = php_stream_open_wrapper(Z_STRVAL_PP(out), "wb", REPORT_ERRORS, NULL);
2436        break;
2437    }
2438
2439    if (!writer) {
2440        RETURN_FALSE;
2441    }
2442
2443    IMAPG(gets_stream) = writer;
2444    mail_parameters(NIL, SET_GETS, (void *) php_mail_gets);
2445    mail_fetchbody_full(imap_ptr->imap_stream, msgno, section, NULL, flags);
2446    mail_parameters(NIL, SET_GETS, (void *) NULL);
2447    IMAPG(gets_stream) = NULL;
2448
2449    if (close_stream) {
2450        php_stream_close(writer);
2451    }
2452
2453    RETURN_TRUE;
2454}
2455/* }}} */
2456
2457/* {{{ proto string imap_base64(string text)
2458   Decode BASE64 encoded text */
2459PHP_FUNCTION(imap_base64)
2460{
2461    char *text, *decode;
2462    int text_len;
2463    unsigned long newlength;
2464
2465    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &text, &text_len) == FAILURE) {
2466        return;
2467    }
2468
2469    decode = (char *) rfc822_base64((unsigned char *) text, text_len, &newlength);
2470
2471    if (decode == NULL) {
2472        RETURN_FALSE;
2473    }
2474
2475    RETVAL_STRINGL(decode, newlength, 1);
2476    fs_give((void**) &decode);
2477}
2478/* }}} */
2479
2480/* {{{ proto string imap_qprint(string text)
2481   Convert a quoted-printable string to an 8-bit string */
2482PHP_FUNCTION(imap_qprint)
2483{
2484    char *text, *decode;
2485    int text_len;
2486    unsigned long newlength;
2487
2488    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &text, &text_len) == FAILURE) {
2489        return;
2490    }
2491
2492    decode = (char *) rfc822_qprint((unsigned char *) text, text_len, &newlength);
2493
2494    if (decode == NULL) {
2495        RETURN_FALSE;
2496    }
2497
2498    RETVAL_STRINGL(decode, newlength, 1);
2499    fs_give((void**) &decode);
2500}
2501/* }}} */
2502
2503/* {{{ proto string imap_8bit(string text)
2504   Convert an 8-bit string to a quoted-printable string */
2505PHP_FUNCTION(imap_8bit)
2506{
2507    char *text, *decode;
2508    int text_len;
2509    unsigned long newlength;
2510
2511    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &text, &text_len) == FAILURE) {
2512        return;
2513    }
2514
2515    decode = (char *) rfc822_8bit((unsigned char *) text, text_len, &newlength);
2516
2517    if (decode == NULL) {
2518        RETURN_FALSE;
2519    }
2520
2521    RETVAL_STRINGL(decode, newlength, 1);
2522    fs_give((void**) &decode);
2523}
2524/* }}} */
2525
2526/* {{{ proto string imap_binary(string text)
2527   Convert an 8bit string to a base64 string */
2528PHP_FUNCTION(imap_binary)
2529{
2530    char *text, *decode;
2531    int text_len;
2532    unsigned long newlength;
2533
2534    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &text, &text_len) == FAILURE) {
2535        return;
2536    }
2537
2538    decode = rfc822_binary(text, text_len, &newlength);
2539
2540    if (decode == NULL) {
2541        RETURN_FALSE;
2542    }
2543
2544    RETVAL_STRINGL(decode, newlength, 1);
2545    fs_give((void**) &decode);
2546}
2547/* }}} */
2548
2549/* {{{ proto object imap_mailboxmsginfo(resource stream_id)
2550   Returns info about the current mailbox */
2551PHP_FUNCTION(imap_mailboxmsginfo)
2552{
2553    zval *streamind;
2554    pils *imap_le_struct;
2555    char date[100];
2556    unsigned int msgno, unreadmsg, deletedmsg, msize;
2557
2558    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &streamind) == FAILURE) {
2559        return;
2560    }
2561
2562    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
2563
2564    /* Initialize return object */
2565    object_init(return_value);
2566
2567    unreadmsg = 0;
2568    deletedmsg = 0;
2569    msize = 0;
2570
2571    for (msgno = 1; msgno <= imap_le_struct->imap_stream->nmsgs; msgno++) {
2572        MESSAGECACHE * cache = mail_elt (imap_le_struct->imap_stream, msgno);
2573        mail_fetchstructure (imap_le_struct->imap_stream, msgno, NIL);
2574
2575        if (!cache->seen || cache->recent) {
2576            unreadmsg++;
2577        }
2578
2579        if (cache->deleted) {
2580            deletedmsg++;
2581        }
2582        msize = msize + cache->rfc822_size;
2583    }
2584    add_property_long(return_value, "Unread", unreadmsg);
2585    add_property_long(return_value, "Deleted", deletedmsg);
2586    add_property_long(return_value, "Nmsgs", imap_le_struct->imap_stream->nmsgs);
2587    add_property_long(return_value, "Size", msize);
2588    rfc822_date(date);
2589    add_property_string(return_value, "Date", date, 1);
2590    add_property_string(return_value, "Driver", imap_le_struct->imap_stream->dtb->name, 1);
2591    add_property_string(return_value, "Mailbox", imap_le_struct->imap_stream->mailbox, 1);
2592    add_property_long(return_value, "Recent", imap_le_struct->imap_stream->recent);
2593}
2594/* }}} */
2595
2596/* {{{ proto string imap_rfc822_write_address(string mailbox, string host, string personal)
2597   Returns a properly formatted email address given the mailbox, host, and personal info */
2598PHP_FUNCTION(imap_rfc822_write_address)
2599{
2600    char *mailbox, *host, *personal;
2601    int mailbox_len, host_len, personal_len;
2602    ADDRESS *addr;
2603    char *string;
2604
2605    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss", &mailbox, &mailbox_len, &host, &host_len, &personal, &personal_len) == FAILURE) {
2606        return;
2607    }
2608
2609    addr=mail_newaddr();
2610
2611    if (mailbox) {
2612        addr->mailbox = cpystr(mailbox);
2613    }
2614
2615    if (host) {
2616        addr->host = cpystr(host);
2617    }
2618
2619    if (personal) {
2620        addr->personal = cpystr(personal);
2621    }
2622
2623    addr->next=NIL;
2624    addr->error=NIL;
2625    addr->adl=NIL;
2626
2627    string = _php_rfc822_write_address(addr TSRMLS_CC);
2628    if (string) {
2629        RETVAL_STRING(string, 0);
2630    } else {
2631        RETURN_FALSE;
2632    }
2633}
2634/* }}} */
2635
2636/* {{{ proto array imap_rfc822_parse_adrlist(string address_string, string default_host)
2637   Parses an address string */
2638PHP_FUNCTION(imap_rfc822_parse_adrlist)
2639{
2640    zval *tovals;
2641    char *str, *defaulthost, *str_copy;
2642    int str_len, defaulthost_len;
2643    ADDRESS *addresstmp;
2644    ENVELOPE *env;
2645
2646    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &str, &str_len, &defaulthost, &defaulthost_len) == FAILURE) {
2647        return;
2648    }
2649
2650    env = mail_newenvelope();
2651
2652    /* rfc822_parse_adrlist() modifies passed string. Copy it. */
2653    str_copy = estrndup(str, str_len);
2654    rfc822_parse_adrlist(&env->to, str_copy, defaulthost);
2655    efree(str_copy);
2656
2657    array_init(return_value);
2658
2659    addresstmp = env->to;
2660
2661    if (addresstmp) do {
2662        MAKE_STD_ZVAL(tovals);
2663        object_init(tovals);
2664        if (addresstmp->mailbox) {
2665            add_property_string(tovals, "mailbox", addresstmp->mailbox, 1);
2666        }
2667        if (addresstmp->host) {
2668            add_property_string(tovals, "host", addresstmp->host, 1);
2669        }
2670        if (addresstmp->personal) {
2671            add_property_string(tovals, "personal", addresstmp->personal, 1);
2672        }
2673        if (addresstmp->adl) {
2674            add_property_string(tovals, "adl", addresstmp->adl, 1);
2675        }
2676        add_next_index_object(return_value, tovals TSRMLS_CC);
2677    } while ((addresstmp = addresstmp->next));
2678
2679    mail_free_envelope(&env);
2680}
2681/* }}} */
2682
2683/* {{{ proto string imap_utf8(string mime_encoded_text)
2684   Convert a mime-encoded text to UTF-8 */
2685PHP_FUNCTION(imap_utf8)
2686{
2687    char *str;
2688    int str_len;
2689    SIZEDTEXT src, dest;
2690
2691    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) {
2692        return;
2693    }
2694
2695    src.data  = NULL;
2696    src.size  = 0;
2697    dest.data = NULL;
2698    dest.size = 0;
2699
2700    cpytxt(&src, str, str_len);
2701
2702#ifndef HAVE_NEW_MIME2TEXT
2703    utf8_mime2text(&src, &dest);
2704#else
2705    utf8_mime2text(&src, &dest, U8T_DECOMPOSE);
2706#endif
2707    RETVAL_STRINGL(dest.data, dest.size, 1);
2708    if (dest.data) {
2709        free(dest.data);
2710    }
2711    if (src.data && src.data != dest.data) {
2712        free(src.data);
2713    }
2714}
2715/* }}} */
2716
2717/* {{{ macros for the modified utf7 conversion functions
2718 *
2719 * author: Andrew Skalski <askalski@chek.com>
2720 */
2721
2722/* tests `c' and returns true if it is a special character */
2723#define SPECIAL(c) ((c) <= 0x1f || (c) >= 0x7f)
2724
2725/* validate a modified-base64 character */
2726#define B64CHAR(c) (isalnum(c) || (c) == '+' || (c) == ',')
2727
2728/* map the low 64 bits of `n' to the modified-base64 characters */
2729#define B64(n)  ("ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
2730                "abcdefghijklmnopqrstuvwxyz0123456789+,"[(n) & 0x3f])
2731
2732/* map the modified-base64 character `c' to its 64 bit value */
2733#define UNB64(c)    ((c) == '+' ? 62 : (c) == ',' ? 63 : (c) >= 'a' ? \
2734                    (c) - 71 : (c) >= 'A' ? (c) - 65 : (c) + 4)
2735/* }}} */
2736
2737/* {{{ proto string imap_utf7_decode(string buf)
2738   Decode a modified UTF-7 string */
2739PHP_FUNCTION(imap_utf7_decode)
2740{
2741    /* author: Andrew Skalski <askalski@chek.com> */
2742    char *arg;
2743    const unsigned char *in, *inp, *endp;
2744    unsigned char *out, *outp;
2745    unsigned char c;
2746    int arg_len, inlen, outlen;
2747    enum {
2748        ST_NORMAL,  /* printable text */
2749        ST_DECODE0, /* encoded text rotation... */
2750        ST_DECODE1,
2751        ST_DECODE2,
2752        ST_DECODE3
2753    } state;
2754
2755    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) {
2756        return;
2757    }
2758
2759    in = (const unsigned char *) arg;
2760    inlen = arg_len;
2761
2762    /* validate and compute length of output string */
2763    outlen = 0;
2764    state = ST_NORMAL;
2765    for (endp = (inp = in) + inlen; inp < endp; inp++) {
2766        if (state == ST_NORMAL) {
2767            /* process printable character */
2768            if (SPECIAL(*inp)) {
2769                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid modified UTF-7 character: `%c'", *inp);
2770                RETURN_FALSE;
2771            } else if (*inp != '&') {
2772                outlen++;
2773            } else if (inp + 1 == endp) {
2774                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unexpected end of string");
2775                RETURN_FALSE;
2776            } else if (inp[1] != '-') {
2777                state = ST_DECODE0;
2778            } else {
2779                outlen++;
2780                inp++;
2781            }
2782        } else if (*inp == '-') {
2783            /* return to NORMAL mode */
2784            if (state == ST_DECODE1) {
2785                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Stray modified base64 character: `%c'", *--inp);
2786                RETURN_FALSE;
2787            }
2788            state = ST_NORMAL;
2789        } else if (!B64CHAR(*inp)) {
2790            php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid modified base64 character: `%c'", *inp);
2791            RETURN_FALSE;
2792        } else {
2793            switch (state) {
2794                case ST_DECODE3:
2795                    outlen++;
2796                    state = ST_DECODE0;
2797                    break;
2798                case ST_DECODE2:
2799                case ST_DECODE1:
2800                    outlen++;
2801                case ST_DECODE0:
2802                    state++;
2803                case ST_NORMAL:
2804                    break;
2805            }
2806        }
2807    }
2808
2809    /* enforce end state */
2810    if (state != ST_NORMAL) {
2811        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unexpected end of string");
2812        RETURN_FALSE;
2813    }
2814
2815    /* allocate output buffer */
2816    out = emalloc(outlen + 1);
2817
2818    /* decode input string */
2819    outp = out;
2820    state = ST_NORMAL;
2821    for (endp = (inp = in) + inlen; inp < endp; inp++) {
2822        if (state == ST_NORMAL) {
2823            if (*inp == '&' && inp[1] != '-') {
2824                state = ST_DECODE0;
2825            }
2826            else if ((*outp++ = *inp) == '&') {
2827                inp++;
2828            }
2829        }
2830        else if (*inp == '-') {
2831            state = ST_NORMAL;
2832        }
2833        else {
2834            /* decode input character */
2835            switch (state) {
2836            case ST_DECODE0:
2837                *outp = UNB64(*inp) << 2;
2838                state = ST_DECODE1;
2839                break;
2840            case ST_DECODE1:
2841                outp[1] = UNB64(*inp);
2842                c = outp[1] >> 4;
2843                *outp++ |= c;
2844                *outp <<= 4;
2845                state = ST_DECODE2;
2846                break;
2847            case ST_DECODE2:
2848                outp[1] = UNB64(*inp);
2849                c = outp[1] >> 2;
2850                *outp++ |= c;
2851                *outp <<= 6;
2852                state = ST_DECODE3;
2853                break;
2854            case ST_DECODE3:
2855                *outp++ |= UNB64(*inp);
2856                state = ST_DECODE0;
2857            case ST_NORMAL:
2858                break;
2859            }
2860        }
2861    }
2862
2863    *outp = 0;
2864
2865#if PHP_DEBUG
2866    /* warn if we computed outlen incorrectly */
2867    if (outp - out != outlen) {
2868        php_error_docref(NULL TSRMLS_CC, E_WARNING, "outp - out [%ld] != outlen [%d]", outp - out, outlen);
2869    }
2870#endif
2871
2872    RETURN_STRINGL(out, outlen, 0);
2873}
2874/* }}} */
2875
2876/* {{{ proto string imap_utf7_encode(string buf)
2877   Encode a string in modified UTF-7 */
2878PHP_FUNCTION(imap_utf7_encode)
2879{
2880    /* author: Andrew Skalski <askalski@chek.com> */
2881    char *arg;
2882    const unsigned char *in, *inp, *endp;
2883    unsigned char *out, *outp;
2884    unsigned char c;
2885    int arg_len, inlen, outlen;
2886    enum {
2887        ST_NORMAL,  /* printable text */
2888        ST_ENCODE0, /* encoded text rotation... */
2889        ST_ENCODE1,
2890        ST_ENCODE2
2891    } state;
2892
2893    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) {
2894        return;
2895    }
2896
2897    in = (const unsigned char *) arg;
2898    inlen = arg_len;
2899
2900    /* compute the length of the result string */
2901    outlen = 0;
2902    state = ST_NORMAL;
2903    endp = (inp = in) + inlen;
2904    while (inp < endp) {
2905        if (state == ST_NORMAL) {
2906            if (SPECIAL(*inp)) {
2907                state = ST_ENCODE0;
2908                outlen++;
2909            } else if (*inp++ == '&') {
2910                outlen++;
2911            }
2912            outlen++;
2913        } else if (!SPECIAL(*inp)) {
2914            state = ST_NORMAL;
2915        } else {
2916            /* ST_ENCODE0 -> ST_ENCODE1 - two chars
2917             * ST_ENCODE1 -> ST_ENCODE2 - one char
2918             * ST_ENCODE2 -> ST_ENCODE0 - one char
2919             */
2920            if (state == ST_ENCODE2) {
2921                state = ST_ENCODE0;
2922            }
2923            else if (state++ == ST_ENCODE0) {
2924                outlen++;
2925            }
2926            outlen++;
2927            inp++;
2928        }
2929    }
2930
2931    /* allocate output buffer */
2932    out = emalloc(outlen + 1);
2933
2934    /* encode input string */
2935    outp = out;
2936    state = ST_NORMAL;
2937    endp = (inp = in) + inlen;
2938    while (inp < endp || state != ST_NORMAL) {
2939        if (state == ST_NORMAL) {
2940            if (SPECIAL(*inp)) {
2941                /* begin encoding */
2942                *outp++ = '&';
2943                state = ST_ENCODE0;
2944            } else if ((*outp++ = *inp++) == '&') {
2945                *outp++ = '-';
2946            }
2947        } else if (inp == endp || !SPECIAL(*inp)) {
2948            /* flush overflow and terminate region */
2949            if (state != ST_ENCODE0) {
2950                c = B64(*outp);
2951                *outp++ = c;
2952            }
2953            *outp++ = '-';
2954            state = ST_NORMAL;
2955        } else {
2956            /* encode input character */
2957            switch (state) {
2958                case ST_ENCODE0:
2959                    *outp++ = B64(*inp >> 2);
2960                    *outp = *inp++ << 4;
2961                    state = ST_ENCODE1;
2962                    break;
2963                case ST_ENCODE1:
2964                    c = B64(*outp | *inp >> 4);
2965                    *outp++ = c;
2966                    *outp = *inp++ << 2;
2967                    state = ST_ENCODE2;
2968                    break;
2969                case ST_ENCODE2:
2970                    c = B64(*outp | *inp >> 6);
2971                    *outp++ = c;
2972                    *outp++ = B64(*inp++);
2973                    state = ST_ENCODE0;
2974                case ST_NORMAL:
2975                    break;
2976            }
2977        }
2978    }
2979
2980    *outp = 0;
2981
2982#if PHP_DEBUG
2983    /* warn if we computed outlen incorrectly */
2984    if (outp - out != outlen) {
2985        php_error_docref(NULL TSRMLS_CC, E_WARNING, "outp - out [%ld] != outlen [%d]", outp - out, outlen);
2986    }
2987#endif
2988
2989    RETURN_STRINGL(out, outlen, 0);
2990}
2991/* }}} */
2992
2993#undef SPECIAL
2994#undef B64CHAR
2995#undef B64
2996#undef UNB64
2997
2998#ifdef HAVE_IMAP_MUTF7
2999static void php_imap_mutf7(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */
3000{
3001    char *in;
3002    int in_len;
3003    unsigned char *out;
3004
3005    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &in, &in_len) == FAILURE) {
3006        return;
3007    }
3008
3009    if (in_len < 1) {
3010        RETURN_EMPTY_STRING();
3011    }
3012
3013    if (mode == 0) {
3014        out = utf8_to_mutf7((unsigned char *) in);
3015    } else {
3016        out = utf8_from_mutf7((unsigned char *) in);
3017    }
3018
3019    if (out == NIL) {
3020        RETURN_FALSE;
3021    } else {
3022        RETURN_STRING((char *)out, 1);
3023    }
3024}
3025/* }}} */
3026
3027/* {{{ proto string imap_utf8_to_mutf7(string in)
3028   Encode a UTF-8 string to modified UTF-7 */
3029PHP_FUNCTION(imap_utf8_to_mutf7)
3030{
3031    php_imap_mutf7(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
3032}
3033/* }}} */
3034
3035/* {{{ proto string imap_mutf7_to_utf8(string in)
3036   Decode a modified UTF-7 string to UTF-8 */
3037PHP_FUNCTION(imap_mutf7_to_utf8)
3038{
3039    php_imap_mutf7(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
3040}
3041/* }}} */
3042#endif
3043
3044/* {{{ proto bool imap_setflag_full(resource stream_id, string sequence, string flag [, int options])
3045   Sets flags on messages */
3046PHP_FUNCTION(imap_setflag_full)
3047{
3048    zval *streamind;
3049    char *sequence, *flag;
3050    int sequence_len, flag_len;
3051    long flags = 0;
3052    pils *imap_le_struct;
3053
3054    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss|l", &streamind, &sequence, &sequence_len, &flag, &flag_len, &flags) == FAILURE) {
3055        return;
3056    }
3057
3058    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
3059
3060    mail_setflag_full(imap_le_struct->imap_stream, sequence, flag, (flags ? flags : NIL));
3061    RETURN_TRUE;
3062}
3063/* }}} */
3064
3065/* {{{ proto bool imap_clearflag_full(resource stream_id, string sequence, string flag [, int options])
3066   Clears flags on messages */
3067PHP_FUNCTION(imap_clearflag_full)
3068{
3069    zval *streamind;
3070    char *sequence, *flag;
3071    int sequence_len, flag_len;
3072    long flags = 0;
3073    pils *imap_le_struct;
3074    int argc = ZEND_NUM_ARGS();
3075
3076    if (zend_parse_parameters(argc TSRMLS_CC, "rss|l", &streamind, &sequence, &sequence_len, &flag, &flag_len, &flags) ==FAILURE) {
3077        return;
3078    }
3079
3080    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
3081
3082    mail_clearflag_full(imap_le_struct->imap_stream, sequence, flag, (argc == 4 ? flags : NIL));
3083    RETURN_TRUE;
3084}
3085/* }}} */
3086
3087/* {{{ proto array imap_sort(resource stream_id, int criteria, int reverse [, int options [, string search_criteria [, string charset]]])
3088   Sort an array of message headers, optionally including only messages that meet specified criteria. */
3089PHP_FUNCTION(imap_sort)
3090{
3091    zval *streamind;
3092    char *criteria = NULL, *charset = NULL;
3093    int criteria_len, charset_len;
3094    long pgm, rev, flags = 0;
3095    pils *imap_le_struct;
3096    unsigned long *slst, *sl;
3097    char *search_criteria;
3098    SORTPGM *mypgm=NIL;
3099    SEARCHPGM *spg=NIL;
3100    int argc = ZEND_NUM_ARGS();
3101
3102    if (zend_parse_parameters(argc TSRMLS_CC, "rll|lss", &streamind, &pgm, &rev, &flags, &criteria, &criteria_len, &charset, &charset_len) == FAILURE) {
3103        return;
3104    }
3105
3106    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
3107
3108    if (pgm > SORTSIZE) {
3109        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unrecognized sort criteria");
3110        RETURN_FALSE;
3111    }
3112    if (argc >= 4) {
3113        if (flags < 0) {
3114            php_error_docref(NULL TSRMLS_CC, E_WARNING, "Search options parameter has to be greater than or equal to 0");
3115            RETURN_FALSE;
3116        }
3117    }
3118    if (argc >= 5) {
3119        search_criteria = estrndup(criteria, criteria_len);
3120        spg = mail_criteria(search_criteria);
3121        efree(search_criteria);
3122    } else {
3123        spg = mail_newsearchpgm();
3124    }
3125
3126    mypgm = mail_newsortpgm();
3127    mypgm->reverse = rev;
3128    mypgm->function = (short) pgm;
3129    mypgm->next = NIL;
3130
3131    slst = mail_sort(imap_le_struct->imap_stream, (argc == 6 ? charset : NIL), spg, mypgm, (argc >= 4 ? flags : NIL));
3132
3133    if (spg && !(flags & SE_FREE)) {
3134        mail_free_searchpgm(&spg);
3135    }
3136
3137    array_init(return_value);
3138    if (slst != NIL && slst != 0) {
3139        for (sl = slst; *sl; sl++) {
3140            add_next_index_long(return_value, *sl);
3141        }
3142        fs_give ((void **) &slst);
3143    }
3144}
3145/* }}} */
3146
3147/* {{{ proto string imap_fetchheader(resource stream_id, int msg_no [, int options])
3148   Get the full unfiltered header for a message */
3149PHP_FUNCTION(imap_fetchheader)
3150{
3151    zval *streamind;
3152    long msgno, flags=0L;
3153    pils *imap_le_struct;
3154    int msgindex, argc = ZEND_NUM_ARGS();
3155
3156    if (zend_parse_parameters(argc TSRMLS_CC, "rl|l", &streamind, &msgno, &flags) == FAILURE) {
3157        return;
3158    }
3159
3160    if (flags && ((flags & ~(FT_UID|FT_INTERNAL|FT_PREFETCHTEXT)) != 0)) {
3161        php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid value for the options parameter");
3162        RETURN_FALSE;
3163    }
3164
3165    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
3166
3167    if ((argc == 3) && (flags & FT_UID)) {
3168        /* This should be cached; if it causes an extra RTT to the
3169           IMAP server, then that's the price we pay for making sure
3170           we don't crash. */
3171        msgindex = mail_msgno(imap_le_struct->imap_stream, msgno);
3172    } else {
3173        msgindex = msgno;
3174    }
3175
3176    PHP_IMAP_CHECK_MSGNO(msgindex);
3177
3178    RETVAL_STRING(mail_fetchheader_full(imap_le_struct->imap_stream, msgno, NIL, NIL, (argc == 3 ? flags : NIL)), 1);
3179}
3180/* }}} */
3181
3182/* {{{ proto int imap_uid(resource stream_id, int msg_no)
3183   Get the unique message id associated with a standard sequential message number */
3184PHP_FUNCTION(imap_uid)
3185{
3186    zval *streamind;
3187    long msgno;
3188    pils *imap_le_struct;
3189    int msgindex;
3190
3191    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &streamind, &msgno) == FAILURE) {
3192        return;
3193    }
3194
3195    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
3196
3197    msgindex = msgno;
3198    if ((msgindex < 1) || ((unsigned) msgindex > imap_le_struct->imap_stream->nmsgs)) {
3199        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad message number");
3200        RETURN_FALSE;
3201    }
3202
3203    RETURN_LONG(mail_uid(imap_le_struct->imap_stream, msgno));
3204}
3205/* }}} */
3206
3207/* {{{ proto int imap_msgno(resource stream_id, int unique_msg_id)
3208   Get the sequence number associated with a UID */
3209PHP_FUNCTION(imap_msgno)
3210{
3211    zval *streamind;
3212    long msgno;
3213    pils *imap_le_struct;
3214
3215    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &streamind, &msgno) == FAILURE) {
3216        return;
3217    }
3218
3219    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
3220
3221    RETURN_LONG(mail_msgno(imap_le_struct->imap_stream, msgno));
3222}
3223/* }}} */
3224
3225/* {{{ proto object imap_status(resource stream_id, string mailbox, int options)
3226   Get status info from a mailbox */
3227PHP_FUNCTION(imap_status)
3228{
3229    zval *streamind;
3230    char *mbx;
3231    int mbx_len;
3232    long flags;
3233    pils *imap_le_struct;
3234
3235    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsl", &streamind, &mbx, &mbx_len, &flags) == FAILURE) {
3236        return;
3237    }
3238
3239    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
3240
3241    object_init(return_value);
3242
3243    if (mail_status(imap_le_struct->imap_stream, mbx, flags)) {
3244        add_property_long(return_value, "flags", IMAPG(status_flags));
3245        if (IMAPG(status_flags) & SA_MESSAGES) {
3246            add_property_long(return_value, "messages", IMAPG(status_messages));
3247        }
3248        if (IMAPG(status_flags) & SA_RECENT) {
3249            add_property_long(return_value, "recent", IMAPG(status_recent));
3250        }
3251        if (IMAPG(status_flags) & SA_UNSEEN) {
3252            add_property_long(return_value, "unseen", IMAPG(status_unseen));
3253        }
3254        if (IMAPG(status_flags) & SA_UIDNEXT) {
3255            add_property_long(return_value, "uidnext", IMAPG(status_uidnext));
3256        }
3257        if (IMAPG(status_flags) & SA_UIDVALIDITY) {
3258            add_property_long(return_value, "uidvalidity", IMAPG(status_uidvalidity));
3259        }
3260    } else {
3261        RETURN_FALSE;
3262    }
3263}
3264/* }}} */
3265
3266/* {{{ proto object imap_bodystruct(resource stream_id, int msg_no, string section)
3267   Read the structure of a specified body section of a specific message */
3268PHP_FUNCTION(imap_bodystruct)
3269{
3270    zval *streamind;
3271    long msg;
3272    char *section;
3273    int section_len;
3274    pils *imap_le_struct;
3275    zval *parametres, *param, *dparametres, *dparam;
3276    PARAMETER *par, *dpar;
3277    BODY *body;
3278
3279    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rls", &streamind, &msg, &section, &section_len) == FAILURE) {
3280        return;
3281    }
3282
3283    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
3284
3285    if (!msg || msg < 1 || (unsigned) msg > imap_le_struct->imap_stream->nmsgs) {
3286        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad message number");
3287        RETURN_FALSE;
3288    }
3289
3290    object_init(return_value);
3291
3292    body=mail_body(imap_le_struct->imap_stream, msg, section);
3293    if (body == NULL) {
3294        zval_dtor(return_value);
3295        RETURN_FALSE;
3296    }
3297    if (body->type <= TYPEMAX) {
3298        add_property_long(return_value, "type", body->type);
3299    }
3300    if (body->encoding <= ENCMAX) {
3301        add_property_long(return_value, "encoding", body->encoding);
3302    }
3303
3304    if (body->subtype) {
3305        add_property_long(return_value, "ifsubtype", 1);
3306        add_property_string(return_value, "subtype", body->subtype, 1);
3307    } else {
3308        add_property_long(return_value, "ifsubtype", 0);
3309    }
3310
3311    if (body->description) {
3312        add_property_long(return_value, "ifdescription", 1);
3313        add_property_string(return_value, "description", body->description, 1);
3314    } else {
3315        add_property_long(return_value, "ifdescription", 0);
3316    }
3317    if (body->id) {
3318        add_property_long(return_value, "ifid", 1);
3319        add_property_string(return_value, "id", body->id, 1);
3320    } else {
3321        add_property_long(return_value, "ifid", 0);
3322    }
3323
3324    if (body->size.lines) {
3325        add_property_long(return_value, "lines", body->size.lines);
3326    }
3327    if (body->size.bytes) {
3328        add_property_long(return_value, "bytes", body->size.bytes);
3329    }
3330#ifdef IMAP41
3331    if (body->disposition.type) {
3332        add_property_long(return_value, "ifdisposition", 1);
3333        add_property_string(return_value, "disposition", body->disposition.type, 1);
3334    } else {
3335        add_property_long(return_value, "ifdisposition", 0);
3336    }
3337
3338    if (body->disposition.parameter) {
3339        dpar = body->disposition.parameter;
3340        add_property_long(return_value, "ifdparameters", 1);
3341        MAKE_STD_ZVAL(dparametres);
3342        array_init(dparametres);
3343        do {
3344            MAKE_STD_ZVAL(dparam);
3345            object_init(dparam);
3346            add_property_string(dparam, "attribute", dpar->attribute, 1);
3347            add_property_string(dparam, "value", dpar->value, 1);
3348            add_next_index_object(dparametres, dparam TSRMLS_CC);
3349        } while ((dpar = dpar->next));
3350        add_assoc_object(return_value, "dparameters", dparametres TSRMLS_CC);
3351    } else {
3352        add_property_long(return_value, "ifdparameters", 0);
3353    }
3354#endif
3355
3356    if ((par = body->parameter)) {
3357        add_property_long(return_value, "ifparameters", 1);
3358
3359        MAKE_STD_ZVAL(parametres);
3360        array_init(parametres);
3361        do {
3362            MAKE_STD_ZVAL(param);
3363            object_init(param);
3364            if (par->attribute) {
3365                add_property_string(param, "attribute", par->attribute, 1);
3366            }
3367            if (par->value) {
3368                add_property_string(param, "value", par->value, 1);
3369            }
3370
3371            add_next_index_object(parametres, param TSRMLS_CC);
3372        } while ((par = par->next));
3373    } else {
3374        MAKE_STD_ZVAL(parametres);
3375        object_init(parametres);
3376        add_property_long(return_value, "ifparameters", 0);
3377    }
3378    add_assoc_object(return_value, "parameters", parametres TSRMLS_CC);
3379}
3380
3381/* }}} */
3382
3383/* {{{ proto array imap_fetch_overview(resource stream_id, string sequence [, int options])
3384   Read an overview of the information in the headers of the given message sequence */
3385PHP_FUNCTION(imap_fetch_overview)
3386{
3387    zval *streamind;
3388    char *sequence;
3389    int sequence_len;
3390    pils *imap_le_struct;
3391    zval *myoverview;
3392    char *address;
3393    long status, flags = 0L;
3394    int argc = ZEND_NUM_ARGS();
3395
3396    if (zend_parse_parameters(argc TSRMLS_CC, "rs|l", &streamind, &sequence, &sequence_len, &flags) == FAILURE) {
3397        return;
3398    }
3399
3400    if (flags && ((flags & ~FT_UID) != 0)) {
3401        php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid value for the options parameter");
3402        RETURN_FALSE;
3403    }
3404
3405    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
3406
3407    array_init(return_value);
3408
3409    status = (flags & FT_UID)
3410        ? mail_uid_sequence(imap_le_struct->imap_stream, sequence)
3411        : mail_sequence(imap_le_struct->imap_stream, sequence);
3412
3413    if (status) {
3414        MESSAGECACHE *elt;
3415        ENVELOPE *env;
3416        unsigned long i;
3417
3418        for (i = 1; i <= imap_le_struct->imap_stream->nmsgs; i++) {
3419            if (((elt = mail_elt (imap_le_struct->imap_stream, i))->sequence) &&
3420                (env = mail_fetch_structure (imap_le_struct->imap_stream, i, NIL, NIL))) {
3421                MAKE_STD_ZVAL(myoverview);
3422                object_init(myoverview);
3423                if (env->subject) {
3424                    add_property_string(myoverview, "subject", env->subject, 1);
3425                }
3426                if (env->from) {
3427                    env->from->next=NULL;
3428                    address =_php_rfc822_write_address(env->from TSRMLS_CC);
3429                    if (address) {
3430                        add_property_string(myoverview, "from", address, 0);
3431                    }
3432                }
3433                if (env->to) {
3434                    env->to->next = NULL;
3435                    address = _php_rfc822_write_address(env->to TSRMLS_CC);
3436                    if (address) {
3437                        add_property_string(myoverview, "to", address, 0);
3438                    }
3439                }
3440                if (env->date) {
3441                    add_property_string(myoverview, "date", env->date, 1);
3442                }
3443                if (env->message_id) {
3444                    add_property_string(myoverview, "message_id", env->message_id, 1);
3445                }
3446                if (env->references) {
3447                    add_property_string(myoverview, "references", env->references, 1);
3448                }
3449                if (env->in_reply_to) {
3450                    add_property_string(myoverview, "in_reply_to", env->in_reply_to, 1);
3451                }
3452                add_property_long(myoverview, "size", elt->rfc822_size);
3453                add_property_long(myoverview, "uid", mail_uid(imap_le_struct->imap_stream, i));
3454                add_property_long(myoverview, "msgno", i);
3455                add_property_long(myoverview, "recent", elt->recent);
3456                add_property_long(myoverview, "flagged", elt->flagged);
3457                add_property_long(myoverview, "answered", elt->answered);
3458                add_property_long(myoverview, "deleted", elt->deleted);
3459                add_property_long(myoverview, "seen", elt->seen);
3460                add_property_long(myoverview, "draft", elt->draft);
3461                add_property_long(myoverview, "udate", mail_longdate(elt));
3462                add_next_index_object(return_value, myoverview TSRMLS_CC);
3463            }
3464        }
3465    }
3466}
3467/* }}} */
3468
3469/* {{{ proto string imap_mail_compose(array envelope, array body)
3470   Create a MIME message based on given envelope and body sections */
3471PHP_FUNCTION(imap_mail_compose)
3472{
3473    zval *envelope, *body;
3474    char *key;
3475    zval **data, **pvalue, **disp_data, **env_data;
3476    ulong ind;
3477    char *cookie = NIL;
3478    ENVELOPE *env;
3479    BODY *bod=NULL, *topbod=NULL;
3480    PART *mypart=NULL, *part;
3481    PARAMETER *param, *disp_param = NULL, *custom_headers_param = NULL, *tmp_param = NULL;
3482    char *tmp=NULL, *mystring=NULL, *t=NULL, *tempstring=NULL, *str_copy = NULL;
3483    int toppart = 0;
3484
3485    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "aa", &envelope, &body) == FAILURE) {
3486        return;
3487    }
3488
3489#define PHP_RFC822_PARSE_ADRLIST(target, value) \
3490    str_copy = estrndup(Z_STRVAL_PP(value), Z_STRLEN_PP(value)); \
3491    rfc822_parse_adrlist(target, str_copy, "NO HOST"); \
3492    efree(str_copy);
3493
3494    env = mail_newenvelope();
3495    if (zend_hash_find(Z_ARRVAL_P(envelope), "remail", sizeof("remail"), (void **) &pvalue)== SUCCESS) {
3496        convert_to_string_ex(pvalue);
3497        env->remail = cpystr(Z_STRVAL_PP(pvalue));
3498    }
3499    if (zend_hash_find(Z_ARRVAL_P(envelope), "return_path", sizeof("return_path"), (void **) &pvalue)== SUCCESS) {
3500        convert_to_string_ex(pvalue);
3501        PHP_RFC822_PARSE_ADRLIST(&env->return_path, pvalue);
3502    }
3503    if (zend_hash_find(Z_ARRVAL_P(envelope), "date", sizeof("date"), (void **) &pvalue)== SUCCESS) {
3504        convert_to_string_ex(pvalue);
3505        env->date = cpystr(Z_STRVAL_PP(pvalue));
3506    }
3507    if (zend_hash_find(Z_ARRVAL_P(envelope), "from", sizeof("from"), (void **) &pvalue)== SUCCESS) {
3508        convert_to_string_ex(pvalue);
3509        PHP_RFC822_PARSE_ADRLIST(&env->from, pvalue);
3510    }
3511    if (zend_hash_find(Z_ARRVAL_P(envelope), "reply_to", sizeof("reply_to"), (void **) &pvalue)== SUCCESS) {
3512        convert_to_string_ex(pvalue);
3513        PHP_RFC822_PARSE_ADRLIST(&env->reply_to, pvalue);
3514    }
3515    if (zend_hash_find(Z_ARRVAL_P(envelope), "in_reply_to", sizeof("in_reply_to"), (void **) &pvalue)== SUCCESS) {
3516        convert_to_string_ex(pvalue);
3517        env->in_reply_to = cpystr(Z_STRVAL_PP(pvalue));
3518    }
3519    if (zend_hash_find(Z_ARRVAL_P(envelope), "subject", sizeof("subject"), (void **) &pvalue)== SUCCESS) {
3520        convert_to_string_ex(pvalue);
3521        env->subject = cpystr(Z_STRVAL_PP(pvalue));
3522    }
3523    if (zend_hash_find(Z_ARRVAL_P(envelope), "to", sizeof("to"), (void **) &pvalue)== SUCCESS) {
3524        convert_to_string_ex(pvalue);
3525        PHP_RFC822_PARSE_ADRLIST(&env->to, pvalue);
3526    }
3527    if (zend_hash_find(Z_ARRVAL_P(envelope), "cc", sizeof("cc"), (void **) &pvalue)== SUCCESS) {
3528        convert_to_string_ex(pvalue);
3529        PHP_RFC822_PARSE_ADRLIST(&env->cc, pvalue);
3530    }
3531    if (zend_hash_find(Z_ARRVAL_P(envelope), "bcc", sizeof("bcc"), (void **) &pvalue)== SUCCESS) {
3532        convert_to_string_ex(pvalue);
3533        PHP_RFC822_PARSE_ADRLIST(&env->bcc, pvalue);
3534    }
3535    if (zend_hash_find(Z_ARRVAL_P(envelope), "message_id", sizeof("message_id"), (void **) &pvalue)== SUCCESS) {
3536        convert_to_string_ex(pvalue);
3537        env->message_id=cpystr(Z_STRVAL_PP(pvalue));
3538    }
3539
3540    if (zend_hash_find(Z_ARRVAL_P(envelope), "custom_headers", sizeof("custom_headers"), (void **) &pvalue)== SUCCESS) {
3541        if (Z_TYPE_PP(pvalue) == IS_ARRAY) {
3542            custom_headers_param = tmp_param = NULL;
3543            while (zend_hash_get_current_data(Z_ARRVAL_PP(pvalue), (void **) &env_data) == SUCCESS) {
3544                custom_headers_param = mail_newbody_parameter();
3545                convert_to_string_ex(env_data);
3546                custom_headers_param->value = (char *) fs_get(Z_STRLEN_PP(env_data) + 1);
3547                custom_headers_param->attribute = NULL;
3548                memcpy(custom_headers_param->value, Z_STRVAL_PP(env_data), Z_STRLEN_PP(env_data) + 1);
3549                zend_hash_move_forward(Z_ARRVAL_PP(pvalue));
3550                custom_headers_param->next = tmp_param;
3551                tmp_param = custom_headers_param;
3552            }
3553        }
3554    }
3555
3556    zend_hash_internal_pointer_reset(Z_ARRVAL_P(body));
3557    if (zend_hash_get_current_data(Z_ARRVAL_P(body), (void **) &data) != SUCCESS || Z_TYPE_PP(data) != IS_ARRAY) {
3558        php_error_docref(NULL TSRMLS_CC, E_WARNING, "body parameter must be a non-empty array");
3559        RETURN_FALSE;
3560    }
3561
3562    if (Z_TYPE_PP(data) == IS_ARRAY) {
3563        bod = mail_newbody();
3564        topbod = bod;
3565
3566        if (zend_hash_find(Z_ARRVAL_PP(data), "type", sizeof("type"), (void **) &pvalue)== SUCCESS) {
3567            convert_to_long_ex(pvalue);
3568            bod->type = (short) Z_LVAL_PP(pvalue);
3569        }
3570        if (zend_hash_find(Z_ARRVAL_PP(data), "encoding", sizeof("encoding"), (void **) &pvalue)== SUCCESS) {
3571            convert_to_long_ex(pvalue);
3572            bod->encoding = (short) Z_LVAL_PP(pvalue);
3573        }
3574        if (zend_hash_find(Z_ARRVAL_PP(data), "charset", sizeof("charset"), (void **) &pvalue)== SUCCESS) {
3575            convert_to_string_ex(pvalue);
3576            tmp_param = mail_newbody_parameter();
3577            tmp_param->value = cpystr(Z_STRVAL_PP(pvalue));
3578            tmp_param->attribute = cpystr("CHARSET");
3579            tmp_param->next = bod->parameter;
3580            bod->parameter = tmp_param;
3581        }
3582        if (zend_hash_find(Z_ARRVAL_PP(data), "type.parameters", sizeof("type.parameters"), (void **) &pvalue)== SUCCESS) {
3583            if(Z_TYPE_PP(pvalue) == IS_ARRAY) {
3584                disp_param = tmp_param = NULL;
3585                while (zend_hash_get_current_data(Z_ARRVAL_PP(pvalue), (void **) &disp_data) == SUCCESS) {
3586                    disp_param = mail_newbody_parameter();
3587                    zend_hash_get_current_key(Z_ARRVAL_PP(pvalue), &key, &ind, 0);
3588                    disp_param->attribute = cpystr(key);
3589                    convert_to_string_ex(disp_data);
3590                    disp_param->value = (char *) fs_get(Z_STRLEN_PP(disp_data) + 1);
3591                    memcpy(disp_param->value, Z_STRVAL_PP(disp_data), Z_STRLEN_PP(disp_data) + 1);
3592                    zend_hash_move_forward(Z_ARRVAL_PP(pvalue));
3593                    disp_param->next = tmp_param;
3594                    tmp_param = disp_param;
3595                }
3596            bod->parameter = disp_param;
3597            }
3598        }
3599        if (zend_hash_find(Z_ARRVAL_PP(data), "subtype", sizeof("subtype"), (void **) &pvalue)== SUCCESS) {
3600            convert_to_string_ex(pvalue);
3601            bod->subtype = cpystr(Z_STRVAL_PP(pvalue));
3602        }
3603        if (zend_hash_find(Z_ARRVAL_PP(data), "id", sizeof("id"), (void **) &pvalue)== SUCCESS) {
3604            convert_to_string_ex(pvalue);
3605            bod->id = cpystr(Z_STRVAL_PP(pvalue));
3606        }
3607        if (zend_hash_find(Z_ARRVAL_PP(data), "description", sizeof("description"), (void **) &pvalue)== SUCCESS) {
3608            convert_to_string_ex(pvalue);
3609            bod->description = cpystr(Z_STRVAL_PP(pvalue));
3610        }
3611        if (zend_hash_find(Z_ARRVAL_PP(data), "disposition.type", sizeof("disposition.type"), (void **) &pvalue)== SUCCESS) {
3612            convert_to_string_ex(pvalue);
3613            bod->disposition.type = (char *) fs_get(Z_STRLEN_PP(pvalue) + 1);
3614            memcpy(bod->disposition.type, Z_STRVAL_PP(pvalue), Z_STRLEN_PP(pvalue)+1);
3615        }
3616        if (zend_hash_find(Z_ARRVAL_PP(data), "disposition", sizeof("disposition"), (void **) &pvalue)== SUCCESS) {
3617            if (Z_TYPE_PP(pvalue) == IS_ARRAY) {
3618                disp_param = tmp_param = NULL;
3619                while (zend_hash_get_current_data(Z_ARRVAL_PP(pvalue), (void **) &disp_data) == SUCCESS) {
3620                    disp_param = mail_newbody_parameter();
3621                    zend_hash_get_current_key(Z_ARRVAL_PP(pvalue), &key, &ind, 0);
3622                    disp_param->attribute = cpystr(key);
3623                    convert_to_string_ex(disp_data);
3624                    disp_param->value = (char *) fs_get(Z_STRLEN_PP(disp_data) + 1);
3625                    memcpy(disp_param->value, Z_STRVAL_PP(disp_data), Z_STRLEN_PP(disp_data) + 1);
3626                    zend_hash_move_forward(Z_ARRVAL_PP(pvalue));
3627                    disp_param->next = tmp_param;
3628                    tmp_param = disp_param;
3629                }
3630                bod->disposition.parameter = disp_param;
3631            }
3632        }
3633        if (zend_hash_find(Z_ARRVAL_PP(data), "contents.data", sizeof("contents.data"), (void **) &pvalue)== SUCCESS) {
3634            convert_to_string_ex(pvalue);
3635            bod->contents.text.data = (char *) fs_get(Z_STRLEN_PP(pvalue) + 1);
3636            memcpy(bod->contents.text.data, Z_STRVAL_PP(pvalue), Z_STRLEN_PP(pvalue)+1);
3637            bod->contents.text.size = Z_STRLEN_PP(pvalue);
3638        } else {
3639            bod->contents.text.data = (char *) fs_get(1);
3640            memcpy(bod->contents.text.data, "", 1);
3641            bod->contents.text.size = 0;
3642        }
3643        if (zend_hash_find(Z_ARRVAL_PP(data), "lines", sizeof("lines"), (void **) &pvalue)== SUCCESS) {
3644            convert_to_long_ex(pvalue);
3645            bod->size.lines = Z_LVAL_PP(pvalue);
3646        }
3647        if (zend_hash_find(Z_ARRVAL_PP(data), "bytes", sizeof("bytes"), (void **) &pvalue)== SUCCESS) {
3648            convert_to_long_ex(pvalue);
3649            bod->size.bytes = Z_LVAL_PP(pvalue);
3650        }
3651        if (zend_hash_find(Z_ARRVAL_PP(data), "md5", sizeof("md5"), (void **) &pvalue)== SUCCESS) {
3652            convert_to_string_ex(pvalue);
3653            bod->md5 = cpystr(Z_STRVAL_PP(pvalue));
3654        }
3655    }
3656
3657    zend_hash_move_forward(Z_ARRVAL_P(body));
3658
3659    while (zend_hash_get_current_data(Z_ARRVAL_P(body), (void **) &data) == SUCCESS) {
3660        if (Z_TYPE_PP(data) == IS_ARRAY) {
3661            short type = -1;
3662            if (zend_hash_find(Z_ARRVAL_PP(data), "type", sizeof("type"), (void **) &pvalue)== SUCCESS) {
3663                convert_to_long_ex(pvalue);
3664                type = (short) Z_LVAL_PP(pvalue);
3665            }
3666
3667            if (!toppart) {
3668                bod->nested.part = mail_newbody_part();
3669                mypart = bod->nested.part;
3670                toppart = 1;
3671            } else {
3672                mypart->next = mail_newbody_part();
3673                mypart = mypart->next;
3674            }
3675
3676            bod = &mypart->body;
3677
3678            if (type != TYPEMULTIPART) {
3679                bod->type = type;
3680            }
3681
3682            if (zend_hash_find(Z_ARRVAL_PP(data), "encoding", sizeof("encoding"), (void **) &pvalue)== SUCCESS) {
3683                convert_to_long_ex(pvalue);
3684                bod->encoding = (short) Z_LVAL_PP(pvalue);
3685            }
3686            if (zend_hash_find(Z_ARRVAL_PP(data), "charset", sizeof("charset"), (void **) &pvalue)== SUCCESS) {
3687                convert_to_string_ex(pvalue);
3688                tmp_param = mail_newbody_parameter();
3689                tmp_param->value = (char *) fs_get(Z_STRLEN_PP(pvalue) + 1);
3690                memcpy(tmp_param->value, Z_STRVAL_PP(pvalue), Z_STRLEN_PP(pvalue) + 1);
3691                tmp_param->attribute = cpystr("CHARSET");
3692                tmp_param->next = bod->parameter;
3693                bod->parameter = tmp_param;
3694            }
3695            if (zend_hash_find(Z_ARRVAL_PP(data), "type.parameters", sizeof("type.parameters"), (void **) &pvalue)== SUCCESS) {
3696                if(Z_TYPE_PP(pvalue) == IS_ARRAY) {
3697                    disp_param = tmp_param = NULL;
3698                    while (zend_hash_get_current_data(Z_ARRVAL_PP(pvalue), (void **) &disp_data) == SUCCESS) {
3699                        disp_param = mail_newbody_parameter();
3700                        zend_hash_get_current_key(Z_ARRVAL_PP(pvalue), &key, &ind, 0);
3701                        disp_param->attribute = cpystr(key);
3702                        convert_to_string_ex(disp_data);
3703                        disp_param->value = (char *) fs_get(Z_STRLEN_PP(disp_data) + 1);
3704                        memcpy(disp_param->value, Z_STRVAL_PP(disp_data), Z_STRLEN_PP(disp_data) + 1);
3705                        zend_hash_move_forward(Z_ARRVAL_PP(pvalue));
3706                        disp_param->next = tmp_param;
3707                        tmp_param = disp_param;
3708                    }
3709                    bod->parameter = disp_param;
3710                }
3711            }
3712            if (zend_hash_find(Z_ARRVAL_PP(data), "subtype", sizeof("subtype"), (void **) &pvalue)== SUCCESS) {
3713                convert_to_string_ex(pvalue);
3714                bod->subtype = cpystr(Z_STRVAL_PP(pvalue));
3715            }
3716            if (zend_hash_find(Z_ARRVAL_PP(data), "id", sizeof("id"), (void **) &pvalue)== SUCCESS) {
3717                convert_to_string_ex(pvalue);
3718                bod->id = cpystr(Z_STRVAL_PP(pvalue));
3719            }
3720            if (zend_hash_find(Z_ARRVAL_PP(data), "description", sizeof("description"), (void **) &pvalue)== SUCCESS) {
3721                convert_to_string_ex(pvalue);
3722                bod->description = cpystr(Z_STRVAL_PP(pvalue));
3723            }
3724            if (zend_hash_find(Z_ARRVAL_PP(data), "disposition.type", sizeof("disposition.type"), (void **) &pvalue)== SUCCESS) {
3725                convert_to_string_ex(pvalue);
3726                bod->disposition.type = (char *) fs_get(Z_STRLEN_PP(pvalue) + 1);
3727                memcpy(bod->disposition.type, Z_STRVAL_PP(pvalue), Z_STRLEN_PP(pvalue)+1);
3728            }
3729            if (zend_hash_find(Z_ARRVAL_PP(data), "disposition", sizeof("disposition"), (void **) &pvalue)== SUCCESS) {
3730                if (Z_TYPE_PP(pvalue) == IS_ARRAY) {
3731                    disp_param = tmp_param = NULL;
3732                    while (zend_hash_get_current_data(Z_ARRVAL_PP(pvalue), (void **) &disp_data) == SUCCESS) {
3733                        disp_param = mail_newbody_parameter();
3734                        zend_hash_get_current_key(Z_ARRVAL_PP(pvalue), &key, &ind, 0);
3735                        disp_param->attribute = cpystr(key);
3736                        convert_to_string_ex(disp_data);
3737                        disp_param->value = (char *) fs_get(Z_STRLEN_PP(disp_data) + 1);
3738                        memcpy(disp_param->value, Z_STRVAL_PP(disp_data), Z_STRLEN_PP(disp_data) + 1);
3739                        zend_hash_move_forward(Z_ARRVAL_PP(pvalue));
3740                        disp_param->next = tmp_param;
3741                        tmp_param = disp_param;
3742                    }
3743                    bod->disposition.parameter = disp_param;
3744                }
3745            }
3746            if (zend_hash_find(Z_ARRVAL_PP(data), "contents.data", sizeof("contents.data"), (void **) &pvalue)== SUCCESS) {
3747                convert_to_string_ex(pvalue);
3748                bod->contents.text.data = (char *) fs_get(Z_STRLEN_PP(pvalue) + 1);
3749                memcpy(bod->contents.text.data, Z_STRVAL_PP(pvalue), Z_STRLEN_PP(pvalue) + 1);
3750                bod->contents.text.size = Z_STRLEN_PP(pvalue);
3751            } else {
3752                bod->contents.text.data = (char *) fs_get(1);
3753                memcpy(bod->contents.text.data, "", 1);
3754                bod->contents.text.size = 0;
3755            }
3756            if (zend_hash_find(Z_ARRVAL_PP(data), "lines", sizeof("lines"), (void **) &pvalue)== SUCCESS) {
3757                convert_to_long_ex(pvalue);
3758                bod->size.lines = Z_LVAL_PP(pvalue);
3759            }
3760            if (zend_hash_find(Z_ARRVAL_PP(data), "bytes", sizeof("bytes"), (void **) &pvalue)== SUCCESS) {
3761                convert_to_long_ex(pvalue);
3762                bod->size.bytes = Z_LVAL_PP(pvalue);
3763            }
3764            if (zend_hash_find(Z_ARRVAL_PP(data), "md5", sizeof("md5"), (void **) &pvalue)== SUCCESS) {
3765                convert_to_string_ex(pvalue);
3766                bod->md5 = cpystr(Z_STRVAL_PP(pvalue));
3767            }
3768        }
3769        zend_hash_move_forward(Z_ARRVAL_P(body));
3770    }
3771
3772    if (bod && bod->type == TYPEMULTIPART && (!bod->nested.part || !bod->nested.part->next)) {
3773        php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot generate multipart e-mail without components.");
3774        RETVAL_FALSE;
3775        goto done;
3776    }
3777
3778    rfc822_encode_body_7bit(env, topbod);
3779
3780    tmp = emalloc(SENDBUFLEN + 1);
3781
3782    rfc822_header(tmp, env, topbod);
3783
3784    /* add custom envelope headers */
3785    if (custom_headers_param) {
3786        int l = strlen(tmp) - 2, l2;
3787        PARAMETER *tp = custom_headers_param;
3788
3789        /* remove last CRLF from tmp */
3790        tmp[l] = '\0';
3791        tempstring = emalloc(l);
3792        memcpy(tempstring, tmp, l);
3793
3794        do {
3795            l2 = strlen(custom_headers_param->value);
3796            tempstring = erealloc(tempstring, l + l2 + CRLF_LEN + 1);
3797            memcpy(tempstring + l, custom_headers_param->value, l2);
3798            memcpy(tempstring + l + l2, CRLF, CRLF_LEN);
3799            l += l2 + CRLF_LEN;
3800        } while ((custom_headers_param = custom_headers_param->next));
3801
3802        mail_free_body_parameter(&tp);
3803
3804        mystring = emalloc(l + CRLF_LEN + 1);
3805        memcpy(mystring, tempstring, l);
3806        memcpy(mystring + l , CRLF, CRLF_LEN);
3807        mystring[l + CRLF_LEN] = '\0';
3808
3809        efree(tempstring);
3810    } else {
3811        mystring = estrdup(tmp);
3812    }
3813
3814    bod = topbod;
3815
3816    if (bod && bod->type == TYPEMULTIPART) {
3817
3818        /* first body part */
3819            part = bod->nested.part;
3820
3821        /* find cookie */
3822            for (param = bod->parameter; param && !cookie; param = param->next) {
3823                if (!strcmp (param->attribute, "BOUNDARY")) {
3824                    cookie = param->value;
3825                }
3826            }
3827
3828        /* yucky default */
3829            if (!cookie) {
3830                cookie = "-";
3831            } else if (strlen(cookie) > (SENDBUFLEN - 2 - 2 - 2)) { /* validate cookie length -- + CRLF * 2 */
3832                php_error_docref(NULL TSRMLS_CC, E_WARNING, "The boundary should be no longer than 4kb");
3833                RETVAL_FALSE;
3834                goto done;
3835            }
3836
3837        /* for each part */
3838            do {
3839                t = tmp;
3840
3841            /* append mini-header */
3842                *t = '\0';
3843                rfc822_write_body_header(&t, &part->body);
3844
3845            /* output cookie, mini-header, and contents */
3846                spprintf(&tempstring, 0, "%s--%s%s%s%s", mystring, cookie, CRLF, tmp, CRLF);
3847                efree(mystring);
3848                mystring=tempstring;
3849
3850                bod=&part->body;
3851
3852                spprintf(&tempstring, 0, "%s%s%s", mystring, bod->contents.text.data, CRLF);
3853                efree(mystring);
3854                mystring=tempstring;
3855            } while ((part = part->next)); /* until done */
3856
3857            /* output trailing cookie */
3858            spprintf(&tempstring, 0, "%s--%s--%s", mystring, cookie, CRLF);
3859            efree(mystring);
3860            mystring=tempstring;
3861    } else if (bod) {
3862        spprintf(&tempstring, 0, "%s%s%s", mystring, bod->contents.text.data, CRLF);
3863        efree(mystring);
3864        mystring=tempstring;
3865    } else {
3866        efree(mystring);
3867        RETVAL_FALSE;
3868        goto done;
3869    }
3870
3871    RETVAL_STRING(tempstring, 0);
3872done:
3873    if (tmp) {
3874        efree(tmp);
3875    }
3876    mail_free_body(&topbod);
3877    mail_free_envelope(&env);
3878}
3879/* }}} */
3880
3881/* {{{ _php_imap_mail
3882 */
3883int _php_imap_mail(char *to, char *subject, char *message, char *headers, char *cc, char *bcc, char* rpath TSRMLS_DC)
3884{
3885#ifdef PHP_WIN32
3886    int tsm_err;
3887#else
3888    FILE *sendmail;
3889    int ret;
3890#endif
3891
3892#ifdef PHP_WIN32
3893    char *tempMailTo;
3894    char *tsm_errmsg = NULL;
3895    ADDRESS *addr;
3896    char *bufferTo = NULL, *bufferCc = NULL, *bufferBcc = NULL, *bufferHeader = NULL;
3897    int offset, bufferLen = 0;
3898    size_t bt_len;
3899
3900    if (headers) {
3901        bufferLen += strlen(headers);
3902    }
3903    if (to) {
3904        bufferLen += strlen(to) + 6;
3905    }
3906    if (cc) {
3907        bufferLen += strlen(cc) + 6;
3908    }
3909
3910#define PHP_IMAP_CLEAN  if (bufferTo) efree(bufferTo); if (bufferCc) efree(bufferCc); if (bufferBcc) efree(bufferBcc); if (bufferHeader) efree(bufferHeader);
3911#define PHP_IMAP_BAD_DEST PHP_IMAP_CLEAN; efree(tempMailTo); return (BAD_MSG_DESTINATION);
3912
3913    bufferHeader = (char *)emalloc(bufferLen + 1);
3914    memset(bufferHeader, 0, bufferLen);
3915    if (to && *to) {
3916        strlcat(bufferHeader, "To: ", bufferLen + 1);
3917        strlcat(bufferHeader, to, bufferLen + 1);
3918        strlcat(bufferHeader, "\r\n", bufferLen + 1);
3919        tempMailTo = estrdup(to);
3920        bt_len = strlen(to);
3921        bufferTo = (char *)safe_emalloc(bt_len, 1, 1);
3922        bt_len++;
3923        offset = 0;
3924        addr = NULL;
3925        rfc822_parse_adrlist(&addr, tempMailTo, NULL);
3926        while (addr) {
3927            if (addr->host == NULL || strcmp(addr->host, ERRHOST) == 0) {
3928                PHP_IMAP_BAD_DEST;
3929            } else {
3930                bufferTo = safe_erealloc(bufferTo, bt_len, 1, strlen(addr->mailbox));
3931                bt_len += strlen(addr->mailbox);
3932                bufferTo = safe_erealloc(bufferTo, bt_len, 1, strlen(addr->host));
3933                bt_len += strlen(addr->host);
3934                offset += slprintf(bufferTo + offset, bt_len - offset, "%s@%s,", addr->mailbox, addr->host);
3935            }
3936            addr = addr->next;
3937        }
3938        efree(tempMailTo);
3939        if (offset>0) {
3940            bufferTo[offset-1] = 0;
3941        }
3942    }
3943
3944    if (cc && *cc) {
3945        strlcat(bufferHeader, "Cc: ", bufferLen + 1);
3946        strlcat(bufferHeader, cc, bufferLen + 1);
3947        strlcat(bufferHeader, "\r\n", bufferLen + 1);
3948        tempMailTo = estrdup(cc);
3949        bt_len = strlen(cc);
3950        bufferCc = (char *)safe_emalloc(bt_len, 1, 1);
3951        bt_len++;
3952        offset = 0;
3953        addr = NULL;
3954        rfc822_parse_adrlist(&addr, tempMailTo, NULL);
3955        while (addr) {
3956            if (addr->host == NULL || strcmp(addr->host, ERRHOST) == 0) {
3957                PHP_IMAP_BAD_DEST;
3958            } else {
3959                bufferCc = safe_erealloc(bufferCc, bt_len, 1, strlen(addr->mailbox));
3960                bt_len += strlen(addr->mailbox);
3961                bufferCc = safe_erealloc(bufferCc, bt_len, 1, strlen(addr->host));
3962                bt_len += strlen(addr->host);
3963                offset += slprintf(bufferCc + offset, bt_len - offset, "%s@%s,", addr->mailbox, addr->host);
3964            }
3965            addr = addr->next;
3966        }
3967        efree(tempMailTo);
3968        if (offset>0) {
3969            bufferCc[offset-1] = 0;
3970        }
3971    }
3972
3973    if (bcc && *bcc) {
3974        tempMailTo = estrdup(bcc);
3975        bt_len = strlen(bcc);
3976        bufferBcc = (char *)safe_emalloc(bt_len, 1, 1);
3977        bt_len++;
3978        offset = 0;
3979        addr = NULL;
3980        rfc822_parse_adrlist(&addr, tempMailTo, NULL);
3981        while (addr) {
3982            if (addr->host == NULL || strcmp(addr->host, ERRHOST) == 0) {
3983                PHP_IMAP_BAD_DEST;
3984            } else {
3985                bufferBcc = safe_erealloc(bufferBcc, bt_len, 1, strlen(addr->mailbox));
3986                bt_len += strlen(addr->mailbox);
3987                bufferBcc = safe_erealloc(bufferBcc, bt_len, 1, strlen(addr->host));
3988                bt_len += strlen(addr->host);
3989                offset += slprintf(bufferBcc + offset, bt_len - offset, "%s@%s,", addr->mailbox, addr->host);
3990            }
3991            addr = addr->next;
3992        }
3993        efree(tempMailTo);
3994        if (offset>0) {
3995            bufferBcc[offset-1] = 0;
3996        }
3997    }
3998
3999    if (headers && *headers) {
4000        strlcat(bufferHeader, headers, bufferLen + 1);
4001    }
4002
4003    if (TSendMail(INI_STR("SMTP"), &tsm_err, &tsm_errmsg, bufferHeader, subject, bufferTo, message, bufferCc, bufferBcc, rpath TSRMLS_CC) != SUCCESS) {
4004        if (tsm_errmsg) {
4005            php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", tsm_errmsg);
4006            efree(tsm_errmsg);
4007        } else {
4008            php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", GetSMErrorText(tsm_err));
4009        }
4010        PHP_IMAP_CLEAN;
4011        return 0;
4012    }
4013    PHP_IMAP_CLEAN;
4014#else
4015    if (!INI_STR("sendmail_path")) {
4016        return 0;
4017    }
4018    sendmail = popen(INI_STR("sendmail_path"), "w");
4019    if (sendmail) {
4020        if (rpath && rpath[0]) fprintf(sendmail, "From: %s\n", rpath);
4021        fprintf(sendmail, "To: %s\n", to);
4022        if (cc && cc[0]) fprintf(sendmail, "Cc: %s\n", cc);
4023        if (bcc && bcc[0]) fprintf(sendmail, "Bcc: %s\n", bcc);
4024        fprintf(sendmail, "Subject: %s\n", subject);
4025        if (headers != NULL) {
4026            fprintf(sendmail, "%s\n", headers);
4027        }
4028        fprintf(sendmail, "\n%s\n", message);
4029        ret = pclose(sendmail);
4030        if (ret == -1) {
4031            return 0;
4032        } else {
4033            return 1;
4034        }
4035    } else {
4036        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not execute mail delivery program");
4037        return 0;
4038    }
4039#endif
4040    return 1;
4041}
4042/* }}} */
4043
4044/* {{{ proto bool imap_mail(string to, string subject, string message [, string additional_headers [, string cc [, string bcc [, string rpath]]]])
4045   Send an email message */
4046PHP_FUNCTION(imap_mail)
4047{
4048    char *to=NULL, *message=NULL, *headers=NULL, *subject=NULL, *cc=NULL, *bcc=NULL, *rpath=NULL;
4049    int to_len, message_len, headers_len, subject_len, cc_len, bcc_len, rpath_len, argc = ZEND_NUM_ARGS();
4050
4051    if (zend_parse_parameters(argc TSRMLS_CC, "sss|ssss", &to, &to_len, &subject, &subject_len, &message, &message_len,
4052        &headers, &headers_len, &cc, &cc_len, &bcc, &bcc_len, &rpath, &rpath_len) == FAILURE) {
4053        return;
4054    }
4055
4056    /* To: */
4057    if (!to_len) {
4058        php_error_docref(NULL TSRMLS_CC, E_WARNING, "No to field in mail command");
4059        RETURN_FALSE;
4060    }
4061
4062    /* Subject: */
4063    if (!subject_len) {
4064        php_error_docref(NULL TSRMLS_CC, E_WARNING, "No subject field in mail command");
4065        RETURN_FALSE;
4066    }
4067
4068    /* message body */
4069    if (!message_len) {
4070        /* this is not really an error, so it is allowed. */
4071        php_error_docref(NULL TSRMLS_CC, E_WARNING, "No message string in mail command");
4072        message = NULL;
4073    }
4074
4075    if (_php_imap_mail(to, subject, message, headers, cc, bcc, rpath TSRMLS_CC)) {
4076        RETURN_TRUE;
4077    } else {
4078        RETURN_FALSE;
4079    }
4080}
4081/* }}} */
4082
4083/* {{{ proto array imap_search(resource stream_id, string criteria [, int options [, string charset]])
4084   Return a list of messages matching the given criteria */
4085PHP_FUNCTION(imap_search)
4086{
4087    zval *streamind;
4088    char *criteria, *charset = NULL;
4089    int criteria_len, charset_len = 0;
4090    long flags = SE_FREE;
4091    pils *imap_le_struct;
4092    char *search_criteria;
4093    MESSAGELIST *cur;
4094    int argc = ZEND_NUM_ARGS();
4095    SEARCHPGM *pgm = NIL;
4096
4097    if (zend_parse_parameters(argc TSRMLS_CC, "rs|ls", &streamind, &criteria, &criteria_len, &flags, &charset, &charset_len) == FAILURE) {
4098        return;
4099    }
4100
4101    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
4102
4103    search_criteria = estrndup(criteria, criteria_len);
4104
4105    IMAPG(imap_messages) = IMAPG(imap_messages_tail) = NIL;
4106    pgm = mail_criteria(search_criteria);
4107
4108    mail_search_full(imap_le_struct->imap_stream, (argc == 4 ? charset : NIL), pgm, flags);
4109
4110    if (pgm && !(flags & SE_FREE)) {
4111        mail_free_searchpgm(&pgm);
4112    }
4113
4114    if (IMAPG(imap_messages) == NIL) {
4115        efree(search_criteria);
4116        RETURN_FALSE;
4117    }
4118
4119    array_init(return_value);
4120
4121    cur = IMAPG(imap_messages);
4122    while (cur != NIL) {
4123        add_next_index_long(return_value, cur->msgid);
4124        cur = cur->next;
4125    }
4126    mail_free_messagelist(&IMAPG(imap_messages), &IMAPG(imap_messages_tail));
4127    efree(search_criteria);
4128}
4129/* }}} */
4130
4131/* {{{ proto array imap_alerts(void)
4132   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. */
4133/* Author: CJH */
4134PHP_FUNCTION(imap_alerts)
4135{
4136    STRINGLIST *cur=NIL;
4137
4138    if (zend_parse_parameters_none() == FAILURE) {
4139        return;
4140    }
4141
4142    if (IMAPG(imap_alertstack) == NIL) {
4143        RETURN_FALSE;
4144    }
4145
4146    array_init(return_value);
4147
4148    cur = IMAPG(imap_alertstack);
4149    while (cur != NIL) {
4150        add_next_index_string(return_value, cur->LTEXT, 1);
4151        cur = cur->next;
4152    }
4153    mail_free_stringlist(&IMAPG(imap_alertstack));
4154    IMAPG(imap_alertstack) = NIL;
4155}
4156/* }}} */
4157
4158/* {{{ proto array imap_errors(void)
4159   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. */
4160/* Author: CJH */
4161PHP_FUNCTION(imap_errors)
4162{
4163    ERRORLIST *cur=NIL;
4164
4165    if (zend_parse_parameters_none() == FAILURE) {
4166        return;
4167    }
4168
4169    if (IMAPG(imap_errorstack) == NIL) {
4170        RETURN_FALSE;
4171    }
4172
4173    array_init(return_value);
4174
4175    cur = IMAPG(imap_errorstack);
4176    while (cur != NIL) {
4177        add_next_index_string(return_value, cur->LTEXT, 1);
4178        cur = cur->next;
4179    }
4180    mail_free_errorlist(&IMAPG(imap_errorstack));
4181    IMAPG(imap_errorstack) = NIL;
4182}
4183/* }}} */
4184
4185/* {{{ proto string imap_last_error(void)
4186   Returns the last error that was generated by an IMAP function. The error stack is NOT cleared after this call. */
4187/* Author: CJH */
4188PHP_FUNCTION(imap_last_error)
4189{
4190    ERRORLIST *cur=NIL;
4191
4192    if (zend_parse_parameters_none() == FAILURE) {
4193        return;
4194    }
4195
4196    if (IMAPG(imap_errorstack) == NIL) {
4197        RETURN_FALSE;
4198    }
4199
4200    cur = IMAPG(imap_errorstack);
4201    while (cur != NIL) {
4202        if (cur->next == NIL) {
4203            RETURN_STRING(cur->LTEXT, 1);
4204        }
4205        cur = cur->next;
4206    }
4207}
4208/* }}} */
4209
4210/* {{{ proto array imap_mime_header_decode(string str)
4211   Decode mime header element in accordance with RFC 2047 and return array of objects containing 'charset' encoding and decoded 'text' */
4212PHP_FUNCTION(imap_mime_header_decode)
4213{
4214    /* Author: Ted Parnefors <ted@mtv.se> */
4215    zval *myobject;
4216    char *str, *string, *charset, encoding, *text, *decode;
4217    int str_len;
4218    long charset_token, encoding_token, end_token, end, offset=0, i;
4219    unsigned long newlength;
4220
4221    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) {
4222        return;
4223    }
4224
4225    array_init(return_value);
4226
4227    string = str;
4228    end = str_len;
4229
4230    charset = (char *) safe_emalloc((end + 1), 2, 0);
4231    text = &charset[end + 1];
4232    while (offset < end) {  /* Reached end of the string? */
4233        if ((charset_token = (long)php_memnstr(&string[offset], "=?", 2, string + end))) {  /* Is there anything encoded in the string? */
4234            charset_token -= (long)string;
4235            if (offset != charset_token) {  /* Is there anything before the encoded data? */
4236                /* Retrieve unencoded data that is found before encoded data */
4237                memcpy(text, &string[offset], charset_token-offset);
4238                text[charset_token - offset] = 0x00;
4239                MAKE_STD_ZVAL(myobject);
4240                object_init(myobject);
4241                add_property_string(myobject, "charset", "default", 1);
4242                add_property_string(myobject, "text", text, 1);
4243                zend_hash_next_index_insert(Z_ARRVAL_P(return_value), (void *)&myobject, sizeof(zval *), NULL);
4244            }
4245            if ((encoding_token = (long)php_memnstr(&string[charset_token+2], "?", 1, string+end))) {       /* Find token for encoding */
4246                encoding_token -= (long)string;
4247                if ((end_token = (long)php_memnstr(&string[encoding_token+3], "?=", 2, string+end))) {  /* Find token for end of encoded data */
4248                    end_token -= (long)string;
4249                    memcpy(charset, &string[charset_token + 2], encoding_token - (charset_token + 2));  /* Extract charset encoding */
4250                    charset[encoding_token-(charset_token + 2)] = 0x00;
4251                    encoding=string[encoding_token + 1];    /* Extract encoding from string */
4252                    memcpy(text, &string[encoding_token + 3], end_token - (encoding_token + 3));    /* Extract text */
4253                    text[end_token - (encoding_token + 3)] = 0x00;
4254                    decode = text;
4255                    if (encoding == 'q' || encoding == 'Q') {   /* Decode 'q' encoded data */
4256                        for(i=0; text[i] != 0x00; i++) if (text[i] == '_') text[i] = ' ';   /* Replace all *_' with space. */
4257                        decode = (char *)rfc822_qprint((unsigned char *) text, strlen(text), &newlength);
4258                    } else if (encoding == 'b' || encoding == 'B') {
4259                        decode = (char *)rfc822_base64((unsigned char *) text, strlen(text), &newlength); /* Decode 'B' encoded data */
4260                    }
4261                    if (decode == NULL) {
4262                        efree(charset);
4263                        zval_dtor(return_value);
4264                        RETURN_FALSE;
4265                    }
4266                    MAKE_STD_ZVAL(myobject);
4267                    object_init(myobject);
4268                    add_property_string(myobject, "charset", charset, 1);
4269                    add_property_string(myobject, "text", decode, 1);
4270                    zend_hash_next_index_insert(Z_ARRVAL_P(return_value), (void *)&myobject, sizeof(zval *), NULL);
4271
4272                    /* only free decode if it was allocated by rfc822_qprint or rfc822_base64 */
4273                    if (decode != text) {
4274                        fs_give((void**)&decode);
4275                    }
4276
4277                    offset = end_token+2;
4278                    for (i = 0; (string[offset + i] == ' ') || (string[offset + i] == 0x0a) || (string[offset + i] == 0x0d) || (string[offset + i] == '\t'); i++);
4279                    if ((string[offset + i] == '=') && (string[offset + i + 1] == '?') && (offset + i < end)) {
4280                        offset += i;
4281                    }
4282                    continue;   /*/ Iterate the loop again please. */
4283                }
4284            }
4285        } else {
4286            /* Just some tweaking to optimize the code, and get the end statements work in a general manner.
4287             * If we end up here we didn't find a position for "charset_token",
4288             * so we need to set it to the start of the yet unextracted data.
4289             */
4290            charset_token = offset;
4291        }
4292        /* Return the rest of the data as unencoded, as it was either unencoded or was missing separators
4293           which rendered the remainder of the string impossible for us to decode. */
4294        memcpy(text, &string[charset_token], end - charset_token);  /* Extract unencoded text from string */
4295        text[end - charset_token] = 0x00;
4296        MAKE_STD_ZVAL(myobject);
4297        object_init(myobject);
4298        add_property_string(myobject, "charset", "default", 1);
4299        add_property_string(myobject, "text", text, 1);
4300        zend_hash_next_index_insert(Z_ARRVAL_P(return_value), (void *)&myobject, sizeof(zval *), NULL);
4301
4302        offset = end;   /* We have reached the end of the string. */
4303    }
4304    efree(charset);
4305}
4306/* }}} */
4307
4308/* Support Functions */
4309
4310#ifdef HAVE_RFC822_OUTPUT_ADDRESS_LIST
4311/* {{{ _php_rfc822_soutr
4312 */
4313static long _php_rfc822_soutr (void *stream, char *string)
4314{
4315    smart_str *ret = (smart_str*)stream;
4316    int len = strlen(string);
4317
4318    smart_str_appendl(ret, string, len);
4319    return LONGT;
4320}
4321/* }}} */
4322
4323/* {{{ _php_rfc822_write_address
4324 */
4325static char* _php_rfc822_write_address(ADDRESS *addresslist TSRMLS_DC)
4326{
4327    char address[MAILTMPLEN];
4328    smart_str ret = {0};
4329    RFC822BUFFER buf;
4330
4331    buf.beg = address;
4332    buf.cur = buf.beg;
4333    buf.end = buf.beg + sizeof(address) - 1;
4334    buf.s = &ret;
4335    buf.f = _php_rfc822_soutr;
4336    rfc822_output_address_list(&buf, addresslist, 0, NULL);
4337    rfc822_output_flush(&buf);
4338    smart_str_0(&ret);
4339    return ret.c;
4340}
4341/* }}} */
4342
4343#else
4344
4345/* {{{ _php_rfc822_len
4346 * Calculate string length based on imap's rfc822_cat function.
4347 */
4348static int _php_rfc822_len(char *str)
4349{
4350    int len;
4351    char *p;
4352
4353    if (!str || !*str) {
4354        return 0;
4355    }
4356
4357    /* strings with special characters will need to be quoted, as a safety measure we
4358     * add 2 bytes for the quotes just in case.
4359     */
4360    len = strlen(str) + 2;
4361    p = str;
4362    /* rfc822_cat() will escape all " and \ characters, therefor we need to increase
4363     * our buffer length to account for these characters.
4364     */
4365    while ((p = strpbrk(p, "\\\""))) {
4366        p++;
4367        len++;
4368    }
4369
4370    return len;
4371}
4372/* }}} */
4373
4374/* {{{ _php_imap_get_address_size
4375 */
4376static int _php_imap_address_size (ADDRESS *addresslist)
4377{
4378    ADDRESS *tmp;
4379    int ret=0, num_ent=0;
4380
4381    tmp = addresslist;
4382
4383    if (tmp) do {
4384        ret += _php_rfc822_len(tmp->personal);
4385        ret += _php_rfc822_len(tmp->adl);
4386        ret += _php_rfc822_len(tmp->mailbox);
4387        ret += _php_rfc822_len(tmp->host);
4388        num_ent++;
4389    } while ((tmp = tmp->next));
4390
4391    /*
4392     * rfc822_write_address_full() needs some extra space for '<>,', etc.
4393     * for this perpouse we allocate additional PHP_IMAP_ADDRESS_SIZE_BUF bytes
4394     * by default this buffer is 10 bytes long
4395    */
4396    ret += (ret) ? num_ent*PHP_IMAP_ADDRESS_SIZE_BUF : 0;
4397
4398    return ret;
4399}
4400
4401/* }}} */
4402
4403/* {{{ _php_rfc822_write_address
4404 */
4405static char* _php_rfc822_write_address(ADDRESS *addresslist TSRMLS_DC)
4406{
4407    char address[SENDBUFLEN];
4408
4409    if (_php_imap_address_size(addresslist) >= SENDBUFLEN) {
4410        php_error_docref(NULL TSRMLS_CC, E_ERROR, "Address buffer overflow");
4411        return NULL;
4412    }
4413    address[0] = 0;
4414    rfc822_write_address(address, addresslist);
4415    return estrdup(address);
4416}
4417/* }}} */
4418#endif
4419/* {{{ _php_imap_parse_address
4420 */
4421static char* _php_imap_parse_address (ADDRESS *addresslist, zval *paddress TSRMLS_DC)
4422{
4423    char *fulladdress;
4424    ADDRESS *addresstmp;
4425    zval *tmpvals;
4426
4427    addresstmp = addresslist;
4428
4429    fulladdress = _php_rfc822_write_address(addresstmp TSRMLS_CC);
4430
4431    addresstmp = addresslist;
4432    do {
4433        MAKE_STD_ZVAL(tmpvals);
4434        object_init(tmpvals);
4435        if (addresstmp->personal) add_property_string(tmpvals, "personal", addresstmp->personal, 1);
4436        if (addresstmp->adl) add_property_string(tmpvals, "adl", addresstmp->adl, 1);
4437        if (addresstmp->mailbox) add_property_string(tmpvals, "mailbox", addresstmp->mailbox, 1);
4438        if (addresstmp->host) add_property_string(tmpvals, "host", addresstmp->host, 1);
4439        add_next_index_object(paddress, tmpvals TSRMLS_CC);
4440    } while ((addresstmp = addresstmp->next));
4441    return fulladdress;
4442}
4443/* }}} */
4444
4445/* {{{ _php_make_header_object
4446 */
4447static void _php_make_header_object(zval *myzvalue, ENVELOPE *en TSRMLS_DC)
4448{
4449    zval *paddress;
4450    char *fulladdress=NULL;
4451
4452    object_init(myzvalue);
4453
4454    if (en->remail) add_property_string(myzvalue, "remail", en->remail, 1);
4455    if (en->date) add_property_string(myzvalue, "date", en->date, 1);
4456    if (en->date) add_property_string(myzvalue, "Date", en->date, 1);
4457    if (en->subject) add_property_string(myzvalue, "subject", en->subject, 1);
4458    if (en->subject) add_property_string(myzvalue, "Subject", en->subject, 1);
4459    if (en->in_reply_to) add_property_string(myzvalue, "in_reply_to", en->in_reply_to, 1);
4460    if (en->message_id) add_property_string(myzvalue, "message_id", en->message_id, 1);
4461    if (en->newsgroups) add_property_string(myzvalue, "newsgroups", en->newsgroups, 1);
4462    if (en->followup_to) add_property_string(myzvalue, "followup_to", en->followup_to, 1);
4463    if (en->references) add_property_string(myzvalue, "references", en->references, 1);
4464
4465    if (en->to) {
4466        MAKE_STD_ZVAL(paddress);
4467        array_init(paddress);
4468        fulladdress = _php_imap_parse_address(en->to, paddress TSRMLS_CC);
4469        if (fulladdress) {
4470            add_property_string(myzvalue, "toaddress", fulladdress, 0);
4471        }
4472        add_assoc_object(myzvalue, "to", paddress TSRMLS_CC);
4473    }
4474
4475    if (en->from) {
4476        MAKE_STD_ZVAL(paddress);
4477        array_init(paddress);
4478        fulladdress = _php_imap_parse_address(en->from, paddress TSRMLS_CC);
4479        if (fulladdress) {
4480            add_property_string(myzvalue, "fromaddress", fulladdress, 0);
4481        }
4482        add_assoc_object(myzvalue, "from", paddress TSRMLS_CC);
4483    }
4484
4485    if (en->cc) {
4486        MAKE_STD_ZVAL(paddress);
4487        array_init(paddress);
4488        fulladdress = _php_imap_parse_address(en->cc, paddress TSRMLS_CC);
4489        if (fulladdress) {
4490            add_property_string(myzvalue, "ccaddress", fulladdress, 0);
4491        }
4492        add_assoc_object(myzvalue, "cc", paddress TSRMLS_CC);
4493    }
4494
4495    if (en->bcc) {
4496        MAKE_STD_ZVAL(paddress);
4497        array_init(paddress);
4498        fulladdress = _php_imap_parse_address(en->bcc, paddress TSRMLS_CC);
4499        if (fulladdress) {
4500            add_property_string(myzvalue, "bccaddress", fulladdress, 0);
4501        }
4502        add_assoc_object(myzvalue, "bcc", paddress TSRMLS_CC);
4503    }
4504
4505    if (en->reply_to) {
4506        MAKE_STD_ZVAL(paddress);
4507        array_init(paddress);
4508        fulladdress = _php_imap_parse_address(en->reply_to, paddress TSRMLS_CC);
4509        if (fulladdress) {
4510            add_property_string(myzvalue, "reply_toaddress", fulladdress, 0);
4511        }
4512        add_assoc_object(myzvalue, "reply_to", paddress TSRMLS_CC);
4513    }
4514
4515    if (en->sender) {
4516        MAKE_STD_ZVAL(paddress);
4517        array_init(paddress);
4518        fulladdress = _php_imap_parse_address(en->sender, paddress TSRMLS_CC);
4519        if (fulladdress) {
4520            add_property_string(myzvalue, "senderaddress", fulladdress, 0);
4521        }
4522        add_assoc_object(myzvalue, "sender", paddress TSRMLS_CC);
4523    }
4524
4525    if (en->return_path) {
4526        MAKE_STD_ZVAL(paddress);
4527        array_init(paddress);
4528        fulladdress = _php_imap_parse_address(en->return_path, paddress TSRMLS_CC);
4529        if (fulladdress) {
4530            add_property_string(myzvalue, "return_pathaddress", fulladdress, 0);
4531        }
4532        add_assoc_object(myzvalue, "return_path", paddress TSRMLS_CC);
4533    }
4534}
4535/* }}} */
4536
4537/* {{{ _php_imap_add_body
4538 */
4539void _php_imap_add_body(zval *arg, BODY *body TSRMLS_DC)
4540{
4541    zval *parametres, *param, *dparametres, *dparam;
4542    PARAMETER *par, *dpar;
4543    PART *part;
4544
4545    if (body->type <= TYPEMAX) {
4546        add_property_long(arg, "type", body->type);
4547    }
4548
4549    if (body->encoding <= ENCMAX) {
4550        add_property_long(arg, "encoding", body->encoding);
4551    }
4552
4553    if (body->subtype) {
4554        add_property_long(arg, "ifsubtype", 1);
4555        add_property_string(arg, "subtype", body->subtype, 1);
4556    } else {
4557        add_property_long(arg, "ifsubtype", 0);
4558    }
4559
4560    if (body->description) {
4561        add_property_long(arg, "ifdescription", 1);
4562        add_property_string(arg, "description", body->description, 1);
4563    } else {
4564        add_property_long(arg, "ifdescription", 0);
4565    }
4566
4567    if (body->id) {
4568        add_property_long(arg, "ifid", 1);
4569        add_property_string(arg, "id", body->id, 1);
4570    } else {
4571        add_property_long(arg, "ifid", 0);
4572    }
4573
4574    if (body->size.lines) {
4575        add_property_long(arg, "lines", body->size.lines);
4576    }
4577
4578    if (body->size.bytes) {
4579        add_property_long(arg, "bytes", body->size.bytes);
4580    }
4581
4582#ifdef IMAP41
4583    if (body->disposition.type) {
4584        add_property_long(arg, "ifdisposition", 1);
4585        add_property_string(arg, "disposition", body->disposition.type, 1);
4586    } else {
4587        add_property_long(arg, "ifdisposition", 0);
4588    }
4589
4590    if (body->disposition.parameter) {
4591        dpar = body->disposition.parameter;
4592        add_property_long(arg, "ifdparameters", 1);
4593        MAKE_STD_ZVAL(dparametres);
4594        array_init(dparametres);
4595        do {
4596            MAKE_STD_ZVAL(dparam);
4597            object_init(dparam);
4598            add_property_string(dparam, "attribute", dpar->attribute, 1);
4599            add_property_string(dparam, "value", dpar->value, 1);
4600            add_next_index_object(dparametres, dparam TSRMLS_CC);
4601        } while ((dpar = dpar->next));
4602        add_assoc_object(arg, "dparameters", dparametres TSRMLS_CC);
4603    } else {
4604        add_property_long(arg, "ifdparameters", 0);
4605    }
4606#endif
4607
4608    if ((par = body->parameter)) {
4609        add_property_long(arg, "ifparameters", 1);
4610
4611        MAKE_STD_ZVAL(parametres);
4612        array_init(parametres);
4613        do {
4614            MAKE_STD_ZVAL(param);
4615            object_init(param);
4616            if (par->attribute) {
4617                add_property_string(param, "attribute", par->attribute, 1);
4618            }
4619            if (par->value) {
4620                add_property_string(param, "value", par->value, 1);
4621            }
4622
4623            add_next_index_object(parametres, param TSRMLS_CC);
4624        } while ((par = par->next));
4625    } else {
4626        MAKE_STD_ZVAL(parametres);
4627        object_init(parametres);
4628        add_property_long(arg, "ifparameters", 0);
4629    }
4630    add_assoc_object(arg, "parameters", parametres TSRMLS_CC);
4631
4632    /* multipart message ? */
4633    if (body->type == TYPEMULTIPART) {
4634        MAKE_STD_ZVAL(parametres);
4635        array_init(parametres);
4636        for (part = body->CONTENT_PART; part; part = part->next) {
4637            MAKE_STD_ZVAL(param);
4638            object_init(param);
4639            _php_imap_add_body(param, &part->body TSRMLS_CC);
4640            add_next_index_object(parametres, param TSRMLS_CC);
4641        }
4642        add_assoc_object(arg, "parts", parametres TSRMLS_CC);
4643    }
4644
4645    /* encapsulated message ? */
4646    if ((body->type == TYPEMESSAGE) && (!strcasecmp(body->subtype, "rfc822"))) {
4647        body = body->CONTENT_MSG_BODY;
4648        MAKE_STD_ZVAL(parametres);
4649        array_init(parametres);
4650        MAKE_STD_ZVAL(param);
4651        object_init(param);
4652        _php_imap_add_body(param, body TSRMLS_CC);
4653        add_next_index_object(parametres, param TSRMLS_CC);
4654        add_assoc_object(arg, "parts", parametres TSRMLS_CC);
4655    }
4656}
4657/* }}} */
4658
4659/* imap_thread, stealing this from header cclient -rjs3 */
4660/* {{{ build_thread_tree_helper
4661 */
4662static void build_thread_tree_helper(THREADNODE *cur, zval *tree, long *numNodes, char *buf)
4663{
4664    unsigned long thisNode = *numNodes;
4665
4666    /* define "#.num" */
4667    snprintf(buf, 25, "%ld.num", thisNode);
4668
4669    add_assoc_long(tree, buf, cur->num);
4670
4671    snprintf(buf, 25, "%ld.next", thisNode);
4672    if(cur->next) {
4673        (*numNodes)++;
4674        add_assoc_long(tree, buf, *numNodes);
4675        build_thread_tree_helper(cur->next, tree, numNodes, buf);
4676    } else { /* "null pointer" */
4677        add_assoc_long(tree, buf, 0);
4678    }
4679
4680    snprintf(buf, 25, "%ld.branch", thisNode);
4681    if(cur->branch) {
4682        (*numNodes)++;
4683        add_assoc_long(tree, buf, *numNodes);
4684        build_thread_tree_helper(cur->branch, tree, numNodes, buf);
4685    } else { /* "null pointer" */
4686        add_assoc_long(tree, buf, 0);
4687    }
4688}
4689/* }}} */
4690
4691/* {{{ build_thread_tree
4692 */
4693static int build_thread_tree(THREADNODE *top, zval **tree)
4694{
4695    long numNodes = 0;
4696    char buf[25];
4697
4698    array_init(*tree);
4699
4700    build_thread_tree_helper(top, *tree, &numNodes, buf);
4701
4702    return SUCCESS;
4703}
4704/* }}} */
4705
4706/* {{{ proto array imap_thread(resource stream_id [, int options])
4707   Return threaded by REFERENCES tree */
4708PHP_FUNCTION(imap_thread)
4709{
4710    zval *streamind;
4711    pils *imap_le_struct;
4712    long flags = SE_FREE;
4713    char criteria[] = "ALL";
4714    THREADNODE *top;
4715    int argc = ZEND_NUM_ARGS();
4716    SEARCHPGM *pgm = NIL;
4717
4718    if (zend_parse_parameters(argc TSRMLS_CC, "r|l", &streamind, &flags) == FAILURE) {
4719        return;
4720    }
4721
4722    ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
4723
4724    pgm = mail_criteria(criteria);
4725    top = mail_thread(imap_le_struct->imap_stream, "REFERENCES", NIL, pgm, flags);
4726    if (pgm && !(flags & SE_FREE)) {
4727        mail_free_searchpgm(&pgm);
4728    }
4729
4730    if(top == NIL) {
4731        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Function returned an empty tree");
4732        RETURN_FALSE;
4733    }
4734
4735    /* Populate our return value data structure here. */
4736    if(build_thread_tree(top, &return_value) == FAILURE) {
4737        mail_free_threadnode(&top);
4738        RETURN_FALSE;
4739    }
4740    mail_free_threadnode(&top);
4741}
4742/* }}} */
4743
4744/* {{{ proto mixed imap_timeout(int timeout_type [, int timeout])
4745   Set or fetch imap timeout */
4746PHP_FUNCTION(imap_timeout)
4747{
4748    long ttype, timeout=-1;
4749    int timeout_type;
4750
4751    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l", &ttype, &timeout) == FAILURE) {
4752        RETURN_FALSE;
4753    }
4754
4755    if (timeout == -1) {
4756        switch (ttype) {
4757            case 1:
4758                timeout_type = GET_OPENTIMEOUT;
4759                break;
4760            case 2:
4761                timeout_type = GET_READTIMEOUT;
4762                break;
4763            case 3:
4764                timeout_type = GET_WRITETIMEOUT;
4765                break;
4766            case 4:
4767                timeout_type = GET_CLOSETIMEOUT;
4768                break;
4769            default:
4770                RETURN_FALSE;
4771                break;
4772        }
4773
4774        timeout = (long) mail_parameters(NIL, timeout_type, NIL);
4775        RETURN_LONG(timeout);
4776    } else if (timeout >= 0) {
4777        switch (ttype) {
4778            case 1:
4779                timeout_type = SET_OPENTIMEOUT;
4780                break;
4781            case 2:
4782                timeout_type = SET_READTIMEOUT;
4783                break;
4784            case 3:
4785                timeout_type = SET_WRITETIMEOUT;
4786                break;
4787            case 4:
4788                timeout_type = SET_CLOSETIMEOUT;
4789                break;
4790            default:
4791                RETURN_FALSE;
4792                break;
4793        }
4794
4795        timeout = (long) mail_parameters(NIL, timeout_type, (void *) timeout);
4796        RETURN_TRUE;
4797    } else {
4798        RETURN_FALSE;
4799    }
4800}
4801/* }}} */
4802
4803#define GETS_FETCH_SIZE 8196LU
4804static char *php_mail_gets(readfn_t f, void *stream, unsigned long size, GETS_DATA *md) /* {{{ */
4805{
4806    TSRMLS_FETCH();
4807
4808    /*  write to the gets stream if it is set,
4809        otherwise forward to c-clients gets */
4810    if (IMAPG(gets_stream)) {
4811        char buf[GETS_FETCH_SIZE];
4812
4813        while (size) {
4814            unsigned long read;
4815
4816            if (size > GETS_FETCH_SIZE) {
4817                read = GETS_FETCH_SIZE;
4818                size -=GETS_FETCH_SIZE;
4819            } else {
4820                read = size;
4821                size = 0;
4822            }
4823
4824            if (!f(stream, read, buf)) {
4825                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to read from socket");
4826                break;
4827            } else if (read != php_stream_write(IMAPG(gets_stream), buf, read)) {
4828                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to write to stream");
4829                break;
4830            }
4831        }
4832        return NULL;
4833    } else {
4834        char *buf = pemalloc(size + 1, 1);
4835
4836        if (f(stream, size, buf)) {
4837            buf[size] = '\0';
4838        } else {
4839            php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to read from socket");
4840            free(buf);
4841            buf = NULL;
4842        }
4843        return buf;
4844    }
4845}
4846/* }}} */
4847
4848/* {{{ Interfaces to C-client
4849 */
4850PHP_IMAP_EXPORT void mm_searched(MAILSTREAM *stream, unsigned long number)
4851{
4852    MESSAGELIST *cur = NIL;
4853    TSRMLS_FETCH();
4854
4855    if (IMAPG(imap_messages) == NIL) {
4856        IMAPG(imap_messages) = mail_newmessagelist();
4857        IMAPG(imap_messages)->msgid = number;
4858        IMAPG(imap_messages)->next = NIL;
4859        IMAPG(imap_messages_tail) = IMAPG(imap_messages);
4860    } else {
4861        cur = IMAPG(imap_messages_tail);
4862        cur->next = mail_newmessagelist();
4863        cur = cur->next;
4864        cur->msgid = number;
4865        cur->next = NIL;
4866        IMAPG(imap_messages_tail) = cur;
4867    }
4868}
4869
4870PHP_IMAP_EXPORT void mm_exists(MAILSTREAM *stream, unsigned long number)
4871{
4872}
4873
4874PHP_IMAP_EXPORT void mm_expunged(MAILSTREAM *stream, unsigned long number)
4875{
4876}
4877
4878PHP_IMAP_EXPORT void mm_flags(MAILSTREAM *stream, unsigned long number)
4879{
4880}
4881
4882/* Author: CJH */
4883PHP_IMAP_EXPORT void mm_notify(MAILSTREAM *stream, char *str, long errflg)
4884{
4885    STRINGLIST *cur = NIL;
4886    TSRMLS_FETCH();
4887
4888    if (strncmp(str, "[ALERT] ", 8) == 0) {
4889        if (IMAPG(imap_alertstack) == NIL) {
4890            IMAPG(imap_alertstack) = mail_newstringlist();
4891            IMAPG(imap_alertstack)->LSIZE = strlen(IMAPG(imap_alertstack)->LTEXT = cpystr(str));
4892            IMAPG(imap_alertstack)->next = NIL;
4893        } else {
4894            cur = IMAPG(imap_alertstack);
4895            while (cur->next != NIL) {
4896                cur = cur->next;
4897            }
4898            cur->next = mail_newstringlist ();
4899            cur = cur->next;
4900            cur->LSIZE = strlen(cur->LTEXT = cpystr(str));
4901            cur->next = NIL;
4902        }
4903    }
4904}
4905
4906PHP_IMAP_EXPORT void mm_list(MAILSTREAM *stream, DTYPE delimiter, char *mailbox, long attributes)
4907{
4908    STRINGLIST *cur=NIL;
4909    FOBJECTLIST *ocur=NIL;
4910    TSRMLS_FETCH();
4911
4912    if (IMAPG(folderlist_style) == FLIST_OBJECT) {
4913        /* build up a the new array of objects */
4914        /* Author: CJH */
4915        if (IMAPG(imap_folder_objects) == NIL) {
4916            IMAPG(imap_folder_objects) = mail_newfolderobjectlist();
4917            IMAPG(imap_folder_objects)->LSIZE=strlen(IMAPG(imap_folder_objects)->LTEXT=cpystr(mailbox));
4918            IMAPG(imap_folder_objects)->delimiter = delimiter;
4919            IMAPG(imap_folder_objects)->attributes = attributes;
4920            IMAPG(imap_folder_objects)->next = NIL;
4921            IMAPG(imap_folder_objects_tail) = IMAPG(imap_folder_objects);
4922        } else {
4923            ocur=IMAPG(imap_folder_objects_tail);
4924            ocur->next=mail_newfolderobjectlist();
4925            ocur=ocur->next;
4926            ocur->LSIZE = strlen(ocur->LTEXT = cpystr(mailbox));
4927            ocur->delimiter = delimiter;
4928            ocur->attributes = attributes;
4929            ocur->next = NIL;
4930            IMAPG(imap_folder_objects_tail) = ocur;
4931        }
4932
4933    } else {
4934        /* build the old IMAPG(imap_folders) variable to allow old imap_listmailbox() to work */
4935        if (!(attributes & LATT_NOSELECT)) {
4936            if (IMAPG(imap_folders) == NIL) {
4937                IMAPG(imap_folders)=mail_newstringlist();
4938                IMAPG(imap_folders)->LSIZE=strlen(IMAPG(imap_folders)->LTEXT=cpystr(mailbox));
4939                IMAPG(imap_folders)->next=NIL;
4940                IMAPG(imap_folders_tail) = IMAPG(imap_folders);
4941            } else {
4942                cur=IMAPG(imap_folders_tail);
4943                cur->next=mail_newstringlist ();
4944                cur=cur->next;
4945                cur->LSIZE = strlen (cur->LTEXT = cpystr (mailbox));
4946                cur->next = NIL;
4947                IMAPG(imap_folders_tail) = cur;
4948            }
4949        }
4950    }
4951}
4952
4953PHP_IMAP_EXPORT void mm_lsub(MAILSTREAM *stream, DTYPE delimiter, char *mailbox, long attributes)
4954{
4955    STRINGLIST *cur=NIL;
4956    FOBJECTLIST *ocur=NIL;
4957    TSRMLS_FETCH();
4958
4959    if (IMAPG(folderlist_style) == FLIST_OBJECT) {
4960        /* build the array of objects */
4961        /* Author: CJH */
4962        if (IMAPG(imap_sfolder_objects) == NIL) {
4963            IMAPG(imap_sfolder_objects) = mail_newfolderobjectlist();
4964            IMAPG(imap_sfolder_objects)->LSIZE=strlen(IMAPG(imap_sfolder_objects)->LTEXT=cpystr(mailbox));
4965            IMAPG(imap_sfolder_objects)->delimiter = delimiter;
4966            IMAPG(imap_sfolder_objects)->attributes = attributes;
4967            IMAPG(imap_sfolder_objects)->next = NIL;
4968            IMAPG(imap_sfolder_objects_tail) = IMAPG(imap_sfolder_objects);
4969        } else {
4970            ocur=IMAPG(imap_sfolder_objects_tail);
4971            ocur->next=mail_newfolderobjectlist();
4972            ocur=ocur->next;
4973            ocur->LSIZE=strlen(ocur->LTEXT = cpystr(mailbox));
4974            ocur->delimiter = delimiter;
4975            ocur->attributes = attributes;
4976            ocur->next = NIL;
4977            IMAPG(imap_sfolder_objects_tail) = ocur;
4978        }
4979    } else {
4980        /* build the old simple array for imap_listsubscribed() */
4981        if (IMAPG(imap_sfolders) == NIL) {
4982            IMAPG(imap_sfolders)=mail_newstringlist();
4983            IMAPG(imap_sfolders)->LSIZE=strlen(IMAPG(imap_sfolders)->LTEXT=cpystr(mailbox));
4984            IMAPG(imap_sfolders)->next=NIL;
4985            IMAPG(imap_sfolders_tail) = IMAPG(imap_sfolders);
4986        } else {
4987            cur=IMAPG(imap_sfolders_tail);
4988            cur->next=mail_newstringlist ();
4989            cur=cur->next;
4990            cur->LSIZE = strlen (cur->LTEXT = cpystr (mailbox));
4991            cur->next = NIL;
4992            IMAPG(imap_sfolders_tail) = cur;
4993        }
4994    }
4995}
4996
4997PHP_IMAP_EXPORT void mm_status(MAILSTREAM *stream, char *mailbox, MAILSTATUS *status)
4998{
4999    TSRMLS_FETCH();
5000
5001    IMAPG(status_flags)=status->flags;
5002    if (IMAPG(status_flags) & SA_MESSAGES) {
5003        IMAPG(status_messages)=status->messages;
5004    }
5005    if (IMAPG(status_flags) & SA_RECENT) {
5006        IMAPG(status_recent)=status->recent;
5007    }
5008    if (IMAPG(status_flags) & SA_UNSEEN) {
5009        IMAPG(status_unseen)=status->unseen;
5010    }
5011    if (IMAPG(status_flags) & SA_UIDNEXT) {
5012        IMAPG(status_uidnext)=status->uidnext;
5013    }
5014    if (IMAPG(status_flags) & SA_UIDVALIDITY) {
5015        IMAPG(status_uidvalidity)=status->uidvalidity;
5016    }
5017}
5018
5019PHP_IMAP_EXPORT void mm_log(char *str, long errflg)
5020{
5021    ERRORLIST *cur = NIL;
5022    TSRMLS_FETCH();
5023
5024    /* Author: CJH */
5025    if (errflg != NIL) { /* CJH: maybe put these into a more comprehensive log for debugging purposes? */
5026        if (IMAPG(imap_errorstack) == NIL) {
5027            IMAPG(imap_errorstack) = mail_newerrorlist();
5028            IMAPG(imap_errorstack)->LSIZE = strlen(IMAPG(imap_errorstack)->LTEXT = cpystr(str));
5029            IMAPG(imap_errorstack)->errflg = errflg;
5030            IMAPG(imap_errorstack)->next = NIL;
5031        } else {
5032            cur = IMAPG(imap_errorstack);
5033            while (cur->next != NIL) {
5034                cur = cur->next;
5035            }
5036            cur->next = mail_newerrorlist();
5037            cur = cur->next;
5038            cur->LSIZE = strlen(cur->LTEXT = cpystr(str));
5039            cur->errflg = errflg;
5040            cur->next = NIL;
5041        }
5042    }
5043}
5044
5045PHP_IMAP_EXPORT void mm_dlog(char *str)
5046{
5047    /* CJH: this is for debugging; it might be useful to allow setting
5048       the stream to debug mode and capturing this somewhere - syslog?
5049       php debugger? */
5050}
5051
5052PHP_IMAP_EXPORT void mm_login(NETMBX *mb, char *user, char *pwd, long trial)
5053{
5054    TSRMLS_FETCH();
5055
5056    if (*mb->user) {
5057        strlcpy (user, mb->user, MAILTMPLEN);
5058    } else {
5059        strlcpy (user, IMAPG(imap_user), MAILTMPLEN);
5060    }
5061    strlcpy (pwd, IMAPG(imap_password), MAILTMPLEN);
5062}
5063
5064PHP_IMAP_EXPORT void mm_critical(MAILSTREAM *stream)
5065{
5066}
5067
5068PHP_IMAP_EXPORT void mm_nocritical(MAILSTREAM *stream)
5069{
5070}
5071
5072PHP_IMAP_EXPORT long mm_diskerror(MAILSTREAM *stream, long errcode, long serious)
5073{
5074    return 1;
5075}
5076
5077PHP_IMAP_EXPORT void mm_fatal(char *str)
5078{
5079}
5080/* }}} */
5081
5082/*
5083 * Local variables:
5084 * tab-width: 4
5085 * c-basic-offset: 4
5086 * End:
5087 * vim600: sw=4 ts=4 fdm=marker
5088 * vim<600: sw=4 ts=4
5089 */
5090