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