root/ext/imap/php_imap.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mail_close_it
  2. add_assoc_object
  3. add_next_index_object
  4. mail_newfolderobjectlist
  5. mail_free_foblist
  6. mail_newerrorlist
  7. mail_free_errorlist
  8. mail_newmessagelist
  9. mail_free_messagelist
  10. mail_getquota
  11. mail_getacl
  12. PHP_GINIT_FUNCTION
  13. PHP_MINIT_FUNCTION
  14. PHP_RINIT_FUNCTION
  15. PHP_RSHUTDOWN_FUNCTION
  16. PHP_MINFO_FUNCTION
  17. php_imap_do_open
  18. PHP_FUNCTION
  19. PHP_FUNCTION
  20. PHP_FUNCTION
  21. PHP_FUNCTION
  22. PHP_FUNCTION
  23. PHP_FUNCTION
  24. PHP_FUNCTION
  25. PHP_FUNCTION
  26. PHP_FUNCTION
  27. PHP_FUNCTION
  28. PHP_FUNCTION
  29. PHP_FUNCTION
  30. PHP_FUNCTION
  31. PHP_FUNCTION
  32. PHP_FUNCTION
  33. PHP_FUNCTION
  34. PHP_FUNCTION
  35. PHP_FUNCTION
  36. PHP_FUNCTION
  37. PHP_FUNCTION
  38. PHP_FUNCTION
  39. PHP_FUNCTION
  40. PHP_FUNCTION
  41. PHP_FUNCTION
  42. PHP_FUNCTION
  43. PHP_FUNCTION
  44. PHP_FUNCTION
  45. PHP_FUNCTION
  46. PHP_FUNCTION
  47. PHP_FUNCTION
  48. PHP_FUNCTION
  49. PHP_FUNCTION
  50. PHP_FUNCTION
  51. PHP_FUNCTION
  52. PHP_FUNCTION
  53. PHP_FUNCTION
  54. PHP_FUNCTION
  55. PHP_FUNCTION
  56. PHP_FUNCTION
  57. PHP_FUNCTION
  58. PHP_FUNCTION
  59. PHP_FUNCTION
  60. PHP_FUNCTION
  61. PHP_FUNCTION
  62. PHP_FUNCTION
  63. PHP_FUNCTION
  64. PHP_FUNCTION
  65. php_imap_mutf7
  66. PHP_FUNCTION
  67. PHP_FUNCTION
  68. PHP_FUNCTION
  69. PHP_FUNCTION
  70. PHP_FUNCTION
  71. PHP_FUNCTION
  72. PHP_FUNCTION
  73. PHP_FUNCTION
  74. PHP_FUNCTION
  75. PHP_FUNCTION
  76. PHP_FUNCTION
  77. PHP_FUNCTION
  78. _php_imap_mail
  79. PHP_FUNCTION
  80. PHP_FUNCTION
  81. PHP_FUNCTION
  82. PHP_FUNCTION
  83. PHP_FUNCTION
  84. PHP_FUNCTION
  85. _php_rfc822_soutr
  86. _php_rfc822_write_address
  87. _php_rfc822_len
  88. _php_imap_address_size
  89. _php_rfc822_write_address
  90. _php_imap_parse_address
  91. _php_make_header_object
  92. _php_imap_add_body
  93. build_thread_tree_helper
  94. build_thread_tree
  95. PHP_FUNCTION
  96. PHP_FUNCTION
  97. php_mail_gets
  98. mm_searched
  99. mm_exists
  100. mm_expunged
  101. mm_flags
  102. mm_notify
  103. mm_list
  104. mm_lsub
  105. mm_status
  106. mm_log
  107. mm_dlog
  108. mm_login
  109. mm_critical
  110. mm_nocritical
  111. mm_diskerror
  112. mm_fatal

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

/* [<][>][^][v][top][bottom][index][help] */