Browse Source

Imported mailparse extension

@- New mailparse extension for parsing and manipulating MIME mail (Wez)
experimental/pre_new_hash_func
Wez Furlong 25 years ago
parent
commit
6468f8b492
  1. 2
      ext/mailparse/CREDITS
  2. 5
      ext/mailparse/EXPERIMENTAL
  3. 15
      ext/mailparse/Makefile.in
  4. 79
      ext/mailparse/README
  5. 13
      ext/mailparse/config.m4
  6. 7
      ext/mailparse/libs.mk
  7. 799
      ext/mailparse/mailparse.c
  8. 161
      ext/mailparse/mailparse_rfc822.h
  9. 90
      ext/mailparse/php_mailparse.h
  10. 1168
      ext/mailparse/rfc2045.c
  11. 202
      ext/mailparse/rfc2045.h
  12. 123
      ext/mailparse/rfc2045acchk.c
  13. 99
      ext/mailparse/rfc2045acprep.c
  14. 130
      ext/mailparse/rfc2045appendurl.c
  15. 83
      ext/mailparse/rfc2045cdecode.c
  16. 40
      ext/mailparse/rfc2045decode.c
  17. 47
      ext/mailparse/rfc2045find.c
  18. 716
      ext/mailparse/rfc822.c
  19. 99
      ext/mailparse/rfc822_getaddr.c
  20. 92
      ext/mailparse/rfc822_getaddrs.c
  21. 12
      ext/mailparse/tests/001.phpt
  22. 22
      ext/mailparse/tests/002.phpt
  23. 53
      ext/mailparse/try.php

2
ext/mailparse/CREDITS

@ -0,0 +1,2 @@
Mailparse MIME parsing and manipulation functions
Wez Furlong

5
ext/mailparse/EXPERIMENTAL

@ -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!

15
ext/mailparse/Makefile.in

@ -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

79
ext/mailparse/README

@ -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

13
ext/mailparse/config.m4

@ -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

7
ext/mailparse/libs.mk

@ -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)

799
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
*/

161
ext/mailparse/mailparse_rfc822.h

@ -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

90
ext/mailparse/php_mailparse.h

@ -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

202
ext/mailparse/rfc2045.h

@ -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

123
ext/mailparse/rfc2045acchk.c

@ -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);
}

99
ext/mailparse/rfc2045acprep.c

@ -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)
{
}

130
ext/mailparse/rfc2045appendurl.c

@ -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
*/

83
ext/mailparse/rfc2045cdecode.c

@ -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);
}

40
ext/mailparse/rfc2045decode.c

@ -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);
}

47
ext/mailparse/rfc2045find.c

@ -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);
}

716
ext/mailparse/rfc822.c

@ -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);
}

99
ext/mailparse/rfc822_getaddr.c

@ -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);
}

92
ext/mailparse/rfc822_getaddrs.c

@ -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);
}

12
ext/mailparse/tests/001.phpt

@ -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

22
ext/mailparse/tests/002.phpt

@ -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.

53
ext/mailparse/try.php

@ -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>";;
}
?>
Loading…
Cancel
Save