]> granicus.if.org Git - php/commitdiff
Implement stream context and status notification system.
authorWez Furlong <wez@php.net>
Wed, 10 Apr 2002 22:42:32 +0000 (22:42 +0000)
committerWez Furlong <wez@php.net>
Wed, 10 Apr 2002 22:42:32 +0000 (22:42 +0000)
Bump the BC for zlib notice to a warning
# See my RFC to php-dev a few days ago

16 files changed:
ext/standard/Makefile.frag
ext/standard/basic_functions.c
ext/standard/file.c
ext/standard/file.h
ext/standard/ftp_fopen_wrapper.c
ext/standard/http_fopen_wrapper.c
ext/standard/php_fopen_wrapper.c
ext/standard/php_fopen_wrappers.h
ext/zlib/php_zlib.h
ext/zlib/zlib.c
ext/zlib/zlib_fopen_wrapper.c
main/main.c
main/network.c
main/php_streams.h
main/streams.c
main/user_streams.c

index 934f501e6cffcbd32254c19fc531cb2f5d002a22..d48cf2fd1897d2132a137ff0d0137bb3d22d8953 100644 (file)
@@ -6,3 +6,4 @@ $(srcdir)/var_unserializer.c: $(srcdir)/var_unserializer.re
 
 $(srcdir)/url_scanner_ex.c: $(srcdir)/url_scanner_ex.re
        re2c -b $(srcdir)/url_scanner_ex.re > $@
+
index 28b2357c932fc545d6047d6a63c6895fcec86f0f..3a1075030282f1ff98e0f94342369464ea6c1750 100644 (file)
@@ -595,6 +595,8 @@ function_entry basic_functions[] = {
        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 616dba829e3e2e491fd673ca325e65afa0e6f0c1..f5f33e61c895879d900ec48640be73bb13ec8d32 100644 (file)
@@ -109,10 +109,16 @@ php_file_globals file_globals;
 
 /* 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 @@ static void file_globals_dtor(php_file_globals *file_globals_p TSRMLS_DC)
 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 @@ PHP_MINIT_FUNCTION(file)
        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 @@ PHP_FUNCTION(file_get_wrapper_data)
 }
 /* }}} */
 
-/* {{{ proto resource fopen(string filename, string mode [, bool use_include_path])
-   Open a file or a URL and return a file pointer */
-PHP_NAMED_FUNCTION(php_if_fopen)
+/* {{{ 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 **arg1, **arg2, **arg3;
-       int use_include_path = 0;
-       php_stream *stream;
+       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]};
        
-       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;
+       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;
                }
-               convert_to_long_ex(arg3);
-               use_include_path = Z_LVAL_PP(arg3);
-               break;
-       default:
-               WRONG_PARAM_COUNT;
+
+               context->notifier = php_stream_notification_alloc();
+               context->notifier->func = user_space_stream_notifier;
+               context->notifier->ptr = *tmp;
+               ZVAL_ADDREF(*tmp);
        }
-       convert_to_string_ex(arg1);
-       convert_to_string_ex(arg2);
+       
+       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, &params) == 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", &params) == FAILURE) {
+               RETURN_FALSE;
+       }
+       
+       context = php_stream_context_alloc();
+       
+       if (params)
+               parse_context_options(context, params);
+       
+       ZEND_REGISTER_RESOURCE(return_value, context, le_stream_context);
+}
+/* }}} */
 
-       stream = php_stream_open_wrapper(Z_STRVAL_PP(arg1), Z_STRVAL_PP(arg2),
+/* {{{ 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)
+{
+       char *filename, *mode;
+       int filename_len, mode_len;
+       zend_bool use_include_path = 0;
+       zval *zcontext = NULL;
+       php_stream *stream;
+       php_stream_context *context = NULL;
+
+       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 @@ PHPAPI PHP_FUNCTION(fclose)
 }
 
 /* }}} */
+
 /* {{{ proto resource popen(string command, string mode)
    Execute a command and open either a read or a write pipe to it */
 
index 6d08e31ad993b846c95baa92fc3ad9a5c70f09c3..3261aaba08088d3fb42dfd09c7cb81ae87bf2a5a 100644 (file)
@@ -73,6 +73,8 @@ PHP_NAMED_FUNCTION(php_if_fstat);
 
 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 e7f6eef638e0ff224a749da38934ff155946c809..2f3db505936f5f27d08ea214a6793ca8bc7e6ef0 100644 (file)
 
 #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_stream_wrapper php_stream_ftp_wrapper = {
 
 /* {{{ 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 @@ php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, char *path, ch
        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 @@ php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, char *path, ch
        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 * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, char *path, ch
        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 * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, char *path, ch
                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 * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, char *path, ch
        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 @@ php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, char *path, ch
                        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 @@ php_stream * php_stream_url_wrap_ftp(php_stream_wrapper *wrapper, char *path, ch
        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 c96f43ddff218028bbe3dfb3392fae483e2bc033..994e60d719f000a5275abf2bc2f560d077fdb239 100644 (file)
@@ -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 @@ php_stream *php_stream_url_wrap_http(php_stream_wrapper *wrapper, char *path, ch
        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 @@ php_stream *php_stream_url_wrap_http(php_stream_wrapper *wrapper, char *path, ch
        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 @@ php_stream *php_stream_url_wrap_http(php_stream_wrapper *wrapper, char *path, ch
 
                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 @@ php_stream *php_stream_url_wrap_http(php_stream_wrapper *wrapper, char *path, ch
 
                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 @@ php_stream *php_stream_url_wrap_http(php_stream_wrapper *wrapper, char *path, ch
                        }
                        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 @@ php_stream *php_stream_url_wrap_http(php_stream_wrapper *wrapper, char *path, ch
        }
 
        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 @@ php_stream *php_stream_url_wrap_http(php_stream_wrapper *wrapper, char *path, ch
                        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 @@ php_stream *php_stream_url_wrap_http(php_stream_wrapper *wrapper, char *path, ch
                                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 @@ out:
                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 e7f07a9e9bd4c7975e5e5b725e2448f4324758d9..fcca4fce2dc0b13470e7ae364dea9fa1fd3dd19e 100644 (file)
@@ -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 7c82937d05fb4140c6e25209ef0c552c229aa0f0..392b88d063974fe6e6bf1edb53fe6d65b78a856f 100644 (file)
@@ -23,8 +23,8 @@
 #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 b33d57c06ee63edac60e453ec1a486f5c8745e3c..333eb1224b7b37842303428c503d06731ff9fd9b 100644 (file)
@@ -54,7 +54,7 @@ PHP_FUNCTION(ob_gzhandler);
 
 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 ea935d7917d05c93fc62eaf1c514ba6336906bd9..7031efa23be548da40352621d38205fb975c792a 100644 (file)
@@ -285,7 +285,7 @@ PHP_FUNCTION(gzfile)
        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 @@ PHP_FUNCTION(gzopen)
        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 @@ PHP_FUNCTION(readgzfile)
        }
        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 2ed6d3b01a65e15c87301ad81c1bb5234630aecd..bdc2b5a8822c1baf7d6725a983479827e5940d77 100644 (file)
@@ -93,7 +93,8 @@ php_stream_ops php_stream_gzio_ops = {
        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 01d16f2c84b1e8878bd769a7e0a7b3894080f76b..737507ac1d0ea54e61bd422ef7b4e7364c5c2493 100644 (file)
@@ -594,16 +594,9 @@ PHP_FUNCTION(set_time_limit)
  */
 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 7ed301a654a3d0e20e5b072cea6c3a9c327a1914..f2fcfa194870691d87c36795537aa145c787b3a3 100644 (file)
@@ -574,11 +574,18 @@ PHPAPI size_t php_stream_sock_set_chunk_size(php_stream *stream, size_t size TSR
 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 @@ static size_t php_sock_stream_read_internal(php_stream *stream, php_netstream_da
        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 @@ static size_t php_sock_stream_read(php_stream *stream, php_netstream_data_t *soc
 
        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 2243f07de4177b741bbf5b28c64d3cb2fdc8a26c..c5ef2acfdcf4c6ba9b1a2cbba06e2eca5577a374 100755 (executable)
@@ -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)
 
  * 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_ops  {
 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 @@ struct _php_stream_wrapper  {
        void *abstract;                                 /* context for the wrapper */
 };
 
+
 struct _php_stream  {
        php_stream_ops *ops;
        void *abstract;                 /* convenience pointer for abstraction */
@@ -148,6 +182,9 @@ struct _php_stream  {
 #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_init_stream_wrappers(TSRMLS_D);
 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 @@ PHPAPI FILE * _php_stream_open_wrapper_as_file(char * path, char * mode, int opt
 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 cc8c8789da82de6008a1bcbac91652a6201dc22a..3d4c18988d6f9a4ba32267e7e49af36894d7d822 100755 (executable)
@@ -1069,7 +1069,8 @@ PHPAPI int php_unregister_url_stream_wrapper(char *protocol TSRMLS_DC)
 /* }}} */
 
 /* {{{ 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 @@ static php_stream *php_stream_open_url(char *path, char *mode, int options, char
                /* 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 @@ static php_stream *php_stream_open_url(char *path, char *mode, int options, char
                        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 @@ static php_stream *php_stream_open_url(char *path, char *mode, int options, char
 }
 /* }}} */
 
-/* {{{ 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 @@ PHPAPI php_stream *_php_stream_open_wrapper(char *path, char *mode, int options,
                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;
        }
 
@@ -1243,6 +1245,41 @@ PHPAPI int _php_stream_make_seekable(php_stream *origstream, php_stream **newstr
 }
 /* }}} */
 
+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:
  * tab-width: 4
index 4aed5d99ac1332c1c92f10da46e4765253bb65f0..7f9a2c2701a9d8c357e56f58f85d05e8ae0655f0 100644 (file)
@@ -29,7 +29,7 @@ struct php_user_stream_wrapper {
        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 @@ function stream_open($path, $mode, $options, &$opened_path)
    
  * */
 
-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;