main/streams.c

This commit is contained in:
Wez Furlong 2002-04-02 16:46:33 +00:00
parent abc5a2cacb
commit a0f165a5cb
8 changed files with 566 additions and 167 deletions

View File

@ -52,6 +52,7 @@ function_entry mailparse_functions[] = {
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_extract_whole_part_file, NULL)
PHP_FE(mailparse_msg_create, NULL)
PHP_FE(mailparse_msg_free, NULL)
@ -124,6 +125,7 @@ PHP_MINFO_FUNCTION(mailparse)
{
php_info_print_table_start();
php_info_print_table_header(2, "mailparse support", "enabled");
php_info_print_table_row(2, "Revision", "$Revision$");
php_info_print_table_end();
DISPLAY_INI_ENTRIES();
@ -313,7 +315,7 @@ PHP_FUNCTION(mailparse_rfc822_parse_addresses)
}
/* }}} */
/* {{{ proto int mailparse_determine_best_xfer_encoding(resource fp)
/* {{{ proto string mailparse_determine_best_xfer_encoding(resource fp)
Figures 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)
{
@ -322,41 +324,36 @@ PHP_FUNCTION(mailparse_determine_best_xfer_encoding)
int linelen = 0;
int c;
enum mbfl_no_encoding bestenc = mbfl_no_encoding_7bit;
void * what;
int type;
php_stream *stream;
char * name;
if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &file) == FAILURE) {
WRONG_PARAM_COUNT;
}
what = zend_fetch_resource(file TSRMLS_CC, -1, "File-Handle", &type, 1, php_file_le_stream());
ZEND_VERIFY_RESOURCE(what);
stream = zend_fetch_resource(file TSRMLS_CC, -1, "File-Handle", NULL, 1, php_file_le_stream());
ZEND_VERIFY_RESOURCE(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;
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 (longline)
bestenc = mbfl_no_encoding_qprint;
php_stream_rewind(stream);
if (c == '\n')
linelen = 0;
else if (++linelen > 200)
longline = 1;
}
if (longline)
bestenc = mbfl_no_encoding_qprint;
php_stream_rewind(stream);
name = (char *)mbfl_no2preferred_mime_name(bestenc);
if (name)
@ -510,7 +507,7 @@ PHP_FUNCTION(mailparse_msg_parse_file)
zval **filename;
struct rfc2045 *rfcbuf;
char *filebuf;
FILE *fp;
php_stream *stream;
if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &filename) == FAILURE) {
WRONG_PARAM_COUNT;
@ -519,9 +516,8 @@ PHP_FUNCTION(mailparse_msg_parse_file)
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(TSRMLS_C), Z_STRVAL_PP(filename));
stream = php_stream_open_wrapper(Z_STRVAL_PP(filename), "rb", ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL);
if (stream == NULL) {
RETURN_FALSE;
}
@ -531,14 +527,14 @@ PHP_FUNCTION(mailparse_msg_parse_file)
if (rfcbuf) {
ZEND_REGISTER_RESOURCE(return_value, rfcbuf, le_rfc2045);
while(!feof(fp)) {
int got = fread(filebuf, sizeof(char), MAILPARSE_BUFSIZ, fp);
while(!php_stream_eof(stream)) {
int got = php_stream_read(stream, filebuf, MAILPARSE_BUFSIZ);
if (got > 0) {
rfc2045_parse(rfcbuf, filebuf, got);
}
}
fclose(fp);
}
php_stream_close(stream);
efree(filebuf);
}
/* }}} */
@ -661,56 +657,170 @@ static int extract_callback_stdout(const char *p, size_t n, void *ptr)
return 0;
}
/* callback for decoding to a stream */
static int extract_callback_stream(const char *p, size_t n, void *ptr)
{
TSRMLS_FETCH();
php_stream_write((php_stream*)ptr, p, n);
return 0;
}
#define MAILPARSE_DECODE_NONE 0 /* include headers and leave section untouched */
#define MAILPARSE_DECODE_8BIT 1 /* decode body into 8-bit */
#define MAILPARSE_DECODE_NOHEADERS 2 /* don't include the headers */
static int extract_part(struct rfc2045 *rfcbuf, int decode, php_stream *src, void *callbackdata,
rfc2045_decode_user_func_t callback TSRMLS_DC)
{
off_t start, end, body;
off_t nlines;
off_t nbodylines;
off_t start_pos;
char *filebuf = NULL;
int ret = FAILURE;
/* figure out where the message part starts/ends */
rfc2045_mimepos(rfcbuf, &start, &end, &body, &nlines, &nbodylines);
start_pos = decode & MAILPARSE_DECODE_NOHEADERS ? body : start;
if (decode & MAILPARSE_DECODE_8BIT)
rfc2045_cdecode_start(rfcbuf, callback, callbackdata);
if (php_stream_seek(src, start_pos, SEEK_SET) == -1) {
zend_error(E_WARNING, "%s(): unable to seek to section start", get_active_function_name(TSRMLS_C));
goto cleanup;
}
filebuf = emalloc(MAILPARSE_BUFSIZ);
while (start_pos < end)
{
size_t n = MAILPARSE_BUFSIZ - 1;
if ((off_t)n > end - start_pos)
n = end - start_pos;
n = php_stream_read(src, filebuf, n);
if (n == 0)
{
zend_error(E_WARNING, "%s(): error reading from file at offset %d", get_active_function_name(TSRMLS_C), start_pos);
goto cleanup;
}
filebuf[n] = '\0';
if (decode & MAILPARSE_DECODE_8BIT)
rfc2045_cdecode(rfcbuf, filebuf, n);
else
callback(filebuf, n, callbackdata);
start_pos += n;
}
ret = SUCCESS;
cleanup:
if (decode & MAILPARSE_DECODE_8BIT)
rfc2045_cdecode_end(rfcbuf);
if (filebuf)
efree(filebuf);
return ret;
}
static void mailparse_do_extract(INTERNAL_FUNCTION_PARAMETERS, int decode, int isfile)
{
zval *part, *filename, *callbackfunc = NULL;
struct rfc2045 *rfcbuf;
php_stream *srcstream = NULL, *deststream = NULL;
rfc2045_decode_user_func_t cbfunc = NULL;
void *cbdata = NULL;
int close_src_stream = 0;
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz|z", &part, &filename, &callbackfunc)) {
RETURN_FALSE;
}
if (Z_TYPE_P(part) == IS_RESOURCE && Z_LVAL_P(part) == 0) {
RETURN_FALSE;
}
mailparse_fetch_rfc2045_resource(rfcbuf, &part);
/* filename can be a filename or a stream */
if (Z_TYPE_P(filename) == IS_RESOURCE) {
srcstream = (php_stream*)zend_fetch_resource(&filename TSRMLS_CC, -1, "File-Handle", NULL, 1, php_file_le_stream());
ZEND_VERIFY_RESOURCE(srcstream);
} else if (isfile) {
convert_to_string_ex(&filename);
srcstream = php_stream_open_wrapper(Z_STRVAL_P(filename), "rb", ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL);
} else {
/* filename is the actual data */
srcstream = php_stream_memory_open(TEMP_STREAM_READONLY, Z_STRVAL_P(filename), Z_STRLEN_P(filename));
close_src_stream = 1;
}
if (srcstream == NULL) {
RETURN_FALSE;
}
if (callbackfunc != NULL) {
if (Z_TYPE_P(callbackfunc) == IS_NULL) {
cbfunc = extract_callback_stream;
cbdata = deststream = php_stream_memory_create(TEMP_STREAM_DEFAULT);
} else if (Z_TYPE_P(callbackfunc) == IS_RESOURCE) {
deststream = (php_stream*)zend_fetch_resource(&callbackfunc TSRMLS_CC, -1, "File-Handle", NULL, 1, php_file_le_stream());
ZEND_VERIFY_RESOURCE(deststream);
cbfunc = extract_callback_stream;
cbdata = deststream;
deststream = NULL; /* don't free this one */
} else {
if (Z_TYPE_P(callbackfunc) != IS_ARRAY)
convert_to_string_ex(&callbackfunc);
cbfunc = (rfc2045_decode_user_func_t)&extract_callback_user_func;
cbdata = callbackfunc;
}
} else {
cbfunc = extract_callback_stdout;
cbdata = NULL;
}
RETVAL_FALSE;
if (SUCCESS == extract_part(rfcbuf, decode, srcstream, cbdata, cbfunc TSRMLS_CC)) {
if (deststream != NULL) {
/* return it's contents as a string */
char *membuf = NULL;
size_t memlen = 0;
membuf = php_stream_memory_get_buffer(deststream, &memlen);
RETVAL_STRINGL(membuf, memlen, 1);
} else {
RETVAL_TRUE;
}
}
if (deststream)
php_stream_close(deststream);
if (close_src_stream && srcstream)
php_stream_close(srcstream);
}
/* {{{ 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 (Z_TYPE_PP(arg) == IS_RESOURCE && Z_LVAL_PP(arg) == 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;
mailparse_do_extract(INTERNAL_FUNCTION_PARAM_PASSTHRU, MAILPARSE_DECODE_8BIT | MAILPARSE_DECODE_NOHEADERS, 0);
}
/* }}} */
/* {{{ proto string mailparse_msg_extract_whole_part_file(resource rfc2045, string filename [, string callbackfunc])
Extracts a message section including headers without decoding the transfer encoding */
PHP_FUNCTION(mailparse_msg_extract_whole_part_file)
{
mailparse_do_extract(INTERNAL_FUNCTION_PARAM_PASSTHRU, MAILPARSE_DECODE_NONE, 1);
}
/* }}} */
@ -718,83 +828,7 @@ PHP_FUNCTION(mailparse_msg_extract_part)
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 (Z_TYPE_PP(arg) == IS_RESOURCE && Z_LVAL_PP(arg) == 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(TSRMLS_C), 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(TSRMLS_C));
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(TSRMLS_C), 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);
mailparse_do_extract(INTERNAL_FUNCTION_PARAM_PASSTHRU, MAILPARSE_DECODE_8BIT | MAILPARSE_DECODE_NOHEADERS, 1);
}
/* }}} */

View File

@ -43,6 +43,7 @@ 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_extract_whole_part_file);
PHP_FUNCTION(mailparse_msg_create);
PHP_FUNCTION(mailparse_msg_free);

View File

@ -6,10 +6,7 @@
* 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";
$filename = "yourmessage.txt";
/* parse the message and return a mime message resource */
$mime = mailparse_msg_parse_file($filename);

View File

@ -377,6 +377,7 @@ function_entry basic_functions[] = {
PHP_FE(escapeshellarg, NULL)
PHP_FE(passthru, second_arg_force_ref)
PHP_FE(shell_exec, NULL)
PHP_FE(proc_open, third_arg_force_ref)
PHP_FE(rand, NULL)
PHP_FE(srand, NULL)
@ -977,6 +978,7 @@ PHP_MINIT_FUNCTION(basic)
PHP_MINIT(array) (INIT_FUNC_ARGS_PASSTHRU);
PHP_MINIT(assert) (INIT_FUNC_ARGS_PASSTHRU);
PHP_MINIT(url_scanner_ex) (INIT_FUNC_ARGS_PASSTHRU);
PHP_MINIT(proc_open) (INIT_FUNC_ARGS_PASSTHRU);
if (PG(allow_url_fopen)) {

View File

@ -35,6 +35,16 @@
#include <signal.h>
#endif
#if HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#if HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif
#if HAVE_FCNTL_H
#include <fcntl.h>
#endif
/* {{{ php_Exec
* If type==0, only last line of output is returned (exec)
* If type==1, all lines will be printed and last lined returned (system)
@ -477,6 +487,352 @@ PHP_FUNCTION(shell_exec)
}
/* }}} */
static int le_proc_open;
static void proc_open_rsrc_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
{
#if HAVE_SYS_WAIT
int wstatus;
pid_t child, wait_pid;
child = (pid_t)rsrc->ptr;
do {
wait_pid = waitpid(child, &wstatus, 0);
} while (wait_pid == -1 && errno = EINTR);
if (wait_pid == -1)
FG(pclose_ret) = -1;
else
FG(pclose_ret) = wstatus;
#else
FG(pclose_ret) = -1;
#endif
}
PHP_MINIT_FUNCTION(proc_open)
{
le_proc_open = zend_register_list_destructors_ex(proc_open_rsrc_dtor, NULL, "proc-opened-process", module_number);
return SUCCESS;
}
/* {{{ proto resource proc_open(string command, array descriptorspec, array &pipes)
Run a process with more control over it's file descriptors */
PHP_FUNCTION(proc_open)
{
#define MAX_DESCRIPTORS 16
#define DESC_PIPE 1
#define DESC_FILE 2
#define DESC_PARENT_MODE_WRITE 8
#ifndef O_BINARY
#define O_BINARY 0
#endif
#ifdef PHP_WIN32
/* NOINHERIT is actually required for pipes to work correctly when inherited;
* see the win32 specific dup call a little further down */
#define pipe(handles) _pipe((handles), 512, _O_BINARY | _O_NOINHERIT)
#endif
char *command;
long command_len;
zval *descriptorspec;
zval *pipes;
struct {
int index; /* desired fd number in child process */
int parentend, childend; /* fds for pipes in parent/child */
int mode;
} descriptors[MAX_DESCRIPTORS];
int ndesc = 0;
int i;
zval **descitem = NULL;
HashPosition pos;
#ifdef PHP_WIN32
PROCESS_INFORMATION pi;
STARTUPINFO si;
BOOL newprocok;
HANDLE child;
#else
pid_t child;
#endif
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "saz/", &command,
&command_len, &descriptorspec, &pipes) == FAILURE) {
RETURN_FALSE;
}
memset(descriptors, 0, sizeof(descriptors));
/* walk the descriptor spec and set up files/pipes */
zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(descriptorspec), &pos);
while (zend_hash_get_current_data_ex(Z_ARRVAL_P(descriptorspec), (void **)&descitem, &pos) == SUCCESS) {
char *str_index;
ulong nindex;
zval **ztype;
str_index = NULL;
zend_hash_get_current_key_ex(Z_ARRVAL_P(descriptorspec), &str_index, NULL, &nindex, 0, &pos);
if (str_index) {
zend_error(E_WARNING, "%s(): descriptor spec must be an integer indexed array",
get_active_function_name(TSRMLS_C));
RETURN_FALSE;
}
descriptors[ndesc].index = nindex;
if (Z_TYPE_PP(descitem) == IS_RESOURCE) {
/* should be a stream - try and dup the descriptor */
php_stream *stream;
int fd;
ZEND_FETCH_RESOURCE(stream, php_stream *, descitem, -1, "File-Handle", php_file_le_stream());
if (FAILURE == php_stream_cast(stream, PHP_STREAM_AS_FD, (void **)&fd, REPORT_ERRORS)) {
RETURN_FALSE;
}
descriptors[ndesc].childend = dup(fd);
if (descriptors[ndesc].childend < 0) {
zend_error(E_WARNING, "%s(): unable to dup File-Handle for descriptor %d - %s",
get_active_function_name(TSRMLS_C), nindex, strerror(errno));
}
descriptors[ndesc].mode = DESC_FILE;
} else if (Z_TYPE_PP(descitem) != IS_ARRAY) {
zend_error(E_WARNING, "%s(): descriptor item must be either an array or a File-Handle",
get_active_function_name(TSRMLS_C));
RETURN_FALSE;
} else {
zend_hash_index_find(Z_ARRVAL_PP(descitem), 0, (void **)&ztype);
convert_to_string_ex(ztype);
if (strcmp(Z_STRVAL_PP(ztype), "pipe") == 0) {
int newpipe[2];
zval **zmode;
descriptors[ndesc].mode = DESC_PIPE;
if (0 != pipe(newpipe)) {
zend_error(E_WARNING, "%s(): unable to create pipe %s",
get_active_function_name(TSRMLS_C), strerror(errno));
RETURN_FALSE;
}
zend_hash_index_find(Z_ARRVAL_PP(descitem), 1, (void **)&zmode);
convert_to_string_ex(zmode);
if (strcmp(Z_STRVAL_PP(zmode), "w") != 0) {
descriptors[ndesc].parentend = newpipe[1];
descriptors[ndesc].childend = newpipe[0];
descriptors[ndesc].mode |= DESC_PARENT_MODE_WRITE;
} else {
descriptors[ndesc].parentend = newpipe[0];
descriptors[ndesc].childend = newpipe[1];
}
#ifdef PHP_WIN32
{ /* this magic is needed to ensure that pipes work
* correctly in the child */
int tmpfd = dup(descriptors[ndesc].childend);
close(descriptors[ndesc].childend);
descriptors[ndesc].childend = tmpfd;
}
#endif
} else if (strcmp(Z_STRVAL_PP(ztype), "file") == 0) {
zval **zfile, **zmode;
int open_flags = 0;
const struct {
char *modestring;
int flags;
} modemap[] = {
{ "r", O_RDONLY },
{ "rb", O_RDONLY | O_BINARY },
{ "r+", O_RDWR },
{ "rb+", O_RDWR | O_BINARY },
{ "w", O_WRONLY | O_CREAT | O_TRUNC },
{ "wb", O_WRONLY | O_CREAT | O_TRUNC | O_BINARY},
{ "w+", O_RDWR | O_CREAT | O_TRUNC },
{ "wb+", O_RDWR | O_CREAT | O_TRUNC | O_BINARY},
{ "a", O_WRONLY | O_CREAT | O_APPEND },
{ "ab", O_WRONLY | O_CREAT | O_APPEND | O_BINARY },
{ "a+", O_RDWR | O_CREAT | O_APPEND },
{ "ab+", O_RDWR | O_CREAT | O_APPEND | O_BINARY},
{ NULL, 0 }
};
descriptors[ndesc].mode = DESC_FILE;
zend_hash_index_find(Z_ARRVAL_PP(descitem), 1, (void **)&zfile);
convert_to_string_ex(zfile);
zend_hash_index_find(Z_ARRVAL_PP(descitem), 2, (void **)&zmode);
convert_to_string_ex(zmode);
for (i = 0; modemap[i].modestring != NULL; i++) {
if (strcmp(modemap[i].modestring, Z_STRVAL_PP(zmode)) == 0) {
open_flags = modemap[i].flags;
break;
}
}
descriptors[ndesc].childend = VCWD_OPEN_MODE(Z_STRVAL_PP(zfile), open_flags, 0644);
if (descriptors[ndesc].childend < 0) {
if (PG(allow_url_fopen)) {
/* try a wrapper */
int fd;
php_stream *stream;
size_t old_size = FG(def_chunk_size);
FG(def_chunk_size) = 1;
stream = php_stream_open_wrapper(Z_STRVAL_PP(zfile), Z_STRVAL_PP(zmode),
ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL);
FG(def_chunk_size) = old_size;
if (stream == NULL)
RETURN_FALSE;
/* force into an fd */
if (FAILURE == php_stream_cast(stream, PHP_STREAM_CAST_RELEASE|PHP_STREAM_AS_FD, (void **)&fd, REPORT_ERRORS))
RETURN_FALSE;
descriptors[ndesc].childend = fd;
} else {
zend_error(E_WARNING, "%s(): unable to open %s with mode %s",
get_active_function_name(TSRMLS_C),
Z_STRVAL_PP(zfile), Z_STRVAL_PP(zmode));
RETURN_FALSE;
}
}
} else {
zend_error(E_WARNING, "%s(): %s is not a valid descriptor spec/mode",
get_active_function_name(TSRMLS_C), Z_STRVAL_PP(ztype));
RETURN_FALSE;
}
}
zend_hash_move_forward_ex(Z_ARRVAL_P(descriptorspec), &pos);
if (++ndesc == MAX_DESCRIPTORS)
break;
}
#ifdef PHP_WIN32
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
/* redirect stdin/stdout/stderr if requested */
for (i = 0; i < ndesc; i++) {
switch(descriptors[i].index) {
case 0:
si.hStdInput = (HANDLE)_get_osfhandle(descriptors[i].childend);
si.dwFlags |= STARTF_USESTDHANDLES;
break;
case 1:
si.hStdOutput = (HANDLE)_get_osfhandle(descriptors[i].childend);
si.dwFlags |= STARTF_USESTDHANDLES;
break;
case 2:
si.hStdError = (HANDLE)_get_osfhandle(descriptors[i].childend);
si.dwFlags |= STARTF_USESTDHANDLES;
break;
}
}
memset(&pi, 0, sizeof(pi));
newprocok = CreateProcess(NULL, command, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);
if (FALSE == newprocok) {
zend_error(E_WARNING, "%s(): CreateProcess failed", get_active_function_name(TSRMLS_C));
RETURN_FALSE;
}
child = pi.hProcess;
#else
/* the unix way */
child = fork();
if (child == 0) {
/* this is the child process */
/* close those descriptors that we just opened for the parent stuff,
* dup new descriptors into required descriptors and close the original
* cruft */
for (i = 0; i < ndesc; i++) {
switch (descriptors[i].mode & ~DESC_PARENT_MODE_WRITE) {
case DESC_PIPE:
close(descriptors[i].parentend);
break;
}
if (dup2(descriptors[i].childend, descriptors[i].index) < 0)
perror("dup2");
if (descriptors[i].childend != descriptors[i].index)
close(descriptors[i].childend);
}
execl("/bin/sh", "sh", "-c", command, NULL);
_exit(127);
} else if (child < 0) {
/* failed to fork() */
/* clean up all the descriptors */
for (i = 0; i < ndesc; i++) {
close(descriptors[i].childend);
close(descriptors[i].parentend);
}
zend_error(E_WARNING, "%s(): fork failed - %s",
get_active_function_name(TSRMLS_C),
strerror(errno)
);
RETURN_FALSE;
}
#endif
/* we forked/spawned and this is the parent */
array_init(pipes);
/* clean up all the child ends and then open streams on the parent
* ends, where appropriate */
for (i = 0; i < ndesc; i++) {
char *stdiomode;
FILE *fp;
php_stream *stream;
close(descriptors[i].childend);
switch (descriptors[i].mode & ~DESC_PARENT_MODE_WRITE) {
case DESC_PIPE:
stdiomode = descriptors[i].mode & DESC_PARENT_MODE_WRITE ? "w" : "r";
fp = fdopen(descriptors[i].parentend, stdiomode);
if (fp) {
stream = php_stream_fopen_from_file(fp, stdiomode);
if (stream) {
zval *retfp;
MAKE_STD_ZVAL(retfp);
php_stream_to_zval(stream, retfp);
add_index_zval(pipes, descriptors[i].index, retfp);
}
}
break;
}
}
ZEND_REGISTER_RESOURCE(return_value, child, le_proc_open);
}
/* }}} */
/*
* Local variables:
* tab-width: 4

View File

@ -27,6 +27,8 @@ PHP_FUNCTION(escapeshellcmd);
PHP_FUNCTION(escapeshellarg);
PHP_FUNCTION(passthru);
PHP_FUNCTION(shell_exec);
PHP_FUNCTION(proc_open);
PHP_MINIT_FUNCTION(proc_open);
char *php_escape_shell_cmd(char *);
char *php_escape_shell_arg(char *);

View File

@ -120,7 +120,7 @@ static int php_stream_memory_close(php_stream *stream, int close_handle TSRMLS_D
ms = stream->abstract;
assert(ms != NULL);
if (ms->data) {
if (ms->data && close_handle && ms->mode != TEMP_STREAM_READONLY) {
efree(ms->data);
}
efree(ms);
@ -262,13 +262,19 @@ PHPAPI php_stream *_php_stream_memory_open(int mode, char *buf, size_t length ST
{ php_stream *stream;
php_stream_memory_data *ms;
if ((stream = php_stream_memory_create_rel(TEMP_STREAM_DEFAULT)) != NULL) {
if (length) {
assert(buf != NULL);
php_stream_write(stream, buf, length);
}
if ((stream = php_stream_memory_create_rel(mode)) != NULL) {
ms = stream->abstract;
ms->mode = mode;
if (mode == TEMP_STREAM_READONLY) {
/* use the buffer directly */
ms->data = buf;
ms->fsize = length;
} else {
if (length) {
assert(buf != NULL);
php_stream_write(stream, buf, length);
}
}
}
return stream;
}

View File

@ -716,6 +716,7 @@ static int php_stdiop_cast(php_stream *stream, int castas, void **ret TSRMLS_DC)
return FAILURE;
}
if (ret) {
fflush(data->file);
*ret = (void*)fd;
}
return SUCCESS;