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