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)
{
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();
}
/* }}} */
-/* {{{ 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)
{
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);
-
- if (type == php_file_le_stream()) {
- php_stream *stream = (php_stream*)what;
+ stream = zend_fetch_resource(file TSRMLS_CC, -1, "File-Handle", NULL, 1, php_file_le_stream());
+ ZEND_VERIFY_RESOURCE(stream);
- 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)
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;
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;
}
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);
}
/* }}} */
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)
+/* 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)
{
- zval **arg, **bodystr, **cbfunc;
- struct rfc2045 *rfcbuf;
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);
- 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);
+ start_pos = decode & MAILPARSE_DECODE_NOHEADERS ? body : start;
- if (Z_TYPE_PP(arg) == IS_RESOURCE && Z_LVAL_PP(arg) == 0) {
- RETURN_FALSE;
+ 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;
}
- mailparse_fetch_rfc2045_resource(rfcbuf, arg);
-
-
- rfc2045_mimepos(rfcbuf, &start, &end, &body, &nlines, &nbodylines);
+
+ filebuf = emalloc(MAILPARSE_BUFSIZ);
+
+ while (start_pos < end)
+ {
+ size_t n = MAILPARSE_BUFSIZ - 1;
- 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 ((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;
+ }
- if (Z_STRLEN_PP(bodystr) < end)
- end = Z_STRLEN_PP(bodystr);
- else
- end = end-body;
+ filebuf[n] = '\0';
+
+ if (decode & MAILPARSE_DECODE_8BIT)
+ rfc2045_cdecode(rfcbuf, filebuf, n);
+ else
+ callback(filebuf, n, callbackdata);
- rfc2045_cdecode(rfcbuf, Z_STRVAL_PP(bodystr) + body, end);
- rfc2045_cdecode_end(rfcbuf);
+ start_pos += n;
+ }
+ ret = SUCCESS;
- RETURN_TRUE;
+cleanup:
+ if (decode & MAILPARSE_DECODE_8BIT)
+ rfc2045_cdecode_end(rfcbuf);
+ if (filebuf)
+ efree(filebuf);
+
+ return ret;
}
-/* }}} */
-/* {{{ 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)
+static void mailparse_do_extract(INTERNAL_FUNCTION_PARAMETERS, int decode, int isfile)
{
- zval **arg, **filename, **cbfunc;
+ zval *part, *filename, *callbackfunc = NULL;
struct rfc2045 *rfcbuf;
- char *filebuf = NULL;
- FILE *fp = NULL;
- off_t start, end, body;
- off_t nlines;
- off_t nbodylines;
+ php_stream *srcstream = NULL, *deststream = NULL;
+ rfc2045_decode_user_func_t cbfunc = NULL;
+ void *cbdata = NULL;
+ int close_src_stream = 0;
- 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;
+ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz|z", &part, &filename, &callbackfunc)) {
+ RETURN_FALSE;
}
- convert_to_string_ex(filename);
- if (Z_TYPE_PP(arg) == IS_RESOURCE && Z_LVAL_PP(arg) == 0) {
+ if (Z_TYPE_P(part) == IS_RESOURCE && Z_LVAL_P(part) == 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);
+ mailparse_fetch_rfc2045_resource(rfcbuf, &part);
- 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);
+ /* 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;
+ }
- /* 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));
+ if (srcstream == NULL) {
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;
+
+ 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;
}
- filebuf = emalloc(MAILPARSE_BUFSIZ);
+ RETVAL_FALSE;
+
+ if (SUCCESS == extract_part(rfcbuf, decode, srcstream, cbdata, cbfunc TSRMLS_CC)) {
- while (body < end)
- {
- size_t n = MAILPARSE_BUFSIZ;
+ 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);
- 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;
+ } else {
+ RETVAL_TRUE;
}
- rfc2045_cdecode(rfcbuf, filebuf, n);
- body += n;
}
- RETVAL_TRUE;
-cleanup:
- rfc2045_cdecode_end(rfcbuf);
- if (fp)
- fclose(fp);
- if (filebuf)
- efree(filebuf);
+ 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)
+{
+ 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);
+}
+/* }}} */
+
+/* {{{ 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)
+{
+ mailparse_do_extract(INTERNAL_FUNCTION_PARAM_PASSTHRU, MAILPARSE_DECODE_8BIT | MAILPARSE_DECODE_NOHEADERS, 1);
}
/* }}} */
#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)
}
/* }}} */
+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