PageRenderTime 79ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/ext/imap/php_imap.c

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