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