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