cvs: php4 /ext/bz2 bz2.c php_bz2.h /ext/standard Makefile.frag basic_functions.c file.c file.h ftp_fopen_wrapper.c http_fopen_wrapper.c
php_fopen_wrapper.c php_fopen_wrappers.h /ext/zlib php_zlib.h zlib.c zlib_fopen_wrapper.c /main main.c network.c php_streams.h streams.c
user_streams.c
| From: | Wez Furlong | Date: | Wed, 10 Apr 2002 22:42:31 +0000 |
| Subject: | cvs: php4 /ext/bz2 bz2.c php_bz2.h /ext/standard Makefile.frag basic_functions.c file.c file.h ftp_fopen_wrapper.c http_fopen_wrapper.c php_fopen_wrapper.c php_fopen_wrappers.h /ext/zlib php_zlib.h zlib.c zlib_fopen_wrapper.c /main main.c network.c php_streams.h streams.c user_streams.c |
||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-11021@lists.php.net to get a copy of this message | ||
wez Wed Apr 10 18:42:31 2002 EDT
Modified files:
/php4/ext/bz2 bz2.c php_bz2.h
/php4/ext/standard Makefile.frag basic_functions.c file.c file.h
ftp_fopen_wrapper.c http_fopen_wrapper.c
php_fopen_wrapper.c php_fopen_wrappers.h
/php4/ext/zlib php_zlib.h zlib.c zlib_fopen_wrapper.c
/php4/main main.c network.c php_streams.h streams.c user_streams.c
Log:
Implement stream context and status notification system.
Bump the BC for zlib notice to a warning
# See my RFC to php-dev a few days ago
Index: php4/ext/bz2/bz2.c diff -u php4/ext/bz2/bz2.c:1.46 php4/ext/bz2/bz2.c:1.47 --- php4/ext/bz2/bz2.c:1.46 Fri Apr 5 06:51:33 2002 +++ php4/ext/bz2/bz2.c Wed Apr 10 18:42:13 2002 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: bz2.c,v 1.46 2002/04/05 11:51:33 zeev Exp $ */ +/* $Id: bz2.c,v 1.47 2002/04/10 22:42:13 wez Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -156,7 +156,8 @@ char *path, char *mode, int options, - char **opened_path + char **opened_path, + php_stream_context *context STREAMS_DC TSRMLS_DC) { php_stream *retstream = NULL, *stream = NULL; Index: php4/ext/bz2/php_bz2.h diff -u php4/ext/bz2/php_bz2.h:1.12 php4/ext/bz2/php_bz2.h:1.13 --- php4/ext/bz2/php_bz2.h:1.12 Fri Apr 5 08:15:43 2002 +++ php4/ext/bz2/php_bz2.h Wed Apr 10 18:42:16 2002 @@ -52,11 +52,11 @@ # define PHP_BZ2_API #endif -PHP_BZ2_API php_stream *_php_stream_bz2open(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path STREAMS_DC TSRMLS_DC); -PHP_BZ2_API php_stream *_php_stream_bz2open_from_BZFILE(BZFILE *bz, char *mode, php_stream *innerstream STREAMS_DC TSRMLS_DC); +PHP_BZ2_API PHPAPI php_stream *_php_stream_bz2open(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); +PHP_BZ2_API PHPAPI php_stream *_php_stream_bz2open_from_BZFILE(BZFILE *bz, char *mode, php_stream *innerstream STREAMS_DC TSRMLS_DC); #define php_stream_bz2open_from_BZFILE(bz, mode, innerstream) _php_stream_bz2open_from_BZFILE((bz), (mode), (innerstream) STREAMS_CC TSRMLS_CC) -#define php_stream_bz2open(wrapper, path, mode, options, opened_path) _php_stream_bz2open((wrapper), (path), (mode), (options), (opened_path) STREAMS_CC TSRMLS_CC) +#define php_stream_bz2open(wrapper, path, mode, options, opened_path) _php_stream_bz2open((wrapper), (path), (mode), (options), (opened_path), NULL STREAMS_CC TSRMLS_CC) php_stream_ops php_stream_bz2io_ops; #define PHP_STREAM_IS_BZIP2 &php_stream_bz2io_ops Index: php4/ext/standard/Makefile.frag diff -u php4/ext/standard/Makefile.frag:1.1 php4/ext/standard/Makefile.frag:1.2 --- php4/ext/standard/Makefile.frag:1.1 Thu Mar 7 09:19:38 2002 +++ php4/ext/standard/Makefile.frag Wed Apr 10 18:42:21 2002 @@ -6,3 +6,4 @@ $(srcdir)/url_scanner_ex.c: $(srcdir)/url_scanner_ex.re re2c -b $(srcdir)/url_scanner_ex.re > $@ + Index: php4/ext/standard/basic_functions.c diff -u php4/ext/standard/basic_functions.c:1.468 php4/ext/standard/basic_functions.c:1.469 --- php4/ext/standard/basic_functions.c:1.468 Wed Apr 3 08:39:34 2002 +++ php4/ext/standard/basic_functions.c Wed Apr 10 18:42:21 2002 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: basic_functions.c,v 1.468 2002/04/03 13:39:34 wez Exp $ */ +/* $Id: basic_functions.c,v 1.469 2002/04/10 22:42:21 wez Exp $ */ #include "php.h" #include "php_streams.h" @@ -595,6 +595,8 @@ PHP_STATIC_FE("tmpfile", php_if_tmpfile, NULL) PHP_FE(file, NULL) PHP_FE(file_get_contents, NULL) + PHP_FE(file_context_create, NULL) + PHP_FE(file_context_set_params, NULL) PHP_FE(fgetcsv, NULL) PHP_FE(flock, NULL) PHP_FE(get_meta_tags, NULL) Index: php4/ext/standard/file.c diff -u php4/ext/standard/file.c:1.223 php4/ext/standard/file.c:1.224 --- php4/ext/standard/file.c:1.223 Fri Apr 5 06:51:34 2002 +++ php4/ext/standard/file.c Wed Apr 10 18:42:22 2002 @@ -21,7 +21,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: file.c,v 1.223 2002/04/05 11:51:34 zeev Exp $ */ +/* $Id: file.c,v 1.224 2002/04/10 22:42:22 wez Exp $ */ /* Synced with php 3.0 revision 1.218 1999-06-16 [ssb] */ @@ -109,10 +109,16 @@ /* sharing globals is *evil* */ static int le_stream = FAILURE; +static int le_stream_context = FAILURE; /* }}} */ /* {{{ Module-Stuff */ +static ZEND_RSRC_DTOR_FUNC(file_context_dtor) +{ + php_stream_context_free((php_stream_context*)rsrc->ptr); +} + static void _file_stream_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) { php_stream *stream = (php_stream*)rsrc->ptr; @@ -142,6 +148,7 @@ PHP_MINIT_FUNCTION(file) { le_stream = zend_register_list_destructors_ex(_file_stream_dtor, NULL, "stream", module_number); + le_stream_context = zend_register_list_destructors_ex(file_context_dtor, NULL, "stream-context", module_number); #ifdef ZTS ts_allocate_id(&file_globals_id, sizeof(php_file_globals), (ts_allocate_ctor) file_globals_ctor, (ts_allocate_dtor) file_globals_dtor); @@ -157,6 +164,19 @@ REGISTER_LONG_CONSTANT("LOCK_UN", 3, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("LOCK_NB", 4, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_NOTIFY_CONNECT", PHP_STREAM_NOTIFY_CONNECT, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_NOTIFY_AUTH_REQUIRED", PHP_STREAM_NOTIFY_AUTH_REQUIRED, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_NOTIFY_AUTH_RESULT", PHP_STREAM_NOTIFY_AUTH_RESULT, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_NOTIFY_MIME_TYPE_IS", PHP_STREAM_NOTIFY_MIME_TYPE_IS, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_NOTIFY_FILE_SIZE_IS", PHP_STREAM_NOTIFY_FILE_SIZE_IS, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_NOTIFY_REDIRECTED", PHP_STREAM_NOTIFY_REDIRECTED, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_NOTIFY_PROGRESS", PHP_STREAM_NOTIFY_PROGRESS, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_NOTIFY_FAILURE", PHP_STREAM_NOTIFY_FAILURE, CONST_CS | CONST_PERSISTENT); + + REGISTER_LONG_CONSTANT("STREAM_NOTIFY_SEVERITY_INFO", PHP_STREAM_NOTIFY_SEVERITY_INFO, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_NOTIFY_SEVERITY_WARN", PHP_STREAM_NOTIFY_SEVERITY_WARN, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_NOTIFY_SEVERITY_ERR", PHP_STREAM_NOTIFY_SEVERITY_ERR, CONST_CS | CONST_PERSISTENT); + return SUCCESS; } @@ -562,36 +582,126 @@ } /* }}} */ -/* {{{ proto resource fopen(string filename, string mode [, bool use_include_path]) +/* {{{ file_context related functions */ +static void user_space_stream_notifier(php_stream_context *context, int notifycode, int severity, + char *xmsg, int xcode, size_t bytes_sofar, size_t bytes_max, void * ptr TSRMLS_DC) +{ + zval *callback = (zval*)context->notifier->ptr; + zval *retval = NULL; + zval zcode, zseverity, zmsg, zxcode, zsofar, zmax; + zval *ptrs[6] = {&zcode, &zseverity, &zmsg, &zxcode, &zsofar, &zmax}; + zval **args[6] = {&ptrs[0], &ptrs[1], &ptrs[2], &ptrs[3], &ptrs[4], &ptrs[5]}; + + INIT_ZVAL(zcode); + INIT_ZVAL(zseverity); + INIT_ZVAL(zmsg); + INIT_ZVAL(zxcode); + INIT_ZVAL(zsofar); + INIT_ZVAL(zmax); + + ZVAL_LONG(&zcode, notifycode); + ZVAL_LONG(&zseverity, severity); + ZVAL_LONG(&zxcode, xcode); + ZVAL_LONG(&zsofar, bytes_sofar); + ZVAL_LONG(&zmax, bytes_max); + + if (xmsg) { + ZVAL_STRING(&zmsg, xmsg, 0); + } else { + ZVAL_NULL(&zmsg); + } + + if (FAILURE == call_user_function_ex(EG(function_table), NULL, callback, &retval, 6, args, 0, NULL TSRMLS_CC)) { + zend_error(E_WARNING, "failed to call user notifier"); + } + if (retval) + zval_ptr_dtor(&retval); +} + +static int parse_context_options(php_stream_context *context, zval *params) +{ + int ret = SUCCESS; + zval **tmp; + + if (SUCCESS == zend_hash_find(Z_ARRVAL_P(params), "notification", sizeof("notification"), (void**)&tmp)) { + + if (context->notifier) { + php_stream_notification_free(context->notifier); + context->notifier = NULL; + } + + context->notifier = php_stream_notification_alloc(); + context->notifier->func = user_space_stream_notifier; + context->notifier->ptr = *tmp; + ZVAL_ADDREF(*tmp); + } + + return ret; +} +/* }}} */ + +/* {{{ proto bool file_context_set_params(resource context, array options) + Set parameters for a file context */ +PHP_FUNCTION(file_context_set_params) +{ + zval *params, *zcontext; + php_stream_context *context; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ra", &zcontext, ¶ms) == FAILURE) { + RETURN_FALSE; + } + + context = (php_stream_context*)zend_fetch_resource(&zcontext TSRMLS_CC, -1, "Stream-Context", NULL, 1, le_stream_context); + ZEND_VERIFY_RESOURCE(context); + + RETVAL_BOOL(parse_context_options(context, params) == SUCCESS); +} +/* }}} */ + +/* {{{ proto resource file_context_create([array options]) + Create a file context and optionally set parameters */ +PHP_FUNCTION(file_context_create) +{ + zval *params = NULL; + php_stream_context *context; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a", ¶ms) == FAILURE) { + RETURN_FALSE; + } + + context = php_stream_context_alloc(); + + if (params) + parse_context_options(context, params); + + ZEND_REGISTER_RESOURCE(return_value, context, le_stream_context); +} +/* }}} */ + +/* {{{ proto resource fopen(string filename, string mode [, bool use_include_path [, resource context]]) Open a file or a URL and return a file pointer */ PHP_NAMED_FUNCTION(php_if_fopen) { - zval **arg1, **arg2, **arg3; - int use_include_path = 0; + char *filename, *mode; + int filename_len, mode_len; + zend_bool use_include_path = 0; + zval *zcontext = NULL; php_stream *stream; - - switch(ZEND_NUM_ARGS()) { - case 2: - if (zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) { - WRONG_PARAM_COUNT; - } - break; - case 3: - if (zend_get_parameters_ex(3, &arg1, &arg2, &arg3) == FAILURE) { - WRONG_PARAM_COUNT; - } - convert_to_long_ex(arg3); - use_include_path = Z_LVAL_PP(arg3); - break; - default: - WRONG_PARAM_COUNT; - } - convert_to_string_ex(arg1); - convert_to_string_ex(arg2); + php_stream_context *context = NULL; - stream = php_stream_open_wrapper(Z_STRVAL_PP(arg1), Z_STRVAL_PP(arg2), + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|br", &filename, &filename_len, + &mode, &mode_len, &use_include_path, &zcontext) == FAILURE) { + RETURN_FALSE; + } + if (zcontext) { + context = (php_stream_context*)zend_fetch_resource(&zcontext TSRMLS_CC, -1, "Stream-Context", NULL, 1, le_stream_context); + ZEND_VERIFY_RESOURCE(context); + } + + stream = php_stream_open_wrapper_ex(filename, mode, use_include_path | ENFORCE_SAFE_MODE | REPORT_ERRORS, - NULL); + NULL, context); + if (stream == NULL) { RETURN_FALSE; } @@ -622,6 +732,7 @@ } /* }}} */ + /* {{{ proto resource popen(string command, string mode) Execute a command and open either a read or a write pipe to it */ Index: php4/ext/standard/file.h diff -u php4/ext/standard/file.h:1.58 php4/ext/standard/file.h:1.59 --- php4/ext/standard/file.h:1.58 Fri Apr 5 06:51:34 2002 +++ php4/ext/standard/file.h Wed Apr 10 18:42:23 2002 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: file.h,v 1.58 2002/04/05 11:51:34 zeev Exp $ */ +/* $Id: file.h,v 1.59 2002/04/10 22:42:23 wez Exp $ */ /* Synced with php 3.0 revision 1.30 1999-06-16 [ssb] */ @@ -73,6 +73,8 @@ PHP_FUNCTION(file_get_wrapper_data); PHP_FUNCTION(file_register_wrapper); +PHP_FUNCTION(file_context_create); +PHP_FUNCTION(file_context_set_params); PHP_MINIT_FUNCTION(user_streams); PHPAPI int php_set_sock_blocking(int socketd, int block); Index: php4/ext/standard/ftp_fopen_wrapper.c diff -u php4/ext/standard/ftp_fopen_wrapper.c:1.21 php4/ext/standard/ftp_fopen_wrapper.c:1.22 --- php4/ext/standard/ftp_fopen_wrapper.c:1.21 Wed Mar 27 19:48:59 2002 +++ php4/ext/standard/ftp_fopen_wrapper.c Wed Apr 10 18:42:23 2002 @@ -17,7 +17,7 @@ | Hartmut Holzgraefe <hholzgra@php.net> | +----------------------------------------------------------------------+ */ -/* $Id: ftp_fopen_wrapper.c,v 1.21 2002/03/28 00:48:59 wez Exp $ */ +/* $Id: ftp_fopen_wrapper.c,v 1.22 2002/04/10 22:42:23 wez Exp $ */ #include "php.h" #include "php_globals.h" @@ -66,16 +66,16 @@ #include "php_fopen_wrappers.h" -static int php_get_ftp_result(php_stream *stream TSRMLS_DC) -{ - char tmp_line[513]; - while (php_stream_gets(stream, tmp_line, sizeof(tmp_line)-1) && - !(isdigit((int) tmp_line[0]) && isdigit((int) tmp_line[1]) && - isdigit((int) tmp_line[2]) && tmp_line[3] == ' ')); +static inline int get_ftp_result(php_stream *stream, char *buffer, size_t buffer_size TSRMLS_DC) +{ + while (php_stream_gets(stream, buffer, buffer_size-1) && + !(isdigit((int) buffer[0]) && isdigit((int) buffer[1]) && + isdigit((int) buffer[2]) && buffer[3] == ' ')); - return strtol(tmp_line, NULL, 10); + return strtol(buffer, NULL, 10); } +#define GET_FTP_RESULT(stream) get_ftp_result((stream), tmp_line, sizeof(tmp_line) TSRMLS_CC) static int php_stream_ftp_stream_stat(php_stream_wrapper *wrapper, php_stream *stream, @@ -103,7 +103,7 @@ /* {{{ php_fopen_url_wrap_ftp */ -php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path STREAMS_DC TSRMLS_DC) +php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) { php_stream *stream=NULL; php_url *resource=NULL; @@ -113,6 +113,7 @@ int result; int i; char *tpath, *ttpath; + size_t file_size = 0; resource = php_url_parse((char *) path); if (resource == NULL || resource->path == NULL) @@ -126,10 +127,15 @@ if (stream == NULL) goto errexit; + php_stream_context_set(stream, context); + php_stream_notify_info(context, PHP_STREAM_NOTIFY_CONNECT, NULL, 0); + /* Start talking to ftp server */ - result = php_get_ftp_result(stream TSRMLS_CC); - if (result > 299 || result < 200) + result = GET_FTP_RESULT(stream); + if (result > 299 || result < 200) { + php_stream_notify_error(context, PHP_STREAM_NOTIFY_FAILURE, tmp_line, result); goto errexit; + } /* send the user name */ php_stream_write_string(stream, "USER "); @@ -142,10 +148,12 @@ php_stream_write_string(stream, "\r\n"); /* get the response */ - result = php_get_ftp_result(stream TSRMLS_CC); + result = GET_FTP_RESULT(stream); /* if a password is required, send it */ if (result >= 300 && result <= 399) { + php_stream_notify_info(context, PHP_STREAM_NOTIFY_AUTH_REQUIRED, tmp_line, 0); + php_stream_write_string(stream, "PASS "); if (resource->pass != NULL) { php_raw_url_decode(resource->pass, strlen(resource->pass)); @@ -162,14 +170,20 @@ php_stream_write_string(stream, "\r\n"); /* read the response */ - result = php_get_ftp_result(stream TSRMLS_CC); + result = GET_FTP_RESULT(stream); + + if (result > 299 || result < 200) { + php_stream_notify_error(context, PHP_STREAM_NOTIFY_AUTH_RESULT, tmp_line, result); + } else { + php_stream_notify_info(context, PHP_STREAM_NOTIFY_AUTH_RESULT, tmp_line, result); + } } if (result > 299 || result < 200) goto errexit; /* set the connection to be binary */ php_stream_write_string(stream, "TYPE I\r\n"); - result = php_get_ftp_result(stream TSRMLS_CC); + result = GET_FTP_RESULT(stream); if (result > 299 || result < 200) goto errexit; @@ -179,13 +193,22 @@ php_stream_write_string(stream, "\r\n"); /* read the response */ - result = php_get_ftp_result(stream TSRMLS_CC); + result = GET_FTP_RESULT(stream); if (mode[0] == 'r') { + char *sizestr; + /* when reading file, it must exist */ if (result > 299 || result < 200) { errno = ENOENT; goto errexit; } + + sizestr = strchr(tmp_line, ' '); + if (sizestr) { + sizestr++; + file_size = atoi(sizestr); + php_stream_notify_file_size(context, file_size, tmp_line, result); + } } else { /* when writing file, it must NOT exist */ if (result <= 299 && result >= 200) { @@ -193,25 +216,23 @@ goto errexit; } } - + /* set up the passive connection */ /* We try EPSV first, needed for IPv6 and works on some IPv4 servers */ php_stream_write_string(stream, "EPSV\r\n"); - while (php_stream_gets(stream, tmp_line, sizeof(tmp_line)-1) && - !(isdigit((int) tmp_line[0]) && isdigit((int) tmp_line[1]) && - isdigit((int) tmp_line[2]) && tmp_line[3] == ' ')); + result = GET_FTP_RESULT(stream); /* check if we got a 229 response */ - if (strncmp(tmp_line, "229", 3)) { + if (result != 229) { /* EPSV failed, let's try PASV */ php_stream_write_string(stream, "PASV\r\n"); - while (php_stream_gets(stream, tmp_line, sizeof(tmp_line)-1) && - !(isdigit((int) tmp_line[0]) && isdigit((int) tmp_line[1]) && - isdigit((int) tmp_line[2]) && tmp_line[3] == ' ')); + result = GET_FTP_RESULT(stream); + /* make sure we got a 227 response */ - if (strncmp(tmp_line, "227", 3)) + if (result != 227) goto errexit; + /* parse pasv command (129, 80, 95, 25, 13, 221) */ tpath = tmp_line; /* skip over the "227 Some message " part */ @@ -279,13 +300,20 @@ if (stream == NULL) goto errexit; + php_stream_context_set(stream, context); + php_stream_notify_progress_init(context, 0, file_size); + php_url_free(resource); return stream; errexit: php_url_free(resource); - if (stream) + if (stream) { + php_stream_notify_error(context, PHP_STREAM_NOTIFY_FAILURE, tmp_line, result); php_stream_close(stream); + } + if (tmp_line[0] != '\0') + zend_error(E_WARNING, "FTP server reports %s", tmp_line); return NULL; } /* }}} */ Index: php4/ext/standard/http_fopen_wrapper.c diff -u php4/ext/standard/http_fopen_wrapper.c:1.30 php4/ext/standard/http_fopen_wrapper.c:1.31 --- php4/ext/standard/http_fopen_wrapper.c:1.30 Wed Mar 27 19:48:59 2002 +++ php4/ext/standard/http_fopen_wrapper.c Wed Apr 10 18:42:23 2002 @@ -18,7 +18,7 @@ | Wez Furlong <wez@thebrainroom.com> | +----------------------------------------------------------------------+ */ -/* $Id: http_fopen_wrapper.c,v 1.30 2002/03/28 00:48:59 wez Exp $ */ +/* $Id: http_fopen_wrapper.c,v 1.31 2002/04/10 22:42:23 wez Exp $ */ #include "php.h" #include "php_globals.h" @@ -70,7 +70,7 @@ #define HTTP_HEADER_BLOCK_SIZE 1024 -php_stream *php_stream_url_wrap_http(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path STREAMS_DC TSRMLS_DC) +php_stream *php_stream_url_wrap_http(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) { php_stream *stream = NULL; php_url *resource = NULL; @@ -84,6 +84,8 @@ int reqok = 0; char *http_header_line = NULL; char tmp_line[128]; + size_t chunk_size, file_size = 0; + int redirected = 0; resource = php_url_parse(path); if (resource == NULL) @@ -101,6 +103,13 @@ if (stream == NULL) goto out; + /* avoid buffering issues while reading header */ + chunk_size = php_stream_sock_set_chunk_size(stream, 1 TSRMLS_CC); + + php_stream_context_set(stream, context); + + php_stream_notify_info(context, PHP_STREAM_NOTIFY_CONNECT, NULL, 0); + #if HAVE_OPENSSL_EXT if (use_ssl) { if (php_stream_sock_ssl_activate(stream, 1) == FAILURE) { @@ -146,8 +155,10 @@ tmp = php_base64_encode((unsigned char*)scratch, strlen(scratch), NULL); - if (snprintf(scratch, scratch_len, "Authorization: Basic %s\r\n", tmp) > 0) + if (snprintf(scratch, scratch_len, "Authorization: Basic %s\r\n", tmp) > 0) { php_stream_write(stream, scratch, strlen(scratch)); + php_stream_notify_info(context, PHP_STREAM_NOTIFY_AUTH_REQUIRED, NULL, 0); + } efree(tmp); tmp = NULL; @@ -179,10 +190,22 @@ if (php_stream_gets(stream, tmp_line, sizeof(tmp_line)-1) != NULL) { zval *http_response; + int response_code; MAKE_STD_ZVAL(http_response); - if (strncmp(tmp_line + 8, " 200 ", 5) == 0) + response_code = atoi(tmp_line + 9); + if (response_code == 200) { reqok = 1; + } else { + switch(response_code) { + case 403: + php_stream_notify_error(context, PHP_STREAM_NOTIFY_AUTH_RESULT, tmp_line, response_code); + break; + default: + php_stream_notify_error(context, PHP_STREAM_NOTIFY_FAILURE, tmp_line, response_code); + } + } + Z_STRLEN_P(http_response) = strlen(tmp_line); Z_STRVAL_P(http_response) = estrndup(tmp_line, Z_STRLEN_P(http_response)); if (Z_STRVAL_P(http_response)[Z_STRLEN_P(http_response)-1]=='\n') { @@ -223,8 +246,15 @@ } http_header_line_length = p-http_header_line+1; - if (!strncasecmp(http_header_line, "Location: ", 10)) + if (!strncasecmp(http_header_line, "Location: ", 10)) { strlcpy(location, http_header_line + 10, sizeof(location)); + } else if (!strncasecmp(http_header_line, "Content-Type: ", 14)) { + php_stream_notify_info(context, PHP_STREAM_NOTIFY_MIME_TYPE_IS, http_header_line + 14, 0); + } else if (!strncasecmp(http_header_line, "Content-Length: ", 16)) { + file_size = atoi(http_header_line + 16); + php_stream_notify_file_size(context, file_size, http_header_line, 0); + } + if (http_header_line[0] == '\0') body = 1; @@ -243,6 +273,10 @@ } if (!reqok) { + + if (location[0] != '\0') + php_stream_notify_info(context, PHP_STREAM_NOTIFY_REDIRECTED, location, 0); + php_stream_close(stream); stream = NULL; @@ -267,8 +301,9 @@ else { strlcpy(new_path, location, sizeof(new_path)); } - stream = php_stream_url_wrap_http(NULL, new_path, mode, options, opened_path STREAMS_CC TSRMLS_CC); - if (stream->wrapperdata) { + redirected = 1; + stream = php_stream_url_wrap_http(NULL, new_path, mode, options, opened_path, context STREAMS_CC TSRMLS_CC); + if (stream && stream->wrapperdata) { entryp = &entry; MAKE_STD_ZVAL(entry); ZVAL_EMPTY_STRING(entry); @@ -282,9 +317,10 @@ zval_dtor(stream->wrapperdata); FREE_ZVAL(stream->wrapperdata); } + } else { + if (options & REPORT_ERRORS) + zend_error(E_WARNING, "HTTP request failed! %s", tmp_line); } - else if (options & REPORT_ERRORS) - zend_error(E_WARNING, "HTTP request failed! %s", tmp_line); } out: if (http_header_line) @@ -293,8 +329,11 @@ efree(scratch); php_url_free(resource); - if (stream) + if (stream) { stream->wrapperdata = response_header; + php_stream_notify_progress_init(context, 0, file_size); + php_stream_sock_set_chunk_size(stream, chunk_size TSRMLS_CC); + } if (response_header) { zval *sym; Index: php4/ext/standard/php_fopen_wrapper.c diff -u php4/ext/standard/php_fopen_wrapper.c:1.18 php4/ext/standard/php_fopen_wrapper.c:1.19 --- php4/ext/standard/php_fopen_wrapper.c:1.18 Wed Mar 27 19:48:59 2002 +++ php4/ext/standard/php_fopen_wrapper.c Wed Apr 10 18:42:24 2002 @@ -17,7 +17,7 @@ | Hartmut Holzgraefe <hholzgra@php.net> | +----------------------------------------------------------------------+ */ -/* $Id: php_fopen_wrapper.c,v 1.18 2002/03/28 00:48:59 wez Exp $ */ +/* $Id: php_fopen_wrapper.c,v 1.19 2002/04/10 22:42:24 wez Exp $ */ #include <stdio.h> #include <stdlib.h> @@ -30,7 +30,7 @@ #include "php_standard.h" #include "php_fopen_wrappers.h" -php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path STREAMS_DC TSRMLS_DC) +php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_wrapper_options *exoptions STREAMS_DC TSRMLS_DC) { FILE * fp = NULL; php_stream * stream = NULL; Index: php4/ext/standard/php_fopen_wrappers.h diff -u php4/ext/standard/php_fopen_wrappers.h:1.12 php4/ext/standard/php_fopen_wrappers.h:1.13 --- php4/ext/standard/php_fopen_wrappers.h:1.12 Sun Mar 24 13:04:54 2002 +++ php4/ext/standard/php_fopen_wrappers.h Wed Apr 10 18:42:24 2002 @@ -18,13 +18,13 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_fopen_wrappers.h,v 1.12 2002/03/24 18:04:54 wez Exp $ */ +/* $Id: php_fopen_wrappers.h,v 1.13 2002/04/10 22:42:24 wez Exp $ */ #ifndef PHP_FOPEN_WRAPPERS_H #define PHP_FOPEN_WRAPPERS_H -php_stream *php_stream_url_wrap_http(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path STREAMS_DC TSRMLS_DC); -php_stream *php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path STREAMS_DC TSRMLS_DC); +php_stream *php_stream_url_wrap_http(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); +php_stream *php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); php_stream_wrapper php_stream_http_wrapper; php_stream_wrapper php_stream_ftp_wrapper; php_stream_wrapper php_stream_php_wrapper; Index: php4/ext/zlib/php_zlib.h diff -u php4/ext/zlib/php_zlib.h:1.29 php4/ext/zlib/php_zlib.h:1.30 --- php4/ext/zlib/php_zlib.h:1.29 Fri Apr 5 08:07:43 2002 +++ php4/ext/zlib/php_zlib.h Wed Apr 10 18:42:24 2002 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_zlib.h,v 1.29 2002/04/05 13:07:43 ssb Exp $ */ +/* $Id: php_zlib.h,v 1.30 2002/04/10 22:42:24 wez Exp $ */ #ifndef PHP_ZLIB_H #define PHP_ZLIB_H @@ -54,7 +54,7 @@ int php_enable_output_compression(int buffer_size TSRMLS_DC); -php_stream *php_stream_gzopen(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path STREAMS_DC TSRMLS_DC); +php_stream *php_stream_gzopen(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); extern php_stream_ops php_stream_gzio_ops; extern php_stream_wrapper php_stream_gzip_wrapper; Index: php4/ext/zlib/zlib.c diff -u php4/ext/zlib/zlib.c:1.123 php4/ext/zlib/zlib.c:1.124 --- php4/ext/zlib/zlib.c:1.123 Fri Apr 5 08:07:43 2002 +++ php4/ext/zlib/zlib.c Wed Apr 10 18:42:26 2002 @@ -18,7 +18,7 @@ | Jade Nicoletti <nicoletti@nns.ch> | +----------------------------------------------------------------------+ */ -/* $Id: zlib.c,v 1.123 2002/04/05 13:07:43 ssb Exp $ */ +/* $Id: zlib.c,v 1.124 2002/04/10 22:42:26 wez Exp $ */ #define IS_EXT_MODULE #ifdef HAVE_CONFIG_H @@ -285,7 +285,7 @@ convert_to_string_ex(filename); /* using a stream here is a bit more efficient (resource wise) than php_gzopen_wrapper */ - stream = php_stream_gzopen(NULL, Z_STRVAL_PP(filename), "rb", use_include_path|ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL STREAMS_CC TSRMLS_CC); + stream = php_stream_gzopen(NULL, Z_STRVAL_PP(filename), "rb", use_include_path|ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL, NULL STREAMS_CC TSRMLS_CC); if (stream == NULL) { php_error(E_WARNING,"gzFile(\"%s\") - %s",Z_STRVAL_PP(filename),strerror(errno)); RETURN_FALSE; @@ -341,7 +341,7 @@ convert_to_string_ex(arg2); p = estrndup(Z_STRVAL_PP(arg2),Z_STRLEN_PP(arg2)); - stream = php_stream_gzopen(NULL, Z_STRVAL_PP(arg1), p, use_include_path|ENFORCE_SAFE_MODE, NULL STREAMS_CC TSRMLS_CC); + stream = php_stream_gzopen(NULL, Z_STRVAL_PP(arg1), p, use_include_path|ENFORCE_SAFE_MODE, NULL, NULL STREAMS_CC TSRMLS_CC); if (!stream) { RETURN_FALSE; } @@ -382,7 +382,7 @@ } convert_to_string_ex(arg1); - stream = php_stream_gzopen(NULL, Z_STRVAL_PP(arg1), "rb", use_include_path|ENFORCE_SAFE_MODE, NULL STREAMS_CC TSRMLS_CC); + stream = php_stream_gzopen(NULL, Z_STRVAL_PP(arg1), "rb", use_include_path|ENFORCE_SAFE_MODE, NULL, NULL STREAMS_CC TSRMLS_CC); if (!stream) { RETURN_FALSE; } Index: php4/ext/zlib/zlib_fopen_wrapper.c diff -u php4/ext/zlib/zlib_fopen_wrapper.c:1.23 php4/ext/zlib/zlib_fopen_wrapper.c:1.24 --- php4/ext/zlib/zlib_fopen_wrapper.c:1.23 Sat Apr 6 12:29:39 2002 +++ php4/ext/zlib/zlib_fopen_wrapper.c Wed Apr 10 18:42:27 2002 @@ -16,7 +16,7 @@ | Hartmut Holzgraefe <hartmut@six.de> | +----------------------------------------------------------------------+ */ -/* $Id: zlib_fopen_wrapper.c,v 1.23 2002/04/06 17:29:39 wez Exp $ */ +/* $Id: zlib_fopen_wrapper.c,v 1.24 2002/04/10 22:42:27 wez Exp $ */ #define IS_EXT_MODULE #define _GNU_SOURCE @@ -93,7 +93,8 @@ NULL, NULL }; -php_stream *php_stream_gzopen(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path STREAMS_DC TSRMLS_DC) +php_stream *php_stream_gzopen(php_stream_wrapper *wrapper, char *path, char *mode, + int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) { struct php_gz_stream_data_t *self; php_stream *stream = NULL; Index: php4/main/main.c diff -u php4/main/main.c:1.443 php4/main/main.c:1.444 --- php4/main/main.c:1.443 Tue Apr 9 21:27:44 2002 +++ php4/main/main.c Wed Apr 10 18:42:28 2002 @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: main.c,v 1.443 2002/04/10 01:27:44 helly Exp $ */ +/* $Id: main.c,v 1.444 2002/04/10 22:42:28 wez Exp $ */ /* {{{ includes */ @@ -594,16 +594,9 @@ */ static FILE *php_fopen_wrapper_for_zend(const char *filename, char **opened_path) { - FILE *retval = NULL; - size_t old_chunk_size; TSRMLS_FETCH(); - old_chunk_size = FG(def_chunk_size); - FG(def_chunk_size) = 1; - retval = php_stream_open_wrapper_as_file((char *)filename, "rb", USE_PATH|IGNORE_URL_WIN|REPORT_ERRORS, opened_path); - FG(def_chunk_size) = old_chunk_size; - - return retval; + return php_stream_open_wrapper_as_file((char *)filename, "rb", USE_PATH|IGNORE_URL_WIN|REPORT_ERRORS, opened_path); } /* }}} */ Index: php4/main/network.c diff -u php4/main/network.c:1.44 php4/main/network.c:1.45 --- php4/main/network.c:1.44 Wed Mar 27 19:49:00 2002 +++ php4/main/network.c Wed Apr 10 18:42:28 2002 @@ -15,7 +15,7 @@ | Author: Stig Venaas <venaas@uninett.no> | +----------------------------------------------------------------------+ */ -/* $Id: network.c,v 1.44 2002/03/28 00:49:00 wez Exp $ */ +/* $Id: network.c,v 1.45 2002/04/10 22:42:28 wez Exp $ */ #define MAX_CHUNKS_PER_READ 10 @@ -574,11 +574,18 @@ static size_t php_sockop_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC) { php_netstream_data_t *sock = (php_netstream_data_t*)stream->abstract; + size_t didwrite; + #if HAVE_OPENSSL_EXT if (sock->ssl_active) - return SSL_write(sock->ssl_handle, buf, count); + didwrite = SSL_write(sock->ssl_handle, buf, count); + else #endif - return send(sock->socket, buf, count, 0); + didwrite = send(sock->socket, buf, count, 0); + + php_stream_notify_progress_increment(stream->context, didwrite, 0); + + return didwrite; } static void php_sock_stream_wait_for_data(php_stream *stream, php_netstream_data_t *sock TSRMLS_DC) { @@ -638,6 +645,8 @@ nr_bytes = recv(sock->socket, buf, sock->chunk_size, 0); if(nr_bytes > 0) { + php_stream_notify_progress_increment(stream->context, nr_bytes, 0); + /* try to avoid ever expanding buffer */ if (sock->readpos > 0) { memmove(sock->readbuf, READPTR(sock), sock->readbuflen - sock->readpos); @@ -669,7 +678,10 @@ for(i = 0; !sock->eof && i < MAX_CHUNKS_PER_READ; i++) { nr_bytes = php_sock_stream_read_internal(stream, sock TSRMLS_CC); - if(nr_bytes == 0) break; + if(nr_bytes == 0) + break; + + nr_read += nr_bytes; } Index: php4/main/php_streams.h diff -u php4/main/php_streams.h:1.27 php4/main/php_streams.h:1.28 --- php4/main/php_streams.h:1.27 Wed Mar 27 19:49:00 2002 +++ php4/main/php_streams.h Wed Apr 10 18:42:29 2002 @@ -69,7 +69,8 @@ #define php_stream_fopen_temporary_file_rel(dir, pfx, opened_path) _php_stream_fopen_temporary_file((dir), (pfx), (opened_path) STREAMS_REL_CC TSRMLS_CC) -#define php_stream_open_wrapper_rel(path, mode, options, opened) _php_stream_open_wrapper((path), (mode), (options), (opened) STREAMS_REL_CC TSRMLS_CC) +#define php_stream_open_wrapper_rel(path, mode, options, opened) _php_stream_open_wrapper_ex((path), (mode), (options), (opened), NULL STREAMS_REL_CC TSRMLS_CC) +#define php_stream_open_wrapper_ex_rel(path, mode, options, opened, context) _php_stream_open_wrapper_ex((path), (mode), (options), (opened), (context) STREAMS_REL_CC TSRMLS_CC) #define php_stream_make_seekable_rel(origstream, newstream, flags) _php_stream_make_seekable((origstream), (newstream), (flags) STREAMS_REL_CC TSRMLS_CC) @@ -85,16 +86,48 @@ * the php_stream->abstract pointer to hold their context, and streams * opened via stream_open_wrappers can use the zval ptr in * php_stream->wrapperdata to hold meta data for php scripts to - * retrieve using fgetwrapperdata(). */ + * retrieve using file_get_wrapper_data(). */ typedef struct _php_stream php_stream; typedef struct _php_stream_wrapper php_stream_wrapper; +typedef struct _php_stream_context php_stream_context; + +/* callback for status notifications */ +typedef void (*php_stream_notification_func)(php_stream_context *context, + int notifycode, int severity, + char *xmsg, int xcode, + size_t bytes_sofar, size_t bytes_max, + void * ptr TSRMLS_DC); typedef struct _php_stream_statbuf { struct stat sb; /* regular info */ /* extended info to go here some day */ } php_stream_statbuf; +#define PHP_STREAM_NOTIFIER_PROGRESS 1 + +typedef struct _php_stream_notifier { + php_stream_notification_func func; + void *ptr; + int mask; + size_t progress, progress_max; /* position for progress notification */ +} php_stream_notifier; + +struct _php_stream_context { + php_stream_notifier *notifier; + +}; + +typedef struct _php_stream_wrapper_options { + int valid_options; /* PHP_STREAM_WRAPPER_OPT_XXX */ + + php_stream_notification_func notifier; + void *notifier_ptr; + + /* other info like user-agent, SSL cert and cookie information + * to go here some day */ +} php_stream_wrapper_options; + typedef struct _php_stream_ops { /* stdio like functions - these are mandatory! */ size_t (*write)(php_stream *stream, const char *buf, size_t count TSRMLS_DC); @@ -114,7 +147,7 @@ typedef struct _php_stream_wrapper_ops { /* open/create a wrapped stream */ php_stream *(*opener)(php_stream_wrapper *wrapper, char *filename, char *mode, - int options, char **opened_path STREAMS_DC TSRMLS_DC); + int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); /* close/destroy a wrapped stream */ int (*closer)(php_stream_wrapper *wrapper, php_stream *stream TSRMLS_DC); /* stat a wrapped stream */ @@ -128,6 +161,7 @@ void *abstract; /* context for the wrapper */ }; + struct _php_stream { php_stream_ops *ops; void *abstract; /* convenience pointer for abstraction */ @@ -148,6 +182,9 @@ #if ZEND_DEBUG int __exposed; /* non-zero if exposed as a zval somewhere */ #endif + + php_stream_context *context; + }; /* php_stream */ /* state definitions when closing down; these are private to streams.c */ #define PHP_STREAM_FCLOSE_NONE 0 @@ -305,8 +342,10 @@ int php_shutdown_stream_wrappers(TSRMLS_D); PHPAPI int php_register_url_stream_wrapper(char *protocol, php_stream_wrapper *wrapper TSRMLS_DC); PHPAPI int php_unregister_url_stream_wrapper(char *protocol TSRMLS_DC); -PHPAPI php_stream *_php_stream_open_wrapper(char *path, char *mode, int options, char **opened_path STREAMS_DC TSRMLS_DC); -#define php_stream_open_wrapper(path, mode, options, opened) _php_stream_open_wrapper((path), (mode), (options), (opened) STREAMS_CC TSRMLS_CC) +PHPAPI php_stream *_php_stream_open_wrapper_ex(char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); + +#define php_stream_open_wrapper(path, mode, options, opened) _php_stream_open_wrapper_ex((path), (mode), (options), (opened), NULL STREAMS_CC TSRMLS_CC) +#define php_stream_open_wrapper_ex(path, mode, options, opened, context) _php_stream_open_wrapper_ex((path), (mode), (options), (opened), (context) STREAMS_CC TSRMLS_CC) #define PHP_STREAM_UNCHANGED 0 /* orig stream was seekable anyway */ #define PHP_STREAM_RELEASED 1 /* newstream should be used; origstream is no longer valid */ @@ -328,6 +367,58 @@ extern php_stream_ops php_stream_userspace_ops; #define PHP_STREAM_IS_USERSPACE &php_stream_userspace_ops +PHPAPI void php_stream_context_free(php_stream_context *context); +PHPAPI php_stream_context *php_stream_context_alloc(void); + +PHPAPI php_stream_notifier *php_stream_notification_alloc(void); +PHPAPI void php_stream_notification_free(php_stream_notifier *notifier); + +#define PHP_STREAM_NOTIFY_RESOLVE 1 +#define PHP_STREAM_NOTIFY_CONNECT 2 +#define PHP_STREAM_NOTIFY_AUTH_REQUIRED 3 +#define PHP_STREAM_NOTIFY_MIME_TYPE_IS 4 +#define PHP_STREAM_NOTIFY_FILE_SIZE_IS 5 +#define PHP_STREAM_NOTIFY_REDIRECTED 6 +#define PHP_STREAM_NOTIFY_PROGRESS 7 +#define PHP_STREAM_NOTIFY_COMPLETED 8 +#define PHP_STREAM_NOTIFY_FAILURE 9 +#define PHP_STREAM_NOTIFY_AUTH_RESULT 10 + +#define PHP_STREAM_NOTIFY_SEVERITY_INFO 0 +#define PHP_STREAM_NOTIFY_SEVERITY_WARN 1 +#define PHP_STREAM_NOTIFY_SEVERITY_ERR 2 + +PHPAPI void php_stream_notification_notify(php_stream_context *context, int notifycode, int severity, + char *xmsg, int xcode, size_t bytes_sofar, size_t bytes_max, void * ptr TSRMLS_DC); +PHPAPI php_stream_context *php_stream_context_set(php_stream *stream, php_stream_context *context); + +#define php_stream_notify_info(context, code, xmsg, xcode) do { if ((context) && (context)->notifier) { \ + php_stream_notification_notify((context), (code), PHP_STREAM_NOTIFY_SEVERITY_INFO, \ + (xmsg), (xcode), 0, 0, NULL TSRMLS_CC); } } while (0) + +#define php_stream_notify_progress(context, bsofar, bmax) do { if ((context) && (context)->notifier) { \ + php_stream_notification_notify((context), PHP_STREAM_NOTIFY_PROGRESS, PHP_STREAM_NOTIFY_SEVERITY_INFO, \ + NULL, 0, (bsofar), (bmax), NULL TSRMLS_CC); } } while(0) + +#define php_stream_notify_progress_init(context, sofar, bmax) do { if ((context)->notifier) { \ + (context)->notifier->progress = (sofar); \ + (context)->notifier->progress_max = (bmax); \ + (context)->notifier->mask |= PHP_STREAM_NOTIFIER_PROGRESS; \ + php_stream_notify_progress((context), (sofar), (bmax)); } } while (0) + +#define php_stream_notify_progress_increment(context, dsofar, dmax) do { if ((context) && (context)->notifier && (context)->notifier->mask & PHP_STREAM_NOTIFIER_PROGRESS) { \ + (context)->notifier->progress += (dsofar); \ + (context)->notifier->progress_max += (dmax); \ + php_stream_notify_progress((context), (context)->notifier->progress, (context)->notifier->progress_max); } } while (0) + +#define php_stream_notify_file_size(context, file_size, xmsg, xcode) do { if ((context) && (context)->notifier) { \ + php_stream_notification_notify((context), PHP_STREAM_NOTIFY_FILE_SIZE_IS, PHP_STREAM_NOTIFY_SEVERITY_INFO, \ + (xmsg), (xcode), 0, (file_size), NULL TSRMLS_CC); } } while(0) + +#define php_stream_notify_error(context, code, xmsg, xcode) do { if ((context) && (context)->notifier) {\ + php_stream_notification_notify((context), (code), PHP_STREAM_NOTIFY_SEVERITY_ERR, \ + (xmsg), (xcode), 0, 0, NULL TSRMLS_CC); } } while(0) + #endif /* Index: php4/main/streams.c diff -u php4/main/streams.c:1.46 php4/main/streams.c:1.47 --- php4/main/streams.c:1.46 Sat Apr 6 12:29:38 2002 +++ php4/main/streams.c Wed Apr 10 18:42:29 2002 @@ -1069,7 +1069,8 @@ /* }}} */ /* {{{ php_stream_open_url */ -static php_stream *php_stream_open_url(char *path, char *mode, int options, char **opened_path STREAMS_DC TSRMLS_DC) +static php_stream *php_stream_open_url(char *path, char *mode, int options, + char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) { php_stream_wrapper *wrapper; const char *p, *protocol = NULL; @@ -1085,7 +1086,7 @@ /* BC with older php scripts and zlib wrapper */ protocol = path; n = 4; - zend_error(E_NOTICE, "Use of \"zlib:\" wrapper is deprecated; please use \"zlib://\" instead."); + zend_error(E_WARNING, "Use of \"zlib:\" wrapper is deprecated; please use \"zlib://\" instead."); } if (protocol) { @@ -1103,7 +1104,7 @@ protocol = NULL; } if (wrapper) { - php_stream *stream = wrapper->wops->opener(wrapper, path, mode, options, opened_path STREAMS_REL_CC TSRMLS_CC); + php_stream *stream = wrapper->wops->opener(wrapper, path, mode, options, opened_path, context STREAMS_REL_CC TSRMLS_CC); if (stream) stream->wrapper = wrapper; return stream; @@ -1126,8 +1127,9 @@ } /* }}} */ -/* {{{ php_stream_open_wrapper */ -PHPAPI php_stream *_php_stream_open_wrapper(char *path, char *mode, int options, char **opened_path STREAMS_DC TSRMLS_DC) +/* {{{ php_stream_open_wrapper_ex */ +PHPAPI php_stream *_php_stream_open_wrapper_ex(char *path, char *mode, int options, + char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) { php_stream *stream = NULL; @@ -1138,7 +1140,7 @@ return NULL; if (PG(allow_url_fopen) && !(options & IGNORE_URL)) { - stream = php_stream_open_url(path, mode, options, opened_path STREAMS_REL_CC TSRMLS_CC); + stream = php_stream_open_url(path, mode, options, opened_path, context STREAMS_REL_CC TSRMLS_CC); goto out; } @@ -1242,6 +1244,41 @@ return PHP_STREAM_RELEASED; } /* }}} */ + +PHPAPI php_stream_context *php_stream_context_set(php_stream *stream, php_stream_context *context) +{ + php_stream_context *oldcontext = stream->context; + stream->context = context; + return oldcontext; +} + +PHPAPI void php_stream_notification_notify(php_stream_context *context, int notifycode, int severity, + char *xmsg, int xcode, size_t bytes_sofar, size_t bytes_max, void * ptr TSRMLS_DC) +{ + if (context && context->notifier) + context->notifier->func(context, notifycode, severity, xmsg, xcode, bytes_sofar, bytes_max, ptr TSRMLS_CC); +} + +PHPAPI void php_stream_context_free(php_stream_context *context) +{ + efree(context); +} + +PHPAPI php_stream_context *php_stream_context_alloc(void) +{ + return ecalloc(1, sizeof(php_stream_context)); +} + +PHPAPI php_stream_notifier *php_stream_notification_alloc(void) +{ + return ecalloc(1, sizeof(php_stream_notifier)); +} + +PHPAPI void php_stream_notification_free(php_stream_notifier *notifier) +{ + efree(notifier); +} + /* * Local variables: Index: php4/main/user_streams.c diff -u php4/main/user_streams.c:1.10 php4/main/user_streams.c:1.11 --- php4/main/user_streams.c:1.10 Thu Mar 28 20:19:02 2002 +++ php4/main/user_streams.c Wed Apr 10 18:42:30 2002 @@ -29,7 +29,7 @@ php_stream_wrapper wrapper; }; -static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, char *filename, char *mode, int options, char **opened_path STREAMS_DC TSRMLS_DC); +static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, char *filename, char *mode, int options, char **opened_path, php_stream_wrapper_options *exoptions STREAMS_DC TSRMLS_DC); static php_stream_wrapper_ops user_stream_wops = { user_wrapper_opener, @@ -115,7 +115,7 @@ * */ -static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, char *filename, char *mode, int options, char **opened_path STREAMS_DC TSRMLS_DC) +static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, char *filename, char *mode, int options, char **opened_path, php_stream_wrapper_options *exoptions STREAMS_DC TSRMLS_DC) { struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract; php_userstream_data_t *us;
Index: php4/ext/bz2/bz2.c diff -u php4/ext/bz2/bz2.c:1.46 php4/ext/bz2/bz2.c:1.47 --- php4/ext/bz2/bz2.c:1.46 Fri Apr 5 06:51:33 2002 +++ php4/ext/bz2/bz2.c Wed Apr 10 18:42:13 2002 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: bz2.c,v 1.46 2002/04/05 11:51:33 zeev Exp $ */ +/* $Id: bz2.c,v 1.47 2002/04/10 22:42:13 wez Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -156,7 +156,8 @@ char *path, char *mode, int options, - char **opened_path + char **opened_path, + php_stream_context *context STREAMS_DC TSRMLS_DC) { php_stream *retstream = NULL, *stream = NULL; Index: php4/ext/bz2/php_bz2.h diff -u php4/ext/bz2/php_bz2.h:1.12 php4/ext/bz2/php_bz2.h:1.13 --- php4/ext/bz2/php_bz2.h:1.12 Fri Apr 5 08:15:43 2002 +++ php4/ext/bz2/php_bz2.h Wed Apr 10 18:42:16 2002 @@ -52,11 +52,11 @@ # define PHP_BZ2_API #endif -PHP_BZ2_API php_stream *_php_stream_bz2open(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path STREAMS_DC TSRMLS_DC); -PHP_BZ2_API php_stream *_php_stream_bz2open_from_BZFILE(BZFILE *bz, char *mode, php_stream *innerstream STREAMS_DC TSRMLS_DC); +PHP_BZ2_API PHPAPI php_stream *_php_stream_bz2open(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); +PHP_BZ2_API PHPAPI php_stream *_php_stream_bz2open_from_BZFILE(BZFILE *bz, char *mode, php_stream *innerstream STREAMS_DC TSRMLS_DC); #define php_stream_bz2open_from_BZFILE(bz, mode, innerstream) _php_stream_bz2open_from_BZFILE((bz), (mode), (innerstream) STREAMS_CC TSRMLS_CC) -#define php_stream_bz2open(wrapper, path, mode, options, opened_path) _php_stream_bz2open((wrapper), (path), (mode), (options), (opened_path) STREAMS_CC TSRMLS_CC) +#define php_stream_bz2open(wrapper, path, mode, options, opened_path) _php_stream_bz2open((wrapper), (path), (mode), (options), (opened_path), NULL STREAMS_CC TSRMLS_CC) php_stream_ops php_stream_bz2io_ops; #define PHP_STREAM_IS_BZIP2 &php_stream_bz2io_ops Index: php4/ext/standard/Makefile.frag diff -u php4/ext/standard/Makefile.frag:1.1 php4/ext/standard/Makefile.frag:1.2 --- php4/ext/standard/Makefile.frag:1.1 Thu Mar 7 09:19:38 2002 +++ php4/ext/standard/Makefile.frag Wed Apr 10 18:42:21 2002 @@ -6,3 +6,4 @@ $(srcdir)/url_scanner_ex.c: $(srcdir)/url_scanner_ex.re re2c -b $(srcdir)/url_scanner_ex.re > $@ + Index: php4/ext/standard/basic_functions.c diff -u php4/ext/standard/basic_functions.c:1.468 php4/ext/standard/basic_functions.c:1.469 --- php4/ext/standard/basic_functions.c:1.468 Wed Apr 3 08:39:34 2002 +++ php4/ext/standard/basic_functions.c Wed Apr 10 18:42:21 2002 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: basic_functions.c,v 1.468 2002/04/03 13:39:34 wez Exp $ */ +/* $Id: basic_functions.c,v 1.469 2002/04/10 22:42:21 wez Exp $ */ #include "php.h" #include "php_streams.h" @@ -595,6 +595,8 @@ PHP_STATIC_FE("tmpfile", php_if_tmpfile, NULL) PHP_FE(file, NULL) PHP_FE(file_get_contents, NULL) + PHP_FE(file_context_create, NULL) + PHP_FE(file_context_set_params, NULL) PHP_FE(fgetcsv, NULL) PHP_FE(flock, NULL) PHP_FE(get_meta_tags, NULL) Index: php4/ext/standard/file.c diff -u php4/ext/standard/file.c:1.223 php4/ext/standard/file.c:1.224 --- php4/ext/standard/file.c:1.223 Fri Apr 5 06:51:34 2002 +++ php4/ext/standard/file.c Wed Apr 10 18:42:22 2002 @@ -21,7 +21,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: file.c,v 1.223 2002/04/05 11:51:34 zeev Exp $ */ +/* $Id: file.c,v 1.224 2002/04/10 22:42:22 wez Exp $ */ /* Synced with php 3.0 revision 1.218 1999-06-16 [ssb] */ @@ -109,10 +109,16 @@ /* sharing globals is *evil* */ static int le_stream = FAILURE; +static int le_stream_context = FAILURE; /* }}} */ /* {{{ Module-Stuff */ +static ZEND_RSRC_DTOR_FUNC(file_context_dtor) +{ + php_stream_context_free((php_stream_context*)rsrc->ptr); +} + static void _file_stream_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) { php_stream *stream = (php_stream*)rsrc->ptr; @@ -142,6 +148,7 @@ PHP_MINIT_FUNCTION(file) { le_stream = zend_register_list_destructors_ex(_file_stream_dtor, NULL, "stream", module_number); + le_stream_context = zend_register_list_destructors_ex(file_context_dtor, NULL, "stream-context", module_number); #ifdef ZTS ts_allocate_id(&file_globals_id, sizeof(php_file_globals), (ts_allocate_ctor) file_globals_ctor, (ts_allocate_dtor) file_globals_dtor); @@ -157,6 +164,19 @@ REGISTER_LONG_CONSTANT("LOCK_UN", 3, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("LOCK_NB", 4, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_NOTIFY_CONNECT", PHP_STREAM_NOTIFY_CONNECT, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_NOTIFY_AUTH_REQUIRED", PHP_STREAM_NOTIFY_AUTH_REQUIRED, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_NOTIFY_AUTH_RESULT", PHP_STREAM_NOTIFY_AUTH_RESULT, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_NOTIFY_MIME_TYPE_IS", PHP_STREAM_NOTIFY_MIME_TYPE_IS, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_NOTIFY_FILE_SIZE_IS", PHP_STREAM_NOTIFY_FILE_SIZE_IS, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_NOTIFY_REDIRECTED", PHP_STREAM_NOTIFY_REDIRECTED, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_NOTIFY_PROGRESS", PHP_STREAM_NOTIFY_PROGRESS, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_NOTIFY_FAILURE", PHP_STREAM_NOTIFY_FAILURE, CONST_CS | CONST_PERSISTENT); + + REGISTER_LONG_CONSTANT("STREAM_NOTIFY_SEVERITY_INFO", PHP_STREAM_NOTIFY_SEVERITY_INFO, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_NOTIFY_SEVERITY_WARN", PHP_STREAM_NOTIFY_SEVERITY_WARN, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_NOTIFY_SEVERITY_ERR", PHP_STREAM_NOTIFY_SEVERITY_ERR, CONST_CS | CONST_PERSISTENT); + return SUCCESS; } @@ -562,36 +582,126 @@ } /* }}} */ -/* {{{ proto resource fopen(string filename, string mode [, bool use_include_path]) +/* {{{ file_context related functions */ +static void user_space_stream_notifier(php_stream_context *context, int notifycode, int severity, + char *xmsg, int xcode, size_t bytes_sofar, size_t bytes_max, void * ptr TSRMLS_DC) +{ + zval *callback = (zval*)context->notifier->ptr; + zval *retval = NULL; + zval zcode, zseverity, zmsg, zxcode, zsofar, zmax; + zval *ptrs[6] = {&zcode, &zseverity, &zmsg, &zxcode, &zsofar, &zmax}; + zval **args[6] = {&ptrs[0], &ptrs[1], &ptrs[2], &ptrs[3], &ptrs[4], &ptrs[5]}; + + INIT_ZVAL(zcode); + INIT_ZVAL(zseverity); + INIT_ZVAL(zmsg); + INIT_ZVAL(zxcode); + INIT_ZVAL(zsofar); + INIT_ZVAL(zmax); + + ZVAL_LONG(&zcode, notifycode); + ZVAL_LONG(&zseverity, severity); + ZVAL_LONG(&zxcode, xcode); + ZVAL_LONG(&zsofar, bytes_sofar); + ZVAL_LONG(&zmax, bytes_max); + + if (xmsg) { + ZVAL_STRING(&zmsg, xmsg, 0); + } else { + ZVAL_NULL(&zmsg); + } + + if (FAILURE == call_user_function_ex(EG(function_table), NULL, callback, &retval, 6, args, 0, NULL TSRMLS_CC)) { + zend_error(E_WARNING, "failed to call user notifier"); + } + if (retval) + zval_ptr_dtor(&retval); +} + +static int parse_context_options(php_stream_context *context, zval *params) +{ + int ret = SUCCESS; + zval **tmp; + + if (SUCCESS == zend_hash_find(Z_ARRVAL_P(params), "notification", sizeof("notification"), (void**)&tmp)) { + + if (context->notifier) { + php_stream_notification_free(context->notifier); + context->notifier = NULL; + } + + context->notifier = php_stream_notification_alloc(); + context->notifier->func = user_space_stream_notifier; + context->notifier->ptr = *tmp; + ZVAL_ADDREF(*tmp); + } + + return ret; +} +/* }}} */ + +/* {{{ proto bool file_context_set_params(resource context, array options) + Set parameters for a file context */ +PHP_FUNCTION(file_context_set_params) +{ + zval *params, *zcontext; + php_stream_context *context; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ra", &zcontext, ¶ms) == FAILURE) { + RETURN_FALSE; + } + + context = (php_stream_context*)zend_fetch_resource(&zcontext TSRMLS_CC, -1, "Stream-Context", NULL, 1, le_stream_context); + ZEND_VERIFY_RESOURCE(context); + + RETVAL_BOOL(parse_context_options(context, params) == SUCCESS); +} +/* }}} */ + +/* {{{ proto resource file_context_create([array options]) + Create a file context and optionally set parameters */ +PHP_FUNCTION(file_context_create) +{ + zval *params = NULL; + php_stream_context *context; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a", ¶ms) == FAILURE) { + RETURN_FALSE; + } + + context = php_stream_context_alloc(); + + if (params) + parse_context_options(context, params); + + ZEND_REGISTER_RESOURCE(return_value, context, le_stream_context); +} +/* }}} */ + +/* {{{ proto resource fopen(string filename, string mode [, bool use_include_path [, resource context]]) Open a file or a URL and return a file pointer */ PHP_NAMED_FUNCTION(php_if_fopen) { - zval **arg1, **arg2, **arg3; - int use_include_path = 0; + char *filename, *mode; + int filename_len, mode_len; + zend_bool use_include_path = 0; + zval *zcontext = NULL; php_stream *stream; - - switch(ZEND_NUM_ARGS()) { - case 2: - if (zend_get_parameters_ex(2, &arg1, &arg2) == FAILURE) { - WRONG_PARAM_COUNT; - } - break; - case 3: - if (zend_get_parameters_ex(3, &arg1, &arg2, &arg3) == FAILURE) { - WRONG_PARAM_COUNT; - } - convert_to_long_ex(arg3); - use_include_path = Z_LVAL_PP(arg3); - break; - default: - WRONG_PARAM_COUNT; - } - convert_to_string_ex(arg1); - convert_to_string_ex(arg2); + php_stream_context *context = NULL; - stream = php_stream_open_wrapper(Z_STRVAL_PP(arg1), Z_STRVAL_PP(arg2), + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|br", &filename, &filename_len, + &mode, &mode_len, &use_include_path, &zcontext) == FAILURE) { + RETURN_FALSE; + } + if (zcontext) { + context = (php_stream_context*)zend_fetch_resource(&zcontext TSRMLS_CC, -1, "Stream-Context", NULL, 1, le_stream_context); + ZEND_VERIFY_RESOURCE(context); + } + + stream = php_stream_open_wrapper_ex(filename, mode, use_include_path | ENFORCE_SAFE_MODE | REPORT_ERRORS, - NULL); + NULL, context); + if (stream == NULL) { RETURN_FALSE; } @@ -622,6 +732,7 @@ } /* }}} */ + /* {{{ proto resource popen(string command, string mode) Execute a command and open either a read or a write pipe to it */ Index: php4/ext/standard/file.h diff -u php4/ext/standard/file.h:1.58 php4/ext/standard/file.h:1.59 --- php4/ext/standard/file.h:1.58 Fri Apr 5 06:51:34 2002 +++ php4/ext/standard/file.h Wed Apr 10 18:42:23 2002 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: file.h,v 1.58 2002/04/05 11:51:34 zeev Exp $ */ +/* $Id: file.h,v 1.59 2002/04/10 22:42:23 wez Exp $ */ /* Synced with php 3.0 revision 1.30 1999-06-16 [ssb] */ @@ -73,6 +73,8 @@ PHP_FUNCTION(file_get_wrapper_data); PHP_FUNCTION(file_register_wrapper); +PHP_FUNCTION(file_context_create); +PHP_FUNCTION(file_context_set_params); PHP_MINIT_FUNCTION(user_streams); PHPAPI int php_set_sock_blocking(int socketd, int block); Index: php4/ext/standard/ftp_fopen_wrapper.c diff -u php4/ext/standard/ftp_fopen_wrapper.c:1.21 php4/ext/standard/ftp_fopen_wrapper.c:1.22 --- php4/ext/standard/ftp_fopen_wrapper.c:1.21 Wed Mar 27 19:48:59 2002 +++ php4/ext/standard/ftp_fopen_wrapper.c Wed Apr 10 18:42:23 2002 @@ -17,7 +17,7 @@ | Hartmut Holzgraefe <hholzgra@php.net> | +----------------------------------------------------------------------+ */ -/* $Id: ftp_fopen_wrapper.c,v 1.21 2002/03/28 00:48:59 wez Exp $ */ +/* $Id: ftp_fopen_wrapper.c,v 1.22 2002/04/10 22:42:23 wez Exp $ */ #include "php.h" #include "php_globals.h" @@ -66,16 +66,16 @@ #include "php_fopen_wrappers.h" -static int php_get_ftp_result(php_stream *stream TSRMLS_DC) -{ - char tmp_line[513]; - while (php_stream_gets(stream, tmp_line, sizeof(tmp_line)-1) && - !(isdigit((int) tmp_line[0]) && isdigit((int) tmp_line[1]) && - isdigit((int) tmp_line[2]) && tmp_line[3] == ' ')); +static inline int get_ftp_result(php_stream *stream, char *buffer, size_t buffer_size TSRMLS_DC) +{ + while (php_stream_gets(stream, buffer, buffer_size-1) && + !(isdigit((int) buffer[0]) && isdigit((int) buffer[1]) && + isdigit((int) buffer[2]) && buffer[3] == ' ')); - return strtol(tmp_line, NULL, 10); + return strtol(buffer, NULL, 10); } +#define GET_FTP_RESULT(stream) get_ftp_result((stream), tmp_line, sizeof(tmp_line) TSRMLS_CC) static int php_stream_ftp_stream_stat(php_stream_wrapper *wrapper, php_stream *stream, @@ -103,7 +103,7 @@ /* {{{ php_fopen_url_wrap_ftp */ -php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path STREAMS_DC TSRMLS_DC) +php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) { php_stream *stream=NULL; php_url *resource=NULL; @@ -113,6 +113,7 @@ int result; int i; char *tpath, *ttpath; + size_t file_size = 0; resource = php_url_parse((char *) path); if (resource == NULL || resource->path == NULL) @@ -126,10 +127,15 @@ if (stream == NULL) goto errexit; + php_stream_context_set(stream, context); + php_stream_notify_info(context, PHP_STREAM_NOTIFY_CONNECT, NULL, 0); + /* Start talking to ftp server */ - result = php_get_ftp_result(stream TSRMLS_CC); - if (result > 299 || result < 200) + result = GET_FTP_RESULT(stream); + if (result > 299 || result < 200) { + php_stream_notify_error(context, PHP_STREAM_NOTIFY_FAILURE, tmp_line, result); goto errexit; + } /* send the user name */ php_stream_write_string(stream, "USER "); @@ -142,10 +148,12 @@ php_stream_write_string(stream, "\r\n"); /* get the response */ - result = php_get_ftp_result(stream TSRMLS_CC); + result = GET_FTP_RESULT(stream); /* if a password is required, send it */ if (result >= 300 && result <= 399) { + php_stream_notify_info(context, PHP_STREAM_NOTIFY_AUTH_REQUIRED, tmp_line, 0); + php_stream_write_string(stream, "PASS "); if (resource->pass != NULL) { php_raw_url_decode(resource->pass, strlen(resource->pass)); @@ -162,14 +170,20 @@ php_stream_write_string(stream, "\r\n"); /* read the response */ - result = php_get_ftp_result(stream TSRMLS_CC); + result = GET_FTP_RESULT(stream); + + if (result > 299 || result < 200) { + php_stream_notify_error(context, PHP_STREAM_NOTIFY_AUTH_RESULT, tmp_line, result); + } else { + php_stream_notify_info(context, PHP_STREAM_NOTIFY_AUTH_RESULT, tmp_line, result); + } } if (result > 299 || result < 200) goto errexit; /* set the connection to be binary */ php_stream_write_string(stream, "TYPE I\r\n"); - result = php_get_ftp_result(stream TSRMLS_CC); + result = GET_FTP_RESULT(stream); if (result > 299 || result < 200) goto errexit; @@ -179,13 +193,22 @@ php_stream_write_string(stream, "\r\n"); /* read the response */ - result = php_get_ftp_result(stream TSRMLS_CC); + result = GET_FTP_RESULT(stream); if (mode[0] == 'r') { + char *sizestr; + /* when reading file, it must exist */ if (result > 299 || result < 200) { errno = ENOENT; goto errexit; } + + sizestr = strchr(tmp_line, ' '); + if (sizestr) { + sizestr++; + file_size = atoi(sizestr); + php_stream_notify_file_size(context, file_size, tmp_line, result); + } } else { /* when writing file, it must NOT exist */ if (result <= 299 && result >= 200) { @@ -193,25 +216,23 @@ goto errexit; } } - + /* set up the passive connection */ /* We try EPSV first, needed for IPv6 and works on some IPv4 servers */ php_stream_write_string(stream, "EPSV\r\n"); - while (php_stream_gets(stream, tmp_line, sizeof(tmp_line)-1) && - !(isdigit((int) tmp_line[0]) && isdigit((int) tmp_line[1]) && - isdigit((int) tmp_line[2]) && tmp_line[3] == ' ')); + result = GET_FTP_RESULT(stream); /* check if we got a 229 response */ - if (strncmp(tmp_line, "229", 3)) { + if (result != 229) { /* EPSV failed, let's try PASV */ php_stream_write_string(stream, "PASV\r\n"); - while (php_stream_gets(stream, tmp_line, sizeof(tmp_line)-1) && - !(isdigit((int) tmp_line[0]) && isdigit((int) tmp_line[1]) && - isdigit((int) tmp_line[2]) && tmp_line[3] == ' ')); + result = GET_FTP_RESULT(stream); + /* make sure we got a 227 response */ - if (strncmp(tmp_line, "227", 3)) + if (result != 227) goto errexit; + /* parse pasv command (129, 80, 95, 25, 13, 221) */ tpath = tmp_line; /* skip over the "227 Some message " part */ @@ -279,13 +300,20 @@ if (stream == NULL) goto errexit; + php_stream_context_set(stream, context); + php_stream_notify_progress_init(context, 0, file_size); + php_url_free(resource); return stream; errexit: php_url_free(resource); - if (stream) + if (stream) { + php_stream_notify_error(context, PHP_STREAM_NOTIFY_FAILURE, tmp_line, result); php_stream_close(stream); + } + if (tmp_line[0] != '\0') + zend_error(E_WARNING, "FTP server reports %s", tmp_line); return NULL; } /* }}} */ Index: php4/ext/standard/http_fopen_wrapper.c diff -u php4/ext/standard/http_fopen_wrapper.c:1.30 php4/ext/standard/http_fopen_wrapper.c:1.31 --- php4/ext/standard/http_fopen_wrapper.c:1.30 Wed Mar 27 19:48:59 2002 +++ php4/ext/standard/http_fopen_wrapper.c Wed Apr 10 18:42:23 2002 @@ -18,7 +18,7 @@ | Wez Furlong <wez@thebrainroom.com> | +----------------------------------------------------------------------+ */ -/* $Id: http_fopen_wrapper.c,v 1.30 2002/03/28 00:48:59 wez Exp $ */ +/* $Id: http_fopen_wrapper.c,v 1.31 2002/04/10 22:42:23 wez Exp $ */ #include "php.h" #include "php_globals.h" @@ -70,7 +70,7 @@ #define HTTP_HEADER_BLOCK_SIZE 1024 -php_stream *php_stream_url_wrap_http(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path STREAMS_DC TSRMLS_DC) +php_stream *php_stream_url_wrap_http(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) { php_stream *stream = NULL; php_url *resource = NULL; @@ -84,6 +84,8 @@ int reqok = 0; char *http_header_line = NULL; char tmp_line[128]; + size_t chunk_size, file_size = 0; + int redirected = 0; resource = php_url_parse(path); if (resource == NULL) @@ -101,6 +103,13 @@ if (stream == NULL) goto out; + /* avoid buffering issues while reading header */ + chunk_size = php_stream_sock_set_chunk_size(stream, 1 TSRMLS_CC); + + php_stream_context_set(stream, context); + + php_stream_notify_info(context, PHP_STREAM_NOTIFY_CONNECT, NULL, 0); + #if HAVE_OPENSSL_EXT if (use_ssl) { if (php_stream_sock_ssl_activate(stream, 1) == FAILURE) { @@ -146,8 +155,10 @@ tmp = php_base64_encode((unsigned char*)scratch, strlen(scratch), NULL); - if (snprintf(scratch, scratch_len, "Authorization: Basic %s\r\n", tmp) > 0) + if (snprintf(scratch, scratch_len, "Authorization: Basic %s\r\n", tmp) > 0) { php_stream_write(stream, scratch, strlen(scratch)); + php_stream_notify_info(context, PHP_STREAM_NOTIFY_AUTH_REQUIRED, NULL, 0); + } efree(tmp); tmp = NULL; @@ -179,10 +190,22 @@ if (php_stream_gets(stream, tmp_line, sizeof(tmp_line)-1) != NULL) { zval *http_response; + int response_code; MAKE_STD_ZVAL(http_response); - if (strncmp(tmp_line + 8, " 200 ", 5) == 0) + response_code = atoi(tmp_line + 9); + if (response_code == 200) { reqok = 1; + } else { + switch(response_code) { + case 403: + php_stream_notify_error(context, PHP_STREAM_NOTIFY_AUTH_RESULT, tmp_line, response_code); + break; + default: + php_stream_notify_error(context, PHP_STREAM_NOTIFY_FAILURE, tmp_line, response_code); + } + } + Z_STRLEN_P(http_response) = strlen(tmp_line); Z_STRVAL_P(http_response) = estrndup(tmp_line, Z_STRLEN_P(http_response)); if (Z_STRVAL_P(http_response)[Z_STRLEN_P(http_response)-1]=='\n') { @@ -223,8 +246,15 @@ } http_header_line_length = p-http_header_line+1; - if (!strncasecmp(http_header_line, "Location: ", 10)) + if (!strncasecmp(http_header_line, "Location: ", 10)) { strlcpy(location, http_header_line + 10, sizeof(location)); + } else if (!strncasecmp(http_header_line, "Content-Type: ", 14)) { + php_stream_notify_info(context, PHP_STREAM_NOTIFY_MIME_TYPE_IS, http_header_line + 14, 0); + } else if (!strncasecmp(http_header_line, "Content-Length: ", 16)) { + file_size = atoi(http_header_line + 16); + php_stream_notify_file_size(context, file_size, http_header_line, 0); + } + if (http_header_line[0] == '\0') body = 1; @@ -243,6 +273,10 @@ } if (!reqok) { + + if (location[0] != '\0') + php_stream_notify_info(context, PHP_STREAM_NOTIFY_REDIRECTED, location, 0); + php_stream_close(stream); stream = NULL; @@ -267,8 +301,9 @@ else { strlcpy(new_path, location, sizeof(new_path)); } - stream = php_stream_url_wrap_http(NULL, new_path, mode, options, opened_path STREAMS_CC TSRMLS_CC); - if (stream->wrapperdata) { + redirected = 1; + stream = php_stream_url_wrap_http(NULL, new_path, mode, options, opened_path, context STREAMS_CC TSRMLS_CC); + if (stream && stream->wrapperdata) { entryp = &entry; MAKE_STD_ZVAL(entry); ZVAL_EMPTY_STRING(entry); @@ -282,9 +317,10 @@ zval_dtor(stream->wrapperdata); FREE_ZVAL(stream->wrapperdata); } + } else { + if (options & REPORT_ERRORS) + zend_error(E_WARNING, "HTTP request failed! %s", tmp_line); } - else if (options & REPORT_ERRORS) - zend_error(E_WARNING, "HTTP request failed! %s", tmp_line); } out: if (http_header_line) @@ -293,8 +329,11 @@ efree(scratch); php_url_free(resource); - if (stream) + if (stream) { stream->wrapperdata = response_header; + php_stream_notify_progress_init(context, 0, file_size); + php_stream_sock_set_chunk_size(stream, chunk_size TSRMLS_CC); + } if (response_header) { zval *sym; Index: php4/ext/standard/php_fopen_wrapper.c diff -u php4/ext/standard/php_fopen_wrapper.c:1.18 php4/ext/standard/php_fopen_wrapper.c:1.19 --- php4/ext/standard/php_fopen_wrapper.c:1.18 Wed Mar 27 19:48:59 2002 +++ php4/ext/standard/php_fopen_wrapper.c Wed Apr 10 18:42:24 2002 @@ -17,7 +17,7 @@ | Hartmut Holzgraefe <hholzgra@php.net> | +----------------------------------------------------------------------+ */ -/* $Id: php_fopen_wrapper.c,v 1.18 2002/03/28 00:48:59 wez Exp $ */ +/* $Id: php_fopen_wrapper.c,v 1.19 2002/04/10 22:42:24 wez Exp $ */ #include <stdio.h> #include <stdlib.h> @@ -30,7 +30,7 @@ #include "php_standard.h" #include "php_fopen_wrappers.h" -php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path STREAMS_DC TSRMLS_DC) +php_stream * php_stream_url_wrap_php(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_wrapper_options *exoptions STREAMS_DC TSRMLS_DC) { FILE * fp = NULL; php_stream * stream = NULL; Index: php4/ext/standard/php_fopen_wrappers.h diff -u php4/ext/standard/php_fopen_wrappers.h:1.12 php4/ext/standard/php_fopen_wrappers.h:1.13 --- php4/ext/standard/php_fopen_wrappers.h:1.12 Sun Mar 24 13:04:54 2002 +++ php4/ext/standard/php_fopen_wrappers.h Wed Apr 10 18:42:24 2002 @@ -18,13 +18,13 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_fopen_wrappers.h,v 1.12 2002/03/24 18:04:54 wez Exp $ */ +/* $Id: php_fopen_wrappers.h,v 1.13 2002/04/10 22:42:24 wez Exp $ */ #ifndef PHP_FOPEN_WRAPPERS_H #define PHP_FOPEN_WRAPPERS_H -php_stream *php_stream_url_wrap_http(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path STREAMS_DC TSRMLS_DC); -php_stream *php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path STREAMS_DC TSRMLS_DC); +php_stream *php_stream_url_wrap_http(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); +php_stream *php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); php_stream_wrapper php_stream_http_wrapper; php_stream_wrapper php_stream_ftp_wrapper; php_stream_wrapper php_stream_php_wrapper; Index: php4/ext/zlib/php_zlib.h diff -u php4/ext/zlib/php_zlib.h:1.29 php4/ext/zlib/php_zlib.h:1.30 --- php4/ext/zlib/php_zlib.h:1.29 Fri Apr 5 08:07:43 2002 +++ php4/ext/zlib/php_zlib.h Wed Apr 10 18:42:24 2002 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_zlib.h,v 1.29 2002/04/05 13:07:43 ssb Exp $ */ +/* $Id: php_zlib.h,v 1.30 2002/04/10 22:42:24 wez Exp $ */ #ifndef PHP_ZLIB_H #define PHP_ZLIB_H @@ -54,7 +54,7 @@ int php_enable_output_compression(int buffer_size TSRMLS_DC); -php_stream *php_stream_gzopen(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path STREAMS_DC TSRMLS_DC); +php_stream *php_stream_gzopen(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); extern php_stream_ops php_stream_gzio_ops; extern php_stream_wrapper php_stream_gzip_wrapper; Index: php4/ext/zlib/zlib.c diff -u php4/ext/zlib/zlib.c:1.123 php4/ext/zlib/zlib.c:1.124 --- php4/ext/zlib/zlib.c:1.123 Fri Apr 5 08:07:43 2002 +++ php4/ext/zlib/zlib.c Wed Apr 10 18:42:26 2002 @@ -18,7 +18,7 @@ | Jade Nicoletti <nicoletti@nns.ch> | +----------------------------------------------------------------------+ */ -/* $Id: zlib.c,v 1.123 2002/04/05 13:07:43 ssb Exp $ */ +/* $Id: zlib.c,v 1.124 2002/04/10 22:42:26 wez Exp $ */ #define IS_EXT_MODULE #ifdef HAVE_CONFIG_H @@ -285,7 +285,7 @@ convert_to_string_ex(filename); /* using a stream here is a bit more efficient (resource wise) than php_gzopen_wrapper */ - stream = php_stream_gzopen(NULL, Z_STRVAL_PP(filename), "rb", use_include_path|ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL STREAMS_CC TSRMLS_CC); + stream = php_stream_gzopen(NULL, Z_STRVAL_PP(filename), "rb", use_include_path|ENFORCE_SAFE_MODE|REPORT_ERRORS, NULL, NULL STREAMS_CC TSRMLS_CC); if (stream == NULL) { php_error(E_WARNING,"gzFile(\"%s\") - %s",Z_STRVAL_PP(filename),strerror(errno)); RETURN_FALSE; @@ -341,7 +341,7 @@ convert_to_string_ex(arg2); p = estrndup(Z_STRVAL_PP(arg2),Z_STRLEN_PP(arg2)); - stream = php_stream_gzopen(NULL, Z_STRVAL_PP(arg1), p, use_include_path|ENFORCE_SAFE_MODE, NULL STREAMS_CC TSRMLS_CC); + stream = php_stream_gzopen(NULL, Z_STRVAL_PP(arg1), p, use_include_path|ENFORCE_SAFE_MODE, NULL, NULL STREAMS_CC TSRMLS_CC); if (!stream) { RETURN_FALSE; } @@ -382,7 +382,7 @@ } convert_to_string_ex(arg1); - stream = php_stream_gzopen(NULL, Z_STRVAL_PP(arg1), "rb", use_include_path|ENFORCE_SAFE_MODE, NULL STREAMS_CC TSRMLS_CC); + stream = php_stream_gzopen(NULL, Z_STRVAL_PP(arg1), "rb", use_include_path|ENFORCE_SAFE_MODE, NULL, NULL STREAMS_CC TSRMLS_CC); if (!stream) { RETURN_FALSE; } Index: php4/ext/zlib/zlib_fopen_wrapper.c diff -u php4/ext/zlib/zlib_fopen_wrapper.c:1.23 php4/ext/zlib/zlib_fopen_wrapper.c:1.24 --- php4/ext/zlib/zlib_fopen_wrapper.c:1.23 Sat Apr 6 12:29:39 2002 +++ php4/ext/zlib/zlib_fopen_wrapper.c Wed Apr 10 18:42:27 2002 @@ -16,7 +16,7 @@ | Hartmut Holzgraefe <hartmut@six.de> | +----------------------------------------------------------------------+ */ -/* $Id: zlib_fopen_wrapper.c,v 1.23 2002/04/06 17:29:39 wez Exp $ */ +/* $Id: zlib_fopen_wrapper.c,v 1.24 2002/04/10 22:42:27 wez Exp $ */ #define IS_EXT_MODULE #define _GNU_SOURCE @@ -93,7 +93,8 @@ NULL, NULL }; -php_stream *php_stream_gzopen(php_stream_wrapper *wrapper, char *path, char *mode, int options, char **opened_path STREAMS_DC TSRMLS_DC) +php_stream *php_stream_gzopen(php_stream_wrapper *wrapper, char *path, char *mode, + int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) { struct php_gz_stream_data_t *self; php_stream *stream = NULL; Index: php4/main/main.c diff -u php4/main/main.c:1.443 php4/main/main.c:1.444 --- php4/main/main.c:1.443 Tue Apr 9 21:27:44 2002 +++ php4/main/main.c Wed Apr 10 18:42:28 2002 @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: main.c,v 1.443 2002/04/10 01:27:44 helly Exp $ */ +/* $Id: main.c,v 1.444 2002/04/10 22:42:28 wez Exp $ */ /* {{{ includes */ @@ -594,16 +594,9 @@ */ static FILE *php_fopen_wrapper_for_zend(const char *filename, char **opened_path) { - FILE *retval = NULL; - size_t old_chunk_size; TSRMLS_FETCH(); - old_chunk_size = FG(def_chunk_size); - FG(def_chunk_size) = 1; - retval = php_stream_open_wrapper_as_file((char *)filename, "rb", USE_PATH|IGNORE_URL_WIN|REPORT_ERRORS, opened_path); - FG(def_chunk_size) = old_chunk_size; - - return retval; + return php_stream_open_wrapper_as_file((char *)filename, "rb", USE_PATH|IGNORE_URL_WIN|REPORT_ERRORS, opened_path); } /* }}} */ Index: php4/main/network.c diff -u php4/main/network.c:1.44 php4/main/network.c:1.45 --- php4/main/network.c:1.44 Wed Mar 27 19:49:00 2002 +++ php4/main/network.c Wed Apr 10 18:42:28 2002 @@ -15,7 +15,7 @@ | Author: Stig Venaas <venaas@uninett.no> | +----------------------------------------------------------------------+ */ -/* $Id: network.c,v 1.44 2002/03/28 00:49:00 wez Exp $ */ +/* $Id: network.c,v 1.45 2002/04/10 22:42:28 wez Exp $ */ #define MAX_CHUNKS_PER_READ 10 @@ -574,11 +574,18 @@ static size_t php_sockop_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC) { php_netstream_data_t *sock = (php_netstream_data_t*)stream->abstract; + size_t didwrite; + #if HAVE_OPENSSL_EXT if (sock->ssl_active) - return SSL_write(sock->ssl_handle, buf, count); + didwrite = SSL_write(sock->ssl_handle, buf, count); + else #endif - return send(sock->socket, buf, count, 0); + didwrite = send(sock->socket, buf, count, 0); + + php_stream_notify_progress_increment(stream->context, didwrite, 0); + + return didwrite; } static void php_sock_stream_wait_for_data(php_stream *stream, php_netstream_data_t *sock TSRMLS_DC) { @@ -638,6 +645,8 @@ nr_bytes = recv(sock->socket, buf, sock->chunk_size, 0); if(nr_bytes > 0) { + php_stream_notify_progress_increment(stream->context, nr_bytes, 0); + /* try to avoid ever expanding buffer */ if (sock->readpos > 0) { memmove(sock->readbuf, READPTR(sock), sock->readbuflen - sock->readpos); @@ -669,7 +678,10 @@ for(i = 0; !sock->eof && i < MAX_CHUNKS_PER_READ; i++) { nr_bytes = php_sock_stream_read_internal(stream, sock TSRMLS_CC); - if(nr_bytes == 0) break; + if(nr_bytes == 0) + break; + + nr_read += nr_bytes; } Index: php4/main/php_streams.h diff -u php4/main/php_streams.h:1.27 php4/main/php_streams.h:1.28 --- php4/main/php_streams.h:1.27 Wed Mar 27 19:49:00 2002 +++ php4/main/php_streams.h Wed Apr 10 18:42:29 2002 @@ -69,7 +69,8 @@ #define php_stream_fopen_temporary_file_rel(dir, pfx, opened_path) _php_stream_fopen_temporary_file((dir), (pfx), (opened_path) STREAMS_REL_CC TSRMLS_CC) -#define php_stream_open_wrapper_rel(path, mode, options, opened) _php_stream_open_wrapper((path), (mode), (options), (opened) STREAMS_REL_CC TSRMLS_CC) +#define php_stream_open_wrapper_rel(path, mode, options, opened) _php_stream_open_wrapper_ex((path), (mode), (options), (opened), NULL STREAMS_REL_CC TSRMLS_CC) +#define php_stream_open_wrapper_ex_rel(path, mode, options, opened, context) _php_stream_open_wrapper_ex((path), (mode), (options), (opened), (context) STREAMS_REL_CC TSRMLS_CC) #define php_stream_make_seekable_rel(origstream, newstream, flags) _php_stream_make_seekable((origstream), (newstream), (flags) STREAMS_REL_CC TSRMLS_CC) @@ -85,16 +86,48 @@ * the php_stream->abstract pointer to hold their context, and streams * opened via stream_open_wrappers can use the zval ptr in * php_stream->wrapperdata to hold meta data for php scripts to - * retrieve using fgetwrapperdata(). */ + * retrieve using file_get_wrapper_data(). */ typedef struct _php_stream php_stream; typedef struct _php_stream_wrapper php_stream_wrapper; +typedef struct _php_stream_context php_stream_context; + +/* callback for status notifications */ +typedef void (*php_stream_notification_func)(php_stream_context *context, + int notifycode, int severity, + char *xmsg, int xcode, + size_t bytes_sofar, size_t bytes_max, + void * ptr TSRMLS_DC); typedef struct _php_stream_statbuf { struct stat sb; /* regular info */ /* extended info to go here some day */ } php_stream_statbuf; +#define PHP_STREAM_NOTIFIER_PROGRESS 1 + +typedef struct _php_stream_notifier { + php_stream_notification_func func; + void *ptr; + int mask; + size_t progress, progress_max; /* position for progress notification */ +} php_stream_notifier; + +struct _php_stream_context { + php_stream_notifier *notifier; + +}; + +typedef struct _php_stream_wrapper_options { + int valid_options; /* PHP_STREAM_WRAPPER_OPT_XXX */ + + php_stream_notification_func notifier; + void *notifier_ptr; + + /* other info like user-agent, SSL cert and cookie information + * to go here some day */ +} php_stream_wrapper_options; + typedef struct _php_stream_ops { /* stdio like functions - these are mandatory! */ size_t (*write)(php_stream *stream, const char *buf, size_t count TSRMLS_DC); @@ -114,7 +147,7 @@ typedef struct _php_stream_wrapper_ops { /* open/create a wrapped stream */ php_stream *(*opener)(php_stream_wrapper *wrapper, char *filename, char *mode, - int options, char **opened_path STREAMS_DC TSRMLS_DC); + int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); /* close/destroy a wrapped stream */ int (*closer)(php_stream_wrapper *wrapper, php_stream *stream TSRMLS_DC); /* stat a wrapped stream */ @@ -128,6 +161,7 @@ void *abstract; /* context for the wrapper */ }; + struct _php_stream { php_stream_ops *ops; void *abstract; /* convenience pointer for abstraction */ @@ -148,6 +182,9 @@ #if ZEND_DEBUG int __exposed; /* non-zero if exposed as a zval somewhere */ #endif + + php_stream_context *context; + }; /* php_stream */ /* state definitions when closing down; these are private to streams.c */ #define PHP_STREAM_FCLOSE_NONE 0 @@ -305,8 +342,10 @@ int php_shutdown_stream_wrappers(TSRMLS_D); PHPAPI int php_register_url_stream_wrapper(char *protocol, php_stream_wrapper *wrapper TSRMLS_DC); PHPAPI int php_unregister_url_stream_wrapper(char *protocol TSRMLS_DC); -PHPAPI php_stream *_php_stream_open_wrapper(char *path, char *mode, int options, char **opened_path STREAMS_DC TSRMLS_DC); -#define php_stream_open_wrapper(path, mode, options, opened) _php_stream_open_wrapper((path), (mode), (options), (opened) STREAMS_CC TSRMLS_CC) +PHPAPI php_stream *_php_stream_open_wrapper_ex(char *path, char *mode, int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC); + +#define php_stream_open_wrapper(path, mode, options, opened) _php_stream_open_wrapper_ex((path), (mode), (options), (opened), NULL STREAMS_CC TSRMLS_CC) +#define php_stream_open_wrapper_ex(path, mode, options, opened, context) _php_stream_open_wrapper_ex((path), (mode), (options), (opened), (context) STREAMS_CC TSRMLS_CC) #define PHP_STREAM_UNCHANGED 0 /* orig stream was seekable anyway */ #define PHP_STREAM_RELEASED 1 /* newstream should be used; origstream is no longer valid */ @@ -328,6 +367,58 @@ extern php_stream_ops php_stream_userspace_ops; #define PHP_STREAM_IS_USERSPACE &php_stream_userspace_ops +PHPAPI void php_stream_context_free(php_stream_context *context); +PHPAPI php_stream_context *php_stream_context_alloc(void); + +PHPAPI php_stream_notifier *php_stream_notification_alloc(void); +PHPAPI void php_stream_notification_free(php_stream_notifier *notifier); + +#define PHP_STREAM_NOTIFY_RESOLVE 1 +#define PHP_STREAM_NOTIFY_CONNECT 2 +#define PHP_STREAM_NOTIFY_AUTH_REQUIRED 3 +#define PHP_STREAM_NOTIFY_MIME_TYPE_IS 4 +#define PHP_STREAM_NOTIFY_FILE_SIZE_IS 5 +#define PHP_STREAM_NOTIFY_REDIRECTED 6 +#define PHP_STREAM_NOTIFY_PROGRESS 7 +#define PHP_STREAM_NOTIFY_COMPLETED 8 +#define PHP_STREAM_NOTIFY_FAILURE 9 +#define PHP_STREAM_NOTIFY_AUTH_RESULT 10 + +#define PHP_STREAM_NOTIFY_SEVERITY_INFO 0 +#define PHP_STREAM_NOTIFY_SEVERITY_WARN 1 +#define PHP_STREAM_NOTIFY_SEVERITY_ERR 2 + +PHPAPI void php_stream_notification_notify(php_stream_context *context, int notifycode, int severity, + char *xmsg, int xcode, size_t bytes_sofar, size_t bytes_max, void * ptr TSRMLS_DC); +PHPAPI php_stream_context *php_stream_context_set(php_stream *stream, php_stream_context *context); + +#define php_stream_notify_info(context, code, xmsg, xcode) do { if ((context) && (context)->notifier) { \ + php_stream_notification_notify((context), (code), PHP_STREAM_NOTIFY_SEVERITY_INFO, \ + (xmsg), (xcode), 0, 0, NULL TSRMLS_CC); } } while (0) + +#define php_stream_notify_progress(context, bsofar, bmax) do { if ((context) && (context)->notifier) { \ + php_stream_notification_notify((context), PHP_STREAM_NOTIFY_PROGRESS, PHP_STREAM_NOTIFY_SEVERITY_INFO, \ + NULL, 0, (bsofar), (bmax), NULL TSRMLS_CC); } } while(0) + +#define php_stream_notify_progress_init(context, sofar, bmax) do { if ((context)->notifier) { \ + (context)->notifier->progress = (sofar); \ + (context)->notifier->progress_max = (bmax); \ + (context)->notifier->mask |= PHP_STREAM_NOTIFIER_PROGRESS; \ + php_stream_notify_progress((context), (sofar), (bmax)); } } while (0) + +#define php_stream_notify_progress_increment(context, dsofar, dmax) do { if ((context) && (context)->notifier && (context)->notifier->mask & PHP_STREAM_NOTIFIER_PROGRESS) { \ + (context)->notifier->progress += (dsofar); \ + (context)->notifier->progress_max += (dmax); \ + php_stream_notify_progress((context), (context)->notifier->progress, (context)->notifier->progress_max); } } while (0) + +#define php_stream_notify_file_size(context, file_size, xmsg, xcode) do { if ((context) && (context)->notifier) { \ + php_stream_notification_notify((context), PHP_STREAM_NOTIFY_FILE_SIZE_IS, PHP_STREAM_NOTIFY_SEVERITY_INFO, \ + (xmsg), (xcode), 0, (file_size), NULL TSRMLS_CC); } } while(0) + +#define php_stream_notify_error(context, code, xmsg, xcode) do { if ((context) && (context)->notifier) {\ + php_stream_notification_notify((context), (code), PHP_STREAM_NOTIFY_SEVERITY_ERR, \ + (xmsg), (xcode), 0, 0, NULL TSRMLS_CC); } } while(0) + #endif /* Index: php4/main/streams.c diff -u php4/main/streams.c:1.46 php4/main/streams.c:1.47 --- php4/main/streams.c:1.46 Sat Apr 6 12:29:38 2002 +++ php4/main/streams.c Wed Apr 10 18:42:29 2002 @@ -1069,7 +1069,8 @@ /* }}} */ /* {{{ php_stream_open_url */ -static php_stream *php_stream_open_url(char *path, char *mode, int options, char **opened_path STREAMS_DC TSRMLS_DC) +static php_stream *php_stream_open_url(char *path, char *mode, int options, + char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) { php_stream_wrapper *wrapper; const char *p, *protocol = NULL; @@ -1085,7 +1086,7 @@ /* BC with older php scripts and zlib wrapper */ protocol = path; n = 4; - zend_error(E_NOTICE, "Use of \"zlib:\" wrapper is deprecated; please use \"zlib://\" instead."); + zend_error(E_WARNING, "Use of \"zlib:\" wrapper is deprecated; please use \"zlib://\" instead."); } if (protocol) { @@ -1103,7 +1104,7 @@ protocol = NULL; } if (wrapper) { - php_stream *stream = wrapper->wops->opener(wrapper, path, mode, options, opened_path STREAMS_REL_CC TSRMLS_CC); + php_stream *stream = wrapper->wops->opener(wrapper, path, mode, options, opened_path, context STREAMS_REL_CC TSRMLS_CC); if (stream) stream->wrapper = wrapper; return stream; @@ -1126,8 +1127,9 @@ } /* }}} */ -/* {{{ php_stream_open_wrapper */ -PHPAPI php_stream *_php_stream_open_wrapper(char *path, char *mode, int options, char **opened_path STREAMS_DC TSRMLS_DC) +/* {{{ php_stream_open_wrapper_ex */ +PHPAPI php_stream *_php_stream_open_wrapper_ex(char *path, char *mode, int options, + char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC) { php_stream *stream = NULL; @@ -1138,7 +1140,7 @@ return NULL; if (PG(allow_url_fopen) && !(options & IGNORE_URL)) { - stream = php_stream_open_url(path, mode, options, opened_path STREAMS_REL_CC TSRMLS_CC); + stream = php_stream_open_url(path, mode, options, opened_path, context STREAMS_REL_CC TSRMLS_CC); goto out; } @@ -1242,6 +1244,41 @@ return PHP_STREAM_RELEASED; } /* }}} */ + +PHPAPI php_stream_context *php_stream_context_set(php_stream *stream, php_stream_context *context) +{ + php_stream_context *oldcontext = stream->context; + stream->context = context; + return oldcontext; +} + +PHPAPI void php_stream_notification_notify(php_stream_context *context, int notifycode, int severity, + char *xmsg, int xcode, size_t bytes_sofar, size_t bytes_max, void * ptr TSRMLS_DC) +{ + if (context && context->notifier) + context->notifier->func(context, notifycode, severity, xmsg, xcode, bytes_sofar, bytes_max, ptr TSRMLS_CC); +} + +PHPAPI void php_stream_context_free(php_stream_context *context) +{ + efree(context); +} + +PHPAPI php_stream_context *php_stream_context_alloc(void) +{ + return ecalloc(1, sizeof(php_stream_context)); +} + +PHPAPI php_stream_notifier *php_stream_notification_alloc(void) +{ + return ecalloc(1, sizeof(php_stream_notifier)); +} + +PHPAPI void php_stream_notification_free(php_stream_notifier *notifier) +{ + efree(notifier); +} + /* * Local variables: Index: php4/main/user_streams.c diff -u php4/main/user_streams.c:1.10 php4/main/user_streams.c:1.11 --- php4/main/user_streams.c:1.10 Thu Mar 28 20:19:02 2002 +++ php4/main/user_streams.c Wed Apr 10 18:42:30 2002 @@ -29,7 +29,7 @@ php_stream_wrapper wrapper; }; -static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, char *filename, char *mode, int options, char **opened_path STREAMS_DC TSRMLS_DC); +static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, char *filename, char *mode, int options, char **opened_path, php_stream_wrapper_options *exoptions STREAMS_DC TSRMLS_DC); static php_stream_wrapper_ops user_stream_wops = { user_wrapper_opener, @@ -115,7 +115,7 @@ * */ -static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, char *filename, char *mode, int options, char **opened_path STREAMS_DC TSRMLS_DC) +static php_stream *user_wrapper_opener(php_stream_wrapper *wrapper, char *filename, char *mode, int options, char **opened_path, php_stream_wrapper_options *exoptions STREAMS_DC TSRMLS_DC) { struct php_user_stream_wrapper *uwrap = (struct php_user_stream_wrapper*)wrapper->abstract; php_userstream_data_t *us;