lbarnaud Thu Sep 11 11:51:07 2008 UTC Modified files: /php-src/ext/session php_session.h session.c Log: Implemented ability to provide upload progress feedback through session data.
http://cvs.php.net/viewvc.cgi/php-src/ext/session/php_session.h?r1=1.116&r2=1.117&diff_format=u Index: php-src/ext/session/php_session.h diff -u php-src/ext/session/php_session.h:1.116 php-src/ext/session/php_session.h:1.117 --- php-src/ext/session/php_session.h:1.116 Fri Mar 7 23:20:15 2008 +++ php-src/ext/session/php_session.h Thu Sep 11 11:51:07 2008 @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_session.h,v 1.116 2008/03/07 23:20:15 gwynne Exp $ */ +/* $Id: php_session.h,v 1.117 2008/09/11 11:51:07 lbarnaud Exp $ */ #ifndef PHP_SESSION_H #define PHP_SESSION_H @@ -95,6 +95,23 @@ php_session_active } php_session_status; +typedef struct _php_session_rfc1867_progress { + zval prefix; + zval name; + zval sname; + zval sid; + zval key; + long update_step; + long next_update; + zval *data; + size_t content_length; + zval *post_bytes_processed; + zval *files; + zval *current_file; + zval *current_file_bytes_processed; + zend_bool apply_trans_sid; +} php_session_rfc1867_progress; + typedef struct _php_ps_globals { char *save_path; char *session_name; @@ -143,6 +160,12 @@ int send_cookie; int define_sid; zend_bool invalid_session_id; /* allows the driver to report about an invalid session id and request id regeneration */ + + zend_bool rfc1867_enabled; + zstr rfc1867_prefix; + zstr rfc1867_name; + long rfc1867_freq; + php_session_rfc1867_progress *rfc1867_progress; } php_ps_globals; typedef php_ps_globals zend_ps_globals; http://cvs.php.net/viewvc.cgi/php-src/ext/session/session.c?r1=1.492&r2=1.493&diff_format=u Index: php-src/ext/session/session.c diff -u php-src/ext/session/session.c:1.492 php-src/ext/session/session.c:1.493 --- php-src/ext/session/session.c:1.492 Wed Aug 6 05:34:55 2008 +++ php-src/ext/session/session.c Thu Sep 11 11:51:07 2008 @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: session.c,v 1.492 2008/08/06 05:34:55 jani Exp $ */ +/* $Id: session.c,v 1.493 2008/09/11 11:51:07 lbarnaud Exp $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -36,6 +36,8 @@ #include "php_ini.h" #include "SAPI.h" +#include "rfc1867.h" +#include "php_variables.h" #include "php_session.h" #include "ext/standard/md5.h" #include "ext/standard/sha1.h" @@ -57,6 +59,9 @@ PHPAPI ZEND_DECLARE_MODULE_GLOBALS(ps); +static int (*php_session_rfc1867_orig_callback)(unsigned int event, void *event_data, void **extra TSRMLS_DC); +static int php_session_rfc1867_callback(unsigned int event, void *event_data, void **extra TSRMLS_DC); + /* *********** * Helpers * *********** */ @@ -630,12 +635,32 @@ return SUCCESS; } } -#endif /* HAVE_HASH_EXT */ +#endif /* HAVE_HASH_EXT }}} */ return FAILURE; } /* }}} */ +static PHP_INI_MH(OnUpdateRfc1867Freq) /* {{{ */ +{ + int tmp; + tmp = zend_atoi(new_value, new_value_length); + if(tmp < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "session.upload_progress.freq must be greater than or equal to zero"); + return FAILURE; + } + if(new_value_length > 0 && new_value[new_value_length-1] == '%') { + if(tmp > 100) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "session.upload_progress.freq cannot be over 100%%"); + return FAILURE; + } + PS(rfc1867_freq) = -tmp; + } else { + PS(rfc1867_freq) = tmp; + } + return SUCCESS; +} /* }}} */ + /* {{{ PHP_INI */ PHP_INI_BEGIN() @@ -663,6 +688,15 @@ PHP_INI_ENTRY("session.hash_function", "0", PHP_INI_ALL, OnUpdateHashFunc) STD_PHP_INI_ENTRY("session.hash_bits_per_character", "4", PHP_INI_ALL, OnUpdateLong, hash_bits_per_character, php_ps_globals, ps_globals) + /* Upload progress */ + STD_PHP_INI_BOOLEAN("session.upload_progress.enabled", + "1", ZEND_INI_PERDIR, OnUpdateBool, rfc1867_enabled, php_ps_globals, ps_globals) + STD_PHP_INI_ENTRY("session.upload_progress.prefix", + "upload_progress_", ZEND_INI_PERDIR, OnUpdateUTF8String, rfc1867_prefix, php_ps_globals, ps_globals) + STD_PHP_INI_ENTRY("session.upload_progress.name", + "PHP_SESSION_UPLOAD_PROGRESS", ZEND_INI_PERDIR, OnUpdateUTF8String, rfc1867_name, php_ps_globals, ps_globals) + STD_PHP_INI_ENTRY("session.upload_progress.freq", "1%", ZEND_INI_PERDIR, OnUpdateRfc1867Freq, rfc1867_freq, php_ps_globals, ps_globals) + /* Commented out until future discussion */ /* PHP_INI_ENTRY("session.encode_sources", "globals,track", PHP_INI_ALL, NULL) */ PHP_INI_END() @@ -1917,7 +1951,7 @@ * Module Setup and Destruction * ******************************** */ -static PHP_RINIT_FUNCTION(session) /* {{{ */ +static inline int php_rinit_session(zend_bool auto_start TSRMLS_DC) /* {{{ */ { php_rinit_session_globals(TSRMLS_C); @@ -1945,11 +1979,16 @@ return SUCCESS; } - if (PS(auto_start)) { + if (auto_start) { php_session_start(TSRMLS_C); } return SUCCESS; +} /* }}} */ + +static PHP_RINIT_FUNCTION(session) /* {{{ */ +{ + return php_rinit_session(PS(auto_start) TSRMLS_CC); } /* }}} */ @@ -2002,6 +2041,8 @@ #ifdef HAVE_LIBMM PHP_MINIT(ps_mm) (INIT_FUNC_ARGS_PASSTHRU); #endif + php_session_rfc1867_orig_callback = php_rfc1867_callback; + php_rfc1867_callback = php_session_rfc1867_callback; return SUCCESS; } /* }}} */ @@ -2070,6 +2111,250 @@ } /* }}} */ +/* ************************ + * Upload hook handling * + ************************ */ + +#define USTR_EQUAL(s1, len1, s2, len2) \ + ((len1) == (len2) && \ + (UG(unicode) ? \ + (zend_u_binary_strcmp((s1).u, (len1), (s2).u, (len2)) == 0) \ + : (zend_binary_strcmp((s1).s, (len1), (s2).s, (len2)) == 0))) + +static inline void php_session_rfc1867_early_find_sid(php_session_rfc1867_progress *progress TSRMLS_DC) /* {{{ */ +{ + zval **ppid; + + if (PS(use_cookies)) { + sapi_module.treat_data(PARSE_COOKIE, NULL, NULL TSRMLS_CC); + if (PG(http_globals)[TRACK_VARS_COOKIE] + && zend_u_hash_find(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_COOKIE]), Z_TYPE(progress->sname), Z_UNIVAL(progress->sname), Z_UNILEN(progress->sname)+1, (void **)&ppid) == SUCCESS) { + + zval_dtor(&progress->sid); + ZVAL_ZVAL(&progress->sid, *ppid, 1, 0); + convert_to_string(&progress->sid); + progress->apply_trans_sid = 0; + return; + } + } + if (PS(use_only_cookies)) { + return; + } + sapi_module.treat_data(PARSE_GET, NULL, NULL TSRMLS_CC); + if (PG(http_globals)[TRACK_VARS_GET] + && zend_u_hash_find(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_GET]), Z_TYPE(progress->sname), Z_UNIVAL(progress->sname), Z_UNILEN(progress->sname)+1, (void **)&ppid) == SUCCESS) { + + zval_dtor(&progress->sid); + ZVAL_ZVAL(&progress->sid, *ppid, 1, 0); + convert_to_string(&progress->sid); + } +} /* }}} */ + +static inline void php_session_rfc1867_update(php_session_rfc1867_progress *progress TSRMLS_DC) /* {{{ */ +{ + php_session_initialize(TSRMLS_C); + PS(session_status) = php_session_active; + IF_SESSION_VARS() { + Z_ADDREF_P(progress->data); + zend_u_symtable_update(Z_ARRVAL_P(PS(http_session_vars)), Z_TYPE(progress->key), Z_UNIVAL(progress->key), Z_UNILEN(progress->key)+1, &progress->data, sizeof(zval *), NULL); + } + php_session_flush(TSRMLS_C); +} /* }}} */ + +static int php_session_rfc1867_callback(unsigned int event, void *event_data, void **extra TSRMLS_DC) /* {{{ */ +{ + php_session_rfc1867_progress *progress; + int retval = SUCCESS; + + if (php_session_rfc1867_orig_callback) { + retval = php_session_rfc1867_orig_callback(event, event_data, extra TSRMLS_CC); + } + if (!PS(rfc1867_enabled)) { + return retval; + } + + progress = PS(rfc1867_progress); + + switch(event) { + case MULTIPART_EVENT_START: { + multipart_event_start *data = (multipart_event_start *) event_data; + + progress = ecalloc(1, sizeof(php_session_rfc1867_progress)); + progress->content_length = data->content_length; + + /* We need to have a runtime-encoding encoded PS(session_name) so that + * we can compare to incomming POST variables name. zvals also allow + * to keep track of length. */ + ZVAL_RT_STRING(&progress->sname, PS(session_name), ZSTR_DUPLICATE); + ZVAL_TEXT(&progress->prefix, PS(rfc1867_prefix), 0); + ZVAL_TEXT(&progress->name, PS(rfc1867_name), 0); + + PS(rfc1867_progress) = progress; + } + break; + case MULTIPART_EVENT_FORMDATA: { + multipart_event_formdata *data = (multipart_event_formdata *) event_data; + size_t name_len, value_len; + zstr str; + + /* orig callback may have modified *data->newlength */ + if (data->newlength) { + value_len = *data->newlength; + } else { + value_len = data->length; + } + + /* Search PS(session_name) and PS(rfc1867_name) in incomming POST variables */ + if (data->name.v && data->value && value_len) { + name_len = USTR_LEN(data->name); + + if (USTR_EQUAL(Z_UNIVAL(progress->sname), Z_UNILEN(progress->sname), data->name, name_len)) { + zval_dtor(&progress->sid); + ZVAL_TEXTL(&progress->sid, (*data->value), value_len, ZSTR_DUPLICATE); + convert_to_string(&progress->sid); + + } else if (USTR_EQUAL(Z_UNIVAL(progress->name), Z_UNILEN(progress->name), data->name, name_len)) { + size_t len = Z_UNILEN(progress->prefix) + value_len; + str.v = emalloc(TEXT_BYTES(len+1)); + memcpy(str.s, Z_UNIVAL(progress->prefix).v, TEXT_BYTES(Z_UNILEN(progress->prefix))); + memcpy(str.s+TEXT_BYTES(Z_UNILEN(progress->prefix)), (*data->value).v, TEXT_BYTES(value_len+1)); + + zval_dtor(&progress->key); + ZVAL_TEXTL(&progress->key, str, len, 0); + + progress->apply_trans_sid = PS(use_trans_sid); + php_session_rfc1867_early_find_sid(progress TSRMLS_CC); + } + } + } + break; + case MULTIPART_EVENT_FILE_START: { + multipart_event_file_start *data = (multipart_event_file_start *) event_data; + + /* Do nothing when $_POST[session.upload_progress.name] is not set + * or when no session id was sent */ + if (!Z_TYPE(progress->sid) || !Z_TYPE(progress->key)) { + break; + } + + /* First FILE_START event, initializing */ + if (!progress->data) { + + php_rinit_session(0 TSRMLS_CC); + PS(id) = estrndup(Z_STRVAL(progress->sid), Z_STRLEN(progress->sid)); + PS(apply_trans_sid) = progress->apply_trans_sid; + PS(send_cookie) = 0; + + if (PS(rfc1867_freq) >= 0) { + progress->update_step = PS(rfc1867_freq); + } else if (PS(rfc1867_freq) < 0) { /* % of total size */ + progress->update_step = progress->content_length * -PS(rfc1867_freq) / 100; + } + progress->next_update = 0; + + ALLOC_INIT_ZVAL(progress->data); + array_init(progress->data); + + ALLOC_INIT_ZVAL(progress->post_bytes_processed); + ZVAL_LONG(progress->post_bytes_processed, data->post_bytes_processed); + + ALLOC_INIT_ZVAL(progress->files); + array_init(progress->files); + + add_ascii_assoc_long_ex(progress->data, "start_time", sizeof("start_time"), (long)sapi_get_request_time(TSRMLS_C)); + add_ascii_assoc_long_ex(progress->data, "content_length", sizeof("content_length"), progress->content_length); + add_ascii_assoc_zval_ex(progress->data, "bytes_processed", sizeof("bytes_processed"), progress->post_bytes_processed); + add_ascii_assoc_bool_ex(progress->data, "done", sizeof("done"), 0); + add_ascii_assoc_zval_ex(progress->data, "files", sizeof("files"), progress->files); + } + + ALLOC_INIT_ZVAL(progress->current_file); + array_init(progress->current_file); + + ALLOC_INIT_ZVAL(progress->current_file_bytes_processed); + ZVAL_LONG(progress->current_file_bytes_processed, 0); + + add_ascii_assoc_text_ex(progress->current_file, "field_name", sizeof("field_name"), data->name, 1); + add_ascii_assoc_text_ex(progress->current_file, "name", sizeof("name"), *data->filename, 1); + add_ascii_assoc_null_ex(progress->current_file, "tmp_name", sizeof("tmp_name")); + add_ascii_assoc_long_ex(progress->current_file, "error", sizeof("error"), 0); + + add_ascii_assoc_long_ex(progress->current_file, "done", sizeof("done"), 0); + add_ascii_assoc_long_ex(progress->current_file, "start_time", sizeof("start_time"), (long)time(NULL)); + add_ascii_assoc_zval_ex(progress->current_file, "bytes_processed", sizeof("bytes_processed"), progress->current_file_bytes_processed); + + add_next_index_zval(progress->files, progress->current_file); + + Z_LVAL_P(progress->post_bytes_processed) = data->post_bytes_processed; + + if (data->post_bytes_processed >= progress->next_update) { + php_session_rfc1867_update(progress TSRMLS_CC); + progress->next_update = data->post_bytes_processed + progress->update_step; + } + } + break; + case MULTIPART_EVENT_FILE_DATA: { + multipart_event_file_data *data = (multipart_event_file_data *) event_data; + + if (!Z_TYPE(progress->sid) || !Z_TYPE(progress->key)) { + break; + } + + Z_LVAL_P(progress->current_file_bytes_processed) = data->offset + data->length; + Z_LVAL_P(progress->post_bytes_processed) = data->post_bytes_processed; + + if (data->post_bytes_processed >= progress->next_update) { + php_session_rfc1867_update(progress TSRMLS_CC); + progress->next_update = data->post_bytes_processed + progress->update_step; + } + } + break; + case MULTIPART_EVENT_FILE_END: { + multipart_event_file_end *data = (multipart_event_file_end *) event_data; + + if (!Z_TYPE(progress->sid) || !Z_TYPE(progress->key)) { + break; + } + + if (data->temp_filename.v) { + add_ascii_assoc_text_ex(progress->current_file, "tmp_name", sizeof("tmp_name"), data->temp_filename, 1); + } + add_ascii_assoc_long_ex(progress->current_file, "error", sizeof("error"), data->cancel_upload); + add_ascii_assoc_bool_ex(progress->current_file, "done", sizeof("done"), 1); + + Z_LVAL_P(progress->post_bytes_processed) = data->post_bytes_processed; + + if (data->post_bytes_processed >= progress->next_update) { + php_session_rfc1867_update(progress TSRMLS_CC); + progress->next_update = data->post_bytes_processed + progress->update_step; + } + } + break; + case MULTIPART_EVENT_END: { + multipart_event_end *data = (multipart_event_end *) event_data; + + if (Z_TYPE(progress->sid) && Z_TYPE(progress->key)) { + add_ascii_assoc_bool_ex(progress->data, "done", sizeof("done"), 1); + Z_LVAL_P(progress->post_bytes_processed) = data->post_bytes_processed; + php_session_rfc1867_update(progress TSRMLS_CC); + php_rshutdown_session_globals(TSRMLS_C); + } + + zval_dtor(&progress->sname); + zval_dtor(&progress->sid); + zval_dtor(&progress->key); + if (progress->data) { + zval_ptr_dtor(&progress->data); + } + efree(progress); + } + break; + } + + return retval; + +} /* }}} */ + zend_module_entry session_module_entry = { STANDARD_MODULE_HEADER, "session",
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php