summaryrefslogtreecommitdiff
path: root/ext/mailparse/mailparse.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/mailparse/mailparse.c')
-rwxr-xr-xext/mailparse/mailparse.c799
1 files changed, 799 insertions, 0 deletions
diff --git a/ext/mailparse/mailparse.c b/ext/mailparse/mailparse.c
new file mode 100755
index 0000000000..f8d2514e38
--- /dev/null
+++ b/ext/mailparse/mailparse.c
@@ -0,0 +1,799 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP version 4.0 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 2.02 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available at through the world-wide-web at |
+ | http://www.php.net/license/2_02.txt. |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: |
+ | Wez Furlong (wez@thebrainroom.com) |
+ | Credit also given to Double Precision Inc. who wrote the code that |
+ | the support routines for this extension were based upon. |
+ +----------------------------------------------------------------------+
+ */
+/* $Id$ */
+
+#include "php.h"
+#include "php_ini.h"
+#include "ext/standard/file.h"
+#include "php_mailparse.h"
+#include "mailparse_rfc822.h"
+#include "ext/standard/info.h"
+#include "ext/standard/php_output.h"
+
+/* just in case the config check doesn't enable mbstring automatically */
+#if !HAVE_MBSTRING
+#error The mailparse extension requires the mbstring extension!
+#endif
+
+#include "ext/mbstring/mbfilter.h"
+
+static int le_rfc2045;
+/* this is for sections we "found": we mustn't free them, as this will cause
+ * a SEGFAULT when the parent is freed */
+static int le_rfc2045_nofree;
+
+
+function_entry mailparse_functions[] = {
+ PHP_FE(mailparse_msg_parse_file, NULL)
+ PHP_FE(mailparse_msg_get_part, NULL)
+ PHP_FE(mailparse_msg_get_structure, NULL)
+ PHP_FE(mailparse_msg_get_part_data, NULL)
+ PHP_FE(mailparse_msg_extract_part, NULL)
+ PHP_FE(mailparse_msg_extract_part_file, NULL)
+
+ PHP_FE(mailparse_msg_create, NULL)
+ PHP_FE(mailparse_msg_free, NULL)
+ PHP_FE(mailparse_msg_parse, NULL)
+ PHP_FE(mailparse_rfc822_parse_addresses, NULL)
+ PHP_FE(mailparse_determine_best_xfer_encoding, NULL)
+ PHP_FE(mailparse_stream_encode, NULL)
+
+ {NULL, NULL, NULL}
+};
+
+zend_module_entry mailparse_module_entry = {
+ "mailparse",
+ mailparse_functions,
+ PHP_MINIT(mailparse),
+ PHP_MSHUTDOWN(mailparse),
+ PHP_RINIT(mailparse),
+ PHP_RSHUTDOWN(mailparse),
+ PHP_MINFO(mailparse),
+ STANDARD_MODULE_PROPERTIES
+};
+
+ZEND_DECLARE_MODULE_GLOBALS(mailparse)
+
+#ifdef COMPILE_DL_MAILPARSE
+ZEND_GET_MODULE(mailparse)
+#endif
+
+
+ZEND_RSRC_DTOR_FUNC(rfc2045_dtor)
+{
+ rfc2045_free(rsrc->ptr);
+}
+
+PHP_INI_BEGIN()
+ STD_PHP_INI_ENTRY("mailparse.def_charset", RFC2045CHARSET, PHP_INI_ALL, OnUpdateString, def_charset, zend_mailparse_globals, mailparse_globals)
+PHP_INI_END()
+
+#define mailparse_msg_name "mailparse_mail_structure"
+
+#define mailparse_fetch_rfc2045_resource(rfcvar, zvalarg) ZEND_FETCH_RESOURCE2(rfcvar, struct rfc2045 *, zvalarg, -1, mailparse_msg_name, le_rfc2045, le_rfc2045_nofree)
+
+PHP_MINIT_FUNCTION(mailparse)
+{
+ le_rfc2045 = zend_register_list_destructors_ex(rfc2045_dtor, NULL, mailparse_msg_name, module_number);
+ le_rfc2045_nofree = zend_register_list_destructors_ex(NULL, NULL, mailparse_msg_name, module_number);
+
+ REGISTER_INI_ENTRIES();
+
+ return SUCCESS;
+}
+
+PHP_MSHUTDOWN_FUNCTION(mailparse)
+{
+ UNREGISTER_INI_ENTRIES();
+ return SUCCESS;
+}
+
+PHP_MINFO_FUNCTION(mailparse)
+{
+ php_info_print_table_start();
+ php_info_print_table_header(2, "mailparse support", "enabled");
+ php_info_print_table_end();
+
+ DISPLAY_INI_ENTRIES();
+}
+
+
+PHP_RINIT_FUNCTION(mailparse)
+{
+ return SUCCESS;
+}
+
+
+PHP_RSHUTDOWN_FUNCTION(mailparse)
+{
+ return SUCCESS;
+}
+
+static void mailparse_rfc822t_errfunc(const char * msg, int num)
+{
+ php_error(E_WARNING, "%s(): %s %d", get_active_function_name(), msg, num);
+}
+
+/* {{{ proto array mailparse_rfc822_parse_addresses(string addresses)
+ parse addresses and return a hash containing that data
+*/
+PHP_FUNCTION(mailparse_rfc822_parse_addresses)
+{
+ zval ** addresses;
+ struct rfc822t * tokens;
+ struct rfc822a * addrs;
+ int i;
+
+ if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &addresses) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_string_ex(addresses);
+
+ tokens = mailparse_rfc822t_alloc(Z_STRVAL_PP(addresses), mailparse_rfc822t_errfunc);
+
+ if (tokens) {
+ addrs = mailparse_rfc822a_alloc(tokens);
+ if (addrs) {
+
+ array_init(return_value);
+
+ for (i = 0; i < addrs->naddrs; i++) {
+ char * p;
+ zval * item;
+
+ MAKE_STD_ZVAL(item);
+
+ if (array_init(item) == FAILURE)
+ break;
+
+ p = mailparse_rfc822_getname(addrs, i);
+ add_assoc_string(item, "display", p, 0); /* don't duplicate - getname allocated the memory for us */
+ p = mailparse_rfc822_getaddr(addrs, i);
+ add_assoc_string(item, "address", p, 0); /* don't duplicate - getaddr allocated the memory for us */
+
+ /* add this to the result */
+ zend_hash_next_index_insert(HASH_OF(return_value), &item, sizeof(item), NULL);
+ }
+
+ mailparse_rfc822a_free(addrs);
+ }
+
+ mailparse_rfc822t_free(tokens);
+ }
+}
+/* }}} */
+
+/* {{{ proto long mailparse_determine_best_xfer_encoding(resource fp)
+ figure out the best way of encoding the content read from the file pointer fp, which must be seek-able.
+*/
+PHP_FUNCTION(mailparse_determine_best_xfer_encoding)
+{
+ zval ** file;
+ FILE * fp;
+ int longline = 0;
+ int linelen = 0;
+ int c;
+ enum mbfl_no_encoding bestenc = mbfl_no_encoding_7bit;
+ void * what;
+ int type;
+ char * name;
+
+ if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &file) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ what = zend_fetch_resource(file, -1, "File-Handle", &type, 2, php_file_le_fopen(), php_file_le_stream());
+ ZEND_VERIFY_RESOURCE(what);
+
+#if HAVE_PHP_STREAM
+ if (type == php_file_le_stream()) {
+ php_stream * stream = (php_stream*)what;
+
+ php_stream_rewind(stream);
+ while(!php_stream_eof(stream)) {
+ c = php_stream_getc(stream);
+ if (c == EOF)
+ break;
+ if (c > 0x80)
+ bestenc = mbfl_no_encoding_8bit;
+ else if (c == 0) {
+ bestenc = mbfl_no_encoding_base64;
+ longline = 0;
+ break;
+ }
+ if (c == '\n')
+ linelen = 0;
+ else if (++linelen > 200)
+ longline = 1;
+ }
+ if (longline)
+ bestenc = mbfl_no_encoding_qprint;
+ php_stream_rewind(stream);
+ }
+ else {
+#endif
+ fp = (FILE*)what;
+
+ rewind(fp);
+ while(!feof(fp)) {
+ c = fgetc(fp);
+ if (c == EOF)
+ break;
+ if (c > 0x80)
+ bestenc = mbfl_no_encoding_8bit;
+ else if (c == 0) {
+ bestenc = mbfl_no_encoding_base64;
+ longline = 0;
+ break;
+ }
+ if (c == '\n')
+ linelen = 0;
+ else if (++linelen > 200)
+ longline = 1;
+ }
+ if (longline)
+ bestenc = mbfl_no_encoding_qprint;
+ rewind(fp);
+#if HAVE_PHP_STREAM
+ }
+#endif
+
+ name = (char *)mbfl_no2preferred_mime_name(bestenc);
+ if (name)
+ {
+ RETVAL_STRING(name, 1);
+ }
+ else
+ {
+ RETVAL_FALSE;
+ }
+}
+/* }}} */
+
+/* {{{ proto boolean mailparse_stream_encode(resource sourcefp, resource destfp, string encoding)
+ stream data from source file pointer, apply encoding and write to destfp
+*/
+
+static int mailparse_fp_output(int c, void * fp)
+{
+ return fputc(c, (FILE*)fp);
+}
+static int mailparse_fp_flush(void * fp)
+{
+ return fflush((FILE*)fp);
+}
+
+PHP_FUNCTION(mailparse_stream_encode)
+{
+ zval ** srcfile, ** destfile, ** encod;
+ FILE * srcfp, * destfp;
+ char * buf;
+ size_t len;
+ size_t bufsize = 2048;
+ enum mbfl_no_encoding enc;
+ mbfl_convert_filter * conv = NULL;
+
+ if (ZEND_NUM_ARGS() != 3 || zend_get_parameters_ex(3, &srcfile, &destfile, &encod) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ if ((*srcfile)->type == IS_RESOURCE && (*srcfile)->value.lval == 0) {
+ RETURN_FALSE;
+ }
+ ZEND_FETCH_RESOURCE(srcfp, FILE *, srcfile, -1, "File-Handle", php_file_le_fopen());
+
+ if ((*destfile)->type == IS_RESOURCE && (*destfile)->value.lval == 0) {
+ RETURN_FALSE;
+ }
+ ZEND_FETCH_RESOURCE(destfp, FILE *, destfile, -1, "File-Handle", php_file_le_fopen());
+
+ convert_to_string_ex(encod);
+ enc = mbfl_name2no_encoding(Z_STRVAL_PP(encod));
+ if (enc == mbfl_no_encoding_invalid) {
+ zend_error(E_WARNING, "%s(): unknown encoding \"%s\"",
+ get_active_function_name(),
+ Z_STRVAL_PP(encod)
+ );
+ RETURN_FALSE;
+ }
+
+ convert_to_long_ex(encod);
+ enc = Z_LVAL_PP(encod);
+
+ buf = emalloc(bufsize);
+ RETVAL_TRUE;
+
+ conv = mbfl_convert_filter_new(mbfl_no_encoding_8bit,
+ enc,
+ mailparse_fp_output,
+ mailparse_fp_flush,
+ destfp
+ );
+ while(!feof(srcfp)) {
+ len = fread(buf, sizeof(char), bufsize, srcfp);
+ if (len > 0)
+ {
+ int i;
+ for (i=0; i<len; i++)
+ mbfl_convert_filter_feed(buf[i], conv);
+ }
+ }
+
+ mbfl_convert_filter_flush(conv);
+ mbfl_convert_filter_delete(conv);
+ efree(buf);
+}
+/* }}} */
+
+/* {{{ proto void mailparse_msg_parse(resource rfc2045buf, string data)
+ Incrementally parse data into buffer
+*/
+PHP_FUNCTION(mailparse_msg_parse)
+{
+ zval ** arg, ** data;
+ struct rfc2045 * rfcbuf;
+
+ if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &arg, &data) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ if ((*arg)->type == IS_RESOURCE && (*arg)->value.lval == 0) {
+ RETURN_FALSE;
+ }
+
+ mailparse_fetch_rfc2045_resource(rfcbuf, arg);
+
+ convert_to_string_ex(data);
+
+ rfc2045_parse(rfcbuf, (*data)->value.str.val, (*data)->value.str.len);
+}
+/* }}} */
+
+/* {{{ proto resource mailparse_msg_parse_file(string filename)
+ Parse file and return a resource representing the structure
+*/
+PHP_FUNCTION(mailparse_msg_parse_file)
+{
+ zval ** filename;
+ struct rfc2045 * rfcbuf;
+ char * filebuf;
+ FILE * fp;
+
+ if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &filename) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ convert_to_string_ex(filename);
+
+ /* open file and read it in */
+ fp = VCWD_FOPEN(Z_STRVAL_PP(filename), "r");
+ if (fp == NULL) {
+ zend_error(E_WARNING, "%s(): unable to open file %s", get_active_function_name(), Z_STRVAL_PP(filename));
+ RETURN_FALSE;
+ }
+
+ filebuf = emalloc(MAILPARSE_BUFSIZ);
+
+ rfcbuf = rfc2045_alloc_ac();
+ if (rfcbuf) {
+ ZEND_REGISTER_RESOURCE(return_value, rfcbuf, le_rfc2045);
+
+ while(!feof(fp)) {
+ int got = fread(filebuf, sizeof(char), MAILPARSE_BUFSIZ, fp);
+ if (got > 0) {
+ rfc2045_parse(rfcbuf, filebuf, got);
+ }
+ }
+ fclose(fp);
+ }
+ efree(filebuf);
+}
+/* }}} */
+
+/* {{{ proto void mailparse_msg_free(resource rfc2045buf)
+ Frees a handle allocated by mailparse_msg_create
+*/
+PHP_FUNCTION(mailparse_msg_free)
+{
+ zval **arg;
+ struct rfc2045 * rfcbuf;
+
+ if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ if ((*arg)->type == IS_RESOURCE && (*arg)->value.lval == 0) {
+ RETURN_FALSE;
+ }
+
+ ZEND_FETCH_RESOURCE(rfcbuf, struct rfc2045 *, arg, -1, mailparse_msg_name, le_rfc2045);
+
+ zend_list_delete((*arg)->value.lval);
+ RETURN_TRUE;
+}
+/* }}} */
+
+
+/* {{{ proto long mailparse_msg_create()
+ Return a handle that can be used to parse a message
+*/
+PHP_FUNCTION(mailparse_msg_create)
+{
+ struct rfc2045 * rfcbuf;
+
+ rfcbuf = rfc2045_alloc_ac();
+
+ ZEND_REGISTER_RESOURCE(return_value, rfcbuf, le_rfc2045);
+}
+/* }}} */
+
+static void get_structure_callback(struct rfc2045 *p, struct rfc2045id * id, void * ptr)
+{
+ zval * return_value = (zval *)ptr;
+ char intbuf[16];
+ char buf[256];
+ int len, i = 0;
+ while(id && i < sizeof(buf)) {
+ sprintf(intbuf, "%d", id->idnum);
+ len = strlen(intbuf);
+ if (len > (sizeof(buf)-i)) {
+ /* too many sections: bail */
+ zend_error(E_WARNING, "%s(): too many nested sections in message", get_active_function_name());
+ return;
+ }
+ sprintf(&buf[i], "%s%c", intbuf, id->next ? '.' : '\0');
+ i += len + (id->next ? 1 : 0);
+ id = id->next;
+ }
+ add_next_index_string(return_value, buf,1);
+}
+
+/* {{{ proto array mailparse_msg_get_structure(resource rfc2045)
+ Returns an array of mime section names in the supplied message
+*/
+PHP_FUNCTION(mailparse_msg_get_structure)
+{
+ zval **arg;
+ struct rfc2045 * rfcbuf;
+
+ if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ if ((*arg)->type == IS_RESOURCE && (*arg)->value.lval == 0) {
+ RETURN_FALSE;
+ }
+
+ mailparse_fetch_rfc2045_resource(rfcbuf, arg);
+
+ if (array_init(return_value) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+ rfc2045_decode(rfcbuf, &get_structure_callback, return_value);
+}
+/* }}} */
+
+/* callback for decoding using a "userdefined" php function */
+static int extract_callback_user_func(const char *p, size_t n, zval *userfunc)
+{
+ zval * retval;
+ zval * arg;
+ ELS_FETCH();
+
+ MAKE_STD_ZVAL(retval);
+ retval->type = IS_BOOL;
+ retval->value.lval = 0;
+
+ MAKE_STD_ZVAL(arg);
+ ZVAL_STRINGL(arg, (char*)p, (int)n, 1);
+
+ /* TODO: use zend_is_callable */
+
+ if (call_user_function(EG(function_table), NULL, userfunc, retval, 1, &arg) == FAILURE)
+ zend_error(E_WARNING, "%s(): unable to call user function", get_active_function_name());
+
+ zval_dtor(retval);
+ zval_dtor(arg);
+ efree(retval);
+ efree(arg);
+
+ return 0;
+}
+
+/* callback for decoding to the current output buffer */
+static int extract_callback_stdout(const char *p, size_t n, void *ptr)
+{
+ ZEND_WRITE(p, n);
+ return 0;
+}
+
+/* {{{ proto void mailparse_msg_extract_part(resource rfc2045, string msgbody[, string callbackfunc])
+ Extracts/decodes a message section. If callbackfunc is not specified, the contents will be sent to "stdout".
+*/
+PHP_FUNCTION(mailparse_msg_extract_part)
+{
+ zval **arg, **bodystr, **cbfunc;
+ struct rfc2045 * rfcbuf;
+ off_t start, end, body;
+ off_t nlines;
+ off_t nbodylines;
+
+ switch(ZEND_NUM_ARGS()) {
+ case 3:
+ if (zend_get_parameters_ex(3, &arg, &bodystr, &cbfunc) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ if (Z_TYPE_PP(cbfunc) != IS_ARRAY)
+ convert_to_string_ex(cbfunc);
+ break;
+ case 2:
+ if (zend_get_parameters_ex(2, &arg, &bodystr) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ cbfunc = NULL;
+ break;
+ }
+ convert_to_string_ex(bodystr);
+
+ if ((*arg)->type == IS_RESOURCE && (*arg)->value.lval == 0) {
+ RETURN_FALSE;
+ }
+ mailparse_fetch_rfc2045_resource(rfcbuf, arg);
+
+
+ rfc2045_mimepos(rfcbuf, &start, &end, &body, &nlines, &nbodylines);
+
+ if (cbfunc)
+ rfc2045_cdecode_start(rfcbuf, (rfc2045_decode_user_func_t)&extract_callback_user_func, *cbfunc);
+ else
+ rfc2045_cdecode_start(rfcbuf, &extract_callback_stdout, NULL);
+
+ if (Z_STRLEN_PP(bodystr) < end)
+ end = Z_STRLEN_PP(bodystr);
+ else
+ end = end-body;
+
+ rfc2045_cdecode(rfcbuf, Z_STRVAL_PP(bodystr) + body, end);
+ rfc2045_cdecode_end(rfcbuf);
+
+ RETURN_TRUE;
+
+}
+/* }}} */
+
+/* {{{ proto string mailparse_msg_extract_part_file(resource rfc2045, string filename[, string callbackfunc])
+ Extracts/decodes a message section, decoding the transfer encoding
+*/
+PHP_FUNCTION(mailparse_msg_extract_part_file)
+{
+ zval **arg, **filename, **cbfunc;
+ struct rfc2045 * rfcbuf;
+ char * filebuf = NULL;
+ FILE * fp = NULL;
+ off_t start, end, body;
+ off_t nlines;
+ off_t nbodylines;
+
+ switch(ZEND_NUM_ARGS()) {
+ case 3:
+ if (zend_get_parameters_ex(3, &arg, &filename, &cbfunc) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ if (Z_TYPE_PP(cbfunc) != IS_ARRAY)
+ convert_to_string_ex(cbfunc);
+ break;
+ case 2:
+ if (zend_get_parameters_ex(2, &arg, &filename) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ cbfunc = NULL;
+ break;
+ }
+ convert_to_string_ex(filename);
+
+ if ((*arg)->type == IS_RESOURCE && (*arg)->value.lval == 0) {
+ RETURN_FALSE;
+ }
+ mailparse_fetch_rfc2045_resource(rfcbuf, arg);
+
+ /* figure out where the message part starts/ends */
+ rfc2045_mimepos(rfcbuf, &start, &end, &body, &nlines, &nbodylines);
+
+ if (cbfunc)
+ rfc2045_cdecode_start(rfcbuf, (rfc2045_decode_user_func_t)&extract_callback_user_func, *cbfunc);
+ else
+ rfc2045_cdecode_start(rfcbuf, &extract_callback_stdout, NULL);
+
+ /* open file and read it in */
+ fp = VCWD_FOPEN(Z_STRVAL_PP(filename), "rb");
+ if (fp == NULL) {
+ zend_error(E_WARNING, "%s(): unable to open file %s", get_active_function_name(), Z_STRVAL_PP(filename));
+ RETURN_FALSE;
+ }
+ if (fseek(fp, body, SEEK_SET) == -1)
+ {
+ zend_error(E_WARNING, "%s(): unable to seek to section start", get_active_function_name());
+ RETVAL_FALSE;
+ goto cleanup;
+ }
+ filebuf = emalloc(MAILPARSE_BUFSIZ);
+
+
+ while (body < end)
+ {
+ size_t n = MAILPARSE_BUFSIZ;
+
+ if ((off_t)n > end-body)
+ n=end-body;
+ n = fread(filebuf, sizeof(char), n, fp);
+ if (n == 0)
+ {
+ zend_error(E_WARNING, "%s(): error reading from file \"%s\", offset %d", get_active_function_name(), Z_STRVAL_PP(filename), body);
+ RETVAL_FALSE;
+ goto cleanup;
+ }
+ rfc2045_cdecode(rfcbuf, filebuf, n);
+ body += n;
+ }
+ RETVAL_TRUE;
+
+cleanup:
+ rfc2045_cdecode_end(rfcbuf);
+ if (fp)
+ fclose(fp);
+ if (filebuf)
+ efree(filebuf);
+}
+/* }}} */
+
+/* {{{ proto array mailparse_msg_get_part_data(resource rfc2045)
+ Return an assoc. array of info about the message
+*/
+/* NOTE: you may add keys to the array, but PLEASE do not remove the key/value pairs
+ that are emitted here - it will break my PHP scripts if you do! */
+PHP_FUNCTION(mailparse_msg_get_part_data)
+{
+ zval ** arg;
+ struct rfc2045 * rfcbuf;
+ char * content_type, *transfer_encoding, *charset;
+ off_t start, end, body, nlines, nbodylines;
+ char * disposition, * disposition_name, *disposition_filename;
+ char *p;
+ struct rfc2045attr * attr;
+ zval * headers;
+
+ if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &arg) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ if ((*arg)->type == IS_RESOURCE && (*arg)->value.lval == 0) {
+ RETURN_FALSE;
+ }
+
+
+ mailparse_fetch_rfc2045_resource(rfcbuf, arg);
+
+ if (array_init(return_value) == FAILURE) {
+ RETURN_FALSE;
+ }
+
+
+ rfc2045_mimeinfo(rfcbuf, (const char**)&content_type, (const char**)&transfer_encoding, (const char**)&charset);
+ rfc2045_mimepos(rfcbuf, &start, &end, &body, &nlines, &nbodylines);
+
+ if (content_type && *content_type)
+ add_assoc_string(return_value, "content-type", content_type, 1);
+
+ /* get attributes for content-type */
+ attr = rfcbuf->content_type_attr;
+ while (attr != NULL) {
+ char buf[80];
+ strcpy(buf, "content-");
+ strcat(buf, attr->name);
+ add_assoc_string(return_value, buf, attr->value, 1);
+ attr = attr->next;
+ }
+ /* get attributes for content-disposition */
+ attr = rfcbuf->content_disposition_attr;
+ while (attr != NULL) {
+ char buf[80];
+ strcpy(buf, "disposition-");
+ strcat(buf, attr->name);
+ add_assoc_string(return_value, buf, attr->value, 1);
+ attr = attr->next;
+ }
+ /* get headers for this section */
+ MAKE_STD_ZVAL(headers);
+ *headers = *rfcbuf->headerhash;
+ INIT_PZVAL(headers);
+ zval_copy_ctor(headers);
+ /* add to result */
+ zend_hash_update(HASH_OF(return_value), "headers", sizeof("headers"), &headers, sizeof(headers), NULL);
+
+ add_assoc_string(return_value, "transfer-encoding", transfer_encoding, 1);
+ add_assoc_string(return_value, "charset", charset, 1);
+
+ rfc2045_dispositioninfo(rfcbuf, (const char**)&disposition, (const char**)&disposition_name, (const char**)&disposition_filename);
+ if (disposition && *disposition)
+ add_assoc_string(return_value, "content-disposition", disposition, 1);
+
+ if (*(p=(char*)rfc2045_content_id(rfcbuf)))
+ add_assoc_string(return_value, "content-id", p, 1);
+ if (*(p=(char*)rfc2045_content_description(rfcbuf)))
+ add_assoc_string(return_value, "content-description", p, 1);
+ if (*(p=(char*)rfc2045_content_language(rfcbuf)))
+ add_assoc_string(return_value, "content-language", p, 1);
+ if (*(p=(char*)rfc2045_content_md5(rfcbuf)))
+ add_assoc_string(return_value, "content-md5", p, 1);
+ if (*(p=(char*)rfc2045_content_base(rfcbuf))) {
+ add_assoc_string(return_value, "content-base", p, 1);
+ /* content base allocates mem */
+ efree(p);
+ }
+
+
+ add_assoc_long(return_value, "starting-pos", start);
+ add_assoc_long(return_value, "starting-pos-body", body);
+ add_assoc_long(return_value, "ending-pos", end);
+ add_assoc_long(return_value, "line-count", nlines);
+ add_assoc_long(return_value, "body-line-count", nbodylines);
+}
+/* }}} */
+
+
+/* {{{ proto long mailparse_msg_get_part(resource rfc2045, string mimesection)
+ Return a handle on a given section in a mimemessage
+*/
+PHP_FUNCTION(mailparse_msg_get_part)
+{
+ zval ** arg, ** mimesection;
+ struct rfc2045 * rfcbuf, * newsection;
+
+ if (ZEND_NUM_ARGS() != 2 || zend_get_parameters_ex(2, &arg, &mimesection) == FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+
+ if ((*arg)->type == IS_RESOURCE && (*arg)->value.lval == 0) {
+ RETURN_FALSE;
+ }
+
+ mailparse_fetch_rfc2045_resource(rfcbuf, arg);
+
+ convert_to_string_ex(mimesection);
+
+ newsection = rfc2045_find(rfcbuf, (*mimesection)->value.str.val);
+
+ if (!newsection) {
+ php_error(E_WARNING, "%s(): cannot find section %s in message", get_active_function_name(), (*mimesection)->value.str.val);
+ RETURN_FALSE;
+ }
+ ZEND_REGISTER_RESOURCE(return_value, newsection, le_rfc2045_nofree);
+}
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim: tw=78 ts=4 sw=4
+ */