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