Browse Source
Imported mailparse extension
Imported mailparse extension
@- New mailparse extension for parsing and manipulating MIME mail (Wez)experimental/pre_new_hash_func
23 changed files with 4057 additions and 0 deletions
-
2ext/mailparse/CREDITS
-
5ext/mailparse/EXPERIMENTAL
-
15ext/mailparse/Makefile.in
-
79ext/mailparse/README
-
13ext/mailparse/config.m4
-
7ext/mailparse/libs.mk
-
799ext/mailparse/mailparse.c
-
161ext/mailparse/mailparse_rfc822.h
-
90ext/mailparse/php_mailparse.h
-
1168ext/mailparse/rfc2045.c
-
202ext/mailparse/rfc2045.h
-
123ext/mailparse/rfc2045acchk.c
-
99ext/mailparse/rfc2045acprep.c
-
130ext/mailparse/rfc2045appendurl.c
-
83ext/mailparse/rfc2045cdecode.c
-
40ext/mailparse/rfc2045decode.c
-
47ext/mailparse/rfc2045find.c
-
716ext/mailparse/rfc822.c
-
99ext/mailparse/rfc822_getaddr.c
-
92ext/mailparse/rfc822_getaddrs.c
-
12ext/mailparse/tests/001.phpt
-
22ext/mailparse/tests/002.phpt
-
53ext/mailparse/try.php
@ -0,0 +1,2 @@ |
|||
Mailparse MIME parsing and manipulation functions |
|||
Wez Furlong |
|||
@ -0,0 +1,5 @@ |
|||
this extension is experimental, |
|||
its functions may change their names |
|||
or move to extension all together |
|||
so do not rely to much on them |
|||
you have been warned! |
|||
@ -0,0 +1,15 @@ |
|||
# $Id$
|
|||
|
|||
LTLIBRARY_NAME = libmailparse.la |
|||
LTLIBRARY_SOURCES = \
|
|||
mailparse.c rfc2045.c \
|
|||
rfc2045acchk.c rfc2045acprep.c \
|
|||
rfc2045appendurl.c rfc2045cdecode.c rfc2045decode.c \
|
|||
rfc2045find.c \
|
|||
rfc822.c rfc822_getaddr.c \
|
|||
rfc822_getaddrs.c |
|||
|
|||
LTLIBRARY_SHARED_NAME = mailparse.la |
|||
LTLIBRARY_SHARED_LIBADD = $(MAILPARSE_SHARED_LIBADD) |
|||
|
|||
include $(top_srcdir)/build/dynlib.mk |
|||
@ -0,0 +1,79 @@ |
|||
mailparse library for PHP 4 |
|||
=========================== |
|||
|
|||
This library is build upon the librfc822 and librfc2045 libraries that |
|||
originated from the maildrop component of the courier mail server. |
|||
The copyright for most of the work belongs to Double Precision Inc., |
|||
although distribution of the library is carried out under the terms of the |
|||
GPL. |
|||
|
|||
Example for PHP: |
|||
============= |
|||
|
|||
$file = "/path/to/rfc822/compliant/message"; |
|||
|
|||
$mime = mailparse_rfc2045_parse_file($file); |
|||
$ostruct = mailparse_rfc2045_getstructure($mime); |
|||
foreach($ostruct as $st) { |
|||
$section = mailparse_rfc2045_find($mime, $st); |
|||
$struct[$st] = mailparse_rfc2045_getinfo($section); |
|||
} |
|||
var_dump($struct); |
|||
|
|||
array mailparse_rfc822_parse_addresses(string addresses) |
|||
parses an rfc822 compliant recipient list, such as that found in To: From: |
|||
headers. Returns a indexed array of assoc. arrays for each recipient: |
|||
array(0 => array("display" => "Wez Furlong", "address" => "wez@php.net")) |
|||
|
|||
resource mailparse_rfc2045_create() |
|||
Create a mime mail resource |
|||
|
|||
boolean mailparse_rfc2045_parse(resource mimemail, string data) |
|||
incrementally parse data into the supplied mime mail resource. |
|||
Concept: you can stream portions of a file at a time, rather than read |
|||
and parse the whole thing. |
|||
|
|||
|
|||
resource mailparse_rfc2045_parse_file(string $filename) |
|||
Parse a file and return a $mime resource. |
|||
The file is opened and streamed through the parser. |
|||
This is the optimal way of parsing a mail file that |
|||
you have on disk. |
|||
|
|||
|
|||
array mailparse_rfc2045_getstructure(resource mimemail) |
|||
returns an array containing a list of message parts in the form: |
|||
array("1", "1.1", "1.2") |
|||
|
|||
resource mailparse_rfc2045_find(resource mimemail, string partname) |
|||
returns an mime mail resource representing the named section |
|||
|
|||
array mailparse_rfc2045_getinfo(resource mimemail) |
|||
returns an array containing the bounds, content type and headers of the |
|||
section. |
|||
|
|||
mailparse_rfc2045_extract_file(resource mimemail, string filename[, string |
|||
callbackfunc]) |
|||
Extracts/decodes a message section from the supplied filename. |
|||
If no callback func is supplied, it outputs the results into the current |
|||
output buffer, otherwise it calls the callback with a string parameter |
|||
containing the text. |
|||
The contents of the section will be decoded according to their transfer |
|||
encoding - base64, quoted-printable and uuencoded text are supported. |
|||
|
|||
All operations are done incrementally; streaming the input and output so that |
|||
memory usage is on the whole lower than something like procmail or doing this |
|||
stuff in PHP space. The aim is that it stays this way to handle large |
|||
quantities of email. |
|||
|
|||
TODO: |
|||
===== |
|||
|
|||
. Add support for binhex encoding? |
|||
. Extracting a message part without decoding the transfer encoding so that |
|||
eg: pgp-signatures can be verified. |
|||
|
|||
. Work the other way around - build up a rfc2045 compliant message file from |
|||
simple structure information and filenames/variables. |
|||
|
|||
vim:tw=78 |
|||
@ -0,0 +1,13 @@ |
|||
dnl $Id$ |
|||
dnl config.m4 for extension mailparse |
|||
|
|||
PHP_ARG_ENABLE(mailparse, whether to enable mailparse support, |
|||
[ --enable-mailparse Enable mailparse support]) |
|||
|
|||
if test "$PHP_MAILPARSE" != "no"; then |
|||
if test "$ext_shared" != "yes" && test "$enable_mbstring" != "yes"; then |
|||
AC_MSG_WARN(Activating mbstring) |
|||
enable_mbstring=yes |
|||
fi |
|||
PHP_EXTENSION(mailparse, $ext_shared) |
|||
fi |
|||
@ -0,0 +1,7 @@ |
|||
include $(top_builddir)/config_vars.mk |
|||
LTLIBRARY_OBJECTS = $(LTLIBRARY_SOURCES:.c=.lo) $(LTLIBRARY_OBJECTS_X) |
|||
LTLIBRARY_SHARED_OBJECTS = $(LTLIBRARY_OBJECTS:.lo=.slo) |
|||
$(LTLIBRARY_NAME): $(LTLIBRARY_OBJECTS) $(LTLIBRARY_DEPENDENCIES) |
|||
$(LINK) $(LTLIBRARY_LDFLAGS) $(LTLIBRARY_OBJECTS) $(LTLIBRARY_LIBADD) |
|||
|
|||
targets = $(LTLIBRARY_NAME) |
|||
@ -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 |
|||
*/ |
|||
@ -0,0 +1,161 @@ |
|||
/* $Id$ */ |
|||
#ifndef mailparse_rfc822_h |
|||
#define mailparse_rfc822_h |
|||
|
|||
/* |
|||
** Copyright 1998 - 2000 Double Precision, Inc. |
|||
** See COPYING for distribution information. |
|||
*/ |
|||
|
|||
#include <time.h> |
|||
|
|||
#ifdef __cplusplus |
|||
extern "C" { |
|||
#endif |
|||
|
|||
/* |
|||
** The text string we want to parse is first tokenized into an array of |
|||
** struct rfc822token records. 'ptr' points into the original text |
|||
** string, and 'len' has how many characters from 'ptr' belongs to this |
|||
** token. |
|||
*/ |
|||
|
|||
struct rfc822token { |
|||
struct rfc822token *next; /* Unused by librfc822, for use by |
|||
** clients */ |
|||
int token; |
|||
/* |
|||
Values for token: |
|||
|
|||
'(' - comment |
|||
'"' - quoted string |
|||
'<', '>', '@', ',', ';', ':', '.', '[', ']', '%', '!', '=', '?', '/' - RFC atoms. |
|||
0 - atom |
|||
*/ |
|||
|
|||
#define mailparse_rfc822_is_atom(p) ( (p) == 0 || (p) == '"' || (p) == '(' ) |
|||
|
|||
const char *ptr; /* Pointer to value for the token. */ |
|||
int len; /* Length of token value */ |
|||
} ; |
|||
|
|||
/* |
|||
** After the struct rfc822token array is built, it is used to create |
|||
** the rfc822addr array, which is the array of addresses (plus |
|||
** syntactical fluff) extracted from those text strings. Each rfc822addr |
|||
** record has several possible interpretation: |
|||
** |
|||
** tokens is NULL - syntactical fluff, look in name/nname for tokens |
|||
** representing the syntactical fluff ( which is semicolons |
|||
** and list name: |
|||
** |
|||
** tokens is not NULL - actual address. The tokens representing the actual |
|||
** address is in tokens/ntokens. If there are comments in |
|||
** the address that are possible "real name" for the address |
|||
** they are saved in name/nname (name may be null if there |
|||
** is none). |
|||
** If nname is 1, and name points to a comment token, |
|||
** the address was specified in old-style format. Otherwise |
|||
** the address was specified in new-style route-addr format. |
|||
** |
|||
** The tokens and name pointers are set to point to the original rfc822token |
|||
** array. |
|||
*/ |
|||
|
|||
struct rfc822addr { |
|||
struct rfc822token *tokens; |
|||
struct rfc822token *name; |
|||
} ; |
|||
|
|||
/*************************************************************************** |
|||
** |
|||
** rfc822 tokens |
|||
** |
|||
***************************************************************************/ |
|||
|
|||
struct rfc822t { |
|||
struct rfc822token *tokens; |
|||
int ntokens; |
|||
} ; |
|||
|
|||
struct rfc822t * mailparse_rfc822t_alloc(const char *p, |
|||
void (*err_func)(const char *, int)); /* Parse addresses */ |
|||
void mailparse_rfc822t_free(struct rfc822t *); /* Free rfc822 structure */ |
|||
|
|||
void mailparse_rfc822tok_print(const struct rfc822token *, void (*)(char, void *), void *); |
|||
/* Print the tokens */ |
|||
|
|||
/*************************************************************************** |
|||
** |
|||
** rfc822 addresses |
|||
** |
|||
***************************************************************************/ |
|||
|
|||
struct rfc822a { |
|||
struct rfc822addr *addrs; |
|||
int naddrs; |
|||
} ; |
|||
|
|||
struct rfc822a * mailparse_rfc822a_alloc(struct rfc822t *); |
|||
void mailparse_rfc822a_free(struct rfc822a *); /* Free rfc822 structure */ |
|||
|
|||
void mailparse_rfc822_deladdr(struct rfc822a *, int); |
|||
|
|||
/* rfc822_print "unparses" the rfc822 structure. Each rfc822addr is "printed" |
|||
(via the attached function). NOTE: instead of separating addresses by |
|||
commas, the print_separator function is called. |
|||
*/ |
|||
|
|||
void mailparse_rfc822_print(const struct rfc822a *a, |
|||
void (*print_func)(char, void *), |
|||
void (*print_separator)(const char *, void *), void *); |
|||
|
|||
/* rfc822_print_common is an internal function */ |
|||
|
|||
void mailparse_rfc822_print_common(const struct rfc822a *a, |
|||
char *(*decode_func)(const char *, const char *), |
|||
const char *chset, |
|||
void (*print_func)(char, void *), |
|||
void (*print_separator)(const char *, void *), void *); |
|||
|
|||
/* Another unparser, except that only the raw addresses are extracted, |
|||
and each address is followed by a newline character */ |
|||
|
|||
void mailparse_rfc822_addrlist(const struct rfc822a *, void (*print_func)(char, void *), |
|||
void *); |
|||
|
|||
/* Now, just the comments. If comments not given, the address. */ |
|||
void mailparse_rfc822_namelist(const struct rfc822a *, void (*print_func)(char, void *), |
|||
void *); |
|||
|
|||
/* Unparse an individual name/addr from a list of addresses. If the given |
|||
index points to some syntactical fluff, this is a noop */ |
|||
|
|||
void mailparse_rfc822_prname(const struct rfc822a *, int, void (*)(char, void *), void *); |
|||
void mailparse_rfc822_praddr(const struct rfc822a *, int, void (*)(char, void *), void *); |
|||
|
|||
/* Like rfc822_prname, except that we'll also print the legacy format |
|||
** of a list designation. |
|||
*/ |
|||
|
|||
void mailparse_rfc822_prname_orlist(const struct rfc822a *, int, |
|||
void (*)(char, void *), void *); |
|||
|
|||
/* Extra functions */ |
|||
|
|||
char *mailparse_rfc822_gettok(const struct rfc822token *); |
|||
char *mailparse_rfc822_getaddr(const struct rfc822a *, int); |
|||
char *mailparse_rfc822_getname(const struct rfc822a *, int); |
|||
char *mailparse_rfc822_getname_orlist(const struct rfc822a *, int); |
|||
char *mailparse_rfc822_getaddrs(const struct rfc822a *); |
|||
char *mailparse_rfc822_getaddrs_wrap(const struct rfc822a *, int); |
|||
|
|||
|
|||
char *mailparse_rfc822_coresubj(const char *, int *); |
|||
char *mailparse_rfc822_coresubj_nouc(const char *, int *); |
|||
|
|||
#ifdef __cplusplus |
|||
} |
|||
#endif |
|||
|
|||
#endif |
|||
@ -0,0 +1,90 @@ |
|||
/* |
|||
+----------------------------------------------------------------------+ |
|||
| PHP version 4.0 | |
|||
+----------------------------------------------------------------------+ |
|||
| Copyright (c) 1997, 1998, 1999, 2000 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$ */ |
|||
|
|||
#ifndef PHP_MAILPARSE_H |
|||
#define PHP_MAILPARSE_H |
|||
|
|||
extern zend_module_entry mailparse_module_entry; |
|||
#define phpext_mailparse_ptr &mailparse_module_entry |
|||
|
|||
#ifdef PHP_WIN32 |
|||
#define PHP_MAILPARSE_API __declspec(dllexport) |
|||
#else |
|||
#define PHP_MAILPARSE_API |
|||
#endif |
|||
|
|||
PHP_MINIT_FUNCTION(mailparse); |
|||
PHP_MSHUTDOWN_FUNCTION(mailparse); |
|||
PHP_RINIT_FUNCTION(mailparse); |
|||
PHP_RSHUTDOWN_FUNCTION(mailparse); |
|||
PHP_MINFO_FUNCTION(mailparse); |
|||
|
|||
PHP_FUNCTION(mailparse_msg_parse_file); |
|||
PHP_FUNCTION(mailparse_msg_get_part); |
|||
PHP_FUNCTION(mailparse_msg_get_structure); |
|||
PHP_FUNCTION(mailparse_msg_get_part_data); |
|||
PHP_FUNCTION(mailparse_msg_extract_part); |
|||
PHP_FUNCTION(mailparse_msg_extract_part_file); |
|||
|
|||
PHP_FUNCTION(mailparse_msg_create); |
|||
PHP_FUNCTION(mailparse_msg_free); |
|||
PHP_FUNCTION(mailparse_msg_parse); |
|||
PHP_FUNCTION(mailparse_msg_parse_file); |
|||
|
|||
PHP_FUNCTION(mailparse_msg_find); |
|||
PHP_FUNCTION(mailparse_msg_getstructure); |
|||
PHP_FUNCTION(mailparse_msg_getinfo); |
|||
PHP_FUNCTION(mailparse_msg_extract); |
|||
PHP_FUNCTION(mailparse_msg_extract_file); |
|||
PHP_FUNCTION(mailparse_rfc822_parse_addresses); |
|||
PHP_FUNCTION(mailparse_determine_best_xfer_encoding); |
|||
PHP_FUNCTION(mailparse_stream_encode); |
|||
|
|||
#include "rfc2045.h" |
|||
#include "mailparse_rfc822.h" |
|||
|
|||
#define MAILPARSE_BUFSIZ 4096 |
|||
ZEND_BEGIN_MODULE_GLOBALS(mailparse) |
|||
char * def_charset; /* default charset for use in (re)writing mail */ |
|||
ZEND_END_MODULE_GLOBALS(mailparse); |
|||
|
|||
extern ZEND_DECLARE_MODULE_GLOBALS(mailparse); |
|||
|
|||
|
|||
#ifdef ZTS |
|||
#define MAILPARSEG(v) (mailparse_globals->v) |
|||
#define MAILPARSELS_FETCH() zend_mailparse_globals *mailparse_globals = ts_resource(mailparse_globals_id) |
|||
#else |
|||
#define MAILPARSEG(v) (mailparse_globals.v) |
|||
#define MAILPARSELS_FETCH() |
|||
#endif |
|||
|
|||
#endif |
|||
|
|||
|
|||
/* |
|||
* Local variables: |
|||
* tab-width: 4 |
|||
* c-basic-offset: 4 |
|||
* End: |
|||
* vim: sw=4 ts=4 tw=78 |
|||
*/ |
|||
1168
ext/mailparse/rfc2045.c
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,202 @@ |
|||
/* |
|||
** Copyright 1998 - 2000 Double Precision, Inc. See COPYING for |
|||
** distribution information. |
|||
*/ |
|||
|
|||
/* |
|||
** $Id$ |
|||
*/ |
|||
#ifndef rfc2045_h |
|||
#define rfc2045_h |
|||
|
|||
#include "php_mailparse.h" |
|||
#include "ext/mbstring/mbfilter.h" |
|||
|
|||
#define RFC2045CHARSET "us-ascii" |
|||
#define RFC2045MIMEMSG "This is a MIME-formatted message.\n" |
|||
|
|||
|
|||
#ifdef __cplusplus |
|||
extern "C" { |
|||
#endif |
|||
|
|||
#define RFC2045_ISMIME1(p) ((p) && atoi(p) == 1) |
|||
#define RFC2045_ISMIME1DEF(p) (!(p) || atoi(p) == 1) |
|||
|
|||
struct rfc2045; |
|||
|
|||
/* callback for de/encoding */ |
|||
typedef int (*rfc2045_decode_user_func_t)(const char *p, size_t n, void *ptr); |
|||
typedef int (*rfc2045_decode_func_t)(struct rfc2045 * part, const char * buf, size_t n); |
|||
|
|||
/* the attributes of a given header */ |
|||
struct rfc2045attr { |
|||
struct rfc2045attr *next; |
|||
char *name; |
|||
char *value; |
|||
}; |
|||
|
|||
struct rfc2045 { |
|||
struct rfc2045 *parent; |
|||
unsigned pindex; |
|||
struct rfc2045 *next; |
|||
|
|||
off_t startpos, /* At which offset in msg this section starts */ |
|||
endpos, /* Where it ends */ |
|||
startbody, /* Where the body of the msg starts */ |
|||
endbody; /* endpos - trailing CRLF terminator */ |
|||
off_t nlines; /* Number of lines in message */ |
|||
off_t nbodylines; /* Number of lines only in the body */ |
|||
char *mime_version; |
|||
char *content_type; |
|||
struct rfc2045attr *content_type_attr; /* Content-Type: attributes */ |
|||
|
|||
char *content_disposition; |
|||
char *boundary; |
|||
struct rfc2045attr *content_disposition_attr; |
|||
char *content_transfer_encoding; |
|||
/* Set if content_transfer_encoding is 8bit */ |
|||
int content_8bit; |
|||
char *content_id; |
|||
char *content_description; |
|||
char *content_language; |
|||
char *content_md5; |
|||
char *content_base; |
|||
char *content_location; |
|||
struct rfc2045ac *rfc2045acptr; |
|||
int has8bitchars; /* For rewriting */ |
|||
int haslongline; /* For rewriting */ |
|||
unsigned rfcviolation; /* Boo-boos */ |
|||
|
|||
#define RFC2045_ERR8BITHEADER 1 /* 8 bit characters in headers */ |
|||
#define RFC2045_ERR8BITCONTENT 2 /* 8 bit contents, but no 8bit content-transfer-encoding */ |
|||
#define RFC2045_ERR2COMPLEX 4 /* Too many nested contents */ |
|||
#define RFC2045_ERRNOMIMEVERSION 8 /* missing Mime-Version header, but boundary set in content type */ |
|||
unsigned numparts; /* # of parts allocated */ |
|||
|
|||
char *rw_transfer_encoding; /* For rewriting */ |
|||
|
|||
#define RFC2045_RW_7BIT 1 |
|||
#define RFC2045_RW_8BIT 2 |
|||
|
|||
/* Subsections */ |
|||
|
|||
struct rfc2045 *firstpart, *lastpart; |
|||
|
|||
/* Working area */ |
|||
|
|||
char *workbuf; |
|||
size_t workbufsize; |
|||
size_t workbuflen; |
|||
int workinheader; |
|||
int workclosed; |
|||
int isdummy; |
|||
int informdata; /* In a middle of a long form-data part */ |
|||
char *header; |
|||
size_t headersize; |
|||
size_t headerlen; |
|||
|
|||
zval * headerhash; /* a record of all of the headers */ |
|||
|
|||
/* decoding filter to use */ |
|||
mbfl_convert_filter * decode_filter; |
|||
/* "user" function to accept the decoding output */ |
|||
rfc2045_decode_user_func_t udecode_func; |
|||
/* this is passed as the last param to the user decode func */ |
|||
void *misc_decode_ptr; |
|||
} ; |
|||
|
|||
|
|||
struct rfc2045 *rfc2045_alloc(); |
|||
void rfc2045_parse(struct rfc2045 *, const char *, size_t); |
|||
void rfc2045_free(struct rfc2045 *); |
|||
|
|||
|
|||
const char *rfc2045_contentname(const struct rfc2045 *); |
|||
void rfc2045_mimeinfo(const struct rfc2045 *, |
|||
const char **, |
|||
const char **, |
|||
const char **); |
|||
const char *rfc2045_boundary(const struct rfc2045 *); |
|||
char *rfc2045_related_start(const struct rfc2045 *); |
|||
const char *rfc2045_content_id(const struct rfc2045 *); |
|||
const char *rfc2045_content_description(const struct rfc2045 *); |
|||
const char *rfc2045_content_language(const struct rfc2045 *); |
|||
const char *rfc2045_content_md5(const struct rfc2045 *); |
|||
|
|||
void rfc2045_dispositioninfo(const struct rfc2045 *, |
|||
const char **, |
|||
const char **, |
|||
const char **); |
|||
|
|||
void rfc2045_mimepos(const struct rfc2045 *, off_t *, off_t *, off_t *, |
|||
off_t *, off_t *); |
|||
unsigned rfc2045_mimepartcount(const struct rfc2045 *); |
|||
|
|||
struct rfc2045id { |
|||
struct rfc2045id *next; |
|||
int idnum; |
|||
} ; |
|||
|
|||
void rfc2045_decode(struct rfc2045 *, |
|||
void (*)(struct rfc2045 *, struct rfc2045id *, void *), |
|||
void *); |
|||
|
|||
struct rfc2045 *rfc2045_find(struct rfc2045 *, const char *); |
|||
|
|||
|
|||
|
|||
|
|||
/* begin an en/decoding process */ |
|||
void rfc2045_cdecode_start(struct rfc2045 *, rfc2045_decode_user_func_t cb, void *); |
|||
int rfc2045_cdecode(struct rfc2045 *, const char *, size_t); |
|||
int rfc2045_cdecode_end(struct rfc2045 *); |
|||
|
|||
struct rfc2045ac { |
|||
void (*start_section)(struct rfc2045ac *, struct rfc2045 *); |
|||
void (*section_contents)(struct rfc2045ac *, const char *, size_t); |
|||
void (*end_section)(struct rfc2045ac *); |
|||
/* private vars used in acprep */ |
|||
int curlinepos; |
|||
struct rfc2045 *currwp; |
|||
enum { |
|||
raw, |
|||
quotedprint, |
|||
qpseeneq, |
|||
qpseeneqh, |
|||
base64 |
|||
} curstate; |
|||
int statechar; |
|||
|
|||
|
|||
}; |
|||
|
|||
struct rfc2045 *rfc2045_alloc_ac(); |
|||
int rfc2045_ac_check(struct rfc2045 *, int); |
|||
int rfc2045_rewrite(struct rfc2045 *, int, int, const char *); |
|||
int rfc2045_rewrite_func(struct rfc2045 *p, int, |
|||
int (*)(const char *, int, void *), void *, |
|||
const char *); |
|||
|
|||
/* Internal functions */ |
|||
|
|||
int rfc2045_try_boundary(struct rfc2045 *, int, const char *); |
|||
char *rfc2045_mk_boundary(struct rfc2045 *, int); |
|||
const char *rfc2045_getattr(const struct rfc2045attr *, const char *); |
|||
void rfc2045_setattr(struct rfc2045attr **, const char *, const char *); |
|||
|
|||
/* MIME content base/location */ |
|||
|
|||
char *rfc2045_content_base(struct rfc2045 *p); |
|||
/* This joins Content-Base: and Content-Location:, as best as I |
|||
** can figure it out. |
|||
*/ |
|||
|
|||
char *rfc2045_append_url(const char *, const char *); |
|||
/* Do this with two arbitrary URLs */ |
|||
|
|||
#ifdef __cplusplus |
|||
} |
|||
#endif |
|||
|
|||
#endif |
|||
@ -0,0 +1,123 @@ |
|||
/* $Id$ */ |
|||
/* |
|||
** Copyright 1998 - 1999 Double Precision, Inc. See COPYING for |
|||
** distribution information. |
|||
*/ |
|||
#include "php.h" |
|||
#include "php_mailparse.h" |
|||
|
|||
|
|||
int rfc2045_ac_check(struct rfc2045 *p, int rwmode) |
|||
{ |
|||
int flag=0; /* Flag - rewriting suggested */ |
|||
struct rfc2045 *c; |
|||
int hasnon7bit=p->has8bitchars; |
|||
/* hasnon7bit: 8bit chars in this section or subsections */ |
|||
const char *te; |
|||
int is8bitte; |
|||
MAILPARSELS_FETCH(); |
|||
|
|||
for (c=p->firstpart; c; c=c->next) |
|||
if (!c->isdummy) |
|||
{ |
|||
if (rfc2045_ac_check(c, rwmode)) flag=1; |
|||
if (strcmp(c->content_transfer_encoding, "7bit") && |
|||
strcmp(c->content_transfer_encoding, "quoted-printable")) |
|||
hasnon7bit=1; |
|||
if (c->has8bitchars) |
|||
p->has8bitchars=1; |
|||
} |
|||
|
|||
if (RFC2045_ISMIME1DEF(p->mime_version) && !p->content_type) |
|||
{ |
|||
p->content_type = estrdup("text/plain"); |
|||
if (p->mime_version) |
|||
{ |
|||
flag=1; |
|||
} |
|||
} |
|||
|
|||
if (RFC2045_ISMIME1DEF(p->mime_version) |
|||
&& !rfc2045_getattr(p->content_type_attr, "charset") |
|||
&& strncasecmp(p->content_type, "text/", 5) == 0) |
|||
{ |
|||
rfc2045_setattr(&p->content_type_attr, "charset", |
|||
MAILPARSEG(def_charset)); |
|||
|
|||
if (p->mime_version |
|||
|
|||
&& p->firstpart == 0 /* sam - don't trigger rewrites on changes to multipart headers */ |
|||
|
|||
) |
|||
{ |
|||
flag=1; |
|||
} |
|||
} |
|||
|
|||
if (RFC2045_ISMIME1DEF(p->mime_version) |
|||
&& !p->content_transfer_encoding) |
|||
{ |
|||
p->content_transfer_encoding = estrdup(hasnon7bit ? "8bit":"7bit"); |
|||
if (p->mime_version |
|||
|
|||
&& p->firstpart == 0 /* sam - don't trigger rewrites on changes to multipart headers */ |
|||
) |
|||
{ |
|||
flag=1; |
|||
} |
|||
} |
|||
|
|||
#if 0 |
|||
if (RFC2045_ISMIME1DEF(p->mime_version) |
|||
&& strncmp(p->content_type, "text/", 5) == 0 && !hasnon7bit |
|||
&& strcmp(p->content_transfer_encoding, "7bit")) |
|||
{ |
|||
if (p->mime_version) |
|||
{ |
|||
flag=1; |
|||
} |
|||
} |
|||
#endif |
|||
|
|||
if (RFC2045_ISMIME1DEF(p->mime_version)) |
|||
{ |
|||
/* Check for conversions */ |
|||
|
|||
te=p->content_transfer_encoding; |
|||
is8bitte=strcasecmp(te, "base64") && |
|||
strcasecmp(te, "quoted-printable") && |
|||
strcasecmp(te, "7bit"); /* 8 bit contents */ |
|||
|
|||
if (is8bitte && !p->has8bitchars && !p->haslongline) |
|||
{ |
|||
if (p->rw_transfer_encoding) |
|||
efree(p->rw_transfer_encoding); |
|||
p->rw_transfer_encoding=estrdup("7bit"); |
|||
flag=1; |
|||
is8bitte=0; |
|||
} |
|||
|
|||
if (rwmode == RFC2045_RW_7BIT && (is8bitte || p->haslongline)) |
|||
{ |
|||
if (p->rw_transfer_encoding) |
|||
efree(p->rw_transfer_encoding); |
|||
p->rw_transfer_encoding=estrdup("quoted-printable"); |
|||
flag=1; |
|||
} |
|||
else if (rwmode == RFC2045_RW_8BIT && |
|||
strcasecmp(te, "quoted-printable") == 0 && |
|||
!p->haslongline) |
|||
{ |
|||
if (p->rw_transfer_encoding) |
|||
efree(p->rw_transfer_encoding); |
|||
p->rw_transfer_encoding=estrdup(hasnon7bit ? "8bit":"7bit"); |
|||
flag=1; |
|||
} |
|||
} |
|||
|
|||
if (!p->mime_version) |
|||
{ |
|||
p->mime_version = estrdup("1.0"); |
|||
} |
|||
return (flag); |
|||
} |
|||
@ -0,0 +1,99 @@ |
|||
/* $Id$ */ |
|||
|
|||
/* |
|||
** Copyright 1998 - 1999 Double Precision, Inc. See COPYING for |
|||
** distribution information. |
|||
*/ |
|||
#include "php.h" |
|||
#include "php_mailparse.h" |
|||
|
|||
|
|||
static void start_rwprep(struct rfc2045ac *, struct rfc2045 *); |
|||
static void do_rwprep(struct rfc2045ac *, const char *, size_t); |
|||
static void end_rwprep(struct rfc2045ac *); |
|||
|
|||
static struct rfc2045ac rfc2045acprep={ |
|||
&start_rwprep, |
|||
&do_rwprep, |
|||
&end_rwprep}; |
|||
|
|||
#define h2nyb(c) ( (c) >= 'a' && (c) <= 'f' ? (c)-('a'-10): \ |
|||
(c) >= 'A' && (c) <= 'F' ? (c)-('A'-10): (c)-'0') |
|||
|
|||
struct rfc2045 *rfc2045_alloc_ac() |
|||
{ |
|||
struct rfc2045 *p=rfc2045_alloc(); |
|||
|
|||
if (p) |
|||
{ |
|||
p->rfc2045acptr = emalloc(sizeof(struct rfc2045ac)); |
|||
memcpy(p->rfc2045acptr, &rfc2045acprep, sizeof(struct rfc2045ac)); |
|||
p->rfc2045acptr->curlinepos = 0; |
|||
p->rfc2045acptr->currwp = NULL; |
|||
} |
|||
return (p); |
|||
} |
|||
|
|||
|
|||
static void start_rwprep(struct rfc2045ac * this_ptr, struct rfc2045 *p) |
|||
{ |
|||
this_ptr->currwp = p; |
|||
this_ptr->curlinepos=0; |
|||
this_ptr->curstate=raw; |
|||
if (p->content_transfer_encoding) |
|||
{ |
|||
if (strcmp(p->content_transfer_encoding, |
|||
"quoted-printable") == 0) |
|||
this_ptr->curstate = quotedprint; |
|||
else if (strcmp(p->content_transfer_encoding, "base64") == 0) |
|||
this_ptr->curstate = base64; |
|||
} |
|||
} |
|||
|
|||
static void do_rwprep(struct rfc2045ac * this_ptr, const char * p, size_t n) |
|||
{ |
|||
if (!this_ptr->currwp) |
|||
return; |
|||
for ( ; n; --n, ++p) |
|||
switch (this_ptr->curstate) { |
|||
case quotedprint: |
|||
if (*p == '=') |
|||
{ |
|||
this_ptr->curstate = qpseeneq; |
|||
continue; |
|||
} |
|||
/* FALLTHRU */ |
|||
case raw: |
|||
if (*p == '\r' || *p == '\n') |
|||
this_ptr->curlinepos = 0; |
|||
else if (++this_ptr->curlinepos > 500) |
|||
this_ptr->currwp->haslongline = 1; |
|||
if ((unsigned char)*p >= 127) |
|||
this_ptr->currwp->has8bitchars = 1; |
|||
break; |
|||
case qpseeneq: |
|||
if (*p == '\n') |
|||
{ |
|||
this_ptr->curstate = quotedprint; |
|||
continue; |
|||
} |
|||
if (isspace((int)(unsigned char)*p)) continue; /* Ignore WSP */ |
|||
this_ptr->statechar = *p; |
|||
this_ptr->curstate = qpseeneqh; |
|||
continue; |
|||
case qpseeneqh: |
|||
this_ptr->curstate = quotedprint; |
|||
if ( (unsigned char) |
|||
( (h2nyb(this_ptr->statechar) << 4) + h2nyb(*p) ) >= 127 |
|||
) this_ptr->currwp->has8bitchars=1; |
|||
if (++this_ptr->curlinepos > 500) |
|||
this_ptr->currwp->haslongline=1; |
|||
continue; |
|||
case base64: |
|||
break; |
|||
} |
|||
} |
|||
|
|||
static void end_rwprep(struct rfc2045ac * this_ptr) |
|||
{ |
|||
} |
|||
@ -0,0 +1,130 @@ |
|||
/* |
|||
+----------------------------------------------------------------------+ |
|||
| 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) | |
|||
+----------------------------------------------------------------------+ |
|||
*/ |
|||
/* $Id$ */ |
|||
|
|||
/* |
|||
** Copyright 2000 Double Precision, Inc. See COPYING for |
|||
** distribution information. |
|||
*/ |
|||
|
|||
#include "php.h" |
|||
#include "php_mailparse.h" |
|||
|
|||
/* |
|||
** --------------------------------------------------------------------- |
|||
** Attempt to parse Content-Base: and Content-Location:, and return the |
|||
** "base" of all the relative URLs in the section. |
|||
** --------------------------------------------------------------------- |
|||
*/ |
|||
|
|||
static void get_method_path(const char *p, |
|||
const char **method, |
|||
unsigned *methodl, |
|||
const char **path) |
|||
{ |
|||
unsigned i; |
|||
|
|||
for (i=0; p && p[i]; i++) |
|||
{ |
|||
if (p[i] == ':') |
|||
{ |
|||
*method=p; |
|||
*methodl= ++i; |
|||
*path=p+i; |
|||
return; |
|||
} |
|||
|
|||
if (!isalpha( (int)(unsigned char)p[i])) |
|||
break; |
|||
} |
|||
|
|||
*method=0; |
|||
*methodl=0; |
|||
*path=p; |
|||
} |
|||
|
|||
char *rfc2045_append_url(const char *base, const char *loc) |
|||
{ |
|||
const char *base_method; |
|||
unsigned base_method_l; |
|||
const char *base_path; |
|||
|
|||
const char *loc_method; |
|||
unsigned loc_method_l; |
|||
const char *loc_path; |
|||
char *buf, *q; |
|||
|
|||
get_method_path(base, &base_method, &base_method_l, &base_path); |
|||
get_method_path(loc, &loc_method, &loc_method_l, &loc_path); |
|||
|
|||
if (loc_method_l) |
|||
{ |
|||
buf = emalloc(strlen(loc)+1); |
|||
strcpy(buf, loc); |
|||
return (buf); |
|||
} |
|||
|
|||
loc_method = base_method; |
|||
loc_method_l = base_method_l; |
|||
|
|||
if (!base_path) base_path = ""; |
|||
if (!loc_path) loc_path = ""; |
|||
|
|||
buf = emalloc(loc_method_l + strlen(base_path)+strlen(loc_path) + 3); |
|||
|
|||
if (loc_method_l) |
|||
memcpy(buf, loc_method, loc_method_l); |
|||
buf[loc_method_l] = 0; |
|||
|
|||
q=buf + loc_method_l; |
|||
|
|||
strcat(strcpy(q, base_path), "/"); |
|||
|
|||
if ( loc_path[0] == '/') |
|||
{ |
|||
char *r; |
|||
|
|||
if (loc_path[1] == '/') { |
|||
*q=0; /* Location is absolute */ |
|||
} |
|||
else if ( q[0] == '/' && q[1] == '/' && (r=strchr(q+2, '/')) != 0) { |
|||
*r=0; /* Relative to top of base */ |
|||
} |
|||
else { |
|||
*q=0; /* No sys in base, just start with / */ |
|||
} |
|||
} |
|||
|
|||
strcat(q, loc_path); |
|||
|
|||
return (buf); |
|||
} |
|||
|
|||
char *rfc2045_content_base(struct rfc2045 *p) |
|||
{ |
|||
return (rfc2045_append_url(p->content_base, p->content_location)); |
|||
} |
|||
|
|||
/* |
|||
* Local variables: |
|||
* tab-width: 4 |
|||
* c-basic-offset: 4 |
|||
* End: |
|||
* vim: tw=78 ts=4 sw=4 |
|||
*/ |
|||
@ -0,0 +1,83 @@ |
|||
/* $Id$ */ |
|||
/* |
|||
** Copyright 1998 - 1999 Double Precision, Inc. See COPYING for |
|||
** distribution information. |
|||
*/ |
|||
|
|||
#include "php.h" |
|||
#include "php_mailparse.h" |
|||
|
|||
|
|||
static int op_func(int c, void *dat) |
|||
{ |
|||
unsigned char C = (unsigned char)c; |
|||
struct rfc2045 * p = (struct rfc2045*)dat; |
|||
|
|||
(*p->udecode_func)(&C, 1, p->misc_decode_ptr); |
|||
|
|||
return c; |
|||
} |
|||
|
|||
void rfc2045_cdecode_start(struct rfc2045 *p, |
|||
rfc2045_decode_user_func_t u, |
|||
void *miscptr) |
|||
{ |
|||
enum mbfl_no_encoding from = mbfl_no_encoding_8bit; |
|||
|
|||
if (p->content_transfer_encoding) |
|||
{ |
|||
from = mbfl_name2no_encoding(p->content_transfer_encoding); |
|||
if (from == mbfl_no_encoding_invalid) { |
|||
zend_error(E_WARNING, "%s(): I don't know how to decode %s transfer encoding!", |
|||
get_active_function_name(), |
|||
p->content_transfer_encoding); |
|||
from = mbfl_no_encoding_8bit; |
|||
} |
|||
} |
|||
|
|||
p->misc_decode_ptr=miscptr; |
|||
p->udecode_func=u; |
|||
p->workbuflen=0; |
|||
|
|||
if (from == mbfl_no_encoding_8bit) |
|||
p->decode_filter = NULL; |
|||
else |
|||
p->decode_filter = mbfl_convert_filter_new( |
|||
from, mbfl_no_encoding_8bit, |
|||
op_func, |
|||
NULL, |
|||
p |
|||
); |
|||
} |
|||
|
|||
int rfc2045_cdecode_end(struct rfc2045 *p) |
|||
{ |
|||
if (p->decode_filter) |
|||
{ |
|||
mbfl_convert_filter_flush(p->decode_filter); |
|||
mbfl_convert_filter_delete(p->decode_filter); |
|||
p->decode_filter = NULL; |
|||
} |
|||
return 0; |
|||
} |
|||
|
|||
int rfc2045_cdecode(struct rfc2045 *p, const char *s, size_t l) |
|||
{ |
|||
if (s && l) |
|||
{ |
|||
int i; |
|||
|
|||
if (p->decode_filter) |
|||
{ |
|||
for (i=0; i<l; i++) |
|||
{ |
|||
if (mbfl_convert_filter_feed(s[i], p->decode_filter) < 0) |
|||
return -1; |
|||
} |
|||
} |
|||
else |
|||
return ((*p->udecode_func)(s,l,p->misc_decode_ptr)); |
|||
|
|||
} |
|||
return (0); |
|||
} |
|||
@ -0,0 +1,40 @@ |
|||
/* $Id$ */ |
|||
/* |
|||
** Copyright 1998 - 1999 Double Precision, Inc. See COPYING for |
|||
** distribution information. |
|||
*/ |
|||
|
|||
#include "php.h" |
|||
#include "php_mailparse.h" |
|||
|
|||
static void decode(struct rfc2045id *topid, |
|||
struct rfc2045id **childidptr, |
|||
struct rfc2045 *r, |
|||
void (*func)(struct rfc2045 *, struct rfc2045id *, void *), |
|||
void *ptr) |
|||
{ |
|||
struct rfc2045id nextid; |
|||
|
|||
*childidptr=0; |
|||
(*func)(r, topid, ptr); |
|||
*childidptr=&nextid; |
|||
nextid.idnum=1; |
|||
if (r->content_type && strncmp(r->content_type, "multipart/", 10) == 0) |
|||
nextid.idnum=0; |
|||
for (r=r->firstpart; r; r=r->next) |
|||
{ |
|||
if (nextid.idnum) |
|||
decode(topid, &nextid.next, r, func, ptr); |
|||
++nextid.idnum; |
|||
} |
|||
} |
|||
|
|||
void rfc2045_decode(struct rfc2045 *p, |
|||
void (*func)(struct rfc2045 *, struct rfc2045id *, void *), |
|||
void *ptr) |
|||
{ |
|||
struct rfc2045id topid; |
|||
|
|||
topid.idnum=1; |
|||
decode(&topid, &topid.next, p, func, ptr); |
|||
} |
|||
@ -0,0 +1,47 @@ |
|||
/* $Id$ */ |
|||
/* |
|||
** Copyright 1998 - 1999 Double Precision, Inc. See COPYING for |
|||
** distribution information. |
|||
*/ |
|||
|
|||
#include "php.h" |
|||
#include "php_mailparse.h" |
|||
|
|||
struct rfc2045findstruct { |
|||
const char *partnum; |
|||
struct rfc2045 *ptr; |
|||
} ; |
|||
|
|||
static void do_decode(struct rfc2045 *p, struct rfc2045id *id, void *ptr) |
|||
{ |
|||
struct rfc2045findstruct *fs=(struct rfc2045findstruct *)ptr; |
|||
const char *partnum=fs->partnum; |
|||
unsigned n; |
|||
|
|||
while (id) |
|||
{ |
|||
if (!isdigit((int)(unsigned char)*partnum)) return; |
|||
n=0; |
|||
while (isdigit((int)(unsigned char)*partnum)) |
|||
n=n*10 + *partnum++ - '0'; |
|||
if (*partnum) |
|||
{ |
|||
if (*partnum != '.') return; |
|||
++partnum; |
|||
} |
|||
if (n != (unsigned)id->idnum) return; |
|||
id=id->next; |
|||
} |
|||
if ( *partnum == '\0') fs->ptr=p; |
|||
} |
|||
|
|||
|
|||
struct rfc2045 *rfc2045_find(struct rfc2045 *p, const char *str) |
|||
{ |
|||
struct rfc2045findstruct fs; |
|||
|
|||
fs.partnum=str; |
|||
fs.ptr=0; |
|||
rfc2045_decode(p, &do_decode, &fs); |
|||
return (fs.ptr); |
|||
} |
|||
@ -0,0 +1,716 @@ |
|||
/* $Id$ */ |
|||
/* |
|||
** Copyright 1998 - 1999 Double Precision, Inc. |
|||
** See COPYING for distribution information. |
|||
*/ |
|||
|
|||
#include "php.h" |
|||
#include "php_mailparse.h" |
|||
|
|||
static void tokenize(const char *p, struct rfc822token *tokp, int *toklen, |
|||
void (*err_func)(const char *, int)) |
|||
{ |
|||
const char *addr=p; |
|||
int i=0; |
|||
int inbracket=0; |
|||
|
|||
*toklen=0; |
|||
while (*p) |
|||
{ |
|||
if (isspace((int)(unsigned char)*p)) |
|||
{ |
|||
p++; |
|||
i++; |
|||
continue; |
|||
} |
|||
|
|||
switch (*p) { |
|||
int level; |
|||
|
|||
case '(': |
|||
if (tokp) |
|||
{ |
|||
tokp->token='('; |
|||
tokp->ptr=p; |
|||
tokp->len=0; |
|||
} |
|||
level=0; |
|||
for (;;) |
|||
{ |
|||
if (!*p) |
|||
{ |
|||
if (err_func) (*err_func)(addr, i); |
|||
if (tokp) tokp->token='"'; |
|||
++*toklen; |
|||
return; |
|||
} |
|||
if (*p == '(') |
|||
++level; |
|||
if (*p == ')' && --level == 0) |
|||
{ |
|||
p++; |
|||
i++; |
|||
if (tokp) tokp->len++; |
|||
break; |
|||
} |
|||
if (*p == '\\' && p[1]) |
|||
{ |
|||
p++; |
|||
i++; |
|||
if (tokp) tokp->len++; |
|||
} |
|||
|
|||
i++; |
|||
if (tokp) tokp->len++; |
|||
p++; |
|||
} |
|||
if (tokp) ++tokp; |
|||
++*toklen; |
|||
continue; |
|||
|
|||
case '"': |
|||
p++; |
|||
i++; |
|||
|
|||
if (tokp) |
|||
{ |
|||
tokp->token='"'; |
|||
tokp->ptr=p; |
|||
} |
|||
while (*p != '"') |
|||
{ |
|||
if (!*p) |
|||
{ |
|||
if (err_func) (*err_func)(addr, i); |
|||
++*toklen; |
|||
return; |
|||
} |
|||
if (*p == '\\' && p[1]) |
|||
{ |
|||
if (tokp) tokp->len++; |
|||
p++; |
|||
i++; |
|||
} |
|||
if (tokp) tokp->len++; |
|||
p++; |
|||
i++; |
|||
} |
|||
++*toklen; |
|||
if (tokp) ++tokp; |
|||
p++; |
|||
i++; |
|||
continue; |
|||
case '\\': |
|||
case ')': |
|||
if (err_func) (*err_func)(addr, i); |
|||
++p; |
|||
++i; |
|||
continue; |
|||
case '<': |
|||
case '>': |
|||
case '@': |
|||
case ',': |
|||
case ';': |
|||
case ':': |
|||
case '.': |
|||
case '[': |
|||
case ']': |
|||
case '%': |
|||
case '!': |
|||
case '?': |
|||
case '=': |
|||
case '/': |
|||
|
|||
if ( (*p == '<' && inbracket) || |
|||
(*p == '>' && !inbracket)) |
|||
{ |
|||
if (err_func) (*err_func)(addr, i); |
|||
++p; |
|||
++i; |
|||
continue; |
|||
} |
|||
|
|||
if (*p == '<') |
|||
inbracket=1; |
|||
|
|||
if (*p == '>') |
|||
inbracket=0; |
|||
|
|||
if (tokp) |
|||
{ |
|||
tokp->token= *p; |
|||
tokp->ptr=p; |
|||
tokp->len=1; |
|||
++tokp; |
|||
} |
|||
++*toklen; |
|||
|
|||
if (*p == '<' && p[1] == '>') |
|||
/* Fake a null address */ |
|||
{ |
|||
if (tokp) |
|||
{ |
|||
tokp->token=0; |
|||
tokp->ptr=""; |
|||
tokp->len=0; |
|||
++tokp; |
|||
} |
|||
++*toklen; |
|||
} |
|||
++p; |
|||
++i; |
|||
continue; |
|||
default: |
|||
|
|||
if (tokp) |
|||
{ |
|||
tokp->token=0; |
|||
tokp->ptr=p; |
|||
tokp->len=0; |
|||
} |
|||
while (*p && !isspace((int)(unsigned char)*p) && strchr( |
|||
"<>@,;:.[]()%!\"\\?=/", *p) == 0) |
|||
{ |
|||
if (tokp) ++tokp->len; |
|||
++p; |
|||
++i; |
|||
} |
|||
if (i == 0) /* Idiot check */ |
|||
{ |
|||
if (err_func) (*err_func)(addr, i); |
|||
if (tokp) |
|||
{ |
|||
tokp->token='"'; |
|||
tokp->ptr=p; |
|||
tokp->len=1; |
|||
++tokp; |
|||
} |
|||
++*toklen; |
|||
++p; |
|||
++i; |
|||
continue; |
|||
} |
|||
if (tokp) ++tokp; |
|||
++*toklen; |
|||
} |
|||
} |
|||
} |
|||
|
|||
static void parseaddr(struct rfc822token *tokens, int ntokens, |
|||
struct rfc822addr *addrs, int *naddrs) |
|||
{ |
|||
int flag, j, k; |
|||
struct rfc822token save_token; |
|||
|
|||
*naddrs=0; |
|||
|
|||
while (ntokens) |
|||
{ |
|||
int i; |
|||
|
|||
/* atoms (token=0) or quoted strings, followed by a : token |
|||
is a list name. */ |
|||
|
|||
for (i=0; i<ntokens; i++) |
|||
if (tokens[i].token && tokens[i].token != '"') |
|||
break; |
|||
if (i < ntokens && tokens[i].token == ':') |
|||
{ |
|||
++i; |
|||
if (addrs) |
|||
{ |
|||
addrs->tokens=0; |
|||
addrs->name=i ? tokens:0; |
|||
for (j=1; j<i; j++) |
|||
addrs->name[j-1].next=addrs->name+j; |
|||
if (i) |
|||
addrs->name[i-1].next=0; |
|||
addrs++; |
|||
} |
|||
++*naddrs; |
|||
tokens += i; |
|||
ntokens -= i; |
|||
continue; /* Group=phrase ":" */ |
|||
} |
|||
|
|||
/* Spurious commas are skipped, ;s are recorded */ |
|||
|
|||
if (tokens->token == ',' || tokens->token == ';') |
|||
{ |
|||
if (tokens->token == ';') |
|||
{ |
|||
if (addrs) |
|||
{ |
|||
addrs->tokens=0; |
|||
addrs->name=tokens; |
|||
addrs->name->next=0; |
|||
addrs++; |
|||
} |
|||
++*naddrs; |
|||
} |
|||
++tokens; |
|||
--ntokens; |
|||
continue; |
|||
} |
|||
|
|||
/* If we can find a '<' before the next comma or semicolon, |
|||
we have new style RFC path address */ |
|||
|
|||
for (i=0; i<ntokens && tokens[i].token != ';' && |
|||
tokens[i].token != ',' && |
|||
tokens[i].token != '<'; i++) |
|||
; |
|||
|
|||
if (i < ntokens && tokens[i].token == '<') |
|||
{ |
|||
int j; |
|||
|
|||
/* Ok -- what to do with the stuff before '>'??? |
|||
If it consists exclusively of atoms, leave them alone. |
|||
Else, make them all a quoted string. */ |
|||
|
|||
for (j=0; j<i && (tokens[j].token == 0 || |
|||
tokens[j].token == '('); j++) |
|||
; |
|||
|
|||
if (j == i) |
|||
{ |
|||
if (addrs) |
|||
{ |
|||
addrs->name= i ? tokens:0; |
|||
for (k=1; k<i; k++) |
|||
addrs->name[k-1].next=addrs->name+k; |
|||
if (i) |
|||
addrs->name[i-1].next=0; |
|||
} |
|||
} |
|||
else /* Intentionally corrupt the original toks */ |
|||
{ |
|||
if (addrs) |
|||
{ |
|||
tokens->len= tokens[i-1].ptr |
|||
+ tokens[i-1].len |
|||
- tokens->ptr; |
|||
/* We know that all the ptrs point |
|||
to parts of the same string. */ |
|||
tokens->token='"'; |
|||
/* Quoted string. */ |
|||
addrs->name=tokens; |
|||
addrs->name->next=0; |
|||
} |
|||
} |
|||
|
|||
/* Any comments in the name part are changed to quotes */ |
|||
|
|||
if (addrs) |
|||
{ |
|||
struct rfc822token *t; |
|||
|
|||
for (t=addrs->name; t; t=t->next) |
|||
if (t->token == '(') |
|||
t->token='"'; |
|||
} |
|||
|
|||
/* Now that's done and over with, see what can |
|||
be done with the <...> part. */ |
|||
|
|||
++i; |
|||
tokens += i; |
|||
ntokens -= i; |
|||
for (i=0; i<ntokens && tokens[i].token != '>'; i++) |
|||
; |
|||
if (addrs) |
|||
{ |
|||
addrs->tokens=i ? tokens:0; |
|||
for (k=1; k<i; k++) |
|||
addrs->tokens[k-1].next=addrs->tokens+k; |
|||
if (i) |
|||
addrs->tokens[i-1].next=0; |
|||
++addrs; |
|||
} |
|||
++*naddrs; |
|||
tokens += i; |
|||
ntokens -= i; |
|||
if (ntokens) /* Skip the '>' token */ |
|||
{ |
|||
--ntokens; |
|||
++tokens; |
|||
} |
|||
continue; |
|||
} |
|||
|
|||
/* Ok - old style address. Assume the worst */ |
|||
|
|||
/* Try to figure out where the address ends. It ends upon: |
|||
a comma, semicolon, or two consecutive atoms. */ |
|||
|
|||
flag=0; |
|||
for (i=0; i<ntokens && tokens[i].token != ',' && |
|||
tokens[i].token != ';'; i++) |
|||
{ |
|||
if (tokens[i].token == '(') continue; |
|||
/* Ignore comments */ |
|||
if (tokens[i].token == 0 || tokens[i].token == '"') |
|||
/* Atom */ |
|||
{ |
|||
if (flag) break; |
|||
flag=1; |
|||
} |
|||
else flag=0; |
|||
} |
|||
if (i == 0) /* Must be spurious comma, or something */ |
|||
{ |
|||
++tokens; |
|||
--ntokens; |
|||
continue; |
|||
} |
|||
|
|||
if (addrs) |
|||
{ |
|||
addrs->name=0; |
|||
} |
|||
|
|||
/* Ok, now get rid of embedded comments in the address. |
|||
Consider the last comment to be the real name */ |
|||
|
|||
if (addrs) |
|||
{ |
|||
|
|||
save_token.ptr=0; |
|||
save_token.len=0; |
|||
|
|||
for (j=k=0; j<i; j++) |
|||
{ |
|||
if (tokens[j].token == '(') |
|||
{ |
|||
save_token=tokens[j]; |
|||
continue; |
|||
} |
|||
tokens[k]=tokens[j]; |
|||
k++; |
|||
} |
|||
|
|||
if (save_token.ptr) |
|||
{ |
|||
tokens[i-1]=save_token; |
|||
addrs->name=tokens+i-1; |
|||
addrs->name->next=0; |
|||
} |
|||
addrs->tokens=k ? tokens:NULL; |
|||
for (j=1; j<k; j++) |
|||
addrs->tokens[j-1].next=addrs->tokens+j; |
|||
if (k) |
|||
addrs->tokens[k-1].next=0; |
|||
++addrs; |
|||
} |
|||
++*naddrs; |
|||
tokens += i; |
|||
ntokens -= i; |
|||
} |
|||
} |
|||
|
|||
static void print_token(const struct rfc822token *token, |
|||
void (*print_func)(char, void *), void *ptr) |
|||
{ |
|||
const char *p; |
|||
int n; |
|||
|
|||
if (token->token == 0 || token->token == '(') |
|||
{ |
|||
for (n=token->len, p=token->ptr; n; --n, ++p) |
|||
(*print_func)(*p, ptr); |
|||
return; |
|||
} |
|||
|
|||
if (token->token != '"') |
|||
{ |
|||
(*print_func)(token->token, ptr); |
|||
return; |
|||
} |
|||
|
|||
(*print_func)('"', ptr); |
|||
n=token->len; |
|||
p=token->ptr; |
|||
while (n) |
|||
{ |
|||
if (*p == '"' || (*p == '\\' && n == 1)) (*print_func)('\\', ptr); |
|||
if (*p == '\\' && n > 1) |
|||
{ |
|||
(*print_func)('\\', ptr); |
|||
++p; |
|||
--n; |
|||
} |
|||
(*print_func)(*p++, ptr); |
|||
--n; |
|||
} |
|||
(*print_func)('"', ptr); |
|||
} |
|||
|
|||
void mailparse_rfc822tok_print(const struct rfc822token *token, |
|||
void (*print_func)(char, void *), void *ptr) |
|||
{ |
|||
int prev_isatom=0; |
|||
int isatom; |
|||
|
|||
while (token) |
|||
{ |
|||
isatom=mailparse_rfc822_is_atom(token->token); |
|||
if (prev_isatom && isatom) |
|||
(*print_func)(' ', ptr); |
|||
print_token(token, print_func, ptr); |
|||
prev_isatom=isatom; |
|||
token=token->next; |
|||
} |
|||
} |
|||
|
|||
void mailparse_rfc822_print(const struct rfc822a *rfcp, void (*print_func)(char, void *), |
|||
void (*print_separator)(const char *s, void *), void *ptr) |
|||
{ |
|||
mailparse_rfc822_print_common(rfcp, 0, 0, print_func, print_separator, ptr); |
|||
} |
|||
|
|||
void mailparse_rfc822_print_common(const struct rfc822a *rfcp, |
|||
char *(*decode_func)(const char *, const char *), const char *chset, |
|||
void (*print_func)(char, void *), |
|||
void (*print_separator)(const char *, void *), void *ptr) |
|||
{ |
|||
const struct rfc822addr *addrs=rfcp->addrs; |
|||
int naddrs=rfcp->naddrs; |
|||
|
|||
while (naddrs) |
|||
{ |
|||
if (addrs->tokens == 0) |
|||
{ |
|||
mailparse_rfc822tok_print(addrs->name, print_func, ptr); |
|||
++addrs; |
|||
--naddrs; |
|||
if (addrs[-1].name && naddrs) |
|||
{ |
|||
struct rfc822token *t; |
|||
|
|||
for (t=addrs[-1].name; t && t->next; t=t->next) |
|||
; |
|||
|
|||
if (t && (t->token == ':' || t->token == ';')) |
|||
(*print_separator)(" ", ptr); |
|||
} |
|||
continue; |
|||
} |
|||
else if (addrs->name && addrs->name->token == '(') |
|||
{ /* old style */ |
|||
char *p; |
|||
|
|||
mailparse_rfc822tok_print(addrs->tokens, print_func, ptr); |
|||
(*print_func)(' ', ptr); |
|||
|
|||
if (decode_func && (p=mailparse_rfc822_gettok(addrs->name))!=0) |
|||
{ |
|||
char *q= (*decode_func)(p, chset); |
|||
char *r; |
|||
|
|||
for (r=q; r && *r; r++) |
|||
(*print_func)( (int)(unsigned char)*r, |
|||
ptr); |
|||
if (q) efree(q); |
|||
efree(p); |
|||
} |
|||
else mailparse_rfc822tok_print(addrs->name, print_func, ptr); |
|||
} |
|||
else |
|||
{ |
|||
int print_braces=0; |
|||
char *p; |
|||
|
|||
if (addrs->name) |
|||
{ |
|||
if (decode_func && |
|||
(p=mailparse_rfc822_gettok(addrs->name)) != 0) |
|||
{ |
|||
char *q= (*decode_func)(p, chset); |
|||
char *r; |
|||
|
|||
for (r=q; r && *r; r++) |
|||
(*print_func)( |
|||
(int)(unsigned char)*r, |
|||
ptr); |
|||
if (q) efree(q); |
|||
efree(p); |
|||
} |
|||
else mailparse_rfc822tok_print(addrs->name, |
|||
print_func, ptr); |
|||
(*print_func)(' ', ptr); |
|||
print_braces=1; |
|||
} |
|||
else |
|||
{ |
|||
struct rfc822token *p; |
|||
|
|||
for (p=addrs->tokens; p && p->next; p=p->next) |
|||
if (mailparse_rfc822_is_atom(p->token) && |
|||
mailparse_rfc822_is_atom(p->next->token)) |
|||
print_braces=1; |
|||
} |
|||
if (print_braces) |
|||
(*print_func)('<', ptr); |
|||
mailparse_rfc822tok_print(addrs->tokens, print_func, ptr); |
|||
if (print_braces) |
|||
{ |
|||
(*print_func)('>', ptr); |
|||
} |
|||
} |
|||
++addrs; |
|||
--naddrs; |
|||
if (naddrs) |
|||
if (addrs->tokens || (addrs->name && |
|||
mailparse_rfc822_is_atom(addrs->name->token))) |
|||
(*print_separator)(", ", ptr); |
|||
} |
|||
} |
|||
|
|||
void mailparse_rfc822t_free(struct rfc822t *p) |
|||
{ |
|||
if (p->tokens) efree(p->tokens); |
|||
efree(p); |
|||
} |
|||
|
|||
void mailparse_rfc822a_free(struct rfc822a *p) |
|||
{ |
|||
if (p->addrs) efree(p->addrs); |
|||
efree(p); |
|||
} |
|||
|
|||
void mailparse_rfc822_deladdr(struct rfc822a *rfcp, int index) |
|||
{ |
|||
int i; |
|||
|
|||
if (index < 0 || index >= rfcp->naddrs) return; |
|||
|
|||
for (i=index+1; i<rfcp->naddrs; i++) |
|||
rfcp->addrs[i-1]=rfcp->addrs[i]; |
|||
if (--rfcp->naddrs == 0) |
|||
{ |
|||
efree(rfcp->addrs); |
|||
rfcp->addrs=0; |
|||
} |
|||
} |
|||
|
|||
struct rfc822t *mailparse_rfc822t_alloc(const char *addr, |
|||
void (*err_func)(const char *, int)) |
|||
{ |
|||
struct rfc822t *p=(struct rfc822t *)emalloc(sizeof(struct rfc822t)); |
|||
|
|||
if (!p) return (NULL); |
|||
memset(p, 0, sizeof(*p)); |
|||
|
|||
tokenize(addr, NULL, &p->ntokens, err_func); |
|||
p->tokens=p->ntokens ? (struct rfc822token *) |
|||
ecalloc(p->ntokens, sizeof(struct rfc822token)):0; |
|||
if (p->ntokens && !p->tokens) |
|||
{ |
|||
mailparse_rfc822t_free(p); |
|||
return (NULL); |
|||
} |
|||
tokenize(addr, p->tokens, &p->ntokens, NULL); |
|||
return (p); |
|||
} |
|||
|
|||
struct rfc822a *mailparse_rfc822a_alloc(struct rfc822t *t) |
|||
{ |
|||
struct rfc822a *p=(struct rfc822a *)emalloc(sizeof(struct rfc822a)); |
|||
|
|||
if (!p) return (NULL); |
|||
memset(p, 0, sizeof(*p)); |
|||
|
|||
parseaddr(t->tokens, t->ntokens, NULL, &p->naddrs); |
|||
p->addrs=p->naddrs ? (struct rfc822addr *) |
|||
ecalloc(p->naddrs, sizeof(struct rfc822addr)):0; |
|||
if (p->naddrs && !p->addrs) |
|||
{ |
|||
mailparse_rfc822a_free(p); |
|||
return (NULL); |
|||
} |
|||
parseaddr(t->tokens, t->ntokens, p->addrs, &p->naddrs); |
|||
return (p); |
|||
} |
|||
|
|||
void mailparse_rfc822_praddr(const struct rfc822a *rfcp, int index, |
|||
void (*print_func)(char, void *), void *ptr) |
|||
{ |
|||
const struct rfc822addr *addrs; |
|||
|
|||
if (index < 0 || index >= rfcp->naddrs) return; |
|||
|
|||
addrs=rfcp->addrs+index; |
|||
if (addrs->tokens) |
|||
{ |
|||
mailparse_rfc822tok_print(addrs->tokens, print_func, ptr); |
|||
(*print_func)('\n', ptr); |
|||
} |
|||
} |
|||
|
|||
void mailparse_rfc822_addrlist(const struct rfc822a *rfcp, |
|||
void (*print_func)(char, void *), void *ptr) |
|||
{ |
|||
int i; |
|||
|
|||
for (i=0; i<rfcp->naddrs; i++) |
|||
mailparse_rfc822_praddr(rfcp, i, print_func, ptr); |
|||
} |
|||
|
|||
void mailparse_rfc822_prname(const struct rfc822a *rfcp, int index, |
|||
void (*print_func)(char, void *), void *ptr) |
|||
{ |
|||
const struct rfc822addr *addrs; |
|||
|
|||
if (index < 0 || index >= rfcp->naddrs) return; |
|||
|
|||
addrs=rfcp->addrs+index; |
|||
|
|||
if (!addrs->tokens) return; |
|||
mailparse_rfc822_prname_orlist(rfcp, index, print_func, ptr); |
|||
} |
|||
|
|||
void mailparse_rfc822_prname_orlist(const struct rfc822a *rfcp, int index, |
|||
void (*print_func)(char, void *), void *ptr) |
|||
{ |
|||
const struct rfc822addr *addrs; |
|||
|
|||
if (index < 0 || index >= rfcp->naddrs) return; |
|||
|
|||
addrs=rfcp->addrs+index; |
|||
|
|||
if (addrs->name) |
|||
{ |
|||
struct rfc822token *i; |
|||
int n; |
|||
int prev_isatom=0; |
|||
int isatom=0; |
|||
|
|||
for (i=addrs->name; i; i=i->next, prev_isatom=isatom) |
|||
{ |
|||
isatom=mailparse_rfc822_is_atom(i->token); |
|||
if (isatom && prev_isatom) |
|||
(*print_func)(' ', ptr); |
|||
|
|||
if (i->token != '(') |
|||
{ |
|||
print_token(i, print_func, ptr); |
|||
continue; |
|||
} |
|||
|
|||
for (n=2; n<i->len; n++) |
|||
(*print_func)(i->ptr[n-1], ptr); |
|||
} |
|||
} else |
|||
mailparse_rfc822tok_print(addrs->tokens, print_func, ptr); |
|||
(*print_func)('\n', ptr); |
|||
} |
|||
|
|||
void mailparse_rfc822_namelist(const struct rfc822a *rfcp, |
|||
void (*print_func)(char, void *), void *ptr) |
|||
{ |
|||
int i; |
|||
|
|||
for (i=0; i<rfcp->naddrs; i++) |
|||
mailparse_rfc822_prname(rfcp, i, print_func, ptr); |
|||
} |
|||
@ -0,0 +1,99 @@ |
|||
/* $Id$ */ |
|||
/* |
|||
** Copyright 1998 - 1999 Double Precision, Inc. |
|||
** See COPYING for distribution information. |
|||
*/ |
|||
|
|||
#include "php.h" |
|||
#include "php_mailparse.h" |
|||
|
|||
static void cntlen(char c, void *p) |
|||
{ |
|||
if (c != '\n') |
|||
++ *(size_t *)p; |
|||
} |
|||
|
|||
static void saveaddr(char c, void *p) |
|||
{ |
|||
if (c != '\n') |
|||
{ |
|||
char **cp=(char **)p; |
|||
|
|||
*(*cp)++=c; |
|||
} |
|||
} |
|||
|
|||
char *mailparse_rfc822_getaddr(const struct rfc822a *rfc, int n) |
|||
{ |
|||
size_t addrbuflen=0; |
|||
char *addrbuf, *ptr; |
|||
|
|||
mailparse_rfc822_praddr(rfc, n, &cntlen, &addrbuflen); |
|||
if (!(addrbuf=emalloc(addrbuflen+1))) |
|||
return (0); |
|||
|
|||
ptr=addrbuf; |
|||
mailparse_rfc822_praddr(rfc, n, &saveaddr, &ptr); |
|||
addrbuf[addrbuflen]=0; |
|||
return (addrbuf); |
|||
} |
|||
|
|||
char *mailparse_rfc822_getname(const struct rfc822a *rfc, int n) |
|||
{ |
|||
char *p, *q; |
|||
size_t addrbuflen=0; |
|||
char *addrbuf, *ptr; |
|||
|
|||
mailparse_rfc822_prname(rfc, n, &cntlen, &addrbuflen); |
|||
if (!(addrbuf=emalloc(addrbuflen+1))) |
|||
return (0); |
|||
|
|||
ptr=addrbuf; |
|||
mailparse_rfc822_prname(rfc, n, &saveaddr, &ptr); |
|||
addrbuf[addrbuflen]=0; |
|||
|
|||
/* Get rid of surrounding quotes */ |
|||
|
|||
for (p=q=addrbuf; *p; p++) |
|||
if (*p != '"') *q++=*p; |
|||
*q=0; |
|||
return (addrbuf); |
|||
} |
|||
|
|||
char *mailparse_rfc822_getname_orlist(const struct rfc822a *rfc, int n) |
|||
{ |
|||
char *p, *q; |
|||
size_t addrbuflen=0; |
|||
char *addrbuf, *ptr; |
|||
|
|||
mailparse_rfc822_prname_orlist(rfc, n, &cntlen, &addrbuflen); |
|||
if (!(addrbuf=emalloc(addrbuflen+1))) |
|||
return (0); |
|||
|
|||
ptr=addrbuf; |
|||
mailparse_rfc822_prname_orlist(rfc, n, &saveaddr, &ptr); |
|||
addrbuf[addrbuflen]=0; |
|||
|
|||
/* Get rid of surrounding quotes */ |
|||
|
|||
for (p=q=addrbuf; *p; p++) |
|||
if (*p != '"') *q++=*p; |
|||
*q=0; |
|||
return (addrbuf); |
|||
} |
|||
|
|||
char *mailparse_rfc822_gettok(const struct rfc822token *t) |
|||
{ |
|||
size_t addrbuflen=0; |
|||
char *addrbuf, *ptr; |
|||
|
|||
mailparse_rfc822tok_print(t, &cntlen, &addrbuflen); |
|||
|
|||
if (!(addrbuf=emalloc(addrbuflen+1))) |
|||
return (0); |
|||
|
|||
ptr=addrbuf; |
|||
mailparse_rfc822tok_print(t, &saveaddr, &ptr); |
|||
addrbuf[addrbuflen]=0; |
|||
return (addrbuf); |
|||
} |
|||
@ -0,0 +1,92 @@ |
|||
/* $Id$ */ |
|||
/* |
|||
** Copyright 1998 - 1999 Double Precision, Inc. |
|||
** See COPYING for distribution information. |
|||
*/ |
|||
|
|||
#include "php.h" |
|||
#include "php_mailparse.h" |
|||
|
|||
static void cntlen(char c, void *p) |
|||
{ |
|||
c=c; |
|||
++ *(size_t *)p; |
|||
} |
|||
|
|||
static void cntlensep(const char *p, void *ptr) |
|||
{ |
|||
while (*p) cntlen(*p++, ptr); |
|||
} |
|||
|
|||
static void saveaddr(char c, void *ptr) |
|||
{ |
|||
*(*(char **)ptr)++=c; |
|||
} |
|||
|
|||
static void saveaddrsep(const char *p, void *ptr) |
|||
{ |
|||
while (*p) saveaddr(*p++, ptr); |
|||
} |
|||
|
|||
char *mailparse_rfc822_getaddrs(const struct rfc822a *rfc) |
|||
{ |
|||
size_t addrbuflen=0; |
|||
char *addrbuf, *ptr; |
|||
|
|||
mailparse_rfc822_print(rfc, &cntlen, &cntlensep, &addrbuflen); |
|||
if (!(addrbuf=emalloc(addrbuflen+1))) |
|||
return (0); |
|||
|
|||
ptr=addrbuf; |
|||
mailparse_rfc822_print(rfc, &saveaddr, &saveaddrsep, &ptr); |
|||
addrbuf[addrbuflen]=0; |
|||
return (addrbuf); |
|||
} |
|||
|
|||
static void saveaddrsep_wrap(const char *p, void *ptr) |
|||
{ |
|||
int c; |
|||
|
|||
while ((c=*p++) != 0) |
|||
{ |
|||
if (c == ' ') c='\n'; |
|||
saveaddr(c, ptr); |
|||
} |
|||
} |
|||
|
|||
char *mailparse_rfc822_getaddrs_wrap(const struct rfc822a *rfc, int w) |
|||
{ |
|||
size_t addrbuflen=0; |
|||
char *addrbuf, *ptr, *start, *lastnl; |
|||
|
|||
mailparse_rfc822_print(rfc, &cntlen, &cntlensep, &addrbuflen); |
|||
if (!(addrbuf=emalloc(addrbuflen+1))) |
|||
return (0); |
|||
|
|||
ptr=addrbuf; |
|||
mailparse_rfc822_print(rfc, &saveaddr, &saveaddrsep_wrap, &ptr); |
|||
addrbuf[addrbuflen]=0; |
|||
|
|||
for (lastnl=0, start=ptr=addrbuf; *ptr; ) |
|||
{ |
|||
while (*ptr && *ptr != '\n') ptr++; |
|||
if (ptr-start < w) |
|||
{ |
|||
if (lastnl) *lastnl=' '; |
|||
lastnl=ptr; |
|||
if (*ptr) ++ptr; |
|||
} |
|||
else |
|||
{ |
|||
if (lastnl) |
|||
start=lastnl+1; |
|||
else |
|||
{ |
|||
start=ptr+1; |
|||
if (*ptr) ++ptr; |
|||
} |
|||
lastnl=0; |
|||
} |
|||
} |
|||
return (addrbuf); |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
--TEST-- |
|||
Check for mailparse presence |
|||
--SKIPIF-- |
|||
<?php if (!extension_loaded("mailparse")) print "skip"; ?> |
|||
--POST-- |
|||
--GET-- |
|||
--FILE-- |
|||
<?php |
|||
echo "mailparse extension is available"; |
|||
?> |
|||
--EXPECT-- |
|||
mailparse extension is available |
|||
@ -0,0 +1,22 @@ |
|||
--TEST-- |
|||
Check stream encoding |
|||
--SKIPIF-- |
|||
<?php if (!extension_loaded("mailparse")) print "skip"; ?> |
|||
--POST-- |
|||
--GET-- |
|||
--FILE-- |
|||
<?php |
|||
$text = <<<EOD |
|||
hello, this is some text=hello. |
|||
EOD; |
|||
$fp = tmpfile(); |
|||
fwrite($fp, $text); |
|||
rewind($fp); |
|||
$dest = tmpfile(); |
|||
mailparse_stream_encode($fp, $dest, "quoted-printable"); |
|||
rewind($dest); |
|||
$data = fread($dest, 2048); |
|||
echo $data; |
|||
?> |
|||
--EXPECT-- |
|||
hello, this is some text=3Dhello. |
|||
@ -0,0 +1,53 @@ |
|||
<?php |
|||
/* |
|||
* This is a simple email viewer. |
|||
* make sure that $filename points to a file containing an email message and |
|||
* load this page in your browser. |
|||
* You will be able to choose a part to view. |
|||
* */ |
|||
|
|||
#$filename = "/home/CLIENTWEB/worlddo/mimetests/namib.rfc822";
|
|||
$filename = "/home/CLIENTWEB/worlddo/mimetests/uumsg"; |
|||
#$filename = "/home/CLIENTWEB/worlddo/mimetests/segblob.txt";
|
|||
#$filename = "yourmessage.txt";
|
|||
|
|||
/* parse the message and return a mime message resource */ |
|||
$mime = mailparse_msg_parse_file($filename); |
|||
/* return an array of message parts - this contsists of the names of the parts |
|||
* only */ |
|||
$struct = mailparse_msg_get_structure($mime); |
|||
|
|||
echo "<table>\n"; |
|||
/* print a choice of sections */ |
|||
foreach($struct as $st) { |
|||
echo "<tr>\n"; |
|||
echo "<td><a href=\"$PHP_SELF?showpart=$st\">$st</a></td>\n";
|
|||
/* get a handle on the message resource for a subsection */ |
|||
$section = mailparse_msg_get_part($mime, $st); |
|||
/* get content-type, encoding and header information for that section */ |
|||
$info = mailparse_msg_get_part_data($section); |
|||
echo "\n"; |
|||
echo "<td>" . $info["content-type"] . "</td>\n"; |
|||
echo "<td>" . $info["content-disposition"] . "</td>\n"; |
|||
echo "<td>" . $info["disposition-filename"] . "</td>\n"; |
|||
echo "<td>" . $info["charset"] . "</td>\n"; |
|||
echo "</tr>"; |
|||
} |
|||
echo "</table>"; |
|||
|
|||
/* if we were called to display a part, do so now */ |
|||
if ($showpart) { |
|||
/* get a handle on the message resource for the desired part */ |
|||
$sec = mailparse_msg_get_part($mime, $showpart); |
|||
|
|||
echo "<table border=1><tr><th>Section $showpart</th></tr><tr><td>"; |
|||
ob_start(); |
|||
/* extract the part from the message file and dump it to the output buffer |
|||
* */ |
|||
mailparse_msg_extract_part_file($sec, $filename); |
|||
$contents = ob_get_contents(); |
|||
ob_end_clean(); |
|||
/* quote the message for safe display in a browser */ |
|||
echo nl2br(htmlentities($contents)) . "</td></tr></table>";; |
|||
} |
|||
?>
|
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue