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