Back to index

php5  5.3.10
php_imap.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | PHP Version 5                                                        |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1997-2012 The PHP Group                                |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 3.01 of the PHP license,      |
00008    | that is bundled with this package in the file LICENSE, and is        |
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.php.net/license/3_01.txt                                  |
00011    | If you did not receive a copy of the PHP license and are unable to   |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@php.net so we can mail you a copy immediately.               |
00014    +----------------------------------------------------------------------+
00015    | Authors: Rex Logan           <veebert@dimensional.com>               |
00016    |          Mark Musone         <musone@afterfive.com>                  |
00017    |          Brian Wang          <brian@vividnet.com>                    |
00018    |          Kaj-Michael Lang    <milang@tal.org>                        |
00019    |          Antoni Pamies Olive <toni@readysoft.net>                    |
00020    |          Rasmus Lerdorf      <rasmus@php.net>                        |
00021    |          Chuck Hagenbuch     <chuck@horde.org>                       |
00022    |          Andrew Skalski      <askalski@chekinc.com>                  |
00023    |          Hartmut Holzgraefe  <hholzgra@php.net>                      |
00024    |          Jani Taskinen       <jani.taskinen@iki.fi>                  |
00025    |          Daniel R. Kalowsky  <kalowsky@php.net>                      |
00026    | PHP 4.0 updates:  Zeev Suraski <zeev@zend.com>                       |
00027    +----------------------------------------------------------------------+
00028  */
00029 /* $Id: php_imap.c 321634 2012-01-01 13:15:04Z felipe $ */
00030 
00031 #define IMAP41
00032 
00033 #ifdef HAVE_CONFIG_H
00034 #include "config.h"
00035 #endif
00036 
00037 #include "php.h"
00038 #include "php_ini.h"
00039 #include "php_streams.h"
00040 #include "ext/standard/php_string.h"
00041 #include "ext/standard/info.h"
00042 #include "ext/standard/file.h"
00043 #include "ext/standard/php_smart_str.h"
00044 #include "ext/pcre/php_pcre.h"
00045 
00046 #ifdef ERROR
00047 #undef ERROR
00048 #endif
00049 #include "php_imap.h"
00050 
00051 #include <time.h>
00052 #include <stdio.h>
00053 #include <ctype.h>
00054 #include <signal.h>
00055 
00056 #ifdef PHP_WIN32
00057 #include <winsock2.h>
00058 #include <stdlib.h>
00059 #include "win32/sendmail.h"
00060 MAILSTREAM DEFAULTPROTO;
00061 #endif
00062 
00063 #define CRLF  "\015\012"
00064 #define CRLF_LEN sizeof("\015\012") - 1
00065 #define PHP_EXPUNGE 32768
00066 #define PHP_IMAP_ADDRESS_SIZE_BUF 10
00067 #ifndef SENDBUFLEN
00068 #define SENDBUFLEN 16385
00069 #endif
00070 
00071 #if defined(__GNUC__) && __GNUC__ >= 4
00072 # define PHP_IMAP_EXPORT __attribute__ ((visibility("default")))
00073 #else
00074 # define PHP_IMAP_EXPORT
00075 #endif
00076 
00077 static void _php_make_header_object(zval *myzvalue, ENVELOPE *en TSRMLS_DC);
00078 static void _php_imap_add_body(zval *arg, BODY *body TSRMLS_DC);
00079 static char* _php_imap_parse_address(ADDRESS *addresslist, zval *paddress TSRMLS_DC);
00080 static char* _php_rfc822_write_address(ADDRESS *addresslist TSRMLS_DC);
00081 
00082 /* the gets we use */
00083 static char *php_mail_gets(readfn_t f, void *stream, unsigned long size, GETS_DATA *md);
00084 
00085 /* These function declarations are missing from the IMAP header files... */
00086 void rfc822_date(char *date);
00087 char *cpystr(const char *str);
00088 char *cpytxt(SIZEDTEXT *dst, char *text, unsigned long size);
00089 #ifndef HAVE_NEW_MIME2TEXT
00090 long utf8_mime2text(SIZEDTEXT *src, SIZEDTEXT *dst);
00091 #else
00092 long utf8_mime2text (SIZEDTEXT *src, SIZEDTEXT *dst, long flags);
00093 #endif
00094 unsigned long find_rightmost_bit(unsigned long *valptr);
00095 void fs_give(void **block);
00096 void *fs_get(size_t size);
00097 
00098 ZEND_DECLARE_MODULE_GLOBALS(imap)
00099 static PHP_GINIT_FUNCTION(imap);
00100 
00101 /* {{{ arginfo */
00102 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_open, 0, 0, 3)
00103        ZEND_ARG_INFO(0, mailbox)
00104        ZEND_ARG_INFO(0, user)
00105        ZEND_ARG_INFO(0, password)
00106        ZEND_ARG_INFO(0, options)
00107        ZEND_ARG_INFO(0, n_retries)
00108        ZEND_ARG_INFO(0, params)
00109 ZEND_END_ARG_INFO()
00110 
00111 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_reopen, 0, 0, 2)
00112        ZEND_ARG_INFO(0, stream_id)
00113        ZEND_ARG_INFO(0, mailbox)
00114        ZEND_ARG_INFO(0, options)
00115        ZEND_ARG_INFO(0, n_retries)
00116 ZEND_END_ARG_INFO()
00117 
00118 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_append, 0, 0, 3)
00119        ZEND_ARG_INFO(0, stream_id)
00120        ZEND_ARG_INFO(0, folder)
00121        ZEND_ARG_INFO(0, message)
00122        ZEND_ARG_INFO(0, options)
00123        ZEND_ARG_INFO(0, date)
00124 ZEND_END_ARG_INFO()
00125 
00126 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_num_msg, 0, 0, 1)
00127        ZEND_ARG_INFO(0, stream_id)
00128 ZEND_END_ARG_INFO()
00129 
00130 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_ping, 0, 0, 1)
00131        ZEND_ARG_INFO(0, stream_id)
00132 ZEND_END_ARG_INFO()
00133 
00134 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_num_recent, 0, 0, 1)
00135        ZEND_ARG_INFO(0, stream_id)
00136 ZEND_END_ARG_INFO()
00137 
00138 #if defined(HAVE_IMAP2000) || defined(HAVE_IMAP2001)
00139 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_get_quota, 0, 0, 2)
00140        ZEND_ARG_INFO(0, stream_id)
00141        ZEND_ARG_INFO(0, qroot)
00142 ZEND_END_ARG_INFO()
00143 
00144 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_get_quotaroot, 0, 0, 2)
00145        ZEND_ARG_INFO(0, stream_id)
00146        ZEND_ARG_INFO(0, mbox)
00147 ZEND_END_ARG_INFO()
00148 
00149 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_set_quota, 0, 0, 3)
00150        ZEND_ARG_INFO(0, stream_id)
00151        ZEND_ARG_INFO(0, qroot)
00152        ZEND_ARG_INFO(0, mailbox_size)
00153 ZEND_END_ARG_INFO()
00154 
00155 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_setacl, 0, 0, 4)
00156        ZEND_ARG_INFO(0, stream_id)
00157        ZEND_ARG_INFO(0, mailbox)
00158        ZEND_ARG_INFO(0, id)
00159        ZEND_ARG_INFO(0, rights)
00160 ZEND_END_ARG_INFO()
00161 
00162 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_getacl, 0, 0, 2)
00163        ZEND_ARG_INFO(0, stream_id)
00164        ZEND_ARG_INFO(0, mailbox)
00165 ZEND_END_ARG_INFO()
00166 #endif
00167 
00168 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_expunge, 0, 0, 1)
00169        ZEND_ARG_INFO(0, stream_id)
00170 ZEND_END_ARG_INFO()
00171 
00172 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_gc, 0, 0, 1)
00173        ZEND_ARG_INFO(0, stream_id)
00174        ZEND_ARG_INFO(0, flags)
00175 ZEND_END_ARG_INFO()
00176 
00177 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_close, 0, 0, 1)
00178        ZEND_ARG_INFO(0, stream_id)
00179        ZEND_ARG_INFO(0, options)
00180 ZEND_END_ARG_INFO()
00181 
00182 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_headers, 0, 0, 1)
00183        ZEND_ARG_INFO(0, stream_id)
00184 ZEND_END_ARG_INFO()
00185 
00186 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_body, 0, 0, 2)
00187        ZEND_ARG_INFO(0, stream_id)
00188        ZEND_ARG_INFO(0, msg_no)
00189        ZEND_ARG_INFO(0, options)
00190 ZEND_END_ARG_INFO()
00191 
00192 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_mail_copy, 0, 0, 3)
00193        ZEND_ARG_INFO(0, stream_id)
00194        ZEND_ARG_INFO(0, msglist)
00195        ZEND_ARG_INFO(0, mailbox)
00196        ZEND_ARG_INFO(0, options)
00197 ZEND_END_ARG_INFO()
00198 
00199 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_mail_move, 0, 0, 3)
00200        ZEND_ARG_INFO(0, stream_id)
00201        ZEND_ARG_INFO(0, sequence)
00202        ZEND_ARG_INFO(0, mailbox)
00203        ZEND_ARG_INFO(0, options)
00204 ZEND_END_ARG_INFO()
00205 
00206 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_createmailbox, 0, 0, 2)
00207        ZEND_ARG_INFO(0, stream_id)
00208        ZEND_ARG_INFO(0, mailbox)
00209 ZEND_END_ARG_INFO()
00210 
00211 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_renamemailbox, 0, 0, 3)
00212        ZEND_ARG_INFO(0, stream_id)
00213        ZEND_ARG_INFO(0, old_name)
00214        ZEND_ARG_INFO(0, new_name)
00215 ZEND_END_ARG_INFO()
00216 
00217 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_deletemailbox, 0, 0, 2)
00218        ZEND_ARG_INFO(0, stream_id)
00219        ZEND_ARG_INFO(0, mailbox)
00220 ZEND_END_ARG_INFO()
00221 
00222 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_list, 0, 0, 3)
00223        ZEND_ARG_INFO(0, stream_id)
00224        ZEND_ARG_INFO(0, ref)
00225        ZEND_ARG_INFO(0, pattern)
00226 ZEND_END_ARG_INFO()
00227 
00228 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_getmailboxes, 0, 0, 3)
00229        ZEND_ARG_INFO(0, stream_id)
00230        ZEND_ARG_INFO(0, ref)
00231        ZEND_ARG_INFO(0, pattern)
00232 ZEND_END_ARG_INFO()
00233 
00234 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_listscan, 0, 0, 4)
00235        ZEND_ARG_INFO(0, stream_id)
00236        ZEND_ARG_INFO(0, ref)
00237        ZEND_ARG_INFO(0, pattern)
00238        ZEND_ARG_INFO(0, content)
00239 ZEND_END_ARG_INFO()
00240 
00241 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_check, 0, 0, 1)
00242        ZEND_ARG_INFO(0, stream_id)
00243 ZEND_END_ARG_INFO()
00244 
00245 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_delete, 0, 0, 2)
00246        ZEND_ARG_INFO(0, stream_id)
00247        ZEND_ARG_INFO(0, msg_no)
00248        ZEND_ARG_INFO(0, options)
00249 ZEND_END_ARG_INFO()
00250 
00251 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_undelete, 0, 0, 2)
00252        ZEND_ARG_INFO(0, stream_id)
00253        ZEND_ARG_INFO(0, msg_no)
00254        ZEND_ARG_INFO(0, flags)
00255 ZEND_END_ARG_INFO()
00256 
00257 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_headerinfo, 0, 0, 2)
00258        ZEND_ARG_INFO(0, stream_id)
00259        ZEND_ARG_INFO(0, msg_no)
00260        ZEND_ARG_INFO(0, from_length)
00261        ZEND_ARG_INFO(0, subject_length)
00262        ZEND_ARG_INFO(0, default_host)
00263 ZEND_END_ARG_INFO()
00264 
00265 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_rfc822_parse_headers, 0, 0, 1)
00266        ZEND_ARG_INFO(0, headers)
00267        ZEND_ARG_INFO(0, default_host)
00268 ZEND_END_ARG_INFO()
00269 
00270 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_lsub, 0, 0, 3)
00271        ZEND_ARG_INFO(0, stream_id)
00272        ZEND_ARG_INFO(0, ref)
00273        ZEND_ARG_INFO(0, pattern)
00274 ZEND_END_ARG_INFO()
00275 
00276 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_getsubscribed, 0, 0, 3)
00277        ZEND_ARG_INFO(0, stream_id)
00278        ZEND_ARG_INFO(0, ref)
00279        ZEND_ARG_INFO(0, pattern)
00280 ZEND_END_ARG_INFO()
00281 
00282 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_subscribe, 0, 0, 2)
00283        ZEND_ARG_INFO(0, stream_id)
00284        ZEND_ARG_INFO(0, mailbox)
00285 ZEND_END_ARG_INFO()
00286 
00287 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_unsubscribe, 0, 0, 2)
00288        ZEND_ARG_INFO(0, stream_id)
00289        ZEND_ARG_INFO(0, mailbox)
00290 ZEND_END_ARG_INFO()
00291 
00292 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_fetchstructure, 0, 0, 2)
00293        ZEND_ARG_INFO(0, stream_id)
00294        ZEND_ARG_INFO(0, msg_no)
00295        ZEND_ARG_INFO(0, options)
00296 ZEND_END_ARG_INFO()
00297 
00298 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_fetchbody, 0, 0, 3)
00299        ZEND_ARG_INFO(0, stream_id)
00300        ZEND_ARG_INFO(0, msg_no)
00301        ZEND_ARG_INFO(0, section)
00302        ZEND_ARG_INFO(0, options)
00303 ZEND_END_ARG_INFO()
00304 
00305 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_savebody, 0, 0, 3)
00306        ZEND_ARG_INFO(0, stream_id)
00307        ZEND_ARG_INFO(0, file)
00308        ZEND_ARG_INFO(0, msg_no)
00309        ZEND_ARG_INFO(0, section)
00310        ZEND_ARG_INFO(0, options)
00311 ZEND_END_ARG_INFO()
00312 
00313 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_base64, 0, 0, 1)
00314        ZEND_ARG_INFO(0, text)
00315 ZEND_END_ARG_INFO()
00316 
00317 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_qprint, 0, 0, 1)
00318        ZEND_ARG_INFO(0, text)
00319 ZEND_END_ARG_INFO()
00320 
00321 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_8bit, 0, 0, 1)
00322        ZEND_ARG_INFO(0, text)
00323 ZEND_END_ARG_INFO()
00324 
00325 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_binary, 0, 0, 1)
00326        ZEND_ARG_INFO(0, text)
00327 ZEND_END_ARG_INFO()
00328 
00329 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_mailboxmsginfo, 0, 0, 1)
00330        ZEND_ARG_INFO(0, stream_id)
00331 ZEND_END_ARG_INFO()
00332 
00333 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_rfc822_write_address, 0, 0, 3)
00334        ZEND_ARG_INFO(0, mailbox)
00335        ZEND_ARG_INFO(0, host)
00336        ZEND_ARG_INFO(0, personal)
00337 ZEND_END_ARG_INFO()
00338 
00339 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_rfc822_parse_adrlist, 0, 0, 2)
00340        ZEND_ARG_INFO(0, address_string)
00341        ZEND_ARG_INFO(0, default_host)
00342 ZEND_END_ARG_INFO()
00343 
00344 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_utf8, 0, 0, 1)
00345        ZEND_ARG_INFO(0, mime_encoded_text)
00346 ZEND_END_ARG_INFO()
00347 
00348 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_utf7_decode, 0, 0, 1)
00349        ZEND_ARG_INFO(0, buf)
00350 ZEND_END_ARG_INFO()
00351 
00352 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_utf7_encode, 0, 0, 1)
00353        ZEND_ARG_INFO(0, buf)
00354 ZEND_END_ARG_INFO()
00355 
00356 #ifdef HAVE_IMAP_MUTF7
00357 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_utf8_to_mutf7, 0, 0, 1)
00358        ZEND_ARG_INFO(0, in)
00359 ZEND_END_ARG_INFO()
00360 
00361 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_mutf7_to_utf8, 0, 0, 1)
00362        ZEND_ARG_INFO(0, in)
00363 ZEND_END_ARG_INFO()
00364 #endif
00365 
00366 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_setflag_full, 0, 0, 3)
00367        ZEND_ARG_INFO(0, stream_id)
00368        ZEND_ARG_INFO(0, sequence)
00369        ZEND_ARG_INFO(0, flag)
00370        ZEND_ARG_INFO(0, options)
00371 ZEND_END_ARG_INFO()
00372 
00373 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_clearflag_full, 0, 0, 3)
00374        ZEND_ARG_INFO(0, stream_id)
00375        ZEND_ARG_INFO(0, sequence)
00376        ZEND_ARG_INFO(0, flag)
00377        ZEND_ARG_INFO(0, options)
00378 ZEND_END_ARG_INFO()
00379 
00380 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_sort, 0, 0, 3)
00381        ZEND_ARG_INFO(0, stream_id)
00382        ZEND_ARG_INFO(0, criteria)
00383        ZEND_ARG_INFO(0, reverse)
00384        ZEND_ARG_INFO(0, options)
00385        ZEND_ARG_INFO(0, search_criteria)
00386        ZEND_ARG_INFO(0, charset)
00387 ZEND_END_ARG_INFO()
00388 
00389 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_fetchheader, 0, 0, 2)
00390        ZEND_ARG_INFO(0, stream_id)
00391        ZEND_ARG_INFO(0, msg_no)
00392        ZEND_ARG_INFO(0, options)
00393 ZEND_END_ARG_INFO()
00394 
00395 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_uid, 0, 0, 2)
00396        ZEND_ARG_INFO(0, stream_id)
00397        ZEND_ARG_INFO(0, msg_no)
00398 ZEND_END_ARG_INFO()
00399 
00400 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_msgno, 0, 0, 2)
00401        ZEND_ARG_INFO(0, stream_id)
00402        ZEND_ARG_INFO(0, unique_msg_id)
00403 ZEND_END_ARG_INFO()
00404 
00405 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_status, 0, 0, 3)
00406        ZEND_ARG_INFO(0, stream_id)
00407        ZEND_ARG_INFO(0, mailbox)
00408        ZEND_ARG_INFO(0, options)
00409 ZEND_END_ARG_INFO()
00410 
00411 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_bodystruct, 0, 0, 3)
00412        ZEND_ARG_INFO(0, stream_id)
00413        ZEND_ARG_INFO(0, msg_no)
00414        ZEND_ARG_INFO(0, section)
00415 ZEND_END_ARG_INFO()
00416 
00417 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_fetch_overview, 0, 0, 2)
00418        ZEND_ARG_INFO(0, stream_id)
00419        ZEND_ARG_INFO(0, sequence)
00420        ZEND_ARG_INFO(0, options)
00421 ZEND_END_ARG_INFO()
00422 
00423 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_mail_compose, 0, 0, 2)
00424        ZEND_ARG_INFO(0, envelope)
00425        ZEND_ARG_INFO(0, body)
00426 ZEND_END_ARG_INFO()
00427 
00428 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_mail, 0, 0, 3)
00429        ZEND_ARG_INFO(0, to)
00430        ZEND_ARG_INFO(0, subject)
00431        ZEND_ARG_INFO(0, message)
00432        ZEND_ARG_INFO(0, additional_headers)
00433        ZEND_ARG_INFO(0, cc)
00434        ZEND_ARG_INFO(0, bcc)
00435        ZEND_ARG_INFO(0, rpath)
00436 ZEND_END_ARG_INFO()
00437 
00438 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_search, 0, 0, 2)
00439        ZEND_ARG_INFO(0, stream_id)
00440        ZEND_ARG_INFO(0, criteria)
00441        ZEND_ARG_INFO(0, options)
00442        ZEND_ARG_INFO(0, charset)
00443 ZEND_END_ARG_INFO()
00444 
00445 ZEND_BEGIN_ARG_INFO(arginfo_imap_alerts, 0)
00446 ZEND_END_ARG_INFO()
00447 
00448 ZEND_BEGIN_ARG_INFO(arginfo_imap_errors, 0)
00449 ZEND_END_ARG_INFO()
00450 
00451 ZEND_BEGIN_ARG_INFO(arginfo_imap_last_error, 0)
00452 ZEND_END_ARG_INFO()
00453 
00454 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_mime_header_decode, 0, 0, 1)
00455        ZEND_ARG_INFO(0, str)
00456 ZEND_END_ARG_INFO()
00457 
00458 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_thread, 0, 0, 1)
00459        ZEND_ARG_INFO(0, stream_id)
00460        ZEND_ARG_INFO(0, options)
00461 ZEND_END_ARG_INFO()
00462 
00463 ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_timeout, 0, 0, 1)
00464        ZEND_ARG_INFO(0, timeout_type)
00465        ZEND_ARG_INFO(0, timeout)
00466 ZEND_END_ARG_INFO()
00467 /* }}} */
00468 
00469 /* {{{ imap_functions[]
00470  */
00471 const zend_function_entry imap_functions[] = {
00472        PHP_FE(imap_open,                                                     arginfo_imap_open)
00473        PHP_FE(imap_reopen,                                                   arginfo_imap_reopen)
00474        PHP_FE(imap_close,                                                    arginfo_imap_close)
00475        PHP_FE(imap_num_msg,                                           arginfo_imap_num_msg)
00476        PHP_FE(imap_num_recent,                                               arginfo_imap_num_recent)
00477        PHP_FE(imap_headers,                                           arginfo_imap_headers)
00478        PHP_FE(imap_headerinfo,                                               arginfo_imap_headerinfo)
00479        PHP_FE(imap_rfc822_parse_headers,                       arginfo_imap_rfc822_parse_headers)
00480        PHP_FE(imap_rfc822_write_address,                       arginfo_imap_rfc822_write_address)
00481        PHP_FE(imap_rfc822_parse_adrlist,                       arginfo_imap_rfc822_parse_adrlist)
00482        PHP_FE(imap_body,                                                     arginfo_imap_body)
00483        PHP_FE(imap_bodystruct,                                               arginfo_imap_bodystruct)
00484        PHP_FE(imap_fetchbody,                                                arginfo_imap_fetchbody)
00485        PHP_FE(imap_fetchmime,                                                arginfo_imap_fetchbody)
00486        PHP_FE(imap_savebody,                                                 arginfo_imap_savebody)
00487        PHP_FE(imap_fetchheader,                                       arginfo_imap_fetchheader)
00488        PHP_FE(imap_fetchstructure,                                    arginfo_imap_fetchstructure)
00489        PHP_FE(imap_gc,                                                                     arginfo_imap_gc)
00490        PHP_FE(imap_expunge,                                           arginfo_imap_expunge)
00491        PHP_FE(imap_delete,                                                   arginfo_imap_delete)
00492        PHP_FE(imap_undelete,                                                 arginfo_imap_undelete)
00493        PHP_FE(imap_check,                                                    arginfo_imap_check)
00494        PHP_FE(imap_listscan,                                                 arginfo_imap_listscan)
00495        PHP_FE(imap_mail_copy,                                                arginfo_imap_mail_copy)
00496        PHP_FE(imap_mail_move,                                                arginfo_imap_mail_move)
00497        PHP_FE(imap_mail_compose,                                      arginfo_imap_mail_compose)
00498        PHP_FE(imap_createmailbox,                                     arginfo_imap_createmailbox)
00499        PHP_FE(imap_renamemailbox,                                     arginfo_imap_renamemailbox)
00500        PHP_FE(imap_deletemailbox,                                     arginfo_imap_deletemailbox)
00501        PHP_FE(imap_subscribe,                                                arginfo_imap_subscribe)
00502        PHP_FE(imap_unsubscribe,                                       arginfo_imap_unsubscribe)
00503        PHP_FE(imap_append,                                                   arginfo_imap_append)
00504        PHP_FE(imap_ping,                                                     arginfo_imap_ping)
00505        PHP_FE(imap_base64,                                                   arginfo_imap_base64)
00506        PHP_FE(imap_qprint,                                                   arginfo_imap_qprint)
00507        PHP_FE(imap_8bit,                                                     arginfo_imap_8bit)
00508        PHP_FE(imap_binary,                                                   arginfo_imap_binary)
00509        PHP_FE(imap_utf8,                                                     arginfo_imap_utf8)
00510        PHP_FE(imap_status,                                                   arginfo_imap_status)
00511        PHP_FE(imap_mailboxmsginfo,                                    arginfo_imap_mailboxmsginfo)
00512        PHP_FE(imap_setflag_full,                                      arginfo_imap_setflag_full)
00513        PHP_FE(imap_clearflag_full,                                    arginfo_imap_clearflag_full)
00514        PHP_FE(imap_sort,                                                     arginfo_imap_sort)
00515        PHP_FE(imap_uid,                                                      arginfo_imap_uid)
00516        PHP_FE(imap_msgno,                                                    arginfo_imap_msgno)
00517        PHP_FE(imap_list,                                                     arginfo_imap_list)
00518        PHP_FE(imap_lsub,                                                     arginfo_imap_lsub)
00519        PHP_FE(imap_fetch_overview,                                    arginfo_imap_fetch_overview)
00520        PHP_FE(imap_alerts,                                                   arginfo_imap_alerts)
00521        PHP_FE(imap_errors,                                                   arginfo_imap_errors)
00522        PHP_FE(imap_last_error,                                               arginfo_imap_last_error)
00523        PHP_FE(imap_search,                                                   arginfo_imap_search)
00524        PHP_FE(imap_utf7_decode,                                       arginfo_imap_utf7_decode)
00525        PHP_FE(imap_utf7_encode,                                       arginfo_imap_utf7_encode)
00526 #ifdef HAVE_IMAP_MUTF7
00527        PHP_FE(imap_utf8_to_mutf7,                                     arginfo_imap_utf8_to_mutf7)
00528        PHP_FE(imap_mutf7_to_utf8,                                     arginfo_imap_mutf7_to_utf8)
00529 #endif
00530        PHP_FE(imap_mime_header_decode,                                arginfo_imap_mime_header_decode)
00531        PHP_FE(imap_thread,                                                   arginfo_imap_thread)
00532        PHP_FE(imap_timeout,                                                  arginfo_imap_timeout)
00533 
00534 #if defined(HAVE_IMAP2000) || defined(HAVE_IMAP2001)
00535        PHP_FE(imap_get_quota,                                                arginfo_imap_get_quota)
00536        PHP_FE(imap_get_quotaroot,                                     arginfo_imap_get_quotaroot)
00537        PHP_FE(imap_set_quota,                                                arginfo_imap_set_quota)
00538        PHP_FE(imap_setacl,                                                   arginfo_imap_setacl)
00539        PHP_FE(imap_getacl,                                                   arginfo_imap_getacl)
00540 #endif
00541 
00542        PHP_FE(imap_mail,                                                     arginfo_imap_mail)
00543 
00544        PHP_FALIAS(imap_header,                   imap_headerinfo,     arginfo_imap_headerinfo)
00545        PHP_FALIAS(imap_listmailbox,       imap_list,                  arginfo_imap_list)
00546        PHP_FALIAS(imap_getmailboxes,      imap_list_full,             arginfo_imap_getmailboxes)
00547        PHP_FALIAS(imap_scanmailbox,       imap_listscan,              arginfo_imap_listscan)
00548        PHP_FALIAS(imap_listsubscribed,    imap_lsub,                  arginfo_imap_lsub)
00549        PHP_FALIAS(imap_getsubscribed,     imap_lsub_full,             arginfo_imap_getsubscribed)
00550        PHP_FALIAS(imap_fetchtext,         imap_body,                  arginfo_imap_body)
00551        PHP_FALIAS(imap_scan,                     imap_listscan,              arginfo_imap_listscan)
00552        PHP_FALIAS(imap_create,                   imap_createmailbox,  arginfo_imap_createmailbox)
00553        PHP_FALIAS(imap_rename,                   imap_renamemailbox,  arginfo_imap_renamemailbox)
00554        PHP_FE_END
00555 };
00556 /* }}} */
00557 
00558 /* {{{ imap dependencies */
00559 static const zend_module_dep imap_deps[] = {
00560        ZEND_MOD_REQUIRED("standard")
00561        ZEND_MOD_END
00562 };
00563 /* }}} */
00564 
00565 /* {{{ imap_module_entry
00566  */
00567 zend_module_entry imap_module_entry = {
00568        STANDARD_MODULE_HEADER_EX, NULL,
00569        imap_deps,
00570        "imap",
00571        imap_functions,
00572        PHP_MINIT(imap),
00573        NULL,
00574        PHP_RINIT(imap),
00575        PHP_RSHUTDOWN(imap),
00576        PHP_MINFO(imap),
00577        NO_VERSION_YET,
00578        PHP_MODULE_GLOBALS(imap),
00579        PHP_GINIT(imap),
00580        NULL,
00581        NULL,
00582        STANDARD_MODULE_PROPERTIES_EX
00583 };
00584 /* }}} */
00585 
00586 #ifdef COMPILE_DL_IMAP
00587 ZEND_GET_MODULE(imap)
00588 #endif
00589 
00590 /* True globals, no need for thread safety */
00591 static int le_imap;
00592 
00593 #define PHP_IMAP_CHECK_MSGNO(msgindex)    \
00594        if ((msgindex < 1) || ((unsigned) msgindex > imap_le_struct->imap_stream->nmsgs)) { \
00595               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad message number");    \
00596               RETURN_FALSE; \
00597        }      \
00598 
00599 /* {{{ mail_close_it
00600  */
00601 static void mail_close_it(zend_rsrc_list_entry *rsrc TSRMLS_DC)
00602 {
00603        pils *imap_le_struct = (pils *)rsrc->ptr;
00604 
00605        /* Do not try to close prototype streams */
00606        if (!(imap_le_struct->flags & OP_PROTOTYPE)) {
00607               mail_close_full(imap_le_struct->imap_stream, imap_le_struct->flags);
00608        }
00609 
00610        if (IMAPG(imap_user)) {
00611               efree(IMAPG(imap_user));
00612               IMAPG(imap_user) = 0;
00613        }
00614        if (IMAPG(imap_password)) {
00615               efree(IMAPG(imap_password));
00616               IMAPG(imap_password) = 0;
00617        }
00618 
00619        efree(imap_le_struct);
00620 }
00621 /* }}} */
00622 
00623 /* {{{ add_assoc_object
00624  */
00625 static int add_assoc_object(zval *arg, char *key, zval *tmp TSRMLS_DC)
00626 {
00627        HashTable *symtable;
00628 
00629        if (Z_TYPE_P(arg) == IS_OBJECT) {
00630               symtable = Z_OBJPROP_P(arg);
00631        } else {
00632               symtable = Z_ARRVAL_P(arg);
00633        }
00634        return zend_hash_update(symtable, key, strlen(key)+1, (void *) &tmp, sizeof(zval *), NULL);
00635 }
00636 /* }}} */
00637 
00638 /* {{{ add_next_index_object
00639  */
00640 static inline int add_next_index_object(zval *arg, zval *tmp TSRMLS_DC)
00641 {
00642        HashTable *symtable;
00643 
00644        if (Z_TYPE_P(arg) == IS_OBJECT) {
00645               symtable = Z_OBJPROP_P(arg);
00646        } else {
00647               symtable = Z_ARRVAL_P(arg);
00648        }
00649 
00650        return zend_hash_next_index_insert(symtable, (void *) &tmp, sizeof(zval *), NULL);
00651 }
00652 /* }}} */
00653 
00654 /* {{{ mail_newfolderobjectlist
00655  *
00656  * Mail instantiate FOBJECTLIST
00657  * Returns: new FOBJECTLIST list
00658  * Author: CJH
00659  */
00660 FOBJECTLIST *mail_newfolderobjectlist(void)
00661 {
00662        return (FOBJECTLIST *) memset(fs_get(sizeof(FOBJECTLIST)), 0, sizeof(FOBJECTLIST));
00663 }
00664 /* }}} */
00665 
00666 /* {{{ mail_free_foblist
00667  *
00668  * Mail garbage collect FOBJECTLIST
00669  * Accepts: pointer to FOBJECTLIST pointer
00670  * Author: CJH
00671  */
00672 void mail_free_foblist(FOBJECTLIST **foblist, FOBJECTLIST **tail)
00673 {
00674        FOBJECTLIST *cur, *next;
00675 
00676        for (cur=*foblist, next=cur->next; cur; cur=next) {
00677               next = cur->next;
00678 
00679               if(cur->text.data)
00680                      fs_give((void **)&(cur->text.data));
00681 
00682               fs_give((void **)&cur);
00683        }
00684 
00685        *tail = NIL;
00686        *foblist = NIL;
00687 }
00688 /* }}} */
00689 
00690 /* {{{ mail_newerrorlist
00691  *
00692  * Mail instantiate ERRORLIST
00693  * Returns: new ERRORLIST list
00694  * Author: CJH
00695  */
00696 ERRORLIST *mail_newerrorlist(void)
00697 {
00698        return (ERRORLIST *) memset(fs_get(sizeof(ERRORLIST)), 0, sizeof(ERRORLIST));
00699 }
00700 /* }}} */
00701 
00702 /* {{{ mail_free_errorlist
00703  *
00704  * Mail garbage collect FOBJECTLIST
00705  * Accepts: pointer to FOBJECTLIST pointer
00706  * Author: CJH
00707  */
00708 void mail_free_errorlist(ERRORLIST **errlist)
00709 {
00710        if (*errlist) {             /* only free if exists */
00711               if ((*errlist)->text.data) {
00712                      fs_give((void **) &(*errlist)->text.data);
00713               }
00714               mail_free_errorlist (&(*errlist)->next);
00715               fs_give((void **) errlist); /* return string to free storage */
00716        }
00717 }
00718 /* }}} */
00719 
00720 /* {{{ mail_newmessagelist
00721  *
00722  * Mail instantiate MESSAGELIST
00723  * Returns: new MESSAGELIST list
00724  * Author: CJH
00725  */
00726 MESSAGELIST *mail_newmessagelist(void)
00727 {
00728        return (MESSAGELIST *) memset(fs_get(sizeof(MESSAGELIST)), 0, sizeof(MESSAGELIST));
00729 }
00730 /* }}} */
00731 
00732 /* {{{ mail_free_messagelist
00733  *
00734  * Mail garbage collect MESSAGELIST
00735  * Accepts: pointer to MESSAGELIST pointer
00736  * Author: CJH
00737  */
00738 void mail_free_messagelist(MESSAGELIST **msglist, MESSAGELIST **tail)
00739 {
00740        MESSAGELIST *cur, *next;
00741 
00742        for (cur = *msglist, next = cur->next; cur; cur = next) {
00743               next = cur->next;
00744               fs_give((void **)&cur);
00745        }
00746 
00747        *tail = NIL;
00748        *msglist = NIL;
00749 }
00750 /* }}} */
00751 
00752 #if defined(HAVE_IMAP2000) || defined(HAVE_IMAP2001)
00753 /* {{{ mail_getquota
00754  *
00755  * Mail GET_QUOTA callback
00756  * Called via the mail_parameter function in c-client:src/c-client/mail.c
00757  * Author DRK
00758  */
00759 
00760 void mail_getquota(MAILSTREAM *stream, char *qroot, QUOTALIST *qlist)
00761 {
00762        zval *t_map, *return_value;
00763        TSRMLS_FETCH();
00764 
00765        return_value = *IMAPG(quota_return);
00766 
00767 /* put parsing code here */
00768        for(; qlist; qlist = qlist->next) {
00769               MAKE_STD_ZVAL(t_map);
00770               array_init(t_map);
00771               if (strncmp(qlist->name, "STORAGE", 7) == 0)
00772               {
00773                      /* this is to add backwards compatibility */
00774                      add_assoc_long_ex(return_value, "usage", sizeof("usage"), qlist->usage);
00775                      add_assoc_long_ex(return_value, "limit", sizeof("limit"), qlist->limit);
00776               }
00777 
00778               add_assoc_long_ex(t_map, "usage", sizeof("usage"), qlist->usage);
00779               add_assoc_long_ex(t_map, "limit", sizeof("limit"), qlist->limit);
00780               add_assoc_zval_ex(return_value, qlist->name, strlen(qlist->name)+1, t_map);
00781        }
00782 }
00783 /* }}} */
00784 
00785 /* {{{ mail_getquota
00786  *
00787  * Mail GET_ACL callback
00788  * Called via the mail_parameter function in c-client:src/c-client/mail.c
00789  */
00790 void mail_getacl(MAILSTREAM *stream, char *mailbox, ACLLIST *alist)
00791 {
00792        TSRMLS_FETCH();
00793 
00794        /* walk through the ACLLIST */
00795        for(; alist; alist = alist->next) {
00796               add_assoc_stringl(IMAPG(imap_acl_list), alist->identifier, alist->rights, strlen(alist->rights), 1);
00797        }
00798 }
00799 /* }}} */
00800 #endif
00801 
00802 /* {{{ PHP_GINIT_FUNCTION
00803  */
00804 static PHP_GINIT_FUNCTION(imap)
00805 {
00806        imap_globals->imap_user = NIL;
00807        imap_globals->imap_password = NIL;
00808 
00809        imap_globals->imap_alertstack = NIL;
00810        imap_globals->imap_errorstack = NIL;
00811 
00812        imap_globals->imap_folders = NIL;
00813        imap_globals->imap_folders_tail = NIL;
00814        imap_globals->imap_sfolders = NIL;
00815        imap_globals->imap_sfolders_tail = NIL;
00816        imap_globals->imap_messages = NIL;
00817        imap_globals->imap_messages_tail = NIL;
00818        imap_globals->imap_folder_objects = NIL;
00819        imap_globals->imap_folder_objects_tail = NIL;
00820        imap_globals->imap_sfolder_objects = NIL;
00821        imap_globals->imap_sfolder_objects_tail = NIL;
00822 
00823        imap_globals->folderlist_style = FLIST_ARRAY;
00824 #if defined(HAVE_IMAP2000) || defined(HAVE_IMAP2001)
00825        imap_globals->quota_return = NIL;
00826        imap_globals->imap_acl_list = NIL;
00827 #endif
00828        imap_globals->gets_stream = NIL;
00829 }
00830 /* }}} */
00831 
00832 /* {{{ PHP_MINIT_FUNCTION
00833  */
00834 PHP_MINIT_FUNCTION(imap)
00835 {
00836        unsigned long sa_all =      SA_MESSAGES | SA_RECENT | SA_UNSEEN | SA_UIDNEXT | SA_UIDVALIDITY;
00837 
00838 #ifndef PHP_WIN32
00839        mail_link(&unixdriver);            /* link in the unix driver */
00840        mail_link(&mhdriver);              /* link in the mh driver */
00841        /* mail_link(&mxdriver); */ /* According to c-client docs (internal.txt) this shouldn't be used. */
00842        mail_link(&mmdfdriver);            /* link in the mmdf driver */
00843        mail_link(&newsdriver);            /* link in the news driver */
00844        mail_link(&philedriver);    /* link in the phile driver */
00845 #endif
00846        mail_link(&imapdriver);            /* link in the imap driver */
00847        mail_link(&nntpdriver);            /* link in the nntp driver */
00848        mail_link(&pop3driver);            /* link in the pop3 driver */
00849        mail_link(&mbxdriver);             /* link in the mbx driver */
00850        mail_link(&tenexdriver);    /* link in the tenex driver */
00851        mail_link(&mtxdriver);             /* link in the mtx driver */
00852        mail_link(&dummydriver);    /* link in the dummy driver */
00853 
00854 #ifndef PHP_WIN32
00855        auth_link(&auth_log);              /* link in the log authenticator */
00856        auth_link(&auth_md5);              /* link in the cram-md5 authenticator */
00857 #if HAVE_IMAP_KRB && defined(HAVE_IMAP_AUTH_GSS)
00858        auth_link(&auth_gss);              /* link in the gss authenticator */
00859 #endif
00860        auth_link(&auth_pla);              /* link in the plain authenticator */
00861 #endif
00862 
00863 #ifdef HAVE_IMAP_SSL
00864        ssl_onceonlyinit ();
00865 #endif
00866 
00867        /* lets allow NIL */
00868        REGISTER_LONG_CONSTANT("NIL", NIL, CONST_PERSISTENT | CONST_CS);
00869 
00870        /* plug in our gets */
00871        mail_parameters(NIL, SET_GETS, (void *) NIL);
00872 
00873        /* set default timeout values */
00874        mail_parameters(NIL, SET_OPENTIMEOUT, (void *) FG(default_socket_timeout));
00875        mail_parameters(NIL, SET_READTIMEOUT, (void *) FG(default_socket_timeout));
00876        mail_parameters(NIL, SET_WRITETIMEOUT, (void *) FG(default_socket_timeout));
00877        mail_parameters(NIL, SET_CLOSETIMEOUT, (void *) FG(default_socket_timeout));
00878 
00879        /* timeout constants */
00880        REGISTER_LONG_CONSTANT("IMAP_OPENTIMEOUT", 1, CONST_PERSISTENT | CONST_CS);
00881        REGISTER_LONG_CONSTANT("IMAP_READTIMEOUT", 2, CONST_PERSISTENT | CONST_CS);
00882        REGISTER_LONG_CONSTANT("IMAP_WRITETIMEOUT", 3, CONST_PERSISTENT | CONST_CS);
00883        REGISTER_LONG_CONSTANT("IMAP_CLOSETIMEOUT", 4, CONST_PERSISTENT | CONST_CS);
00884 
00885        /* Open Options */
00886 
00887        REGISTER_LONG_CONSTANT("OP_DEBUG", OP_DEBUG, CONST_PERSISTENT | CONST_CS);
00888        /* debug protocol negotiations */
00889        REGISTER_LONG_CONSTANT("OP_READONLY", OP_READONLY, CONST_PERSISTENT | CONST_CS);
00890        /* read-only open */
00891        REGISTER_LONG_CONSTANT("OP_ANONYMOUS", OP_ANONYMOUS, CONST_PERSISTENT | CONST_CS);
00892        /* anonymous open of newsgroup */
00893        REGISTER_LONG_CONSTANT("OP_SHORTCACHE", OP_SHORTCACHE, CONST_PERSISTENT | CONST_CS);
00894        /* short (elt-only) caching */
00895        REGISTER_LONG_CONSTANT("OP_SILENT", OP_SILENT, CONST_PERSISTENT | CONST_CS);
00896        /* don't pass up events (internal use) */
00897        REGISTER_LONG_CONSTANT("OP_PROTOTYPE", OP_PROTOTYPE, CONST_PERSISTENT | CONST_CS);
00898        /* return driver prototype */
00899        REGISTER_LONG_CONSTANT("OP_HALFOPEN", OP_HALFOPEN, CONST_PERSISTENT | CONST_CS);
00900        /* half-open (IMAP connect but no select) */
00901        REGISTER_LONG_CONSTANT("OP_EXPUNGE", OP_EXPUNGE, CONST_PERSISTENT | CONST_CS);
00902        /* silently expunge recycle stream */
00903        REGISTER_LONG_CONSTANT("OP_SECURE", OP_SECURE, CONST_PERSISTENT | CONST_CS);
00904        /* don't do non-secure authentication */
00905 
00906        /*
00907        PHP re-assigns CL_EXPUNGE a custom value that can be used as part of the imap_open() bitfield
00908        because it seems like a good idea to be able to indicate that the mailbox should be
00909        automatically expunged during imap_open in case the script get interrupted and it doesn't get
00910        to the imap_close() where this option is normally placed.  If the c-client library adds other
00911        options and the value for this one conflicts, simply make PHP_EXPUNGE higher at the top of
00912        this file
00913        */
00914        REGISTER_LONG_CONSTANT("CL_EXPUNGE", PHP_EXPUNGE, CONST_PERSISTENT | CONST_CS);
00915        /* expunge silently */
00916 
00917        /* Fetch options */
00918 
00919        REGISTER_LONG_CONSTANT("FT_UID", FT_UID, CONST_PERSISTENT | CONST_CS);
00920        /* argument is a UID */
00921        REGISTER_LONG_CONSTANT("FT_PEEK", FT_PEEK, CONST_PERSISTENT | CONST_CS);
00922        /* peek at data */
00923        REGISTER_LONG_CONSTANT("FT_NOT", FT_NOT, CONST_PERSISTENT | CONST_CS);
00924        /* NOT flag for header lines fetch */
00925        REGISTER_LONG_CONSTANT("FT_INTERNAL", FT_INTERNAL, CONST_PERSISTENT | CONST_CS);
00926        /* text can be internal strings */
00927        REGISTER_LONG_CONSTANT("FT_PREFETCHTEXT", FT_PREFETCHTEXT, CONST_PERSISTENT | CONST_CS);
00928        /* IMAP prefetch text when fetching header */
00929 
00930        /* Flagging options */
00931 
00932        REGISTER_LONG_CONSTANT("ST_UID", ST_UID, CONST_PERSISTENT | CONST_CS);
00933        /* argument is a UID sequence */
00934        REGISTER_LONG_CONSTANT("ST_SILENT", ST_SILENT, CONST_PERSISTENT | CONST_CS);
00935        /* don't return results */
00936        REGISTER_LONG_CONSTANT("ST_SET", ST_SET, CONST_PERSISTENT | CONST_CS);
00937        /* set vs. clear */
00938 
00939        /* Copy options */
00940 
00941        REGISTER_LONG_CONSTANT("CP_UID", CP_UID, CONST_PERSISTENT | CONST_CS);
00942        /* argument is a UID sequence */
00943        REGISTER_LONG_CONSTANT("CP_MOVE", CP_MOVE, CONST_PERSISTENT | CONST_CS);
00944        /* delete from source after copying */
00945 
00946        /* Search/sort options */
00947 
00948        REGISTER_LONG_CONSTANT("SE_UID", SE_UID, CONST_PERSISTENT | CONST_CS);
00949        /* return UID */
00950        REGISTER_LONG_CONSTANT("SE_FREE", SE_FREE, CONST_PERSISTENT | CONST_CS);
00951        /* free search program after finished */
00952        REGISTER_LONG_CONSTANT("SE_NOPREFETCH", SE_NOPREFETCH, CONST_PERSISTENT | CONST_CS);
00953        /* no search prefetching */
00954        REGISTER_LONG_CONSTANT("SO_FREE", SO_FREE, CONST_PERSISTENT | CONST_CS);
00955        /* free sort program after finished */
00956        REGISTER_LONG_CONSTANT("SO_NOSERVER", SO_NOSERVER, CONST_PERSISTENT | CONST_CS);
00957        /* don't do server-based sort */
00958 
00959        /* Status options */
00960 
00961        REGISTER_LONG_CONSTANT("SA_MESSAGES", SA_MESSAGES , CONST_PERSISTENT | CONST_CS);
00962        /* number of messages */
00963        REGISTER_LONG_CONSTANT("SA_RECENT", SA_RECENT, CONST_PERSISTENT | CONST_CS);
00964        /* number of recent messages */
00965        REGISTER_LONG_CONSTANT("SA_UNSEEN", SA_UNSEEN , CONST_PERSISTENT | CONST_CS);
00966        /* number of unseen messages */
00967        REGISTER_LONG_CONSTANT("SA_UIDNEXT", SA_UIDNEXT, CONST_PERSISTENT | CONST_CS);
00968        /* next UID to be assigned */
00969        REGISTER_LONG_CONSTANT("SA_UIDVALIDITY", SA_UIDVALIDITY , CONST_PERSISTENT | CONST_CS);
00970        /* UID validity value */
00971        REGISTER_LONG_CONSTANT("SA_ALL", sa_all, CONST_PERSISTENT | CONST_CS);
00972        /* get all status information */
00973 
00974        /* Bits for mm_list() and mm_lsub() */
00975 
00976        REGISTER_LONG_CONSTANT("LATT_NOINFERIORS", LATT_NOINFERIORS , CONST_PERSISTENT | CONST_CS);
00977        REGISTER_LONG_CONSTANT("LATT_NOSELECT", LATT_NOSELECT, CONST_PERSISTENT | CONST_CS);
00978        REGISTER_LONG_CONSTANT("LATT_MARKED", LATT_MARKED, CONST_PERSISTENT | CONST_CS);
00979        REGISTER_LONG_CONSTANT("LATT_UNMARKED", LATT_UNMARKED , CONST_PERSISTENT | CONST_CS);
00980 
00981 #ifdef LATT_REFERRAL
00982        REGISTER_LONG_CONSTANT("LATT_REFERRAL", LATT_REFERRAL, CONST_PERSISTENT | CONST_CS);
00983 #endif
00984 
00985 #ifdef LATT_HASCHILDREN
00986        REGISTER_LONG_CONSTANT("LATT_HASCHILDREN", LATT_HASCHILDREN, CONST_PERSISTENT | CONST_CS);
00987 #endif
00988 
00989 #ifdef LATT_HASNOCHILDREN
00990        REGISTER_LONG_CONSTANT("LATT_HASNOCHILDREN", LATT_HASNOCHILDREN, CONST_PERSISTENT | CONST_CS);
00991 #endif
00992 
00993        /* Sort functions */
00994 
00995        REGISTER_LONG_CONSTANT("SORTDATE", SORTDATE , CONST_PERSISTENT | CONST_CS);
00996        /* date */
00997        REGISTER_LONG_CONSTANT("SORTARRIVAL", SORTARRIVAL , CONST_PERSISTENT | CONST_CS);
00998        /* arrival date */
00999        REGISTER_LONG_CONSTANT("SORTFROM", SORTFROM , CONST_PERSISTENT | CONST_CS);
01000        /* from */
01001        REGISTER_LONG_CONSTANT("SORTSUBJECT", SORTSUBJECT , CONST_PERSISTENT | CONST_CS);
01002        /* subject */
01003        REGISTER_LONG_CONSTANT("SORTTO", SORTTO , CONST_PERSISTENT | CONST_CS);
01004        /* to */
01005        REGISTER_LONG_CONSTANT("SORTCC", SORTCC , CONST_PERSISTENT | CONST_CS);
01006        /* cc */
01007        REGISTER_LONG_CONSTANT("SORTSIZE", SORTSIZE , CONST_PERSISTENT | CONST_CS);
01008        /* size */
01009 
01010        REGISTER_LONG_CONSTANT("TYPETEXT", TYPETEXT , CONST_PERSISTENT | CONST_CS);
01011        REGISTER_LONG_CONSTANT("TYPEMULTIPART", TYPEMULTIPART , CONST_PERSISTENT | CONST_CS);
01012        REGISTER_LONG_CONSTANT("TYPEMESSAGE", TYPEMESSAGE , CONST_PERSISTENT | CONST_CS);
01013        REGISTER_LONG_CONSTANT("TYPEAPPLICATION", TYPEAPPLICATION , CONST_PERSISTENT | CONST_CS);
01014        REGISTER_LONG_CONSTANT("TYPEAUDIO", TYPEAUDIO , CONST_PERSISTENT | CONST_CS);
01015        REGISTER_LONG_CONSTANT("TYPEIMAGE", TYPEIMAGE , CONST_PERSISTENT | CONST_CS);
01016        REGISTER_LONG_CONSTANT("TYPEVIDEO", TYPEVIDEO , CONST_PERSISTENT | CONST_CS);
01017        REGISTER_LONG_CONSTANT("TYPEMODEL", TYPEMODEL , CONST_PERSISTENT | CONST_CS);
01018        REGISTER_LONG_CONSTANT("TYPEOTHER", TYPEOTHER , CONST_PERSISTENT | CONST_CS);
01019        /*
01020        TYPETEXT                unformatted text
01021        TYPEMULTIPART           multiple part
01022        TYPEMESSAGE             encapsulated message
01023        TYPEAPPLICATION         application data
01024        TYPEAUDIO               audio
01025        TYPEIMAGE               static image (GIF, JPEG, etc.)
01026        TYPEVIDEO               video
01027        TYPEMODEL               model
01028        TYPEOTHER               unknown
01029        */
01030 
01031        REGISTER_LONG_CONSTANT("ENC7BIT", ENC7BIT , CONST_PERSISTENT | CONST_CS);
01032        REGISTER_LONG_CONSTANT("ENC8BIT", ENC8BIT , CONST_PERSISTENT | CONST_CS);
01033        REGISTER_LONG_CONSTANT("ENCBINARY", ENCBINARY , CONST_PERSISTENT | CONST_CS);
01034        REGISTER_LONG_CONSTANT("ENCBASE64", ENCBASE64, CONST_PERSISTENT | CONST_CS);
01035        REGISTER_LONG_CONSTANT("ENCQUOTEDPRINTABLE", ENCQUOTEDPRINTABLE , CONST_PERSISTENT | CONST_CS);
01036        REGISTER_LONG_CONSTANT("ENCOTHER", ENCOTHER , CONST_PERSISTENT | CONST_CS);
01037        /*
01038        ENC7BIT                 7 bit SMTP semantic data
01039        ENC8BIT                 8 bit SMTP semantic data
01040        ENCBINARY               8 bit binary data
01041        ENCBASE64               base-64 encoded data
01042        ENCQUOTEDPRINTABLE      human-readable 8-as-7 bit data
01043        ENCOTHER                unknown
01044        */
01045 
01046        REGISTER_LONG_CONSTANT("IMAP_GC_ELT", GC_ELT , CONST_PERSISTENT | CONST_CS);
01047        REGISTER_LONG_CONSTANT("IMAP_GC_ENV", GC_ENV , CONST_PERSISTENT | CONST_CS);
01048        REGISTER_LONG_CONSTANT("IMAP_GC_TEXTS", GC_TEXTS , CONST_PERSISTENT | CONST_CS);
01049        /*
01050        GC_ELT                 message cache elements
01051        GC_ENV                 ENVELOPEs and BODYs
01052        GC_TEXTS               texts
01053        */
01054 
01055        le_imap = zend_register_list_destructors_ex(mail_close_it, NULL, "imap", module_number);
01056        return SUCCESS;
01057 }
01058 /* }}} */
01059 
01060 /* {{{ PHP_RINIT_FUNCTION
01061  */
01062 PHP_RINIT_FUNCTION(imap)
01063 {
01064        IMAPG(imap_errorstack) = NIL;
01065        IMAPG(imap_alertstack) = NIL;
01066        IMAPG(gets_stream) = NIL;
01067        return SUCCESS;
01068 }
01069 /* }}} */
01070 
01071 /* {{{ PHP_RSHUTDOWN_FUNCTION
01072  */
01073 PHP_RSHUTDOWN_FUNCTION(imap)
01074 {
01075        ERRORLIST *ecur = NIL;
01076        STRINGLIST *acur = NIL;
01077 
01078        if (IMAPG(imap_errorstack) != NIL) {
01079               /* output any remaining errors at their original error level */
01080               if (EG(error_reporting) & E_NOTICE) {
01081                      ecur = IMAPG(imap_errorstack);
01082                      while (ecur != NIL) {
01083                             php_error_docref(NULL TSRMLS_CC, E_NOTICE, "%s (errflg=%ld)", ecur->LTEXT, ecur->errflg);
01084                             ecur = ecur->next;
01085                      }
01086               }
01087               mail_free_errorlist(&IMAPG(imap_errorstack));
01088        }
01089 
01090        if (IMAPG(imap_alertstack) != NIL) {
01091               /* output any remaining alerts at E_NOTICE level */
01092               if (EG(error_reporting) & E_NOTICE) {
01093                      acur = IMAPG(imap_alertstack);
01094                      while (acur != NIL) {
01095                             php_error_docref(NULL TSRMLS_CC, E_NOTICE, "%s", acur->LTEXT);
01096                             acur = acur->next;
01097                      }
01098               }
01099               mail_free_stringlist(&IMAPG(imap_alertstack));
01100               IMAPG(imap_alertstack) = NIL;
01101        }
01102        return SUCCESS;
01103 }
01104 /* }}} */
01105 
01106 #if !defined(CCLIENTVERSION)
01107 #if HAVE_IMAP2007e
01108 #define CCLIENTVERSION "2007e"
01109 #elif HAVE_IMAP2007d
01110 #define CCLIENTVERSION "2007d"
01111 #elif HAVE_IMAP2007b
01112 #define CCLIENTVERSION "2007b"
01113 #elif HAVE_IMAP2007a
01114 #define CCLIENTVERSION "2007a"
01115 #elif HAVE_IMAP2004
01116 #define CCLIENTVERSION "2004"
01117 #elif HAVE_IMAP2001
01118 #define CCLIENTVERSION "2001"
01119 #elif HAVE_IMAP2000
01120 #define CCLIENTVERSION "2000"
01121 #elif defined(IMAP41)
01122 #define CCLIENTVERSION "4.1"
01123 #else
01124 #define CCLIENTVERSION "4.0"
01125 #endif
01126 #endif
01127 
01128 /* {{{ PHP_MINFO_FUNCTION
01129  */
01130 PHP_MINFO_FUNCTION(imap)
01131 {
01132        php_info_print_table_start();
01133        php_info_print_table_row(2, "IMAP c-Client Version", CCLIENTVERSION);
01134 #if HAVE_IMAP_SSL
01135        php_info_print_table_row(2, "SSL Support", "enabled");
01136 #endif
01137 #if HAVE_IMAP_KRB && HAVE_IMAP_AUTH_GSS
01138        php_info_print_table_row(2, "Kerberos Support", "enabled");
01139 #endif
01140        php_info_print_table_end();
01141 }
01142 /* }}} */
01143 
01144 /* {{{ imap_do_open
01145  */
01146 static void php_imap_do_open(INTERNAL_FUNCTION_PARAMETERS, int persistent)
01147 {
01148        char *mailbox, *user, *passwd;
01149        int mailbox_len, user_len, passwd_len;
01150        long retries = 0, flags = NIL, cl_flags = NIL;
01151        MAILSTREAM *imap_stream;
01152        pils *imap_le_struct;
01153        zval *params = NULL;
01154        int argc = ZEND_NUM_ARGS();
01155 
01156        if (zend_parse_parameters(argc TSRMLS_CC, "sss|lla", &mailbox, &mailbox_len, &user, &user_len,
01157               &passwd, &passwd_len, &flags, &retries, &params) == FAILURE) {
01158               return;
01159        }
01160 
01161        if (argc >= 4) {
01162               if (flags & PHP_EXPUNGE) {
01163                      cl_flags = CL_EXPUNGE;
01164                      flags ^= PHP_EXPUNGE;
01165               }
01166               if (flags & OP_PROTOTYPE) {
01167                      cl_flags |= OP_PROTOTYPE;
01168               }
01169        }
01170 
01171        if (params) {
01172               zval **disabled_auth_method;
01173 
01174               if (zend_hash_find(HASH_OF(params), "DISABLE_AUTHENTICATOR", sizeof("DISABLE_AUTHENTICATOR"), (void **)&disabled_auth_method) == SUCCESS) {
01175                      switch (Z_TYPE_PP(disabled_auth_method)) {
01176                             case IS_STRING:
01177                                    if (Z_STRLEN_PP(disabled_auth_method) > 1) {
01178                                           mail_parameters (NIL, DISABLE_AUTHENTICATOR, (void *)Z_STRVAL_PP(disabled_auth_method));
01179                                    }
01180                                    break;
01181                             case IS_ARRAY:
01182                                    {
01183                                           zval **z_auth_method;
01184                                           int i;
01185                                           int nelems = zend_hash_num_elements(Z_ARRVAL_PP(disabled_auth_method));
01186 
01187                                           if (nelems == 0 ) {
01188                                                  break;
01189                                           }
01190                                           for (i = 0; i < nelems; i++) {
01191                                                  if (zend_hash_index_find(Z_ARRVAL_PP(disabled_auth_method), i, (void **) &z_auth_method) == SUCCESS) {
01192                                                         if (Z_TYPE_PP(z_auth_method) == IS_STRING) {
01193                                                                if (Z_STRLEN_PP(z_auth_method) > 1) {
01194                                                                       mail_parameters (NIL, DISABLE_AUTHENTICATOR, (void *)Z_STRVAL_PP(disabled_auth_method));
01195                                                                }
01196                                                         } else {
01197                                                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid argument, expect string or array of strings");
01198                                                         }
01199                                                  }
01200                                           }
01201                                    }
01202                                    break;
01203                             case IS_LONG:
01204                             default:
01205                                    php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid argument, expect string or array of strings");
01206                                    break;
01207                      }
01208               }
01209        }
01210 
01211        if (IMAPG(imap_user)) {
01212               efree(IMAPG(imap_user));
01213               IMAPG(imap_user) = 0;
01214        }
01215 
01216        if (IMAPG(imap_password)) {
01217               efree(IMAPG(imap_password));
01218               IMAPG(imap_password) = 0;
01219        }
01220 
01221        /* local filename, need to perform open_basedir and safe_mode checks */
01222        if (mailbox[0] != '{') {
01223               if (strlen(mailbox) != mailbox_len) {
01224                      RETURN_FALSE;
01225               }
01226               if (php_check_open_basedir(mailbox TSRMLS_CC) ||
01227                      (PG(safe_mode) && !php_checkuid(mailbox, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
01228                      RETURN_FALSE;
01229               }
01230        }
01231 
01232        IMAPG(imap_user)     = estrndup(user, user_len);
01233        IMAPG(imap_password) = estrndup(passwd, passwd_len);
01234 
01235 #ifdef SET_MAXLOGINTRIALS
01236        if (argc >= 5) {
01237               if (retries < 0) {
01238                      php_error_docref(NULL TSRMLS_CC, E_WARNING ,"Retries must be greater or equal to 0");
01239               } else {
01240                      mail_parameters(NIL, SET_MAXLOGINTRIALS, (void *) retries);
01241               }
01242        }
01243 #endif
01244 
01245        imap_stream = mail_open(NIL, mailbox, flags);
01246 
01247        if (imap_stream == NIL) {
01248               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't open stream %s", mailbox);
01249               efree(IMAPG(imap_user)); IMAPG(imap_user) = 0;
01250               efree(IMAPG(imap_password)); IMAPG(imap_password) = 0;
01251               RETURN_FALSE;
01252        }
01253 
01254        imap_le_struct = emalloc(sizeof(pils));
01255        imap_le_struct->imap_stream = imap_stream;
01256        imap_le_struct->flags = cl_flags;
01257 
01258        ZEND_REGISTER_RESOURCE(return_value, imap_le_struct, le_imap);
01259 }
01260 /* }}} */
01261 
01262 /* {{{ proto resource imap_open(string mailbox, string user, string password [, int options [, int n_retries]])
01263    Open an IMAP stream to a mailbox */
01264 PHP_FUNCTION(imap_open)
01265 {
01266        php_imap_do_open(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
01267 }
01268 /* }}} */
01269 
01270 /* {{{ proto bool imap_reopen(resource stream_id, string mailbox [, int options [, int n_retries]])
01271    Reopen an IMAP stream to a new mailbox */
01272 PHP_FUNCTION(imap_reopen)
01273 {
01274        zval *streamind;
01275        char *mailbox;
01276        int mailbox_len;
01277        long options = 0, retries = 0;
01278        pils *imap_le_struct;
01279        MAILSTREAM *imap_stream;
01280        long flags=NIL;
01281        long cl_flags=NIL;
01282 
01283        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|ll", &streamind, &mailbox, &mailbox_len, &options, &retries) == FAILURE) {
01284               return;
01285        }
01286 
01287        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
01288 
01289        if (options) {
01290               flags = options;
01291               if (flags & PHP_EXPUNGE) {
01292                      cl_flags = CL_EXPUNGE;
01293                      flags ^= PHP_EXPUNGE;
01294               }
01295               imap_le_struct->flags = cl_flags;
01296        }
01297 #ifdef SET_MAXLOGINTRIALS
01298        if (retries) {
01299               mail_parameters(NIL, SET_MAXLOGINTRIALS, (void *) retries);
01300        }
01301 #endif
01302        /* local filename, need to perform open_basedir and safe_mode checks */
01303        if (mailbox[0] != '{' &&
01304                      (php_check_open_basedir(mailbox TSRMLS_CC) ||
01305                      (PG(safe_mode) && !php_checkuid(mailbox, NULL, CHECKUID_CHECK_FILE_AND_DIR)))) {
01306               RETURN_FALSE;
01307        }
01308 
01309        imap_stream = mail_open(imap_le_struct->imap_stream, mailbox, flags);
01310        if (imap_stream == NIL) {
01311               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't re-open stream");
01312               RETURN_FALSE;
01313        }
01314        imap_le_struct->imap_stream = imap_stream;
01315        RETURN_TRUE;
01316 }
01317 /* }}} */
01318 
01319 /* {{{ proto bool imap_append(resource stream_id, string folder, string message [, string options [, string internal_date]])
01320    Append a new message to a specified mailbox */
01321 PHP_FUNCTION(imap_append)
01322 {
01323        zval *streamind;
01324        char *folder, *message, *internal_date = NULL, *flags = NULL;
01325        int folder_len, message_len, internal_date_len = 0, flags_len = 0;
01326        pils *imap_le_struct;
01327        STRING st;
01328        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}/";
01329        const int regex_len = strlen(regex);
01330        pcre_cache_entry *pce;                           /* Compiled regex */
01331        zval *subpats = NULL;                            /* Parts (not used) */
01332        long regex_flags = 0;                            /* Flags (not used) */
01333        long start_offset = 0;                           /* Start offset (not used) */
01334        int global = 0;
01335 
01336        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) {
01337               return;
01338        }
01339 
01340        if (internal_date) {
01341               /* Make sure the given internal_date string matches the RFC specifiedformat */
01342               if ((pce = pcre_get_compiled_regex_cache(regex, regex_len TSRMLS_CC))== NULL) {
01343                      RETURN_FALSE;
01344               }
01345 
01346               php_pcre_match_impl(pce, internal_date, internal_date_len, return_value, subpats, global,
01347                      0, regex_flags, start_offset TSRMLS_CC);
01348 
01349               if (!Z_LVAL_P(return_value)) {
01350                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "internal date not correctly formatted");
01351                      internal_date = NULL;
01352               }
01353        }
01354 
01355        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
01356 
01357        INIT (&st, mail_string, (void *) message, message_len);
01358 
01359        if (mail_append_full(imap_le_struct->imap_stream, folder, (flags ? flags : NIL), (internal_date ? internal_date : NIL), &st)) {
01360               RETURN_TRUE;
01361        } else {
01362               RETURN_FALSE;
01363        }
01364 }
01365 /* }}} */
01366 
01367 /* {{{ proto int imap_num_msg(resource stream_id)
01368    Gives the number of messages in the current mailbox */
01369 PHP_FUNCTION(imap_num_msg)
01370 {
01371        zval *streamind;
01372        pils *imap_le_struct;
01373 
01374        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &streamind) == FAILURE) {
01375               return;
01376        }
01377 
01378        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
01379 
01380        RETURN_LONG(imap_le_struct->imap_stream->nmsgs);
01381 }
01382 /* }}} */
01383 
01384 /* {{{ proto bool imap_ping(resource stream_id)
01385    Check if the IMAP stream is still active */
01386 PHP_FUNCTION(imap_ping)
01387 {
01388        zval *streamind;
01389        pils *imap_le_struct;
01390 
01391        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &streamind) == FAILURE) {
01392               return;
01393        }
01394 
01395        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
01396 
01397        RETURN_BOOL(mail_ping(imap_le_struct->imap_stream));
01398 }
01399 /* }}} */
01400 
01401 /* {{{ proto int imap_num_recent(resource stream_id)
01402    Gives the number of recent messages in current mailbox */
01403 PHP_FUNCTION(imap_num_recent)
01404 {
01405        zval *streamind;
01406        pils *imap_le_struct;
01407 
01408        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &streamind) == FAILURE) {
01409               return;
01410        }
01411 
01412        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
01413 
01414        RETURN_LONG(imap_le_struct->imap_stream->recent);
01415 }
01416 /* }}} */
01417 
01418 #if defined(HAVE_IMAP2000) || defined(HAVE_IMAP2001)
01419 /* {{{ proto array imap_get_quota(resource stream_id, string qroot)
01420        Returns the quota set to the mailbox account qroot */
01421 PHP_FUNCTION(imap_get_quota)
01422 {
01423        zval *streamind;
01424        char *qroot;
01425        int qroot_len;
01426        pils *imap_le_struct;
01427 
01428        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &streamind, &qroot, &qroot_len) == FAILURE) {
01429               return;
01430        }
01431 
01432        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
01433 
01434        array_init(return_value);
01435        IMAPG(quota_return) = &return_value;
01436 
01437        /* set the callback for the GET_QUOTA function */
01438        mail_parameters(NIL, SET_QUOTA, (void *) mail_getquota);
01439        if (!imap_getquota(imap_le_struct->imap_stream, qroot)) {
01440               php_error_docref(NULL TSRMLS_CC, E_WARNING, "c-client imap_getquota failed");
01441               zval_dtor(return_value);
01442               RETURN_FALSE;
01443        }
01444 }
01445 /* }}} */
01446 
01447 /* {{{ proto array imap_get_quotaroot(resource stream_id, string mbox)
01448        Returns the quota set to the mailbox account mbox */
01449 PHP_FUNCTION(imap_get_quotaroot)
01450 {
01451        zval *streamind;
01452        char *mbox;
01453        int mbox_len;
01454        pils *imap_le_struct;
01455 
01456        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &streamind, &mbox, &mbox_len) == FAILURE) {
01457               return;
01458        }
01459 
01460        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
01461 
01462        array_init(return_value);
01463        IMAPG(quota_return) = &return_value;
01464 
01465        /* set the callback for the GET_QUOTAROOT function */
01466        mail_parameters(NIL, SET_QUOTA, (void *) mail_getquota);
01467        if (!imap_getquotaroot(imap_le_struct->imap_stream, mbox)) {
01468               php_error_docref(NULL TSRMLS_CC, E_WARNING, "c-client imap_getquotaroot failed");
01469               zval_dtor(return_value);
01470               RETURN_FALSE;
01471        }
01472 }
01473 /* }}} */
01474 
01475 /* {{{ proto bool imap_set_quota(resource stream_id, string qroot, int mailbox_size)
01476    Will set the quota for qroot mailbox */
01477 PHP_FUNCTION(imap_set_quota)
01478 {
01479        zval *streamind;
01480        char *qroot;
01481        int qroot_len;
01482        long mailbox_size;
01483        pils *imap_le_struct;
01484        STRINGLIST    limits;
01485 
01486        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsl", &streamind, &qroot, &qroot_len, &mailbox_size) == FAILURE) {
01487               return;
01488        }
01489 
01490        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
01491 
01492        limits.text.data = "STORAGE";
01493        limits.text.size = mailbox_size;
01494        limits.next = NIL;
01495 
01496        RETURN_BOOL(imap_setquota(imap_le_struct->imap_stream, qroot, &limits));
01497 }
01498 /* }}} */
01499 
01500 /* {{{ proto bool imap_setacl(resource stream_id, string mailbox, string id, string rights)
01501        Sets the ACL for a given mailbox */
01502 PHP_FUNCTION(imap_setacl)
01503 {
01504        zval *streamind;
01505        char *mailbox, *id, *rights;
01506        int mailbox_len, id_len, rights_len;
01507        pils *imap_le_struct;
01508 
01509        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsss", &streamind, &mailbox, &mailbox_len, &id, &id_len, &rights, &rights_len) == FAILURE) {
01510               return;
01511        }
01512 
01513        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
01514 
01515        RETURN_BOOL(imap_setacl(imap_le_struct->imap_stream, mailbox, id, rights));
01516 }
01517 /* }}} */
01518 
01519 /* {{{ proto array imap_getacl(resource stream_id, string mailbox)
01520        Gets the ACL for a given mailbox */
01521 PHP_FUNCTION(imap_getacl)
01522 {
01523        zval *streamind;
01524        char *mailbox;
01525        int mailbox_len;
01526        pils *imap_le_struct;
01527 
01528        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &streamind, &mailbox, &mailbox_len) == FAILURE) {
01529               return;
01530        }
01531 
01532        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
01533 
01534        /* initializing the special array for the return values */
01535        array_init(return_value);
01536 
01537        IMAPG(imap_acl_list) = return_value;
01538 
01539        /* set the callback for the GET_ACL function */
01540        mail_parameters(NIL, SET_ACL, (void *) mail_getacl);
01541        if (!imap_getacl(imap_le_struct->imap_stream, mailbox)) {
01542               php_error(E_WARNING, "c-client imap_getacl failed");
01543               zval_dtor(return_value);
01544               RETURN_FALSE;
01545        }
01546 
01547        IMAPG(imap_acl_list) = NIL;
01548 }
01549 /* }}} */
01550 #endif /* HAVE_IMAP2000 || HAVE_IMAP2001 */
01551 
01552 /* {{{ proto bool imap_expunge(resource stream_id)
01553    Permanently delete all messages marked for deletion */
01554 PHP_FUNCTION(imap_expunge)
01555 {
01556        zval *streamind;
01557        pils *imap_le_struct;
01558 
01559        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &streamind) == FAILURE) {
01560               return;
01561        }
01562 
01563        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
01564 
01565        mail_expunge (imap_le_struct->imap_stream);
01566 
01567        RETURN_TRUE;
01568 }
01569 /* }}} */
01570 
01571 /* {{{ proto bool imap_gc(resource stream_id, int flags)
01572    This function garbage collects (purges) the cache of entries of a specific type. */
01573 PHP_FUNCTION(imap_gc)
01574 {
01575        zval *streamind;
01576        pils *imap_le_struct;
01577        long flags;
01578 
01579        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &streamind, &flags) == FAILURE) {
01580               return;
01581        }
01582 
01583        if (flags && ((flags & ~(GC_TEXTS | GC_ELT | GC_ENV)) != 0)) {
01584               php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid value for the flags parameter");
01585               RETURN_FALSE;
01586        }
01587 
01588        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
01589 
01590        mail_gc(imap_le_struct->imap_stream, flags);
01591 
01592        RETURN_TRUE;
01593 }
01594 /* }}} */
01595 
01596 /* {{{ proto bool imap_close(resource stream_id [, int options])
01597    Close an IMAP stream */
01598 PHP_FUNCTION(imap_close)
01599 {
01600        zval *streamind;
01601        pils *imap_le_struct=NULL;
01602        long options = 0, flags = NIL;
01603        int argc = ZEND_NUM_ARGS();
01604 
01605        if (zend_parse_parameters(argc TSRMLS_CC, "r|l", &streamind, &options) == FAILURE) {
01606               return;
01607        }
01608 
01609        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
01610 
01611        if (argc == 2) {
01612               flags = options;
01613 
01614               /* Check that flags is exactly equal to PHP_EXPUNGE or zero */
01615               if (flags && ((flags & ~PHP_EXPUNGE) != 0)) {
01616                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid value for the flags parameter");
01617                      RETURN_FALSE;
01618               }
01619 
01620               /* Do the translation from PHP's internal PHP_EXPUNGE define to c-client's CL_EXPUNGE */
01621               if (flags & PHP_EXPUNGE) {
01622                      flags ^= PHP_EXPUNGE;
01623                      flags |= CL_EXPUNGE;
01624               }
01625               imap_le_struct->flags = flags;
01626        }
01627 
01628        zend_list_delete(Z_RESVAL_P(streamind));
01629 
01630        RETURN_TRUE;
01631 }
01632 /* }}} */
01633 
01634 /* {{{ proto array imap_headers(resource stream_id)
01635    Returns headers for all messages in a mailbox */
01636 PHP_FUNCTION(imap_headers)
01637 {
01638        zval *streamind;
01639        pils *imap_le_struct;
01640        unsigned long i;
01641        char *t;
01642        unsigned int msgno;
01643        char tmp[MAILTMPLEN];
01644 
01645        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &streamind) == FAILURE) {
01646               return;
01647        }
01648 
01649        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
01650 
01651        /* Initialize return array */
01652        array_init(return_value);
01653 
01654        for (msgno = 1; msgno <= imap_le_struct->imap_stream->nmsgs; msgno++) {
01655               MESSAGECACHE * cache = mail_elt (imap_le_struct->imap_stream, msgno);
01656               mail_fetchstructure(imap_le_struct->imap_stream, msgno, NIL);
01657               tmp[0] = cache->recent ? (cache->seen ? 'R': 'N') : ' ';
01658               tmp[1] = (cache->recent | cache->seen) ? ' ' : 'U';
01659               tmp[2] = cache->flagged ? 'F' : ' ';
01660               tmp[3] = cache->answered ? 'A' : ' ';
01661               tmp[4] = cache->deleted ? 'D' : ' ';
01662               tmp[5] = cache->draft ? 'X' : ' ';
01663               snprintf(tmp + 6, sizeof(tmp) - 6, "%4ld) ", cache->msgno);
01664               mail_date(tmp+11, cache);
01665               tmp[22] = ' ';
01666               tmp[23] = '\0';
01667               mail_fetchfrom(tmp+23, imap_le_struct->imap_stream, msgno, (long)20);
01668               strcat(tmp, " ");
01669               if ((i = cache->user_flags)) {
01670                      strcat(tmp, "{");
01671                      while (i) {
01672                             strlcat(tmp, imap_le_struct->imap_stream->user_flags[find_rightmost_bit (&i)], sizeof(tmp));
01673                             if (i) strlcat(tmp, " ", sizeof(tmp));
01674                      }
01675                      strlcat(tmp, "} ", sizeof(tmp));
01676               }
01677               mail_fetchsubject(t = tmp + strlen(tmp), imap_le_struct->imap_stream, msgno, (long)25);
01678               snprintf(t += strlen(t), sizeof(tmp) - strlen(tmp), " (%ld chars)", cache->rfc822_size);
01679               add_next_index_string(return_value, tmp, 1);
01680        }
01681 }
01682 /* }}} */
01683 
01684 /* {{{ proto string imap_body(resource stream_id, int msg_no [, int options])
01685    Read the message body */
01686 PHP_FUNCTION(imap_body)
01687 {
01688        zval *streamind;
01689        long msgno, flags = 0;
01690        pils *imap_le_struct;
01691        int msgindex, argc = ZEND_NUM_ARGS();
01692        char *body;
01693        unsigned long body_len = 0;
01694 
01695        if (zend_parse_parameters(argc TSRMLS_CC, "rl|l", &streamind, &msgno, &flags) == FAILURE) {
01696               return;
01697        }
01698 
01699        if (flags && ((flags & ~(FT_UID|FT_PEEK|FT_INTERNAL)) != 0)) {
01700               php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid value for the options parameter");
01701               RETURN_FALSE;
01702        }
01703 
01704        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
01705 
01706        if ((argc == 3) && (flags & FT_UID)) {
01707               /* This should be cached; if it causes an extra RTT to the
01708                  IMAP server, then that's the price we pay for making
01709                  sure we don't crash. */
01710               msgindex = mail_msgno(imap_le_struct->imap_stream, msgno);
01711        } else {
01712               msgindex = msgno;
01713        }
01714        if ((msgindex < 1) || ((unsigned) msgindex > imap_le_struct->imap_stream->nmsgs)) {
01715               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad message number");
01716               RETURN_FALSE;
01717        }
01718 
01719        body = mail_fetchtext_full (imap_le_struct->imap_stream, msgno, &body_len, (argc == 3 ? flags : NIL));
01720        if (body_len == 0) {
01721               RETVAL_EMPTY_STRING();
01722        } else {
01723               RETVAL_STRINGL(body, body_len, 1);
01724        }
01725 }
01726 /* }}} */
01727 
01728 /* {{{ proto bool imap_mail_copy(resource stream_id, string msglist, string mailbox [, int options])
01729    Copy specified message to a mailbox */
01730 PHP_FUNCTION(imap_mail_copy)
01731 {
01732        zval *streamind;
01733        long options = 0;
01734        char *seq, *folder;
01735        int seq_len, folder_len, argc = ZEND_NUM_ARGS();
01736        pils *imap_le_struct;
01737 
01738        if (zend_parse_parameters(argc TSRMLS_CC, "rss|l", &streamind, &seq, &seq_len, &folder, &folder_len, &options) == FAILURE) {
01739               return;
01740        }
01741 
01742        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
01743 
01744        if (mail_copy_full(imap_le_struct->imap_stream, seq, folder, (argc == 4 ? options : NIL)) == T) {
01745               RETURN_TRUE;
01746        } else {
01747               RETURN_FALSE;
01748        }
01749 }
01750 /* }}} */
01751 
01752 /* {{{ proto bool imap_mail_move(resource stream_id, string sequence, string mailbox [, int options])
01753    Move specified message to a mailbox */
01754 PHP_FUNCTION(imap_mail_move)
01755 {
01756        zval *streamind;
01757        char *seq, *folder;
01758        int seq_len, folder_len;
01759        long options = 0;
01760        pils *imap_le_struct;
01761        int argc = ZEND_NUM_ARGS();
01762 
01763        if (zend_parse_parameters(argc TSRMLS_CC, "rss|l", &streamind, &seq, &seq_len, &folder, &folder_len, &options) == FAILURE) {
01764               return;
01765        }
01766 
01767        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
01768 
01769        if (mail_copy_full(imap_le_struct->imap_stream, seq, folder, (argc == 4 ? (options | CP_MOVE) : CP_MOVE)) == T) {
01770               RETURN_TRUE;
01771        } else {
01772               RETURN_FALSE;
01773        }
01774 }
01775 /* }}} */
01776 
01777 /* {{{ proto bool imap_createmailbox(resource stream_id, string mailbox)
01778    Create a new mailbox */
01779 PHP_FUNCTION(imap_createmailbox)
01780 {
01781        zval *streamind;
01782        char *folder;
01783        int folder_len;
01784        pils *imap_le_struct;
01785 
01786        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &streamind, &folder, &folder_len) == FAILURE) {
01787               return;
01788        }
01789 
01790        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
01791 
01792        if (mail_create(imap_le_struct->imap_stream, folder) == T) {
01793               RETURN_TRUE;
01794        } else {
01795               RETURN_FALSE;
01796        }
01797 }
01798 /* }}} */
01799 
01800 /* {{{ proto bool imap_renamemailbox(resource stream_id, string old_name, string new_name)
01801    Rename a mailbox */
01802 PHP_FUNCTION(imap_renamemailbox)
01803 {
01804        zval *streamind;
01805        char *old_mailbox, *new_mailbox;
01806        int old_mailbox_len, new_mailbox_len;
01807        pils *imap_le_struct;
01808 
01809        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &streamind, &old_mailbox, &old_mailbox_len, &new_mailbox, &new_mailbox_len) == FAILURE) {
01810               return;
01811        }
01812 
01813        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
01814 
01815        if (mail_rename(imap_le_struct->imap_stream, old_mailbox, new_mailbox) == T) {
01816               RETURN_TRUE;
01817        } else {
01818               RETURN_FALSE;
01819        }
01820 }
01821 /* }}} */
01822 
01823 /* {{{ proto bool imap_deletemailbox(resource stream_id, string mailbox)
01824    Delete a mailbox */
01825 PHP_FUNCTION(imap_deletemailbox)
01826 {
01827        zval *streamind;
01828        char *folder;
01829        int folder_len;
01830        pils *imap_le_struct;
01831 
01832        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &streamind, &folder, &folder_len) == FAILURE) {
01833               return;
01834        }
01835 
01836        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
01837 
01838        if (mail_delete(imap_le_struct->imap_stream, folder) == T) {
01839               RETURN_TRUE;
01840        } else {
01841               RETURN_FALSE;
01842        }
01843 }
01844 /* }}} */
01845 
01846 /* {{{ proto array imap_list(resource stream_id, string ref, string pattern)
01847    Read the list of mailboxes */
01848 PHP_FUNCTION(imap_list)
01849 {
01850        zval *streamind;
01851        char *ref, *pat;
01852        int ref_len, pat_len;
01853        pils *imap_le_struct;
01854        STRINGLIST *cur=NIL;
01855 
01856        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &streamind, &ref, &ref_len, &pat, &pat_len) == FAILURE) {
01857               return;
01858        }
01859 
01860        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
01861 
01862        /* set flag for normal, old mailbox list */
01863        IMAPG(folderlist_style) = FLIST_ARRAY;
01864 
01865        IMAPG(imap_folders) = IMAPG(imap_folders_tail) = NIL;
01866        mail_list(imap_le_struct->imap_stream, ref, pat);
01867        if (IMAPG(imap_folders) == NIL) {
01868               RETURN_FALSE;
01869        }
01870 
01871        array_init(return_value);
01872        cur=IMAPG(imap_folders);
01873        while (cur != NIL) {
01874               add_next_index_string(return_value, cur->LTEXT, 1);
01875               cur=cur->next;
01876        }
01877        mail_free_stringlist (&IMAPG(imap_folders));
01878        IMAPG(imap_folders) = IMAPG(imap_folders_tail) = NIL;
01879 }
01880 
01881 /* }}} */
01882 
01883 /* {{{ proto array imap_getmailboxes(resource stream_id, string ref, string pattern)
01884    Reads the list of mailboxes and returns a full array of objects containing name, attributes, and delimiter */
01885 /* Author: CJH */
01886 PHP_FUNCTION(imap_list_full)
01887 {
01888        zval *streamind, *mboxob;
01889        char *ref, *pat;
01890        int ref_len, pat_len;
01891        pils *imap_le_struct;
01892        FOBJECTLIST *cur=NIL;
01893        char *delim=NIL;
01894 
01895        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &streamind, &ref, &ref_len, &pat, &pat_len) == FAILURE) {
01896               return;
01897        }
01898 
01899        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
01900 
01901        /* set flag for new, improved array of objects mailbox list */
01902        IMAPG(folderlist_style) = FLIST_OBJECT;
01903 
01904        IMAPG(imap_folder_objects) = IMAPG(imap_folder_objects_tail) = NIL;
01905        mail_list(imap_le_struct->imap_stream, ref, pat);
01906        if (IMAPG(imap_folder_objects) == NIL) {
01907               RETURN_FALSE;
01908        }
01909 
01910        array_init(return_value);
01911        delim = safe_emalloc(2, sizeof(char), 0);
01912        cur=IMAPG(imap_folder_objects);
01913        while (cur != NIL) {
01914               MAKE_STD_ZVAL(mboxob);
01915               object_init(mboxob);
01916               add_property_string(mboxob, "name", cur->LTEXT, 1);
01917               add_property_long(mboxob, "attributes", cur->attributes);
01918 #ifdef IMAP41
01919               delim[0] = (char)cur->delimiter;
01920               delim[1] = 0;
01921               add_property_string(mboxob, "delimiter", delim, 1);
01922 #else
01923               add_property_string(mboxob, "delimiter", cur->delimiter, 1);
01924 #endif
01925               add_next_index_object(return_value, mboxob TSRMLS_CC);
01926               cur=cur->next;
01927        }
01928        mail_free_foblist(&IMAPG(imap_folder_objects), &IMAPG(imap_folder_objects_tail));
01929        efree(delim);
01930        IMAPG(folderlist_style) = FLIST_ARRAY;           /* reset to default */
01931 }
01932 /* }}} */
01933 
01934 /* {{{ proto array imap_listscan(resource stream_id, string ref, string pattern, string content)
01935    Read list of mailboxes containing a certain string */
01936 PHP_FUNCTION(imap_listscan)
01937 {
01938        zval *streamind;
01939        char *ref, *pat, *content;
01940        int ref_len, pat_len, content_len;
01941        pils *imap_le_struct;
01942        STRINGLIST *cur=NIL;
01943 
01944        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsss", &streamind, &ref, &ref_len, &pat, &pat_len, &content, &content_len) == FAILURE) {
01945               return;
01946        }
01947 
01948        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
01949 
01950        IMAPG(imap_folders) = NIL;
01951        mail_scan(imap_le_struct->imap_stream, ref, pat, content);
01952        if (IMAPG(imap_folders) == NIL) {
01953               RETURN_FALSE;
01954        }
01955 
01956        array_init(return_value);
01957        cur=IMAPG(imap_folders);
01958        while (cur != NIL) {
01959               add_next_index_string(return_value, cur->LTEXT, 1);
01960               cur=cur->next;
01961        }
01962        mail_free_stringlist (&IMAPG(imap_folders));
01963        IMAPG(imap_folders) = IMAPG(imap_folders_tail) = NIL;
01964 }
01965 
01966 /* }}} */
01967 
01968 /* {{{ proto object imap_check(resource stream_id)
01969    Get mailbox properties */
01970 PHP_FUNCTION(imap_check)
01971 {
01972        zval *streamind;
01973        pils *imap_le_struct;
01974        char date[100];
01975 
01976        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &streamind) == FAILURE) {
01977               return;
01978        }
01979 
01980        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
01981 
01982        if (mail_ping (imap_le_struct->imap_stream) == NIL) {
01983               RETURN_FALSE;
01984        }
01985 
01986        if (imap_le_struct->imap_stream && imap_le_struct->imap_stream->mailbox) {
01987               rfc822_date(date);
01988               object_init(return_value);
01989               add_property_string(return_value, "Date", date, 1);
01990               add_property_string(return_value, "Driver", imap_le_struct->imap_stream->dtb->name, 1);
01991               add_property_string(return_value, "Mailbox", imap_le_struct->imap_stream->mailbox, 1);
01992               add_property_long(return_value, "Nmsgs", imap_le_struct->imap_stream->nmsgs);
01993               add_property_long(return_value, "Recent", imap_le_struct->imap_stream->recent);
01994        } else {
01995               RETURN_FALSE;
01996        }
01997 }
01998 /* }}} */
01999 
02000 /* {{{ proto bool imap_delete(resource stream_id, int msg_no [, int options])
02001    Mark a message for deletion */
02002 PHP_FUNCTION(imap_delete)
02003 {
02004        zval *streamind, **sequence;
02005        pils *imap_le_struct;
02006        long flags = 0;
02007        int argc = ZEND_NUM_ARGS();
02008 
02009        if (zend_parse_parameters(argc TSRMLS_CC, "rZ|l", &streamind, &sequence, &flags) == FAILURE) {
02010               return;
02011        }
02012 
02013        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
02014 
02015        convert_to_string_ex(sequence);
02016 
02017        mail_setflag_full(imap_le_struct->imap_stream, Z_STRVAL_PP(sequence), "\\DELETED", (argc == 3 ? flags : NIL));
02018        RETVAL_TRUE;
02019 }
02020 /* }}} */
02021 
02022 /* {{{ proto bool imap_undelete(resource stream_id, int msg_no [, int flags])
02023    Remove the delete flag from a message */
02024 PHP_FUNCTION(imap_undelete)
02025 {
02026        zval *streamind, **sequence;
02027        long flags = 0;
02028        pils *imap_le_struct;
02029        int argc = ZEND_NUM_ARGS();
02030 
02031        if (zend_parse_parameters(argc TSRMLS_CC, "rZ|l", &streamind, &sequence, &flags) == FAILURE) {
02032               return;
02033        }
02034 
02035        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
02036 
02037        convert_to_string_ex(sequence);
02038 
02039        mail_clearflag_full(imap_le_struct->imap_stream, Z_STRVAL_PP(sequence), "\\DELETED", (argc == 3 ? flags : NIL));
02040        RETVAL_TRUE;
02041 }
02042 /* }}} */
02043 
02044 /* {{{ proto object imap_headerinfo(resource stream_id, int msg_no [, int from_length [, int subject_length [, string default_host]]])
02045    Read the headers of the message */
02046 PHP_FUNCTION(imap_headerinfo)
02047 {
02048        zval *streamind;
02049        char *defaulthost = NULL;
02050        int defaulthost_len = 0, argc = ZEND_NUM_ARGS();
02051        long msgno, fromlength, subjectlength;
02052        pils *imap_le_struct;
02053        MESSAGECACHE *cache;
02054        ENVELOPE *en;
02055        char dummy[2000], fulladdress[MAILTMPLEN + 1];
02056 
02057        if (zend_parse_parameters(argc TSRMLS_CC, "rl|lls", &streamind, &msgno, &fromlength, &subjectlength, &defaulthost, &defaulthost_len) == FAILURE) {
02058               return;
02059        }
02060 
02061        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
02062 
02063        if (argc >= 3) {
02064               if (fromlength < 0 || fromlength > MAILTMPLEN) {
02065                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "From length has to be between 0 and %d", MAILTMPLEN);
02066                      RETURN_FALSE;
02067               }
02068        } else {
02069               fromlength = 0x00;
02070        }
02071        if (argc >= 4) {
02072               if (subjectlength < 0 || subjectlength > MAILTMPLEN) {
02073                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Subject length has to be between 0 and %d", MAILTMPLEN);
02074                      RETURN_FALSE;
02075               }
02076        } else {
02077               subjectlength = 0x00;
02078        }
02079 
02080        PHP_IMAP_CHECK_MSGNO(msgno);
02081 
02082        if (mail_fetchstructure(imap_le_struct->imap_stream, msgno, NIL)) {
02083               cache = mail_elt(imap_le_struct->imap_stream, msgno);
02084        } else {
02085               RETURN_FALSE;
02086        }
02087 
02088        en = mail_fetchenvelope(imap_le_struct->imap_stream, msgno);
02089 
02090        /* call a function to parse all the text, so that we can use the
02091           same function to parse text from other sources */
02092        _php_make_header_object(return_value, en TSRMLS_CC);
02093 
02094        /* now run through properties that are only going to be returned
02095           from a server, not text headers */
02096        add_property_string(return_value, "Recent", cache->recent ? (cache->seen ? "R": "N") : " ", 1);
02097        add_property_string(return_value, "Unseen", (cache->recent | cache->seen) ? " " : "U", 1);
02098        add_property_string(return_value, "Flagged", cache->flagged ? "F" : " ", 1);
02099        add_property_string(return_value, "Answered", cache->answered ? "A" : " ", 1);
02100        add_property_string(return_value, "Deleted", cache->deleted ? "D" : " ", 1);
02101        add_property_string(return_value, "Draft", cache->draft ? "X" : " ", 1);
02102 
02103        snprintf(dummy, sizeof(dummy), "%4ld", cache->msgno);
02104        add_property_string(return_value, "Msgno", dummy, 1);
02105 
02106        mail_date(dummy, cache);
02107        add_property_string(return_value, "MailDate", dummy, 1);
02108 
02109        snprintf(dummy, sizeof(dummy), "%ld", cache->rfc822_size);
02110        add_property_string(return_value, "Size", dummy, 1);
02111 
02112        add_property_long(return_value, "udate", mail_longdate(cache));
02113 
02114        if (en->from && fromlength) {
02115               fulladdress[0] = 0x00;
02116               mail_fetchfrom(fulladdress, imap_le_struct->imap_stream, msgno, fromlength);
02117               add_property_string(return_value, "fetchfrom", fulladdress, 1);
02118        }
02119        if (en->subject && subjectlength) {
02120               fulladdress[0] = 0x00;
02121               mail_fetchsubject(fulladdress, imap_le_struct->imap_stream, msgno, subjectlength);
02122               add_property_string(return_value, "fetchsubject", fulladdress, 1);
02123        }
02124 }
02125 /* }}} */
02126 
02127 /* {{{ proto object imap_rfc822_parse_headers(string headers [, string default_host])
02128    Parse a set of mail headers contained in a string, and return an object similar to imap_headerinfo() */
02129 PHP_FUNCTION(imap_rfc822_parse_headers)
02130 {
02131        char *headers, *defaulthost = NULL;
02132        ENVELOPE *en;
02133        int headers_len, defaulthost_len = 0, argc = ZEND_NUM_ARGS();
02134 
02135        if (zend_parse_parameters(argc TSRMLS_CC, "s|s", &headers, &headers_len, &defaulthost, &defaulthost_len) == FAILURE) {
02136               return;
02137        }
02138 
02139        if (argc == 2) {
02140               rfc822_parse_msg(&en, NULL, headers, headers_len, NULL, defaulthost, NIL);
02141        } else {
02142               rfc822_parse_msg(&en, NULL, headers, headers_len, NULL, "UNKNOWN", NIL);
02143        }
02144 
02145        /* call a function to parse all the text, so that we can use the
02146           same function no matter where the headers are from */
02147        _php_make_header_object(return_value, en TSRMLS_CC);
02148        mail_free_envelope(&en);
02149 }
02150 /* }}} */
02151 
02152 /* KMLANG */
02153 /* {{{ proto array imap_lsub(resource stream_id, string ref, string pattern)
02154    Return a list of subscribed mailboxes */
02155 PHP_FUNCTION(imap_lsub)
02156 {
02157        zval *streamind;
02158        char *ref, *pat;
02159        int ref_len, pat_len;
02160        pils *imap_le_struct;
02161        STRINGLIST *cur=NIL;
02162 
02163        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &streamind, &ref, &ref_len, &pat, &pat_len) == FAILURE) {
02164               return;
02165        }
02166 
02167        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
02168 
02169        /* set flag for normal, old mailbox list */
02170        IMAPG(folderlist_style) = FLIST_ARRAY;
02171 
02172        IMAPG(imap_sfolders) = NIL;
02173        mail_lsub(imap_le_struct->imap_stream, ref, pat);
02174        if (IMAPG(imap_sfolders) == NIL) {
02175               RETURN_FALSE;
02176        }
02177 
02178        array_init(return_value);
02179        cur=IMAPG(imap_sfolders);
02180        while (cur != NIL) {
02181               add_next_index_string(return_value, cur->LTEXT, 1);
02182               cur=cur->next;
02183        }
02184        mail_free_stringlist (&IMAPG(imap_sfolders));
02185        IMAPG(imap_sfolders) = IMAPG(imap_sfolders_tail) = NIL;
02186 }
02187 /* }}} */
02188 
02189 /* {{{ proto array imap_getsubscribed(resource stream_id, string ref, string pattern)
02190    Return a list of subscribed mailboxes, in the same format as imap_getmailboxes() */
02191 /* Author: CJH */
02192 PHP_FUNCTION(imap_lsub_full)
02193 {
02194        zval *streamind, *mboxob;
02195        char *ref, *pat;
02196        int ref_len, pat_len;
02197        pils *imap_le_struct;
02198        FOBJECTLIST *cur=NIL;
02199        char *delim=NIL;
02200 
02201        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss", &streamind, &ref, &ref_len, &pat, &pat_len) == FAILURE) {
02202               return;
02203        }
02204 
02205        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
02206 
02207        /* set flag for new, improved array of objects list */
02208        IMAPG(folderlist_style) = FLIST_OBJECT;
02209 
02210        IMAPG(imap_sfolder_objects) = IMAPG(imap_sfolder_objects_tail) = NIL;
02211        mail_lsub(imap_le_struct->imap_stream, ref, pat);
02212        if (IMAPG(imap_sfolder_objects) == NIL) {
02213               RETURN_FALSE;
02214        }
02215 
02216        array_init(return_value);
02217        delim = safe_emalloc(2, sizeof(char), 0);
02218        cur=IMAPG(imap_sfolder_objects);
02219        while (cur != NIL) {
02220               MAKE_STD_ZVAL(mboxob);
02221               object_init(mboxob);
02222               add_property_string(mboxob, "name", cur->LTEXT, 1);
02223               add_property_long(mboxob, "attributes", cur->attributes);
02224 #ifdef IMAP41
02225               delim[0] = (char)cur->delimiter;
02226               delim[1] = 0;
02227               add_property_string(mboxob, "delimiter", delim, 1);
02228 #else
02229               add_property_string(mboxob, "delimiter", cur->delimiter, 1);
02230 #endif
02231               add_next_index_object(return_value, mboxob TSRMLS_CC);
02232               cur=cur->next;
02233        }
02234        mail_free_foblist (&IMAPG(imap_sfolder_objects), &IMAPG(imap_sfolder_objects_tail));
02235        efree(delim);
02236        IMAPG(folderlist_style) = FLIST_ARRAY; /* reset to default */
02237 }
02238 /* }}} */
02239 
02240 /* {{{ proto bool imap_subscribe(resource stream_id, string mailbox)
02241    Subscribe to a mailbox */
02242 PHP_FUNCTION(imap_subscribe)
02243 {
02244        zval *streamind;
02245        char *folder;
02246        int folder_len;
02247        pils *imap_le_struct;
02248 
02249        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &streamind, &folder, &folder_len) == FAILURE) {
02250               return;
02251        }
02252 
02253        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
02254 
02255        if (mail_subscribe(imap_le_struct->imap_stream, folder) == T) {
02256               RETURN_TRUE;
02257        } else {
02258               RETURN_FALSE;
02259        }
02260 }
02261 /* }}} */
02262 
02263 /* {{{ proto bool imap_unsubscribe(resource stream_id, string mailbox)
02264    Unsubscribe from a mailbox */
02265 PHP_FUNCTION(imap_unsubscribe)
02266 {
02267        zval *streamind;
02268        char *folder;
02269        int folder_len;
02270        pils *imap_le_struct;
02271 
02272        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &streamind, &folder, &folder_len) == FAILURE) {
02273               return;
02274        }
02275 
02276        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
02277 
02278        if (mail_unsubscribe(imap_le_struct->imap_stream, folder) == T) {
02279               RETURN_TRUE;
02280        } else {
02281               RETURN_FALSE;
02282        }
02283 }
02284 /* }}} */
02285 
02286 /* {{{ proto object imap_fetchstructure(resource stream_id, int msg_no [, int options])
02287    Read the full structure of a message */
02288 PHP_FUNCTION(imap_fetchstructure)
02289 {
02290        zval *streamind;
02291        long msgno, flags = 0;
02292        pils *imap_le_struct;
02293        BODY *body;
02294        int msgindex, argc = ZEND_NUM_ARGS();
02295 
02296        if (zend_parse_parameters(argc TSRMLS_CC, "rl|l", &streamind, &msgno, &flags) == FAILURE) {
02297               return;
02298        }
02299 
02300        if (flags && ((flags & ~FT_UID) != 0)) {
02301               php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid value for the options parameter");
02302               RETURN_FALSE;
02303        }
02304 
02305        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
02306 
02307        if (msgno < 1) {
02308               RETURN_FALSE;
02309        }
02310 
02311        object_init(return_value);
02312 
02313        if ((argc == 3) && (flags & FT_UID)) {
02314               /* This should be cached; if it causes an extra RTT to the
02315                  IMAP server, then that's the price we pay for making
02316                  sure we don't crash. */
02317               msgindex = mail_msgno(imap_le_struct->imap_stream, msgno);
02318        } else {
02319               msgindex = msgno;
02320        }
02321        PHP_IMAP_CHECK_MSGNO(msgindex);
02322 
02323        mail_fetchstructure_full(imap_le_struct->imap_stream, msgno, &body , (argc == 3 ? flags : NIL));
02324 
02325        if (!body) {
02326               php_error_docref(NULL TSRMLS_CC, E_WARNING, "No body information available");
02327               RETURN_FALSE;
02328        }
02329 
02330        _php_imap_add_body(return_value, body TSRMLS_CC);
02331 }
02332 /* }}} */
02333 
02334 /* {{{ proto string imap_fetchbody(resource stream_id, int msg_no, string section [, int options])
02335    Get a specific body section */
02336 PHP_FUNCTION(imap_fetchbody)
02337 {
02338        zval *streamind;
02339        long msgno, flags = 0;
02340        pils *imap_le_struct;
02341        char *body, *sec;
02342        int sec_len;
02343        unsigned long len;
02344        int argc = ZEND_NUM_ARGS();
02345 
02346        if (zend_parse_parameters(argc TSRMLS_CC, "rls|l", &streamind, &msgno, &sec, &sec_len, &flags) == FAILURE) {
02347               return;
02348        }
02349 
02350        if (flags && ((flags & ~(FT_UID|FT_PEEK|FT_INTERNAL)) != 0)) {
02351               php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid value for the options parameter");
02352               RETURN_FALSE;
02353        }
02354 
02355        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
02356 
02357        if (argc < 4 || !(flags & FT_UID)) {
02358               /* only perform the check if the msgno is a message number and not a UID */
02359               PHP_IMAP_CHECK_MSGNO(msgno);
02360        }
02361 
02362        body = mail_fetchbody_full(imap_le_struct->imap_stream, msgno, sec, &len, (argc == 4 ? flags : NIL));
02363 
02364        if (!body) {
02365               php_error_docref(NULL TSRMLS_CC, E_WARNING, "No body information available");
02366               RETURN_FALSE;
02367        }
02368        RETVAL_STRINGL(body, len, 1);
02369 }
02370 
02371 /* }}} */
02372 
02373 
02374 /* {{{ proto string imap_fetchmime(resource stream_id, int msg_no, string section [, int options])
02375    Get a specific body section's MIME headers */
02376 PHP_FUNCTION(imap_fetchmime)
02377 {
02378        zval *streamind;
02379        long msgno, flags = 0;
02380        pils *imap_le_struct;
02381        char *body, *sec;
02382        int sec_len;
02383        unsigned long len;
02384        int argc = ZEND_NUM_ARGS();
02385 
02386        if (zend_parse_parameters(argc TSRMLS_CC, "rls|l", &streamind, &msgno, &sec, &sec_len, &flags) == FAILURE) {
02387               return;
02388        }
02389 
02390        if (flags && ((flags & ~(FT_UID|FT_PEEK|FT_INTERNAL)) != 0)) {
02391               php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid value for the options parameter");
02392               RETURN_FALSE;
02393        }
02394 
02395        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
02396 
02397        if (argc < 4 || !(flags & FT_UID)) {
02398               /* only perform the check if the msgno is a message number and not a UID */
02399               PHP_IMAP_CHECK_MSGNO(msgno);
02400        }
02401 
02402        body = mail_fetch_mime(imap_le_struct->imap_stream, msgno, sec, &len, (argc == 4 ? flags : NIL));
02403 
02404        if (!body) {
02405               php_error_docref(NULL TSRMLS_CC, E_WARNING, "No body MIME information available");
02406               RETURN_FALSE;
02407        }
02408        RETVAL_STRINGL(body, len, 1);
02409 }
02410 
02411 /* }}} */
02412 
02413 /* {{{ proto bool imap_savebody(resource stream_id, string|resource file, int msg_no[, string section = ""[, int options = 0]])
02414        Save a specific body section to a file */
02415 PHP_FUNCTION(imap_savebody)
02416 {
02417        zval *stream, **out;
02418        pils *imap_ptr = NULL;
02419        php_stream *writer = NULL;
02420        char *section = "";
02421        int section_len = 0, close_stream = 1;
02422        long msgno, flags = 0;
02423 
02424        if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rZl|sl", &stream, &out, &msgno, &section, &section_len, &flags)) {
02425               RETURN_FALSE;
02426        }
02427 
02428        ZEND_FETCH_RESOURCE(imap_ptr, pils *, &stream, -1, "imap", le_imap);
02429 
02430        if (!imap_ptr) {
02431               RETURN_FALSE;
02432        }
02433 
02434        switch (Z_TYPE_PP(out))
02435        {
02436               case IS_LONG:
02437               case IS_RESOURCE:
02438                      close_stream = 0;
02439                      php_stream_from_zval(writer, out);
02440               break;
02441 
02442               default:
02443                      convert_to_string_ex(out);
02444                      writer = php_stream_open_wrapper(Z_STRVAL_PP(out), "wb", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL);
02445               break;
02446        }
02447 
02448        if (!writer) {
02449               RETURN_FALSE;
02450        }
02451 
02452        IMAPG(gets_stream) = writer;
02453        mail_parameters(NIL, SET_GETS, (void *) php_mail_gets);
02454        mail_fetchbody_full(imap_ptr->imap_stream, msgno, section, NULL, flags);
02455        mail_parameters(NIL, SET_GETS, (void *) NULL);
02456        IMAPG(gets_stream) = NULL;
02457 
02458        if (close_stream) {
02459               php_stream_close(writer);
02460        }
02461 
02462        RETURN_TRUE;
02463 }
02464 /* }}} */
02465 
02466 /* {{{ proto string imap_base64(string text)
02467    Decode BASE64 encoded text */
02468 PHP_FUNCTION(imap_base64)
02469 {
02470        char *text, *decode;
02471        int text_len;
02472        unsigned long newlength;
02473 
02474        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &text, &text_len) == FAILURE) {
02475               return;
02476        }
02477 
02478        decode = (char *) rfc822_base64((unsigned char *) text, text_len, &newlength);
02479 
02480        if (decode == NULL) {
02481               RETURN_FALSE;
02482        }
02483 
02484        RETVAL_STRINGL(decode, newlength, 1);
02485        fs_give((void**) &decode);
02486 }
02487 /* }}} */
02488 
02489 /* {{{ proto string imap_qprint(string text)
02490    Convert a quoted-printable string to an 8-bit string */
02491 PHP_FUNCTION(imap_qprint)
02492 {
02493        char *text, *decode;
02494        int text_len;
02495        unsigned long newlength;
02496 
02497        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &text, &text_len) == FAILURE) {
02498               return;
02499        }
02500 
02501        decode = (char *) rfc822_qprint((unsigned char *) text, text_len, &newlength);
02502 
02503        if (decode == NULL) {
02504               RETURN_FALSE;
02505        }
02506 
02507        RETVAL_STRINGL(decode, newlength, 1);
02508        fs_give((void**) &decode);
02509 }
02510 /* }}} */
02511 
02512 /* {{{ proto string imap_8bit(string text)
02513    Convert an 8-bit string to a quoted-printable string */
02514 PHP_FUNCTION(imap_8bit)
02515 {
02516        char *text, *decode;
02517        int text_len;
02518        unsigned long newlength;
02519 
02520        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &text, &text_len) == FAILURE) {
02521               return;
02522        }
02523 
02524        decode = (char *) rfc822_8bit((unsigned char *) text, text_len, &newlength);
02525 
02526        if (decode == NULL) {
02527               RETURN_FALSE;
02528        }
02529 
02530        RETVAL_STRINGL(decode, newlength, 1);
02531        fs_give((void**) &decode);
02532 }
02533 /* }}} */
02534 
02535 /* {{{ proto string imap_binary(string text)
02536    Convert an 8bit string to a base64 string */
02537 PHP_FUNCTION(imap_binary)
02538 {
02539        char *text, *decode;
02540        int text_len;
02541        unsigned long newlength;
02542 
02543        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &text, &text_len) == FAILURE) {
02544               return;
02545        }
02546 
02547        decode = rfc822_binary(text, text_len, &newlength);
02548 
02549        if (decode == NULL) {
02550               RETURN_FALSE;
02551        }
02552 
02553        RETVAL_STRINGL(decode, newlength, 1);
02554        fs_give((void**) &decode);
02555 }
02556 /* }}} */
02557 
02558 /* {{{ proto object imap_mailboxmsginfo(resource stream_id)
02559    Returns info about the current mailbox */
02560 PHP_FUNCTION(imap_mailboxmsginfo)
02561 {
02562        zval *streamind;
02563        pils *imap_le_struct;
02564        char date[100];
02565        unsigned int msgno, unreadmsg, deletedmsg, msize;
02566 
02567        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &streamind) == FAILURE) {
02568               return;
02569        }
02570 
02571        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
02572 
02573        /* Initialize return object */
02574        object_init(return_value);
02575 
02576        unreadmsg = 0;
02577        deletedmsg = 0;
02578        msize = 0;
02579 
02580        for (msgno = 1; msgno <= imap_le_struct->imap_stream->nmsgs; msgno++) {
02581               MESSAGECACHE * cache = mail_elt (imap_le_struct->imap_stream, msgno);
02582               mail_fetchstructure (imap_le_struct->imap_stream, msgno, NIL);
02583 
02584               if (!cache->seen || cache->recent) {
02585                      unreadmsg++;
02586               }
02587 
02588               if (cache->deleted) {
02589                      deletedmsg++;
02590               }
02591               msize = msize + cache->rfc822_size;
02592        }
02593        add_property_long(return_value, "Unread", unreadmsg);
02594        add_property_long(return_value, "Deleted", deletedmsg);
02595        add_property_long(return_value, "Nmsgs", imap_le_struct->imap_stream->nmsgs);
02596        add_property_long(return_value, "Size", msize);
02597        rfc822_date(date);
02598        add_property_string(return_value, "Date", date, 1);
02599        add_property_string(return_value, "Driver", imap_le_struct->imap_stream->dtb->name, 1);
02600        add_property_string(return_value, "Mailbox", imap_le_struct->imap_stream->mailbox, 1);
02601        add_property_long(return_value, "Recent", imap_le_struct->imap_stream->recent);
02602 }
02603 /* }}} */
02604 
02605 /* {{{ proto string imap_rfc822_write_address(string mailbox, string host, string personal)
02606    Returns a properly formatted email address given the mailbox, host, and personal info */
02607 PHP_FUNCTION(imap_rfc822_write_address)
02608 {
02609        char *mailbox, *host, *personal;
02610        int mailbox_len, host_len, personal_len;
02611        ADDRESS *addr;
02612        char *string;
02613 
02614        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss", &mailbox, &mailbox_len, &host, &host_len, &personal, &personal_len) == FAILURE) {
02615               return;
02616        }
02617 
02618        addr=mail_newaddr();
02619 
02620        if (mailbox) {
02621               addr->mailbox = cpystr(mailbox);
02622        }
02623 
02624        if (host) {
02625               addr->host = cpystr(host);
02626        }
02627 
02628        if (personal) {
02629               addr->personal = cpystr(personal);
02630        }
02631 
02632        addr->next=NIL;
02633        addr->error=NIL;
02634        addr->adl=NIL;
02635 
02636        string = _php_rfc822_write_address(addr TSRMLS_CC);
02637        if (string) {
02638               RETVAL_STRING(string, 0);
02639        } else {
02640               RETURN_FALSE;
02641        }
02642 }
02643 /* }}} */
02644 
02645 /* {{{ proto array imap_rfc822_parse_adrlist(string address_string, string default_host)
02646    Parses an address string */
02647 PHP_FUNCTION(imap_rfc822_parse_adrlist)
02648 {
02649        zval *tovals;
02650        char *str, *defaulthost, *str_copy;
02651        int str_len, defaulthost_len;
02652        ADDRESS *addresstmp;
02653        ENVELOPE *env;
02654 
02655        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &str, &str_len, &defaulthost, &defaulthost_len) == FAILURE) {
02656               return;
02657        }
02658 
02659        env = mail_newenvelope();
02660 
02661        /* rfc822_parse_adrlist() modifies passed string. Copy it. */
02662        str_copy = estrndup(str, str_len);
02663        rfc822_parse_adrlist(&env->to, str_copy, defaulthost);
02664        efree(str_copy);
02665 
02666        array_init(return_value);
02667 
02668        addresstmp = env->to;
02669 
02670        if (addresstmp) do {
02671               MAKE_STD_ZVAL(tovals);
02672               object_init(tovals);
02673               if (addresstmp->mailbox) {
02674                      add_property_string(tovals, "mailbox", addresstmp->mailbox, 1);
02675               }
02676               if (addresstmp->host) {
02677                      add_property_string(tovals, "host", addresstmp->host, 1);
02678               }
02679               if (addresstmp->personal) {
02680                      add_property_string(tovals, "personal", addresstmp->personal, 1);
02681               }
02682               if (addresstmp->adl) {
02683                      add_property_string(tovals, "adl", addresstmp->adl, 1);
02684               }
02685               add_next_index_object(return_value, tovals TSRMLS_CC);
02686        } while ((addresstmp = addresstmp->next));
02687 
02688        mail_free_envelope(&env);
02689 }
02690 /* }}} */
02691 
02692 /* {{{ proto string imap_utf8(string mime_encoded_text)
02693    Convert a mime-encoded text to UTF-8 */
02694 PHP_FUNCTION(imap_utf8)
02695 {
02696        char *str;
02697        int str_len;
02698        SIZEDTEXT src, dest;
02699 
02700        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) {
02701               return;
02702        }
02703 
02704        src.data  = NULL;
02705        src.size  = 0;
02706        dest.data = NULL;
02707        dest.size = 0;
02708 
02709        cpytxt(&src, str, str_len);
02710 
02711 #ifndef HAVE_NEW_MIME2TEXT
02712        utf8_mime2text(&src, &dest);
02713 #else
02714        utf8_mime2text(&src, &dest, U8T_DECOMPOSE);
02715 #endif
02716        RETVAL_STRINGL(dest.data, dest.size, 1);
02717        if (dest.data) {
02718               free(dest.data);
02719        }
02720        if (src.data && src.data != dest.data) {
02721               free(src.data);
02722        }
02723 }
02724 /* }}} */
02725 
02726 /* {{{ macros for the modified utf7 conversion functions
02727  *
02728  * author: Andrew Skalski <askalski@chek.com>
02729  */
02730 
02731 /* tests `c' and returns true if it is a special character */
02732 #define SPECIAL(c) ((c) <= 0x1f || (c) >= 0x7f)
02733 
02734 /* validate a modified-base64 character */
02735 #define B64CHAR(c) (isalnum(c) || (c) == '+' || (c) == ',')
02736 
02737 /* map the low 64 bits of `n' to the modified-base64 characters */
02738 #define B64(n)       ("ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
02739                             "abcdefghijklmnopqrstuvwxyz0123456789+,"[(n) & 0x3f])
02740 
02741 /* map the modified-base64 character `c' to its 64 bit value */
02742 #define UNB64(c)     ((c) == '+' ? 62 : (c) == ',' ? 63 : (c) >= 'a' ? \
02743                                    (c) - 71 : (c) >= 'A' ? (c) - 65 : (c) + 4)
02744 /* }}} */
02745 
02746 /* {{{ proto string imap_utf7_decode(string buf)
02747    Decode a modified UTF-7 string */
02748 PHP_FUNCTION(imap_utf7_decode)
02749 {
02750        /* author: Andrew Skalski <askalski@chek.com> */
02751        char *arg;
02752        const unsigned char *in, *inp, *endp;
02753        unsigned char *out, *outp;
02754        unsigned char c;
02755        int arg_len, inlen, outlen;
02756        enum {
02757               ST_NORMAL,    /* printable text */
02758               ST_DECODE0,   /* encoded text rotation... */
02759               ST_DECODE1,
02760               ST_DECODE2,
02761               ST_DECODE3
02762        } state;
02763 
02764        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) {
02765               return;
02766        }
02767 
02768        in = (const unsigned char *) arg;
02769        inlen = arg_len;
02770 
02771        /* validate and compute length of output string */
02772        outlen = 0;
02773        state = ST_NORMAL;
02774        for (endp = (inp = in) + inlen; inp < endp; inp++) {
02775               if (state == ST_NORMAL) {
02776                      /* process printable character */
02777                      if (SPECIAL(*inp)) {
02778                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid modified UTF-7 character: `%c'", *inp);
02779                             RETURN_FALSE;
02780                      } else if (*inp != '&') {
02781                             outlen++;
02782                      } else if (inp + 1 == endp) {
02783                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unexpected end of string");
02784                             RETURN_FALSE;
02785                      } else if (inp[1] != '-') {
02786                             state = ST_DECODE0;
02787                      } else {
02788                             outlen++;
02789                             inp++;
02790                      }
02791               } else if (*inp == '-') {
02792                      /* return to NORMAL mode */
02793                      if (state == ST_DECODE1) {
02794                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Stray modified base64 character: `%c'", *--inp);
02795                             RETURN_FALSE;
02796                      }
02797                      state = ST_NORMAL;
02798               } else if (!B64CHAR(*inp)) {
02799                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid modified base64 character: `%c'", *inp);
02800                      RETURN_FALSE;
02801               } else {
02802                      switch (state) {
02803                             case ST_DECODE3:
02804                                    outlen++;
02805                                    state = ST_DECODE0;
02806                                    break;
02807                             case ST_DECODE2:
02808                             case ST_DECODE1:
02809                                    outlen++;
02810                             case ST_DECODE0:
02811                                    state++;
02812                             case ST_NORMAL:
02813                                    break;
02814                      }
02815               }
02816        }
02817 
02818        /* enforce end state */
02819        if (state != ST_NORMAL) {
02820               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unexpected end of string");
02821               RETURN_FALSE;
02822        }
02823 
02824        /* allocate output buffer */
02825        out = emalloc(outlen + 1);
02826 
02827        /* decode input string */
02828        outp = out;
02829        state = ST_NORMAL;
02830        for (endp = (inp = in) + inlen; inp < endp; inp++) {
02831               if (state == ST_NORMAL) {
02832                      if (*inp == '&' && inp[1] != '-') {
02833                             state = ST_DECODE0;
02834                      }
02835                      else if ((*outp++ = *inp) == '&') {
02836                             inp++;
02837                      }
02838               }
02839               else if (*inp == '-') {
02840                      state = ST_NORMAL;
02841               }
02842               else {
02843                      /* decode input character */
02844                      switch (state) {
02845                      case ST_DECODE0:
02846                             *outp = UNB64(*inp) << 2;
02847                             state = ST_DECODE1;
02848                             break;
02849                      case ST_DECODE1:
02850                             outp[1] = UNB64(*inp);
02851                             c = outp[1] >> 4;
02852                             *outp++ |= c;
02853                             *outp <<= 4;
02854                             state = ST_DECODE2;
02855                             break;
02856                      case ST_DECODE2:
02857                             outp[1] = UNB64(*inp);
02858                             c = outp[1] >> 2;
02859                             *outp++ |= c;
02860                             *outp <<= 6;
02861                             state = ST_DECODE3;
02862                             break;
02863                      case ST_DECODE3:
02864                             *outp++ |= UNB64(*inp);
02865                             state = ST_DECODE0;
02866                      case ST_NORMAL:
02867                             break;
02868                      }
02869               }
02870        }
02871 
02872        *outp = 0;
02873 
02874 #if PHP_DEBUG
02875        /* warn if we computed outlen incorrectly */
02876        if (outp - out != outlen) {
02877               php_error_docref(NULL TSRMLS_CC, E_WARNING, "outp - out [%ld] != outlen [%d]", outp - out, outlen);
02878        }
02879 #endif
02880 
02881        RETURN_STRINGL(out, outlen, 0);
02882 }
02883 /* }}} */
02884 
02885 /* {{{ proto string imap_utf7_encode(string buf)
02886    Encode a string in modified UTF-7 */
02887 PHP_FUNCTION(imap_utf7_encode)
02888 {
02889        /* author: Andrew Skalski <askalski@chek.com> */
02890        char *arg;
02891        const unsigned char *in, *inp, *endp;
02892        unsigned char *out, *outp;
02893        unsigned char c;
02894        int arg_len, inlen, outlen;
02895        enum {
02896               ST_NORMAL,    /* printable text */
02897               ST_ENCODE0,   /* encoded text rotation... */
02898               ST_ENCODE1,
02899               ST_ENCODE2
02900        } state;
02901 
02902        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) {
02903               return;
02904        }
02905 
02906        in = (const unsigned char *) arg;
02907        inlen = arg_len;
02908 
02909        /* compute the length of the result string */
02910        outlen = 0;
02911        state = ST_NORMAL;
02912        endp = (inp = in) + inlen;
02913        while (inp < endp) {
02914               if (state == ST_NORMAL) {
02915                      if (SPECIAL(*inp)) {
02916                             state = ST_ENCODE0;
02917                             outlen++;
02918                      } else if (*inp++ == '&') {
02919                             outlen++;
02920                      }
02921                      outlen++;
02922               } else if (!SPECIAL(*inp)) {
02923                      state = ST_NORMAL;
02924               } else {
02925                      /* ST_ENCODE0 -> ST_ENCODE1 - two chars
02926                       * ST_ENCODE1 -> ST_ENCODE2 - one char
02927                       * ST_ENCODE2 -> ST_ENCODE0 - one char
02928                       */
02929                      if (state == ST_ENCODE2) {
02930                             state = ST_ENCODE0;
02931                      }
02932                      else if (state++ == ST_ENCODE0) {
02933                             outlen++;
02934                      }
02935                      outlen++;
02936                      inp++;
02937               }
02938        }
02939 
02940        /* allocate output buffer */
02941        out = emalloc(outlen + 1);
02942 
02943        /* encode input string */
02944        outp = out;
02945        state = ST_NORMAL;
02946        endp = (inp = in) + inlen;
02947        while (inp < endp || state != ST_NORMAL) {
02948               if (state == ST_NORMAL) {
02949                      if (SPECIAL(*inp)) {
02950                             /* begin encoding */
02951                             *outp++ = '&';
02952                             state = ST_ENCODE0;
02953                      } else if ((*outp++ = *inp++) == '&') {
02954                             *outp++ = '-';
02955                      }
02956               } else if (inp == endp || !SPECIAL(*inp)) {
02957                      /* flush overflow and terminate region */
02958                      if (state != ST_ENCODE0) {
02959                             c = B64(*outp);
02960                             *outp++ = c;
02961                      }
02962                      *outp++ = '-';
02963                      state = ST_NORMAL;
02964               } else {
02965                      /* encode input character */
02966                      switch (state) {
02967                             case ST_ENCODE0:
02968                                    *outp++ = B64(*inp >> 2);
02969                                    *outp = *inp++ << 4;
02970                                    state = ST_ENCODE1;
02971                                    break;
02972                             case ST_ENCODE1:
02973                                    c = B64(*outp | *inp >> 4);
02974                                    *outp++ = c;
02975                                    *outp = *inp++ << 2;
02976                                    state = ST_ENCODE2;
02977                                    break;
02978                             case ST_ENCODE2:
02979                                    c = B64(*outp | *inp >> 6);
02980                                    *outp++ = c;
02981                                    *outp++ = B64(*inp++);
02982                                    state = ST_ENCODE0;
02983                             case ST_NORMAL:
02984                                    break;
02985                      }
02986               }
02987        }
02988 
02989        *outp = 0;
02990 
02991 #if PHP_DEBUG
02992        /* warn if we computed outlen incorrectly */
02993        if (outp - out != outlen) {
02994               php_error_docref(NULL TSRMLS_CC, E_WARNING, "outp - out [%ld] != outlen [%d]", outp - out, outlen);
02995        }
02996 #endif
02997 
02998        RETURN_STRINGL(out, outlen, 0);
02999 }
03000 /* }}} */
03001 
03002 #undef SPECIAL
03003 #undef B64CHAR
03004 #undef B64
03005 #undef UNB64
03006 
03007 #ifdef HAVE_IMAP_MUTF7
03008 static void php_imap_mutf7(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */
03009 {
03010        char *in;
03011        int in_len;
03012        unsigned char *out;
03013 
03014        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &in, &in_len) == FAILURE) {
03015               return;
03016        }
03017 
03018        if (in_len < 1) {
03019               RETURN_EMPTY_STRING();
03020        }
03021 
03022        if (mode == 0) {
03023               out = utf8_to_mutf7((unsigned char *) in);
03024        } else {
03025               out = utf8_from_mutf7((unsigned char *) in);
03026        }
03027 
03028        if (out == NIL) {
03029               RETURN_FALSE;
03030        } else {
03031               RETURN_STRING((char *)out, 1);
03032        }
03033 }
03034 /* }}} */
03035 
03036 /* {{{ proto string imap_utf8_to_mutf7(string in)
03037    Encode a UTF-8 string to modified UTF-7 */
03038 PHP_FUNCTION(imap_utf8_to_mutf7)
03039 {
03040        php_imap_mutf7(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
03041 }
03042 /* }}} */
03043 
03044 /* {{{ proto string imap_mutf7_to_utf8(string in)
03045    Decode a modified UTF-7 string to UTF-8 */
03046 PHP_FUNCTION(imap_mutf7_to_utf8)
03047 {
03048        php_imap_mutf7(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
03049 }
03050 /* }}} */
03051 #endif
03052 
03053 /* {{{ proto bool imap_setflag_full(resource stream_id, string sequence, string flag [, int options])
03054    Sets flags on messages */
03055 PHP_FUNCTION(imap_setflag_full)
03056 {
03057        zval *streamind;
03058        char *sequence, *flag;
03059        int sequence_len, flag_len;
03060        long flags = 0;
03061        pils *imap_le_struct;
03062 
03063        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rss|l", &streamind, &sequence, &sequence_len, &flag, &flag_len, &flags) == FAILURE) {
03064               return;
03065        }
03066 
03067        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
03068 
03069        mail_setflag_full(imap_le_struct->imap_stream, sequence, flag, (flags ? flags : NIL));
03070        RETURN_TRUE;
03071 }
03072 /* }}} */
03073 
03074 /* {{{ proto bool imap_clearflag_full(resource stream_id, string sequence, string flag [, int options])
03075    Clears flags on messages */
03076 PHP_FUNCTION(imap_clearflag_full)
03077 {
03078        zval *streamind;
03079        char *sequence, *flag;
03080        int sequence_len, flag_len;
03081        long flags = 0;
03082        pils *imap_le_struct;
03083        int argc = ZEND_NUM_ARGS();
03084 
03085        if (zend_parse_parameters(argc TSRMLS_CC, "rss|l", &streamind, &sequence, &sequence_len, &flag, &flag_len, &flags) ==FAILURE) {
03086               return;
03087        }
03088 
03089        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
03090 
03091        mail_clearflag_full(imap_le_struct->imap_stream, sequence, flag, (argc == 4 ? flags : NIL));
03092        RETURN_TRUE;
03093 }
03094 /* }}} */
03095 
03096 /* {{{ proto array imap_sort(resource stream_id, int criteria, int reverse [, int options [, string search_criteria [, string charset]]])
03097    Sort an array of message headers, optionally including only messages that meet specified criteria. */
03098 PHP_FUNCTION(imap_sort)
03099 {
03100        zval *streamind;
03101        char *criteria = NULL, *charset = NULL;
03102        int criteria_len, charset_len;
03103        long pgm, rev, flags = 0;
03104        pils *imap_le_struct;
03105        unsigned long *slst, *sl;
03106        char *search_criteria;
03107        SORTPGM *mypgm=NIL;
03108        SEARCHPGM *spg=NIL;
03109        int argc = ZEND_NUM_ARGS();
03110 
03111        if (zend_parse_parameters(argc TSRMLS_CC, "rll|lss", &streamind, &pgm, &rev, &flags, &criteria, &criteria_len, &charset, &charset_len) == FAILURE) {
03112               return;
03113        }
03114 
03115        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
03116 
03117        if (pgm > SORTSIZE) {
03118               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unrecognized sort criteria");
03119               RETURN_FALSE;
03120        }
03121        if (argc >= 4) {
03122               if (flags < 0) {
03123                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Search options parameter has to be greater than or equal to 0");
03124                      RETURN_FALSE;
03125               }
03126        }
03127        if (argc >= 5) {
03128               search_criteria = estrndup(criteria, criteria_len);
03129               spg = mail_criteria(search_criteria);
03130               efree(search_criteria);
03131        } else {
03132               spg = mail_newsearchpgm();
03133        }
03134 
03135        mypgm = mail_newsortpgm();
03136        mypgm->reverse = rev;
03137        mypgm->function = (short) pgm;
03138        mypgm->next = NIL;
03139 
03140        slst = mail_sort(imap_le_struct->imap_stream, (argc == 6 ? charset : NIL), spg, mypgm, (argc >= 4 ? flags : NIL));
03141 
03142        if (spg && !(flags & SE_FREE)) {
03143               mail_free_searchpgm(&spg);
03144        }
03145 
03146        array_init(return_value);
03147        if (slst != NIL && slst != 0) {
03148               for (sl = slst; *sl; sl++) {
03149                      add_next_index_long(return_value, *sl);
03150               }
03151               fs_give ((void **) &slst);
03152        }
03153 }
03154 /* }}} */
03155 
03156 /* {{{ proto string imap_fetchheader(resource stream_id, int msg_no [, int options])
03157    Get the full unfiltered header for a message */
03158 PHP_FUNCTION(imap_fetchheader)
03159 {
03160        zval *streamind;
03161        long msgno, flags=0L;
03162        pils *imap_le_struct;
03163        int msgindex, argc = ZEND_NUM_ARGS();
03164 
03165        if (zend_parse_parameters(argc TSRMLS_CC, "rl|l", &streamind, &msgno, &flags) == FAILURE) {
03166               return;
03167        }
03168 
03169        if (flags && ((flags & ~(FT_UID|FT_INTERNAL|FT_PREFETCHTEXT)) != 0)) {
03170               php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid value for the options parameter");
03171               RETURN_FALSE;
03172        }
03173 
03174        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
03175 
03176        if ((argc == 3) && (flags & FT_UID)) {
03177               /* This should be cached; if it causes an extra RTT to the
03178                  IMAP server, then that's the price we pay for making sure
03179                  we don't crash. */
03180               msgindex = mail_msgno(imap_le_struct->imap_stream, msgno);
03181        } else {
03182               msgindex = msgno;
03183        }
03184 
03185        PHP_IMAP_CHECK_MSGNO(msgindex);
03186 
03187        RETVAL_STRING(mail_fetchheader_full(imap_le_struct->imap_stream, msgno, NIL, NIL, (argc == 3 ? flags : NIL)), 1);
03188 }
03189 /* }}} */
03190 
03191 /* {{{ proto int imap_uid(resource stream_id, int msg_no)
03192    Get the unique message id associated with a standard sequential message number */
03193 PHP_FUNCTION(imap_uid)
03194 {
03195        zval *streamind;
03196        long msgno;
03197        pils *imap_le_struct;
03198        int msgindex;
03199 
03200        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &streamind, &msgno) == FAILURE) {
03201               return;
03202        }
03203 
03204        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
03205 
03206        msgindex = msgno;
03207        if ((msgindex < 1) || ((unsigned) msgindex > imap_le_struct->imap_stream->nmsgs)) {
03208               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad message number");
03209               RETURN_FALSE;
03210        }
03211 
03212        RETURN_LONG(mail_uid(imap_le_struct->imap_stream, msgno));
03213 }
03214 /* }}} */
03215 
03216 /* {{{ proto int imap_msgno(resource stream_id, int unique_msg_id)
03217    Get the sequence number associated with a UID */
03218 PHP_FUNCTION(imap_msgno)
03219 {
03220        zval *streamind;
03221        long msgno;
03222        pils *imap_le_struct;
03223 
03224        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &streamind, &msgno) == FAILURE) {
03225               return;
03226        }
03227 
03228        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
03229 
03230        RETURN_LONG(mail_msgno(imap_le_struct->imap_stream, msgno));
03231 }
03232 /* }}} */
03233 
03234 /* {{{ proto object imap_status(resource stream_id, string mailbox, int options)
03235    Get status info from a mailbox */
03236 PHP_FUNCTION(imap_status)
03237 {
03238        zval *streamind;
03239        char *mbx;
03240        int mbx_len;
03241        long flags;
03242        pils *imap_le_struct;
03243 
03244        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsl", &streamind, &mbx, &mbx_len, &flags) == FAILURE) {
03245               return;
03246        }
03247 
03248        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
03249 
03250        object_init(return_value);
03251 
03252        if (mail_status(imap_le_struct->imap_stream, mbx, flags)) {
03253               add_property_long(return_value, "flags", IMAPG(status_flags));
03254               if (IMAPG(status_flags) & SA_MESSAGES) {
03255                      add_property_long(return_value, "messages", IMAPG(status_messages));
03256               }
03257               if (IMAPG(status_flags) & SA_RECENT) {
03258                      add_property_long(return_value, "recent", IMAPG(status_recent));
03259               }
03260               if (IMAPG(status_flags) & SA_UNSEEN) {
03261                      add_property_long(return_value, "unseen", IMAPG(status_unseen));
03262               }
03263               if (IMAPG(status_flags) & SA_UIDNEXT) {
03264                      add_property_long(return_value, "uidnext", IMAPG(status_uidnext));
03265               }
03266               if (IMAPG(status_flags) & SA_UIDVALIDITY) {
03267                      add_property_long(return_value, "uidvalidity", IMAPG(status_uidvalidity));
03268               }
03269        } else {
03270               RETURN_FALSE;
03271        }
03272 }
03273 /* }}} */
03274 
03275 /* {{{ proto object imap_bodystruct(resource stream_id, int msg_no, string section)
03276    Read the structure of a specified body section of a specific message */
03277 PHP_FUNCTION(imap_bodystruct)
03278 {
03279        zval *streamind;
03280        long msg;
03281        char *section;
03282        int section_len;
03283        pils *imap_le_struct;
03284        zval *parametres, *param, *dparametres, *dparam;
03285        PARAMETER *par, *dpar;
03286        BODY *body;
03287 
03288        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rls", &streamind, &msg, &section, &section_len) == FAILURE) {
03289               return;
03290        }
03291 
03292        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
03293 
03294        if (!msg || msg < 1 || (unsigned) msg > imap_le_struct->imap_stream->nmsgs) {
03295               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Bad message number");
03296               RETURN_FALSE;
03297        }
03298 
03299        object_init(return_value);
03300 
03301        body=mail_body(imap_le_struct->imap_stream, msg, section);
03302        if (body == NULL) {
03303               zval_dtor(return_value);
03304               RETURN_FALSE;
03305        }
03306        if (body->type <= TYPEMAX) {
03307               add_property_long(return_value, "type", body->type);
03308        }
03309        if (body->encoding <= ENCMAX) {
03310               add_property_long(return_value, "encoding", body->encoding);
03311        }
03312 
03313        if (body->subtype) {
03314               add_property_long(return_value, "ifsubtype", 1);
03315               add_property_string(return_value, "subtype", body->subtype, 1);
03316        } else {
03317               add_property_long(return_value, "ifsubtype", 0);
03318        }
03319 
03320        if (body->description) {
03321               add_property_long(return_value, "ifdescription", 1);
03322               add_property_string(return_value, "description", body->description, 1);
03323        } else {
03324               add_property_long(return_value, "ifdescription", 0);
03325        }
03326        if (body->id) {
03327               add_property_long(return_value, "ifid", 1);
03328               add_property_string(return_value, "id", body->id, 1);
03329        } else {
03330               add_property_long(return_value, "ifid", 0);
03331        }
03332 
03333        if (body->size.lines) {
03334               add_property_long(return_value, "lines", body->size.lines);
03335        }
03336        if (body->size.bytes) {
03337               add_property_long(return_value, "bytes", body->size.bytes);
03338        }
03339 #ifdef IMAP41
03340        if (body->disposition.type) {
03341               add_property_long(return_value, "ifdisposition", 1);
03342               add_property_string(return_value, "disposition", body->disposition.type, 1);
03343        } else {
03344               add_property_long(return_value, "ifdisposition", 0);
03345        }
03346 
03347        if (body->disposition.parameter) {
03348               dpar = body->disposition.parameter;
03349               add_property_long(return_value, "ifdparameters", 1);
03350               MAKE_STD_ZVAL(dparametres);
03351               array_init(dparametres);
03352               do {
03353                      MAKE_STD_ZVAL(dparam);
03354                      object_init(dparam);
03355                      add_property_string(dparam, "attribute", dpar->attribute, 1);
03356                      add_property_string(dparam, "value", dpar->value, 1);
03357                      add_next_index_object(dparametres, dparam TSRMLS_CC);
03358               } while ((dpar = dpar->next));
03359               add_assoc_object(return_value, "dparameters", dparametres TSRMLS_CC);
03360        } else {
03361               add_property_long(return_value, "ifdparameters", 0);
03362        }
03363 #endif
03364 
03365        if ((par = body->parameter)) {
03366               add_property_long(return_value, "ifparameters", 1);
03367 
03368               MAKE_STD_ZVAL(parametres);
03369               array_init(parametres);
03370               do {
03371                      MAKE_STD_ZVAL(param);
03372                      object_init(param);
03373                      if (par->attribute) {
03374                             add_property_string(param, "attribute", par->attribute, 1);
03375                      }
03376                      if (par->value) {
03377                             add_property_string(param, "value", par->value, 1);
03378                      }
03379 
03380                      add_next_index_object(parametres, param TSRMLS_CC);
03381               } while ((par = par->next));
03382        } else {
03383               MAKE_STD_ZVAL(parametres);
03384               object_init(parametres);
03385               add_property_long(return_value, "ifparameters", 0);
03386        }
03387        add_assoc_object(return_value, "parameters", parametres TSRMLS_CC);
03388 }
03389 
03390 /* }}} */
03391 
03392 /* {{{ proto array imap_fetch_overview(resource stream_id, string sequence [, int options])
03393    Read an overview of the information in the headers of the given message sequence */
03394 PHP_FUNCTION(imap_fetch_overview)
03395 {
03396        zval *streamind;
03397        char *sequence;
03398        int sequence_len;
03399        pils *imap_le_struct;
03400        zval *myoverview;
03401        char *address;
03402        long status, flags = 0L;
03403        int argc = ZEND_NUM_ARGS();
03404 
03405        if (zend_parse_parameters(argc TSRMLS_CC, "rs|l", &streamind, &sequence, &sequence_len, &flags) == FAILURE) {
03406               return;
03407        }
03408 
03409        if (flags && ((flags & ~FT_UID) != 0)) {
03410               php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid value for the options parameter");
03411               RETURN_FALSE;
03412        }
03413 
03414        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
03415 
03416        array_init(return_value);
03417 
03418        status = (flags & FT_UID)
03419               ? mail_uid_sequence(imap_le_struct->imap_stream, sequence)
03420               : mail_sequence(imap_le_struct->imap_stream, sequence);
03421 
03422        if (status) {
03423               MESSAGECACHE *elt;
03424               ENVELOPE *env;
03425               unsigned long i;
03426 
03427               for (i = 1; i <= imap_le_struct->imap_stream->nmsgs; i++) {
03428                      if (((elt = mail_elt (imap_le_struct->imap_stream, i))->sequence) &&
03429                             (env = mail_fetch_structure (imap_le_struct->imap_stream, i, NIL, NIL))) {
03430                             MAKE_STD_ZVAL(myoverview);
03431                             object_init(myoverview);
03432                             if (env->subject) {
03433                                    add_property_string(myoverview, "subject", env->subject, 1);
03434                             }
03435                             if (env->from) {
03436                                    env->from->next=NULL;
03437                                    address =_php_rfc822_write_address(env->from TSRMLS_CC);
03438                                    if (address) {
03439                                           add_property_string(myoverview, "from", address, 0);
03440                                    }
03441                             }
03442                             if (env->to) {
03443                                    env->to->next = NULL;
03444                                    address = _php_rfc822_write_address(env->to TSRMLS_CC);
03445                                    if (address) {
03446                                           add_property_string(myoverview, "to", address, 0);
03447                                    }
03448                             }
03449                             if (env->date) {
03450                                    add_property_string(myoverview, "date", env->date, 1);
03451                             }
03452                             if (env->message_id) {
03453                                    add_property_string(myoverview, "message_id", env->message_id, 1);
03454                             }
03455                             if (env->references) {
03456                                    add_property_string(myoverview, "references", env->references, 1);
03457                             }
03458                             if (env->in_reply_to) {
03459                                    add_property_string(myoverview, "in_reply_to", env->in_reply_to, 1);
03460                             }
03461                             add_property_long(myoverview, "size", elt->rfc822_size);
03462                             add_property_long(myoverview, "uid", mail_uid(imap_le_struct->imap_stream, i));
03463                             add_property_long(myoverview, "msgno", i);
03464                             add_property_long(myoverview, "recent", elt->recent);
03465                             add_property_long(myoverview, "flagged", elt->flagged);
03466                             add_property_long(myoverview, "answered", elt->answered);
03467                             add_property_long(myoverview, "deleted", elt->deleted);
03468                             add_property_long(myoverview, "seen", elt->seen);
03469                             add_property_long(myoverview, "draft", elt->draft);
03470                             add_property_long(myoverview, "udate", mail_longdate(elt));
03471                             add_next_index_object(return_value, myoverview TSRMLS_CC);
03472                      }
03473               }
03474        }
03475 }
03476 /* }}} */
03477 
03478 /* {{{ proto string imap_mail_compose(array envelope, array body)
03479    Create a MIME message based on given envelope and body sections */
03480 PHP_FUNCTION(imap_mail_compose)
03481 {
03482        zval *envelope, *body;
03483        char *key;
03484        zval **data, **pvalue, **disp_data, **env_data;
03485        ulong ind;
03486        char *cookie = NIL;
03487        ENVELOPE *env;
03488        BODY *bod=NULL, *topbod=NULL;
03489        PART *mypart=NULL, *part;
03490        PARAMETER *param, *disp_param = NULL, *custom_headers_param = NULL, *tmp_param = NULL;
03491        char *tmp=NULL, *mystring=NULL, *t=NULL, *tempstring=NULL, *str_copy = NULL;
03492        int toppart = 0;
03493 
03494        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "aa", &envelope, &body) == FAILURE) {
03495               return;
03496        }
03497 
03498 #define PHP_RFC822_PARSE_ADRLIST(target, value) \
03499        str_copy = estrndup(Z_STRVAL_PP(value), Z_STRLEN_PP(value)); \
03500        rfc822_parse_adrlist(target, str_copy, "NO HOST"); \
03501        efree(str_copy);
03502 
03503        env = mail_newenvelope();
03504        if (zend_hash_find(Z_ARRVAL_P(envelope), "remail", sizeof("remail"), (void **) &pvalue)== SUCCESS) {
03505               convert_to_string_ex(pvalue);
03506               env->remail = cpystr(Z_STRVAL_PP(pvalue));
03507        }
03508        if (zend_hash_find(Z_ARRVAL_P(envelope), "return_path", sizeof("return_path"), (void **) &pvalue)== SUCCESS) {
03509               convert_to_string_ex(pvalue);
03510               PHP_RFC822_PARSE_ADRLIST(&env->return_path, pvalue);
03511        }
03512        if (zend_hash_find(Z_ARRVAL_P(envelope), "date", sizeof("date"), (void **) &pvalue)== SUCCESS) {
03513               convert_to_string_ex(pvalue);
03514               env->date = cpystr(Z_STRVAL_PP(pvalue));
03515        }
03516        if (zend_hash_find(Z_ARRVAL_P(envelope), "from", sizeof("from"), (void **) &pvalue)== SUCCESS) {
03517               convert_to_string_ex(pvalue);
03518               PHP_RFC822_PARSE_ADRLIST(&env->from, pvalue);
03519        }
03520        if (zend_hash_find(Z_ARRVAL_P(envelope), "reply_to", sizeof("reply_to"), (void **) &pvalue)== SUCCESS) {
03521               convert_to_string_ex(pvalue);
03522               PHP_RFC822_PARSE_ADRLIST(&env->reply_to, pvalue);
03523        }
03524        if (zend_hash_find(Z_ARRVAL_P(envelope), "in_reply_to", sizeof("in_reply_to"), (void **) &pvalue)== SUCCESS) {
03525               convert_to_string_ex(pvalue);
03526               env->in_reply_to = cpystr(Z_STRVAL_PP(pvalue));
03527        }
03528        if (zend_hash_find(Z_ARRVAL_P(envelope), "subject", sizeof("subject"), (void **) &pvalue)== SUCCESS) {
03529               convert_to_string_ex(pvalue);
03530               env->subject = cpystr(Z_STRVAL_PP(pvalue));
03531        }
03532        if (zend_hash_find(Z_ARRVAL_P(envelope), "to", sizeof("to"), (void **) &pvalue)== SUCCESS) {
03533               convert_to_string_ex(pvalue);
03534               PHP_RFC822_PARSE_ADRLIST(&env->to, pvalue);
03535        }
03536        if (zend_hash_find(Z_ARRVAL_P(envelope), "cc", sizeof("cc"), (void **) &pvalue)== SUCCESS) {
03537               convert_to_string_ex(pvalue);
03538               PHP_RFC822_PARSE_ADRLIST(&env->cc, pvalue);
03539        }
03540        if (zend_hash_find(Z_ARRVAL_P(envelope), "bcc", sizeof("bcc"), (void **) &pvalue)== SUCCESS) {
03541               convert_to_string_ex(pvalue);
03542               PHP_RFC822_PARSE_ADRLIST(&env->bcc, pvalue);
03543        }
03544        if (zend_hash_find(Z_ARRVAL_P(envelope), "message_id", sizeof("message_id"), (void **) &pvalue)== SUCCESS) {
03545               convert_to_string_ex(pvalue);
03546               env->message_id=cpystr(Z_STRVAL_PP(pvalue));
03547        }
03548 
03549        if (zend_hash_find(Z_ARRVAL_P(envelope), "custom_headers", sizeof("custom_headers"), (void **) &pvalue)== SUCCESS) {
03550               if (Z_TYPE_PP(pvalue) == IS_ARRAY) {
03551                      custom_headers_param = tmp_param = NULL;
03552                      while (zend_hash_get_current_data(Z_ARRVAL_PP(pvalue), (void **) &env_data) == SUCCESS) {
03553                             custom_headers_param = mail_newbody_parameter();
03554                             convert_to_string_ex(env_data);
03555                             custom_headers_param->value = (char *) fs_get(Z_STRLEN_PP(env_data) + 1);
03556                             custom_headers_param->attribute = NULL;
03557                             memcpy(custom_headers_param->value, Z_STRVAL_PP(env_data), Z_STRLEN_PP(env_data) + 1);
03558                             zend_hash_move_forward(Z_ARRVAL_PP(pvalue));
03559                             custom_headers_param->next = tmp_param;
03560                             tmp_param = custom_headers_param;
03561                      }
03562               }
03563        }
03564 
03565        zend_hash_internal_pointer_reset(Z_ARRVAL_P(body));
03566        if (zend_hash_get_current_data(Z_ARRVAL_P(body), (void **) &data) != SUCCESS || Z_TYPE_PP(data) != IS_ARRAY) {
03567               php_error_docref(NULL TSRMLS_CC, E_WARNING, "body parameter must be a non-empty array");
03568               RETURN_FALSE;
03569        }
03570 
03571        if (Z_TYPE_PP(data) == IS_ARRAY) {
03572               bod = mail_newbody();
03573               topbod = bod;
03574 
03575               if (zend_hash_find(Z_ARRVAL_PP(data), "type", sizeof("type"), (void **) &pvalue)== SUCCESS) {
03576                      convert_to_long_ex(pvalue);
03577                      bod->type = (short) Z_LVAL_PP(pvalue);
03578               }
03579               if (zend_hash_find(Z_ARRVAL_PP(data), "encoding", sizeof("encoding"), (void **) &pvalue)== SUCCESS) {
03580                      convert_to_long_ex(pvalue);
03581                      bod->encoding = (short) Z_LVAL_PP(pvalue);
03582               }
03583               if (zend_hash_find(Z_ARRVAL_PP(data), "charset", sizeof("charset"), (void **) &pvalue)== SUCCESS) {
03584                      convert_to_string_ex(pvalue);
03585                      tmp_param = mail_newbody_parameter();
03586                      tmp_param->value = cpystr(Z_STRVAL_PP(pvalue));
03587                      tmp_param->attribute = cpystr("CHARSET");
03588                      tmp_param->next = bod->parameter;
03589                      bod->parameter = tmp_param;
03590               }
03591               if (zend_hash_find(Z_ARRVAL_PP(data), "type.parameters", sizeof("type.parameters"), (void **) &pvalue)== SUCCESS) {
03592                      if(Z_TYPE_PP(pvalue) == IS_ARRAY) {
03593                             disp_param = tmp_param = NULL;
03594                             while (zend_hash_get_current_data(Z_ARRVAL_PP(pvalue), (void **) &disp_data) == SUCCESS) {
03595                                    disp_param = mail_newbody_parameter();
03596                                    zend_hash_get_current_key(Z_ARRVAL_PP(pvalue), &key, &ind, 0);
03597                                    disp_param->attribute = cpystr(key);
03598                                    convert_to_string_ex(disp_data);
03599                                    disp_param->value = (char *) fs_get(Z_STRLEN_PP(disp_data) + 1);
03600                                    memcpy(disp_param->value, Z_STRVAL_PP(disp_data), Z_STRLEN_PP(disp_data) + 1);
03601                                    zend_hash_move_forward(Z_ARRVAL_PP(pvalue));
03602                                    disp_param->next = tmp_param;
03603                                    tmp_param = disp_param;
03604                             }
03605                      bod->parameter = disp_param;
03606                      }
03607               }
03608               if (zend_hash_find(Z_ARRVAL_PP(data), "subtype", sizeof("subtype"), (void **) &pvalue)== SUCCESS) {
03609                      convert_to_string_ex(pvalue);
03610                      bod->subtype = cpystr(Z_STRVAL_PP(pvalue));
03611               }
03612               if (zend_hash_find(Z_ARRVAL_PP(data), "id", sizeof("id"), (void **) &pvalue)== SUCCESS) {
03613                      convert_to_string_ex(pvalue);
03614                      bod->id = cpystr(Z_STRVAL_PP(pvalue));
03615               }
03616               if (zend_hash_find(Z_ARRVAL_PP(data), "description", sizeof("description"), (void **) &pvalue)== SUCCESS) {
03617                      convert_to_string_ex(pvalue);
03618                      bod->description = cpystr(Z_STRVAL_PP(pvalue));
03619               }
03620               if (zend_hash_find(Z_ARRVAL_PP(data), "disposition.type", sizeof("disposition.type"), (void **) &pvalue)== SUCCESS) {
03621                      convert_to_string_ex(pvalue);
03622                      bod->disposition.type = (char *) fs_get(Z_STRLEN_PP(pvalue) + 1);
03623                      memcpy(bod->disposition.type, Z_STRVAL_PP(pvalue), Z_STRLEN_PP(pvalue)+1);
03624               }
03625               if (zend_hash_find(Z_ARRVAL_PP(data), "disposition", sizeof("disposition"), (void **) &pvalue)== SUCCESS) {
03626                      if (Z_TYPE_PP(pvalue) == IS_ARRAY) {
03627                             disp_param = tmp_param = NULL;
03628                             while (zend_hash_get_current_data(Z_ARRVAL_PP(pvalue), (void **) &disp_data) == SUCCESS) {
03629                                    disp_param = mail_newbody_parameter();
03630                                    zend_hash_get_current_key(Z_ARRVAL_PP(pvalue), &key, &ind, 0);
03631                                    disp_param->attribute = cpystr(key);
03632                                    convert_to_string_ex(disp_data);
03633                                    disp_param->value = (char *) fs_get(Z_STRLEN_PP(disp_data) + 1);
03634                                    memcpy(disp_param->value, Z_STRVAL_PP(disp_data), Z_STRLEN_PP(disp_data) + 1);
03635                                    zend_hash_move_forward(Z_ARRVAL_PP(pvalue));
03636                                    disp_param->next = tmp_param;
03637                                    tmp_param = disp_param;
03638                             }
03639                             bod->disposition.parameter = disp_param;
03640                      }
03641               }
03642               if (zend_hash_find(Z_ARRVAL_PP(data), "contents.data", sizeof("contents.data"), (void **) &pvalue)== SUCCESS) {
03643                      convert_to_string_ex(pvalue);
03644                      bod->contents.text.data = (char *) fs_get(Z_STRLEN_PP(pvalue) + 1);
03645                      memcpy(bod->contents.text.data, Z_STRVAL_PP(pvalue), Z_STRLEN_PP(pvalue)+1);
03646                      bod->contents.text.size = Z_STRLEN_PP(pvalue);
03647               } else {
03648                      bod->contents.text.data = (char *) fs_get(1);
03649                      memcpy(bod->contents.text.data, "", 1);
03650                      bod->contents.text.size = 0;
03651               }
03652               if (zend_hash_find(Z_ARRVAL_PP(data), "lines", sizeof("lines"), (void **) &pvalue)== SUCCESS) {
03653                      convert_to_long_ex(pvalue);
03654                      bod->size.lines = Z_LVAL_PP(pvalue);
03655               }
03656               if (zend_hash_find(Z_ARRVAL_PP(data), "bytes", sizeof("bytes"), (void **) &pvalue)== SUCCESS) {
03657                      convert_to_long_ex(pvalue);
03658                      bod->size.bytes = Z_LVAL_PP(pvalue);
03659               }
03660               if (zend_hash_find(Z_ARRVAL_PP(data), "md5", sizeof("md5"), (void **) &pvalue)== SUCCESS) {
03661                      convert_to_string_ex(pvalue);
03662                      bod->md5 = cpystr(Z_STRVAL_PP(pvalue));
03663               }
03664        }
03665 
03666        zend_hash_move_forward(Z_ARRVAL_P(body));
03667 
03668        while (zend_hash_get_current_data(Z_ARRVAL_P(body), (void **) &data) == SUCCESS) {
03669               if (Z_TYPE_PP(data) == IS_ARRAY) {
03670                      short type = -1;
03671                      if (zend_hash_find(Z_ARRVAL_PP(data), "type", sizeof("type"), (void **) &pvalue)== SUCCESS) {
03672                             convert_to_long_ex(pvalue);
03673                             type = (short) Z_LVAL_PP(pvalue);
03674                      }
03675 
03676                      if (!toppart) {
03677                             bod->nested.part = mail_newbody_part();
03678                             mypart = bod->nested.part;
03679                             toppart = 1;
03680                      } else {
03681                             mypart->next = mail_newbody_part();
03682                             mypart = mypart->next;
03683                      }
03684 
03685                      bod = &mypart->body;
03686 
03687                      if (type != TYPEMULTIPART) {
03688                             bod->type = type;
03689                      }
03690 
03691                      if (zend_hash_find(Z_ARRVAL_PP(data), "encoding", sizeof("encoding"), (void **) &pvalue)== SUCCESS) {
03692                             convert_to_long_ex(pvalue);
03693                             bod->encoding = (short) Z_LVAL_PP(pvalue);
03694                      }
03695                      if (zend_hash_find(Z_ARRVAL_PP(data), "charset", sizeof("charset"), (void **) &pvalue)== SUCCESS) {
03696                             convert_to_string_ex(pvalue);
03697                             tmp_param = mail_newbody_parameter();
03698                             tmp_param->value = (char *) fs_get(Z_STRLEN_PP(pvalue) + 1);
03699                             memcpy(tmp_param->value, Z_STRVAL_PP(pvalue), Z_STRLEN_PP(pvalue) + 1);
03700                             tmp_param->attribute = cpystr("CHARSET");
03701                             tmp_param->next = bod->parameter;
03702                             bod->parameter = tmp_param;
03703                      }
03704                      if (zend_hash_find(Z_ARRVAL_PP(data), "type.parameters", sizeof("type.parameters"), (void **) &pvalue)== SUCCESS) {
03705                             if(Z_TYPE_PP(pvalue) == IS_ARRAY) {
03706                                    disp_param = tmp_param = NULL;
03707                                    while (zend_hash_get_current_data(Z_ARRVAL_PP(pvalue), (void **) &disp_data) == SUCCESS) {
03708                                           disp_param = mail_newbody_parameter();
03709                                           zend_hash_get_current_key(Z_ARRVAL_PP(pvalue), &key, &ind, 0);
03710                                           disp_param->attribute = cpystr(key);
03711                                           convert_to_string_ex(disp_data);
03712                                           disp_param->value = (char *) fs_get(Z_STRLEN_PP(disp_data) + 1);
03713                                           memcpy(disp_param->value, Z_STRVAL_PP(disp_data), Z_STRLEN_PP(disp_data) + 1);
03714                                           zend_hash_move_forward(Z_ARRVAL_PP(pvalue));
03715                                           disp_param->next = tmp_param;
03716                                           tmp_param = disp_param;
03717                                    }
03718                                    bod->parameter = disp_param;
03719                             }
03720                      }
03721                      if (zend_hash_find(Z_ARRVAL_PP(data), "subtype", sizeof("subtype"), (void **) &pvalue)== SUCCESS) {
03722                             convert_to_string_ex(pvalue);
03723                             bod->subtype = cpystr(Z_STRVAL_PP(pvalue));
03724                      }
03725                      if (zend_hash_find(Z_ARRVAL_PP(data), "id", sizeof("id"), (void **) &pvalue)== SUCCESS) {
03726                             convert_to_string_ex(pvalue);
03727                             bod->id = cpystr(Z_STRVAL_PP(pvalue));
03728                      }
03729                      if (zend_hash_find(Z_ARRVAL_PP(data), "description", sizeof("description"), (void **) &pvalue)== SUCCESS) {
03730                             convert_to_string_ex(pvalue);
03731                             bod->description = cpystr(Z_STRVAL_PP(pvalue));
03732                      }
03733                      if (zend_hash_find(Z_ARRVAL_PP(data), "disposition.type", sizeof("disposition.type"), (void **) &pvalue)== SUCCESS) {
03734                             convert_to_string_ex(pvalue);
03735                             bod->disposition.type = (char *) fs_get(Z_STRLEN_PP(pvalue) + 1);
03736                             memcpy(bod->disposition.type, Z_STRVAL_PP(pvalue), Z_STRLEN_PP(pvalue)+1);
03737                      }
03738                      if (zend_hash_find(Z_ARRVAL_PP(data), "disposition", sizeof("disposition"), (void **) &pvalue)== SUCCESS) {
03739                             if (Z_TYPE_PP(pvalue) == IS_ARRAY) {
03740                                    disp_param = tmp_param = NULL;
03741                                    while (zend_hash_get_current_data(Z_ARRVAL_PP(pvalue), (void **) &disp_data) == SUCCESS) {
03742                                           disp_param = mail_newbody_parameter();
03743                                           zend_hash_get_current_key(Z_ARRVAL_PP(pvalue), &key, &ind, 0);
03744                                           disp_param->attribute = cpystr(key);
03745                                           convert_to_string_ex(disp_data);
03746                                           disp_param->value = (char *) fs_get(Z_STRLEN_PP(disp_data) + 1);
03747                                           memcpy(disp_param->value, Z_STRVAL_PP(disp_data), Z_STRLEN_PP(disp_data) + 1);
03748                                           zend_hash_move_forward(Z_ARRVAL_PP(pvalue));
03749                                           disp_param->next = tmp_param;
03750                                           tmp_param = disp_param;
03751                                    }
03752                                    bod->disposition.parameter = disp_param;
03753                             }
03754                      }
03755                      if (zend_hash_find(Z_ARRVAL_PP(data), "contents.data", sizeof("contents.data"), (void **) &pvalue)== SUCCESS) {
03756                             convert_to_string_ex(pvalue);
03757                             bod->contents.text.data = (char *) fs_get(Z_STRLEN_PP(pvalue) + 1);
03758                             memcpy(bod->contents.text.data, Z_STRVAL_PP(pvalue), Z_STRLEN_PP(pvalue) + 1);
03759                             bod->contents.text.size = Z_STRLEN_PP(pvalue);
03760                      } else {
03761                             bod->contents.text.data = (char *) fs_get(1);
03762                             memcpy(bod->contents.text.data, "", 1);
03763                             bod->contents.text.size = 0;
03764                      }
03765                      if (zend_hash_find(Z_ARRVAL_PP(data), "lines", sizeof("lines"), (void **) &pvalue)== SUCCESS) {
03766                             convert_to_long_ex(pvalue);
03767                             bod->size.lines = Z_LVAL_PP(pvalue);
03768                      }
03769                      if (zend_hash_find(Z_ARRVAL_PP(data), "bytes", sizeof("bytes"), (void **) &pvalue)== SUCCESS) {
03770                             convert_to_long_ex(pvalue);
03771                             bod->size.bytes = Z_LVAL_PP(pvalue);
03772                      }
03773                      if (zend_hash_find(Z_ARRVAL_PP(data), "md5", sizeof("md5"), (void **) &pvalue)== SUCCESS) {
03774                             convert_to_string_ex(pvalue);
03775                             bod->md5 = cpystr(Z_STRVAL_PP(pvalue));
03776                      }
03777               }
03778               zend_hash_move_forward(Z_ARRVAL_P(body));
03779        }
03780 
03781        if (bod && bod->type == TYPEMULTIPART && (!bod->nested.part || !bod->nested.part->next)) {
03782               php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot generate multipart e-mail without components.");
03783               RETVAL_FALSE;
03784               goto done;
03785        }
03786 
03787        rfc822_encode_body_7bit(env, topbod);
03788 
03789        tmp = emalloc(SENDBUFLEN + 1);
03790 
03791        rfc822_header(tmp, env, topbod);
03792 
03793        /* add custom envelope headers */
03794        if (custom_headers_param) {
03795               int l = strlen(tmp) - 2, l2;
03796               PARAMETER *tp = custom_headers_param;
03797 
03798               /* remove last CRLF from tmp */
03799               tmp[l] = '\0';
03800               tempstring = emalloc(l);
03801               memcpy(tempstring, tmp, l);
03802 
03803               do {
03804                      l2 = strlen(custom_headers_param->value);
03805                      tempstring = erealloc(tempstring, l + l2 + CRLF_LEN + 1);
03806                      memcpy(tempstring + l, custom_headers_param->value, l2);
03807                      memcpy(tempstring + l + l2, CRLF, CRLF_LEN);
03808                      l += l2 + CRLF_LEN;
03809               } while ((custom_headers_param = custom_headers_param->next));
03810 
03811               mail_free_body_parameter(&tp);
03812 
03813               mystring = emalloc(l + CRLF_LEN + 1);
03814               memcpy(mystring, tempstring, l);
03815               memcpy(mystring + l , CRLF, CRLF_LEN);
03816               mystring[l + CRLF_LEN] = '\0';
03817 
03818               efree(tempstring);
03819        } else {
03820               mystring = estrdup(tmp);
03821        }
03822 
03823        bod = topbod;
03824 
03825        if (bod && bod->type == TYPEMULTIPART) {
03826 
03827               /* first body part */
03828                      part = bod->nested.part;
03829 
03830               /* find cookie */
03831                      for (param = bod->parameter; param && !cookie; param = param->next) {
03832                             if (!strcmp (param->attribute, "BOUNDARY")) {
03833                                    cookie = param->value;
03834                             }
03835                      }
03836 
03837               /* yucky default */
03838                      if (!cookie) {
03839                             cookie = "-";
03840                      } else if (strlen(cookie) > (SENDBUFLEN - 2 - 2 - 2)) { /* validate cookie length -- + CRLF * 2 */
03841                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "The boundary should be no longer than 4kb");
03842                             RETVAL_FALSE;
03843                             goto done;
03844                      }
03845 
03846               /* for each part */
03847                      do {
03848                             t = tmp;
03849 
03850                      /* append mini-header */
03851                             *t = '\0';
03852                             rfc822_write_body_header(&t, &part->body);
03853 
03854                      /* output cookie, mini-header, and contents */
03855                             spprintf(&tempstring, 0, "%s--%s%s%s%s", mystring, cookie, CRLF, tmp, CRLF);
03856                             efree(mystring);
03857                             mystring=tempstring;
03858 
03859                             bod=&part->body;
03860 
03861                             spprintf(&tempstring, 0, "%s%s%s", mystring, bod->contents.text.data, CRLF);
03862                             efree(mystring);
03863                             mystring=tempstring;
03864                      } while ((part = part->next)); /* until done */
03865 
03866                      /* output trailing cookie */
03867                      spprintf(&tempstring, 0, "%s--%s--%s", mystring, cookie, CRLF);
03868                      efree(mystring);
03869                      mystring=tempstring;
03870        } else if (bod) {
03871               spprintf(&tempstring, 0, "%s%s%s", mystring, bod->contents.text.data, CRLF);
03872               efree(mystring);
03873               mystring=tempstring;
03874        } else {
03875               efree(mystring);
03876               RETVAL_FALSE;
03877               goto done;
03878        }
03879 
03880        RETVAL_STRING(tempstring, 0);
03881 done:
03882        if (tmp) {
03883               efree(tmp);
03884        }
03885        mail_free_body(&topbod);
03886        mail_free_envelope(&env);
03887 }
03888 /* }}} */
03889 
03890 /* {{{ _php_imap_mail
03891  */
03892 int _php_imap_mail(char *to, char *subject, char *message, char *headers, char *cc, char *bcc, char* rpath TSRMLS_DC)
03893 {
03894 #ifdef PHP_WIN32
03895        int tsm_err;
03896 #else
03897        FILE *sendmail;
03898        int ret;
03899 #endif
03900 
03901 #ifdef PHP_WIN32
03902        char *tempMailTo;
03903        char *tsm_errmsg = NULL;
03904        ADDRESS *addr;
03905        char *bufferTo = NULL, *bufferCc = NULL, *bufferBcc = NULL, *bufferHeader = NULL;
03906        int offset, bufferLen = 0;
03907        size_t bt_len;
03908 
03909        if (headers) {
03910               bufferLen += strlen(headers);
03911        }
03912        if (to) {
03913               bufferLen += strlen(to) + 6;
03914        }
03915        if (cc) {
03916               bufferLen += strlen(cc) + 6;
03917        }
03918 
03919 #define PHP_IMAP_CLEAN      if (bufferTo) efree(bufferTo); if (bufferCc) efree(bufferCc); if (bufferBcc) efree(bufferBcc); if (bufferHeader) efree(bufferHeader);
03920 #define PHP_IMAP_BAD_DEST PHP_IMAP_CLEAN; efree(tempMailTo); return (BAD_MSG_DESTINATION);
03921 
03922        bufferHeader = (char *)emalloc(bufferLen + 1);
03923        memset(bufferHeader, 0, bufferLen);
03924        if (to && *to) {
03925               strlcat(bufferHeader, "To: ", bufferLen + 1);
03926               strlcat(bufferHeader, to, bufferLen + 1);
03927               strlcat(bufferHeader, "\r\n", bufferLen + 1);
03928               tempMailTo = estrdup(to);
03929               bt_len = strlen(to);
03930               bufferTo = (char *)safe_emalloc(bt_len, 1, 1);
03931               bt_len++;
03932               offset = 0;
03933               addr = NULL;
03934               rfc822_parse_adrlist(&addr, tempMailTo, NULL);
03935               while (addr) {
03936                      if (addr->host == NULL || strcmp(addr->host, ERRHOST) == 0) {
03937                             PHP_IMAP_BAD_DEST;
03938                      } else {
03939                             bufferTo = safe_erealloc(bufferTo, bt_len, 1, strlen(addr->mailbox));
03940                             bt_len += strlen(addr->mailbox);
03941                             bufferTo = safe_erealloc(bufferTo, bt_len, 1, strlen(addr->host));
03942                             bt_len += strlen(addr->host);
03943                             offset += slprintf(bufferTo + offset, bt_len - offset, "%s@%s,", addr->mailbox, addr->host);
03944                      }
03945                      addr = addr->next;
03946               }
03947               efree(tempMailTo);
03948               if (offset>0) {
03949                      bufferTo[offset-1] = 0;
03950               }
03951        }
03952 
03953        if (cc && *cc) {
03954               strlcat(bufferHeader, "Cc: ", bufferLen + 1);
03955               strlcat(bufferHeader, cc, bufferLen + 1);
03956               strlcat(bufferHeader, "\r\n", bufferLen + 1);
03957               tempMailTo = estrdup(cc);
03958               bt_len = strlen(cc);
03959               bufferCc = (char *)safe_emalloc(bt_len, 1, 1);
03960               bt_len++;
03961               offset = 0;
03962               addr = NULL;
03963               rfc822_parse_adrlist(&addr, tempMailTo, NULL);
03964               while (addr) {
03965                      if (addr->host == NULL || strcmp(addr->host, ERRHOST) == 0) {
03966                             PHP_IMAP_BAD_DEST;
03967                      } else {
03968                             bufferCc = safe_erealloc(bufferCc, bt_len, 1, strlen(addr->mailbox));
03969                             bt_len += strlen(addr->mailbox);
03970                             bufferCc = safe_erealloc(bufferCc, bt_len, 1, strlen(addr->host));
03971                             bt_len += strlen(addr->host);
03972                             offset += slprintf(bufferCc + offset, bt_len - offset, "%s@%s,", addr->mailbox, addr->host);
03973                      }
03974                      addr = addr->next;
03975               }
03976               efree(tempMailTo);
03977               if (offset>0) {
03978                      bufferCc[offset-1] = 0;
03979               }
03980        }
03981 
03982        if (bcc && *bcc) {
03983               tempMailTo = estrdup(bcc);
03984               bt_len = strlen(bcc);
03985               bufferBcc = (char *)safe_emalloc(bt_len, 1, 1);
03986               bt_len++;
03987               offset = 0;
03988               addr = NULL;
03989               rfc822_parse_adrlist(&addr, tempMailTo, NULL);
03990               while (addr) {
03991                      if (addr->host == NULL || strcmp(addr->host, ERRHOST) == 0) {
03992                             PHP_IMAP_BAD_DEST;
03993                      } else {
03994                             bufferBcc = safe_erealloc(bufferBcc, bt_len, 1, strlen(addr->mailbox));
03995                             bt_len += strlen(addr->mailbox);
03996                             bufferBcc = safe_erealloc(bufferBcc, bt_len, 1, strlen(addr->host));
03997                             bt_len += strlen(addr->host);
03998                             offset += slprintf(bufferBcc + offset, bt_len - offset, "%s@%s,", addr->mailbox, addr->host);
03999                      }
04000                      addr = addr->next;
04001               }
04002               efree(tempMailTo);
04003               if (offset>0) {
04004                      bufferBcc[offset-1] = 0;
04005               }
04006        }
04007 
04008        if (headers && *headers) {
04009               strlcat(bufferHeader, headers, bufferLen + 1);
04010        }
04011 
04012        if (TSendMail(INI_STR("SMTP"), &tsm_err, &tsm_errmsg, bufferHeader, subject, bufferTo, message, bufferCc, bufferBcc, rpath TSRMLS_CC) != SUCCESS) {
04013               if (tsm_errmsg) {
04014                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", tsm_errmsg);
04015                      efree(tsm_errmsg);
04016               } else {
04017                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", GetSMErrorText(tsm_err));
04018               }
04019               PHP_IMAP_CLEAN;
04020               return 0;
04021        }
04022        PHP_IMAP_CLEAN;
04023 #else
04024        if (!INI_STR("sendmail_path")) {
04025               return 0;
04026        }
04027        sendmail = popen(INI_STR("sendmail_path"), "w");
04028        if (sendmail) {
04029               if (rpath && rpath[0]) fprintf(sendmail, "From: %s\n", rpath);
04030               fprintf(sendmail, "To: %s\n", to);
04031               if (cc && cc[0]) fprintf(sendmail, "Cc: %s\n", cc);
04032               if (bcc && bcc[0]) fprintf(sendmail, "Bcc: %s\n", bcc);
04033               fprintf(sendmail, "Subject: %s\n", subject);
04034               if (headers != NULL) {
04035                      fprintf(sendmail, "%s\n", headers);
04036               }
04037               fprintf(sendmail, "\n%s\n", message);
04038               ret = pclose(sendmail);
04039               if (ret == -1) {
04040                      return 0;
04041               } else {
04042                      return 1;
04043               }
04044        } else {
04045               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not execute mail delivery program");
04046               return 0;
04047        }
04048 #endif
04049        return 1;
04050 }
04051 /* }}} */
04052 
04053 /* {{{ proto bool imap_mail(string to, string subject, string message [, string additional_headers [, string cc [, string bcc [, string rpath]]]])
04054    Send an email message */
04055 PHP_FUNCTION(imap_mail)
04056 {
04057        char *to=NULL, *message=NULL, *headers=NULL, *subject=NULL, *cc=NULL, *bcc=NULL, *rpath=NULL;
04058        int to_len, message_len, headers_len, subject_len, cc_len, bcc_len, rpath_len, argc = ZEND_NUM_ARGS();
04059 
04060        if (zend_parse_parameters(argc TSRMLS_CC, "sss|ssss", &to, &to_len, &subject, &subject_len, &message, &message_len,
04061               &headers, &headers_len, &cc, &cc_len, &bcc, &bcc_len, &rpath, &rpath_len) == FAILURE) {
04062               return;
04063        }
04064 
04065        /* To: */
04066        if (!to_len) {
04067               php_error_docref(NULL TSRMLS_CC, E_WARNING, "No to field in mail command");
04068               RETURN_FALSE;
04069        }
04070 
04071        /* Subject: */
04072        if (!subject_len) {
04073               php_error_docref(NULL TSRMLS_CC, E_WARNING, "No subject field in mail command");
04074               RETURN_FALSE;
04075        }
04076 
04077        /* message body */
04078        if (!message_len) {
04079               /* this is not really an error, so it is allowed. */
04080               php_error_docref(NULL TSRMLS_CC, E_WARNING, "No message string in mail command");
04081               message = NULL;
04082        }
04083 
04084        if (_php_imap_mail(to, subject, message, headers, cc, bcc, rpath TSRMLS_CC)) {
04085               RETURN_TRUE;
04086        } else {
04087               RETURN_FALSE;
04088        }
04089 }
04090 /* }}} */
04091 
04092 /* {{{ proto array imap_search(resource stream_id, string criteria [, int options [, string charset]])
04093    Return a list of messages matching the given criteria */
04094 PHP_FUNCTION(imap_search)
04095 {
04096        zval *streamind;
04097        char *criteria, *charset = NULL;
04098        int criteria_len, charset_len = 0;
04099        long flags = SE_FREE;
04100        pils *imap_le_struct;
04101        char *search_criteria;
04102        MESSAGELIST *cur;
04103        int argc = ZEND_NUM_ARGS();
04104        SEARCHPGM *pgm = NIL;
04105 
04106        if (zend_parse_parameters(argc TSRMLS_CC, "rs|ls", &streamind, &criteria, &criteria_len, &flags, &charset, &charset_len) == FAILURE) {
04107               return;
04108        }
04109 
04110        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
04111 
04112        search_criteria = estrndup(criteria, criteria_len);
04113 
04114        IMAPG(imap_messages) = IMAPG(imap_messages_tail) = NIL;
04115        pgm = mail_criteria(search_criteria);
04116 
04117        mail_search_full(imap_le_struct->imap_stream, (argc == 4 ? charset : NIL), pgm, flags);
04118 
04119        if (pgm && !(flags & SE_FREE)) {
04120               mail_free_searchpgm(&pgm);
04121        }
04122 
04123        if (IMAPG(imap_messages) == NIL) {
04124               efree(search_criteria);
04125               RETURN_FALSE;
04126        }
04127 
04128        array_init(return_value);
04129 
04130        cur = IMAPG(imap_messages);
04131        while (cur != NIL) {
04132               add_next_index_long(return_value, cur->msgid);
04133               cur = cur->next;
04134        }
04135        mail_free_messagelist(&IMAPG(imap_messages), &IMAPG(imap_messages_tail));
04136        efree(search_criteria);
04137 }
04138 /* }}} */
04139 
04140 /* {{{ proto array imap_alerts(void)
04141    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. */
04142 /* Author: CJH */
04143 PHP_FUNCTION(imap_alerts)
04144 {
04145        STRINGLIST *cur=NIL;
04146 
04147        if (zend_parse_parameters_none() == FAILURE) {
04148               return;
04149        }
04150 
04151        if (IMAPG(imap_alertstack) == NIL) {
04152               RETURN_FALSE;
04153        }
04154 
04155        array_init(return_value);
04156 
04157        cur = IMAPG(imap_alertstack);
04158        while (cur != NIL) {
04159               add_next_index_string(return_value, cur->LTEXT, 1);
04160               cur = cur->next;
04161        }
04162        mail_free_stringlist(&IMAPG(imap_alertstack));
04163        IMAPG(imap_alertstack) = NIL;
04164 }
04165 /* }}} */
04166 
04167 /* {{{ proto array imap_errors(void)
04168    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. */
04169 /* Author: CJH */
04170 PHP_FUNCTION(imap_errors)
04171 {
04172        ERRORLIST *cur=NIL;
04173 
04174        if (zend_parse_parameters_none() == FAILURE) {
04175               return;
04176        }
04177 
04178        if (IMAPG(imap_errorstack) == NIL) {
04179               RETURN_FALSE;
04180        }
04181 
04182        array_init(return_value);
04183 
04184        cur = IMAPG(imap_errorstack);
04185        while (cur != NIL) {
04186               add_next_index_string(return_value, cur->LTEXT, 1);
04187               cur = cur->next;
04188        }
04189        mail_free_errorlist(&IMAPG(imap_errorstack));
04190        IMAPG(imap_errorstack) = NIL;
04191 }
04192 /* }}} */
04193 
04194 /* {{{ proto string imap_last_error(void)
04195    Returns the last error that was generated by an IMAP function. The error stack is NOT cleared after this call. */
04196 /* Author: CJH */
04197 PHP_FUNCTION(imap_last_error)
04198 {
04199        ERRORLIST *cur=NIL;
04200 
04201        if (zend_parse_parameters_none() == FAILURE) {
04202               return;
04203        }
04204 
04205        if (IMAPG(imap_errorstack) == NIL) {
04206               RETURN_FALSE;
04207        }
04208 
04209        cur = IMAPG(imap_errorstack);
04210        while (cur != NIL) {
04211               if (cur->next == NIL) {
04212                      RETURN_STRING(cur->LTEXT, 1);
04213               }
04214               cur = cur->next;
04215        }
04216 }
04217 /* }}} */
04218 
04219 /* {{{ proto array imap_mime_header_decode(string str)
04220    Decode mime header element in accordance with RFC 2047 and return array of objects containing 'charset' encoding and decoded 'text' */
04221 PHP_FUNCTION(imap_mime_header_decode)
04222 {
04223        /* Author: Ted Parnefors <ted@mtv.se> */
04224        zval *myobject;
04225        char *str, *string, *charset, encoding, *text, *decode;
04226        int str_len;
04227        long charset_token, encoding_token, end_token, end, offset=0, i;
04228        unsigned long newlength;
04229 
04230        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) {
04231               return;
04232        }
04233 
04234        array_init(return_value);
04235 
04236        string = str;
04237        end = str_len;
04238 
04239        charset = (char *) safe_emalloc((end + 1), 2, 0);
04240        text = &charset[end + 1];
04241        while (offset < end) {      /* Reached end of the string? */
04242               if ((charset_token = (long)php_memnstr(&string[offset], "=?", 2, string + end))) {  /* Is there anything encoded in the string? */
04243                      charset_token -= (long)string;
04244                      if (offset != charset_token) {     /* Is there anything before the encoded data? */
04245                             /* Retrieve unencoded data that is found before encoded data */
04246                             memcpy(text, &string[offset], charset_token-offset);
04247                             text[charset_token - offset] = 0x00;
04248                             MAKE_STD_ZVAL(myobject);
04249                             object_init(myobject);
04250                             add_property_string(myobject, "charset", "default", 1);
04251                             add_property_string(myobject, "text", text, 1);
04252                             zend_hash_next_index_insert(Z_ARRVAL_P(return_value), (void *)&myobject, sizeof(zval *), NULL);
04253                      }
04254                      if ((encoding_token = (long)php_memnstr(&string[charset_token+2], "?", 1, string+end))) {         /* Find token for encoding */
04255                             encoding_token -= (long)string;
04256                             if ((end_token = (long)php_memnstr(&string[encoding_token+3], "?=", 2, string+end))) {     /* Find token for end of encoded data */
04257                                    end_token -= (long)string;
04258                                    memcpy(charset, &string[charset_token + 2], encoding_token - (charset_token + 2));  /* Extract charset encoding */
04259                                    charset[encoding_token-(charset_token + 2)] = 0x00;
04260                                    encoding=string[encoding_token + 1];      /* Extract encoding from string */
04261                                    memcpy(text, &string[encoding_token + 3], end_token - (encoding_token + 3)); /* Extract text */
04262                                    text[end_token - (encoding_token + 3)] = 0x00;
04263                                    decode = text;
04264                                    if (encoding == 'q' || encoding == 'Q') { /* Decode 'q' encoded data */
04265                                           for(i=0; text[i] != 0x00; i++) if (text[i] == '_') text[i] = ' ';     /* Replace all *_' with space. */
04266                                           decode = (char *)rfc822_qprint((unsigned char *) text, strlen(text), &newlength);
04267                                    } else if (encoding == 'b' || encoding == 'B') {
04268                                           decode = (char *)rfc822_base64((unsigned char *) text, strlen(text), &newlength); /* Decode 'B' encoded data */
04269                                    }
04270                                    if (decode == NULL) {
04271                                           efree(charset);
04272                                           zval_dtor(return_value);
04273                                           RETURN_FALSE;
04274                                    }
04275                                    MAKE_STD_ZVAL(myobject);
04276                                    object_init(myobject);
04277                                    add_property_string(myobject, "charset", charset, 1);
04278                                    add_property_string(myobject, "text", decode, 1);
04279                                    zend_hash_next_index_insert(Z_ARRVAL_P(return_value), (void *)&myobject, sizeof(zval *), NULL);
04280 
04281                                    /* only free decode if it was allocated by rfc822_qprint or rfc822_base64 */
04282                                    if (decode != text) {
04283                                           fs_give((void**)&decode);
04284                                    }
04285 
04286                                    offset = end_token+2;
04287                                    for (i = 0; (string[offset + i] == ' ') || (string[offset + i] == 0x0a) || (string[offset + i] == 0x0d) || (string[offset + i] == '\t'); i++);
04288                                    if ((string[offset + i] == '=') && (string[offset + i + 1] == '?') && (offset + i < end)) {
04289                                           offset += i;
04290                                    }
04291                                    continue;     /*/ Iterate the loop again please. */
04292                             }
04293                      }
04294               } else {
04295                      /* Just some tweaking to optimize the code, and get the end statements work in a general manner.
04296                       * If we end up here we didn't find a position for "charset_token",
04297                       * so we need to set it to the start of the yet unextracted data.
04298                       */
04299                      charset_token = offset;
04300               }
04301               /* Return the rest of the data as unencoded, as it was either unencoded or was missing separators
04302                  which rendered the remainder of the string impossible for us to decode. */
04303               memcpy(text, &string[charset_token], end - charset_token);     /* Extract unencoded text from string */
04304               text[end - charset_token] = 0x00;
04305               MAKE_STD_ZVAL(myobject);
04306               object_init(myobject);
04307               add_property_string(myobject, "charset", "default", 1);
04308               add_property_string(myobject, "text", text, 1);
04309               zend_hash_next_index_insert(Z_ARRVAL_P(return_value), (void *)&myobject, sizeof(zval *), NULL);
04310 
04311               offset = end; /* We have reached the end of the string. */
04312        }
04313        efree(charset);
04314 }
04315 /* }}} */
04316 
04317 /* Support Functions */
04318 
04319 #ifdef HAVE_RFC822_OUTPUT_ADDRESS_LIST
04320 /* {{{ _php_rfc822_soutr
04321  */
04322 static long _php_rfc822_soutr (void *stream, char *string)
04323 {
04324        smart_str *ret = (smart_str*)stream;
04325        int len = strlen(string);
04326 
04327        smart_str_appendl(ret, string, len);
04328        return LONGT;
04329 }
04330 /* }}} */
04331 
04332 /* {{{ _php_rfc822_write_address
04333  */
04334 static char* _php_rfc822_write_address(ADDRESS *addresslist TSRMLS_DC)
04335 {
04336        char address[MAILTMPLEN];
04337        smart_str ret = {0};
04338        RFC822BUFFER buf;
04339 
04340        buf.beg = address;
04341        buf.cur = buf.beg;
04342        buf.end = buf.beg + sizeof(address) - 1;
04343        buf.s = &ret;
04344        buf.f = _php_rfc822_soutr;
04345        rfc822_output_address_list(&buf, addresslist, 0, NULL);
04346        rfc822_output_flush(&buf);
04347        smart_str_0(&ret);
04348        return ret.c;
04349 }
04350 /* }}} */
04351 
04352 #else
04353 
04354 /* {{{ _php_rfc822_len
04355  * Calculate string length based on imap's rfc822_cat function.
04356  */
04357 static int _php_rfc822_len(char *str)
04358 {
04359        int len;
04360        char *p;
04361 
04362        if (!str || !*str) {
04363               return 0;
04364        }
04365 
04366        /* strings with special characters will need to be quoted, as a safety measure we
04367         * add 2 bytes for the quotes just in case.
04368         */
04369        len = strlen(str) + 2;
04370        p = str;
04371        /* rfc822_cat() will escape all " and \ characters, therefor we need to increase
04372         * our buffer length to account for these characters.
04373         */
04374        while ((p = strpbrk(p, "\\\""))) {
04375               p++;
04376               len++;
04377        }
04378 
04379        return len;
04380 }
04381 /* }}} */
04382 
04383 /* {{{ _php_imap_get_address_size
04384  */
04385 static int _php_imap_address_size (ADDRESS *addresslist)
04386 {
04387        ADDRESS *tmp;
04388        int ret=0, num_ent=0;
04389 
04390        tmp = addresslist;
04391 
04392        if (tmp) do {
04393               ret += _php_rfc822_len(tmp->personal);
04394               ret += _php_rfc822_len(tmp->adl);
04395               ret += _php_rfc822_len(tmp->mailbox);
04396               ret += _php_rfc822_len(tmp->host);
04397               num_ent++;
04398        } while ((tmp = tmp->next));
04399 
04400        /*
04401         * rfc822_write_address_full() needs some extra space for '<>,', etc.
04402         * for this perpouse we allocate additional PHP_IMAP_ADDRESS_SIZE_BUF bytes
04403         * by default this buffer is 10 bytes long
04404        */
04405        ret += (ret) ? num_ent*PHP_IMAP_ADDRESS_SIZE_BUF : 0;
04406 
04407        return ret;
04408 }
04409 
04410 /* }}} */
04411 
04412 /* {{{ _php_rfc822_write_address
04413  */
04414 static char* _php_rfc822_write_address(ADDRESS *addresslist TSRMLS_DC)
04415 {
04416        char address[SENDBUFLEN];
04417 
04418        if (_php_imap_address_size(addresslist) >= SENDBUFLEN) {
04419               php_error_docref(NULL TSRMLS_CC, E_ERROR, "Address buffer overflow");
04420               return NULL;
04421        }
04422        address[0] = 0;
04423        rfc822_write_address(address, addresslist);
04424        return estrdup(address);
04425 }
04426 /* }}} */
04427 #endif
04428 /* {{{ _php_imap_parse_address
04429  */
04430 static char* _php_imap_parse_address (ADDRESS *addresslist, zval *paddress TSRMLS_DC)
04431 {
04432        char *fulladdress;
04433        ADDRESS *addresstmp;
04434        zval *tmpvals;
04435 
04436        addresstmp = addresslist;
04437 
04438        fulladdress = _php_rfc822_write_address(addresstmp TSRMLS_CC);
04439 
04440        addresstmp = addresslist;
04441        do {
04442               MAKE_STD_ZVAL(tmpvals);
04443               object_init(tmpvals);
04444               if (addresstmp->personal) add_property_string(tmpvals, "personal", addresstmp->personal, 1);
04445               if (addresstmp->adl) add_property_string(tmpvals, "adl", addresstmp->adl, 1);
04446               if (addresstmp->mailbox) add_property_string(tmpvals, "mailbox", addresstmp->mailbox, 1);
04447               if (addresstmp->host) add_property_string(tmpvals, "host", addresstmp->host, 1);
04448               add_next_index_object(paddress, tmpvals TSRMLS_CC);
04449        } while ((addresstmp = addresstmp->next));
04450        return fulladdress;
04451 }
04452 /* }}} */
04453 
04454 /* {{{ _php_make_header_object
04455  */
04456 static void _php_make_header_object(zval *myzvalue, ENVELOPE *en TSRMLS_DC)
04457 {
04458        zval *paddress;
04459        char *fulladdress=NULL;
04460 
04461        object_init(myzvalue);
04462 
04463        if (en->remail) add_property_string(myzvalue, "remail", en->remail, 1);
04464        if (en->date) add_property_string(myzvalue, "date", en->date, 1);
04465        if (en->date) add_property_string(myzvalue, "Date", en->date, 1);
04466        if (en->subject) add_property_string(myzvalue, "subject", en->subject, 1);
04467        if (en->subject) add_property_string(myzvalue, "Subject", en->subject, 1);
04468        if (en->in_reply_to) add_property_string(myzvalue, "in_reply_to", en->in_reply_to, 1);
04469        if (en->message_id) add_property_string(myzvalue, "message_id", en->message_id, 1);
04470        if (en->newsgroups) add_property_string(myzvalue, "newsgroups", en->newsgroups, 1);
04471        if (en->followup_to) add_property_string(myzvalue, "followup_to", en->followup_to, 1);
04472        if (en->references) add_property_string(myzvalue, "references", en->references, 1);
04473 
04474        if (en->to) {
04475               MAKE_STD_ZVAL(paddress);
04476               array_init(paddress);
04477               fulladdress = _php_imap_parse_address(en->to, paddress TSRMLS_CC);
04478               if (fulladdress) {
04479                      add_property_string(myzvalue, "toaddress", fulladdress, 0);
04480               }
04481               add_assoc_object(myzvalue, "to", paddress TSRMLS_CC);
04482        }
04483 
04484        if (en->from) {
04485               MAKE_STD_ZVAL(paddress);
04486               array_init(paddress);
04487               fulladdress = _php_imap_parse_address(en->from, paddress TSRMLS_CC);
04488               if (fulladdress) {
04489                      add_property_string(myzvalue, "fromaddress", fulladdress, 0);
04490               }
04491               add_assoc_object(myzvalue, "from", paddress TSRMLS_CC);
04492        }
04493 
04494        if (en->cc) {
04495               MAKE_STD_ZVAL(paddress);
04496               array_init(paddress);
04497               fulladdress = _php_imap_parse_address(en->cc, paddress TSRMLS_CC);
04498               if (fulladdress) {
04499                      add_property_string(myzvalue, "ccaddress", fulladdress, 0);
04500               }
04501               add_assoc_object(myzvalue, "cc", paddress TSRMLS_CC);
04502        }
04503 
04504        if (en->bcc) {
04505               MAKE_STD_ZVAL(paddress);
04506               array_init(paddress);
04507               fulladdress = _php_imap_parse_address(en->bcc, paddress TSRMLS_CC);
04508               if (fulladdress) {
04509                      add_property_string(myzvalue, "bccaddress", fulladdress, 0);
04510               }
04511               add_assoc_object(myzvalue, "bcc", paddress TSRMLS_CC);
04512        }
04513 
04514        if (en->reply_to) {
04515               MAKE_STD_ZVAL(paddress);
04516               array_init(paddress);
04517               fulladdress = _php_imap_parse_address(en->reply_to, paddress TSRMLS_CC);
04518               if (fulladdress) {
04519                      add_property_string(myzvalue, "reply_toaddress", fulladdress, 0);
04520               }
04521               add_assoc_object(myzvalue, "reply_to", paddress TSRMLS_CC);
04522        }
04523 
04524        if (en->sender) {
04525               MAKE_STD_ZVAL(paddress);
04526               array_init(paddress);
04527               fulladdress = _php_imap_parse_address(en->sender, paddress TSRMLS_CC);
04528               if (fulladdress) {
04529                      add_property_string(myzvalue, "senderaddress", fulladdress, 0);
04530               }
04531               add_assoc_object(myzvalue, "sender", paddress TSRMLS_CC);
04532        }
04533 
04534        if (en->return_path) {
04535               MAKE_STD_ZVAL(paddress);
04536               array_init(paddress);
04537               fulladdress = _php_imap_parse_address(en->return_path, paddress TSRMLS_CC);
04538               if (fulladdress) {
04539                      add_property_string(myzvalue, "return_pathaddress", fulladdress, 0);
04540               }
04541               add_assoc_object(myzvalue, "return_path", paddress TSRMLS_CC);
04542        }
04543 }
04544 /* }}} */
04545 
04546 /* {{{ _php_imap_add_body
04547  */
04548 void _php_imap_add_body(zval *arg, BODY *body TSRMLS_DC)
04549 {
04550        zval *parametres, *param, *dparametres, *dparam;
04551        PARAMETER *par, *dpar;
04552        PART *part;
04553 
04554        if (body->type <= TYPEMAX) {
04555               add_property_long(arg, "type", body->type);
04556        }
04557 
04558        if (body->encoding <= ENCMAX) {
04559               add_property_long(arg, "encoding", body->encoding);
04560        }
04561 
04562        if (body->subtype) {
04563               add_property_long(arg, "ifsubtype", 1);
04564               add_property_string(arg, "subtype", body->subtype, 1);
04565        } else {
04566               add_property_long(arg, "ifsubtype", 0);
04567        }
04568 
04569        if (body->description) {
04570               add_property_long(arg, "ifdescription", 1);
04571               add_property_string(arg, "description", body->description, 1);
04572        } else {
04573               add_property_long(arg, "ifdescription", 0);
04574        }
04575 
04576        if (body->id) {
04577               add_property_long(arg, "ifid", 1);
04578               add_property_string(arg, "id", body->id, 1);
04579        } else {
04580               add_property_long(arg, "ifid", 0);
04581        }
04582 
04583        if (body->size.lines) {
04584               add_property_long(arg, "lines", body->size.lines);
04585        }
04586 
04587        if (body->size.bytes) {
04588               add_property_long(arg, "bytes", body->size.bytes);
04589        }
04590 
04591 #ifdef IMAP41
04592        if (body->disposition.type) {
04593               add_property_long(arg, "ifdisposition", 1);
04594               add_property_string(arg, "disposition", body->disposition.type, 1);
04595        } else {
04596               add_property_long(arg, "ifdisposition", 0);
04597        }
04598 
04599        if (body->disposition.parameter) {
04600               dpar = body->disposition.parameter;
04601               add_property_long(arg, "ifdparameters", 1);
04602               MAKE_STD_ZVAL(dparametres);
04603               array_init(dparametres);
04604               do {
04605                      MAKE_STD_ZVAL(dparam);
04606                      object_init(dparam);
04607                      add_property_string(dparam, "attribute", dpar->attribute, 1);
04608                      add_property_string(dparam, "value", dpar->value, 1);
04609                      add_next_index_object(dparametres, dparam TSRMLS_CC);
04610               } while ((dpar = dpar->next));
04611               add_assoc_object(arg, "dparameters", dparametres TSRMLS_CC);
04612        } else {
04613               add_property_long(arg, "ifdparameters", 0);
04614        }
04615 #endif
04616 
04617        if ((par = body->parameter)) {
04618               add_property_long(arg, "ifparameters", 1);
04619 
04620               MAKE_STD_ZVAL(parametres);
04621               array_init(parametres);
04622               do {
04623                      MAKE_STD_ZVAL(param);
04624                      object_init(param);
04625                      if (par->attribute) {
04626                             add_property_string(param, "attribute", par->attribute, 1);
04627                      }
04628                      if (par->value) {
04629                             add_property_string(param, "value", par->value, 1);
04630                      }
04631 
04632                      add_next_index_object(parametres, param TSRMLS_CC);
04633               } while ((par = par->next));
04634        } else {
04635               MAKE_STD_ZVAL(parametres);
04636               object_init(parametres);
04637               add_property_long(arg, "ifparameters", 0);
04638        }
04639        add_assoc_object(arg, "parameters", parametres TSRMLS_CC);
04640 
04641        /* multipart message ? */
04642        if (body->type == TYPEMULTIPART) {
04643               MAKE_STD_ZVAL(parametres);
04644               array_init(parametres);
04645               for (part = body->CONTENT_PART; part; part = part->next) {
04646                      MAKE_STD_ZVAL(param);
04647                      object_init(param);
04648                      _php_imap_add_body(param, &part->body TSRMLS_CC);
04649                      add_next_index_object(parametres, param TSRMLS_CC);
04650               }
04651               add_assoc_object(arg, "parts", parametres TSRMLS_CC);
04652        }
04653 
04654        /* encapsulated message ? */
04655        if ((body->type == TYPEMESSAGE) && (!strcasecmp(body->subtype, "rfc822"))) {
04656               body = body->CONTENT_MSG_BODY;
04657               MAKE_STD_ZVAL(parametres);
04658               array_init(parametres);
04659               MAKE_STD_ZVAL(param);
04660               object_init(param);
04661               _php_imap_add_body(param, body TSRMLS_CC);
04662               add_next_index_object(parametres, param TSRMLS_CC);
04663               add_assoc_object(arg, "parts", parametres TSRMLS_CC);
04664        }
04665 }
04666 /* }}} */
04667 
04668 /* imap_thread, stealing this from header cclient -rjs3 */
04669 /* {{{ build_thread_tree_helper
04670  */
04671 static void build_thread_tree_helper(THREADNODE *cur, zval *tree, long *numNodes, char *buf)
04672 {
04673        unsigned long thisNode = *numNodes;
04674 
04675        /* define "#.num" */
04676        snprintf(buf, 25, "%ld.num", thisNode);
04677 
04678        add_assoc_long(tree, buf, cur->num);
04679 
04680        snprintf(buf, 25, "%ld.next", thisNode);
04681        if(cur->next) {
04682               (*numNodes)++;
04683               add_assoc_long(tree, buf, *numNodes);
04684               build_thread_tree_helper(cur->next, tree, numNodes, buf);
04685        } else { /* "null pointer" */
04686               add_assoc_long(tree, buf, 0);
04687        }
04688 
04689        snprintf(buf, 25, "%ld.branch", thisNode);
04690        if(cur->branch) {
04691               (*numNodes)++;
04692               add_assoc_long(tree, buf, *numNodes);
04693               build_thread_tree_helper(cur->branch, tree, numNodes, buf);
04694        } else { /* "null pointer" */
04695               add_assoc_long(tree, buf, 0);
04696        }
04697 }
04698 /* }}} */
04699 
04700 /* {{{ build_thread_tree
04701  */
04702 static int build_thread_tree(THREADNODE *top, zval **tree)
04703 {
04704        long numNodes = 0;
04705        char buf[25];
04706 
04707        array_init(*tree);
04708 
04709        build_thread_tree_helper(top, *tree, &numNodes, buf);
04710 
04711        return SUCCESS;
04712 }
04713 /* }}} */
04714 
04715 /* {{{ proto array imap_thread(resource stream_id [, int options])
04716    Return threaded by REFERENCES tree */
04717 PHP_FUNCTION(imap_thread)
04718 {
04719        zval *streamind;
04720        pils *imap_le_struct;
04721        long flags = SE_FREE;
04722        char criteria[] = "ALL";
04723        THREADNODE *top;
04724        int argc = ZEND_NUM_ARGS();
04725        SEARCHPGM *pgm = NIL;
04726 
04727        if (zend_parse_parameters(argc TSRMLS_CC, "r|l", &streamind, &flags) == FAILURE) {
04728               return;
04729        }
04730 
04731        ZEND_FETCH_RESOURCE(imap_le_struct, pils *, &streamind, -1, "imap", le_imap);
04732 
04733        pgm = mail_criteria(criteria);
04734        top = mail_thread(imap_le_struct->imap_stream, "REFERENCES", NIL, pgm, flags);
04735        if (pgm && !(flags & SE_FREE)) {
04736               mail_free_searchpgm(&pgm);
04737        }
04738 
04739        if(top == NIL) {
04740               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Function returned an empty tree");
04741               RETURN_FALSE;
04742        }
04743 
04744        /* Populate our return value data structure here. */
04745        if(build_thread_tree(top, &return_value) == FAILURE) {
04746               mail_free_threadnode(&top);
04747               RETURN_FALSE;
04748        }
04749        mail_free_threadnode(&top);
04750 }
04751 /* }}} */
04752 
04753 /* {{{ proto mixed imap_timeout(int timeout_type [, int timeout])
04754    Set or fetch imap timeout */
04755 PHP_FUNCTION(imap_timeout)
04756 {
04757        long ttype, timeout=-1;
04758        int timeout_type;
04759 
04760        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l", &ttype, &timeout) == FAILURE) {
04761               RETURN_FALSE;
04762        }
04763 
04764        if (timeout == -1) {
04765               switch (ttype) {
04766                      case 1:
04767                             timeout_type = GET_OPENTIMEOUT;
04768                             break;
04769                      case 2:
04770                             timeout_type = GET_READTIMEOUT;
04771                             break;
04772                      case 3:
04773                             timeout_type = GET_WRITETIMEOUT;
04774                             break;
04775                      case 4:
04776                             timeout_type = GET_CLOSETIMEOUT;
04777                             break;
04778                      default:
04779                             RETURN_FALSE;
04780                             break;
04781               }
04782 
04783               timeout = (long) mail_parameters(NIL, timeout_type, NIL);
04784               RETURN_LONG(timeout);
04785        } else if (timeout >= 0) {
04786               switch (ttype) {
04787                      case 1:
04788                             timeout_type = SET_OPENTIMEOUT;
04789                             break;
04790                      case 2:
04791                             timeout_type = SET_READTIMEOUT;
04792                             break;
04793                      case 3:
04794                             timeout_type = SET_WRITETIMEOUT;
04795                             break;
04796                      case 4:
04797                             timeout_type = SET_CLOSETIMEOUT;
04798                             break;
04799                      default:
04800                             RETURN_FALSE;
04801                             break;
04802               }
04803 
04804               timeout = (long) mail_parameters(NIL, timeout_type, (void *) timeout);
04805               RETURN_TRUE;
04806        } else {
04807               RETURN_FALSE;
04808        }
04809 }
04810 /* }}} */
04811 
04812 #define GETS_FETCH_SIZE 8196LU
04813 static char *php_mail_gets(readfn_t f, void *stream, unsigned long size, GETS_DATA *md) /* {{{ */
04814 {
04815        TSRMLS_FETCH();
04816 
04817        /*     write to the gets stream if it is set,
04818               otherwise forward to c-clients gets */
04819        if (IMAPG(gets_stream)) {
04820               char buf[GETS_FETCH_SIZE];
04821 
04822               while (size) {
04823                      unsigned long read;
04824 
04825                      if (size > GETS_FETCH_SIZE) {
04826                             read = GETS_FETCH_SIZE;
04827                             size -=GETS_FETCH_SIZE;
04828                      } else {
04829                             read = size;
04830                             size = 0;
04831                      }
04832 
04833                      if (!f(stream, read, buf)) {
04834                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to read from socket");
04835                             break;
04836                      } else if (read != php_stream_write(IMAPG(gets_stream), buf, read)) {
04837                             php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to write to stream");
04838                             break;
04839                      }
04840               }
04841               return NULL;
04842        } else {
04843               char *buf = pemalloc(size + 1, 1);
04844 
04845               if (f(stream, size, buf)) {
04846                      buf[size] = '\0';
04847               } else {
04848                      php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to read from socket");
04849                      free(buf);
04850                      buf = NULL;
04851               }
04852               return buf;
04853        }
04854 }
04855 /* }}} */
04856 
04857 /* {{{ Interfaces to C-client
04858  */
04859 PHP_IMAP_EXPORT void mm_searched(MAILSTREAM *stream, unsigned long number)
04860 {
04861        MESSAGELIST *cur = NIL;
04862        TSRMLS_FETCH();
04863 
04864        if (IMAPG(imap_messages) == NIL) {
04865               IMAPG(imap_messages) = mail_newmessagelist();
04866               IMAPG(imap_messages)->msgid = number;
04867               IMAPG(imap_messages)->next = NIL;
04868               IMAPG(imap_messages_tail) = IMAPG(imap_messages);
04869        } else {
04870               cur = IMAPG(imap_messages_tail);
04871               cur->next = mail_newmessagelist();
04872               cur = cur->next;
04873               cur->msgid = number;
04874               cur->next = NIL;
04875               IMAPG(imap_messages_tail) = cur;
04876        }
04877 }
04878 
04879 PHP_IMAP_EXPORT void mm_exists(MAILSTREAM *stream, unsigned long number)
04880 {
04881 }
04882 
04883 PHP_IMAP_EXPORT void mm_expunged(MAILSTREAM *stream, unsigned long number)
04884 {
04885 }
04886 
04887 PHP_IMAP_EXPORT void mm_flags(MAILSTREAM *stream, unsigned long number)
04888 {
04889 }
04890 
04891 /* Author: CJH */
04892 PHP_IMAP_EXPORT void mm_notify(MAILSTREAM *stream, char *str, long errflg)
04893 {
04894        STRINGLIST *cur = NIL;
04895        TSRMLS_FETCH();
04896 
04897        if (strncmp(str, "[ALERT] ", 8) == 0) {
04898               if (IMAPG(imap_alertstack) == NIL) {
04899                      IMAPG(imap_alertstack) = mail_newstringlist();
04900                      IMAPG(imap_alertstack)->LSIZE = strlen(IMAPG(imap_alertstack)->LTEXT = cpystr(str));
04901                      IMAPG(imap_alertstack)->next = NIL;
04902               } else {
04903                      cur = IMAPG(imap_alertstack);
04904                      while (cur->next != NIL) {
04905                             cur = cur->next;
04906                      }
04907                      cur->next = mail_newstringlist ();
04908                      cur = cur->next;
04909                      cur->LSIZE = strlen(cur->LTEXT = cpystr(str));
04910                      cur->next = NIL;
04911               }
04912        }
04913 }
04914 
04915 PHP_IMAP_EXPORT void mm_list(MAILSTREAM *stream, DTYPE delimiter, char *mailbox, long attributes)
04916 {
04917        STRINGLIST *cur=NIL;
04918        FOBJECTLIST *ocur=NIL;
04919        TSRMLS_FETCH();
04920 
04921        if (IMAPG(folderlist_style) == FLIST_OBJECT) {
04922               /* build up a the new array of objects */
04923               /* Author: CJH */
04924               if (IMAPG(imap_folder_objects) == NIL) {
04925                      IMAPG(imap_folder_objects) = mail_newfolderobjectlist();
04926                      IMAPG(imap_folder_objects)->LSIZE=strlen(IMAPG(imap_folder_objects)->LTEXT=cpystr(mailbox));
04927                      IMAPG(imap_folder_objects)->delimiter = delimiter;
04928                      IMAPG(imap_folder_objects)->attributes = attributes;
04929                      IMAPG(imap_folder_objects)->next = NIL;
04930                      IMAPG(imap_folder_objects_tail) = IMAPG(imap_folder_objects);
04931               } else {
04932                      ocur=IMAPG(imap_folder_objects_tail);
04933                      ocur->next=mail_newfolderobjectlist();
04934                      ocur=ocur->next;
04935                      ocur->LSIZE = strlen(ocur->LTEXT = cpystr(mailbox));
04936                      ocur->delimiter = delimiter;
04937                      ocur->attributes = attributes;
04938                      ocur->next = NIL;
04939                      IMAPG(imap_folder_objects_tail) = ocur;
04940               }
04941 
04942        } else {
04943               /* build the old IMAPG(imap_folders) variable to allow old imap_listmailbox() to work */
04944               if (!(attributes & LATT_NOSELECT)) {
04945                      if (IMAPG(imap_folders) == NIL) {
04946                             IMAPG(imap_folders)=mail_newstringlist();
04947                             IMAPG(imap_folders)->LSIZE=strlen(IMAPG(imap_folders)->LTEXT=cpystr(mailbox));
04948                             IMAPG(imap_folders)->next=NIL;
04949                             IMAPG(imap_folders_tail) = IMAPG(imap_folders);
04950                      } else {
04951                             cur=IMAPG(imap_folders_tail);
04952                             cur->next=mail_newstringlist ();
04953                             cur=cur->next;
04954                             cur->LSIZE = strlen (cur->LTEXT = cpystr (mailbox));
04955                             cur->next = NIL;
04956                             IMAPG(imap_folders_tail) = cur;
04957                      }
04958               }
04959        }
04960 }
04961 
04962 PHP_IMAP_EXPORT void mm_lsub(MAILSTREAM *stream, DTYPE delimiter, char *mailbox, long attributes)
04963 {
04964        STRINGLIST *cur=NIL;
04965        FOBJECTLIST *ocur=NIL;
04966        TSRMLS_FETCH();
04967 
04968        if (IMAPG(folderlist_style) == FLIST_OBJECT) {
04969               /* build the array of objects */
04970               /* Author: CJH */
04971               if (IMAPG(imap_sfolder_objects) == NIL) {
04972                      IMAPG(imap_sfolder_objects) = mail_newfolderobjectlist();
04973                      IMAPG(imap_sfolder_objects)->LSIZE=strlen(IMAPG(imap_sfolder_objects)->LTEXT=cpystr(mailbox));
04974                      IMAPG(imap_sfolder_objects)->delimiter = delimiter;
04975                      IMAPG(imap_sfolder_objects)->attributes = attributes;
04976                      IMAPG(imap_sfolder_objects)->next = NIL;
04977                      IMAPG(imap_sfolder_objects_tail) = IMAPG(imap_sfolder_objects);
04978               } else {
04979                      ocur=IMAPG(imap_sfolder_objects_tail);
04980                      ocur->next=mail_newfolderobjectlist();
04981                      ocur=ocur->next;
04982                      ocur->LSIZE=strlen(ocur->LTEXT = cpystr(mailbox));
04983                      ocur->delimiter = delimiter;
04984                      ocur->attributes = attributes;
04985                      ocur->next = NIL;
04986                      IMAPG(imap_sfolder_objects_tail) = ocur;
04987               }
04988        } else {
04989               /* build the old simple array for imap_listsubscribed() */
04990               if (IMAPG(imap_sfolders) == NIL) {
04991                      IMAPG(imap_sfolders)=mail_newstringlist();
04992                      IMAPG(imap_sfolders)->LSIZE=strlen(IMAPG(imap_sfolders)->LTEXT=cpystr(mailbox));
04993                      IMAPG(imap_sfolders)->next=NIL;
04994                      IMAPG(imap_sfolders_tail) = IMAPG(imap_sfolders);
04995               } else {
04996                      cur=IMAPG(imap_sfolders_tail);
04997                      cur->next=mail_newstringlist ();
04998                      cur=cur->next;
04999                      cur->LSIZE = strlen (cur->LTEXT = cpystr (mailbox));
05000                      cur->next = NIL;
05001                      IMAPG(imap_sfolders_tail) = cur;
05002               }
05003        }
05004 }
05005 
05006 PHP_IMAP_EXPORT void mm_status(MAILSTREAM *stream, char *mailbox, MAILSTATUS *status)
05007 {
05008        TSRMLS_FETCH();
05009 
05010        IMAPG(status_flags)=status->flags;
05011        if (IMAPG(status_flags) & SA_MESSAGES) {
05012               IMAPG(status_messages)=status->messages;
05013        }
05014        if (IMAPG(status_flags) & SA_RECENT) {
05015               IMAPG(status_recent)=status->recent;
05016        }
05017        if (IMAPG(status_flags) & SA_UNSEEN) {
05018               IMAPG(status_unseen)=status->unseen;
05019        }
05020        if (IMAPG(status_flags) & SA_UIDNEXT) {
05021               IMAPG(status_uidnext)=status->uidnext;
05022        }
05023        if (IMAPG(status_flags) & SA_UIDVALIDITY) {
05024               IMAPG(status_uidvalidity)=status->uidvalidity;
05025        }
05026 }
05027 
05028 PHP_IMAP_EXPORT void mm_log(char *str, long errflg)
05029 {
05030        ERRORLIST *cur = NIL;
05031        TSRMLS_FETCH();
05032 
05033        /* Author: CJH */
05034        if (errflg != NIL) { /* CJH: maybe put these into a more comprehensive log for debugging purposes? */
05035               if (IMAPG(imap_errorstack) == NIL) {
05036                      IMAPG(imap_errorstack) = mail_newerrorlist();
05037                      IMAPG(imap_errorstack)->LSIZE = strlen(IMAPG(imap_errorstack)->LTEXT = cpystr(str));
05038                      IMAPG(imap_errorstack)->errflg = errflg;
05039                      IMAPG(imap_errorstack)->next = NIL;
05040               } else {
05041                      cur = IMAPG(imap_errorstack);
05042                      while (cur->next != NIL) {
05043                             cur = cur->next;
05044                      }
05045                      cur->next = mail_newerrorlist();
05046                      cur = cur->next;
05047                      cur->LSIZE = strlen(cur->LTEXT = cpystr(str));
05048                      cur->errflg = errflg;
05049                      cur->next = NIL;
05050               }
05051        }
05052 }
05053 
05054 PHP_IMAP_EXPORT void mm_dlog(char *str)
05055 {
05056        /* CJH: this is for debugging; it might be useful to allow setting
05057           the stream to debug mode and capturing this somewhere - syslog?
05058           php debugger? */
05059 }
05060 
05061 PHP_IMAP_EXPORT void mm_login(NETMBX *mb, char *user, char *pwd, long trial)
05062 {
05063        TSRMLS_FETCH();
05064 
05065        if (*mb->user) {
05066               strlcpy (user, mb->user, MAILTMPLEN);
05067        } else {
05068               strlcpy (user, IMAPG(imap_user), MAILTMPLEN);
05069        }
05070        strlcpy (pwd, IMAPG(imap_password), MAILTMPLEN);
05071 }
05072 
05073 PHP_IMAP_EXPORT void mm_critical(MAILSTREAM *stream)
05074 {
05075 }
05076 
05077 PHP_IMAP_EXPORT void mm_nocritical(MAILSTREAM *stream)
05078 {
05079 }
05080 
05081 PHP_IMAP_EXPORT long mm_diskerror(MAILSTREAM *stream, long errcode, long serious)
05082 {
05083        return 1;
05084 }
05085 
05086 PHP_IMAP_EXPORT void mm_fatal(char *str)
05087 {
05088 }
05089 /* }}} */
05090 
05091 /*
05092  * Local variables:
05093  * tab-width: 4
05094  * c-basic-offset: 4
05095  * End:
05096  * vim600: sw=4 ts=4 fdm=marker
05097  * vim<600: sw=4 ts=4
05098  */