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

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