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