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