/* +----------------------------------------------------------------------+ | PHP Version 4 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2003 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 2.02 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available at through the world-wide-web at | | http://www.php.net/license/2_02.txt. | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Christian Stocker (chregu@bitflux.ch) | | Derived from: Doru Petrescu (pdoru-php-upm@kappa.ro) Â Â | | http://pdoru.from.ro/upload-progress-meter/ | +----------------------------------------------------------------------+ $Id: uploadprogress.c,v 1.1 2006/12/05 12:00:12 chregu Exp $ */ /* $ Id: $ */ #include "php_uploadprogress.h" #include "rfc1867.h" #if HAVE_UPLOADPROGRESS /* {{{ uploadprogress_functions[] */ function_entry uploadprogress_functions[] = { PHP_FE(uploadprogress_get_info, NULL) { NULL, NULL, NULL } }; /* }}} */ PHP_INI_BEGIN() PHP_INI_ENTRY("uploadprogress.file.filename_template", "/tmp/upt_%s.txt", PHP_INI_ALL, NULL) PHP_INI_END() /* {{{ uploadprogress_module_entry */ zend_module_entry uploadprogress_module_entry = { STANDARD_MODULE_HEADER, "uploadprogress", uploadprogress_functions, PHP_MINIT(uploadprogress), /* Replace with NULL if there is nothing to do at php startup */ PHP_MSHUTDOWN(uploadprogress), /* Replace with NULL if there is nothing to do at php shutdown */ PHP_RINIT(uploadprogress), /* Replace with NULL if there is nothing to do at request start */ PHP_RSHUTDOWN(uploadprogress), /* Replace with NULL if there is nothing to do at request end */ PHP_MINFO(uploadprogress), "0.0.1", STANDARD_MODULE_PROPERTIES }; /* }}} */ #ifdef COMPILE_DL_UPLOADPROGRESS ZEND_GET_MODULE(uploadprogress) #endif extern int (*php_rfc1867_callback)(unsigned int , void *, void ** TSRMLS_DC); static int uploadprogress_php_rfc1867_file(unsigned int event, void *event_data, void **data TSRMLS_DC) { zval handler; char *callable = NULL; uploadprogress_data * progress; int read_bytes; progress = *data; if (event == MULTIPART_EVENT_START) { multipart_event_start *e_data; e_data = (multipart_event_start*) event_data; progress = emalloc( sizeof(uploadprogress_data) ); progress->bytes_total = e_data->content_length; progress->identifier = NULL; progress->identifier_tmp = NULL; progress->time_start = time(NULL); *data = progress; } else if (event == MULTIPART_EVENT_FORMDATA) { multipart_event_formdata *e_data; e_data = (multipart_event_formdata*) event_data; read_bytes = e_data->post_bytes_processed; if (e_data->newlength) { *e_data->newlength = e_data->length; } if (strcmp(e_data->name, "UPLOAD_IDENTIFIER") == 0) { char * template = INI_STR("uploadprogress.file.filename_template"); if (strcmp(template, "") == 0) { return 0; } progress->time_last = time(NULL); progress->speed_average = 0; progress->speed_last = 0; progress->bytes_uploaded = read_bytes; progress->files_uploaded = 0; progress->est_sec = 0; progress->identifier = uploadprogress_mk_filename(*e_data->value, template); progress->identifier_tmp = emalloc(strlen( progress->identifier) + 4); sprintf( progress->identifier_tmp, "%s.wr", progress->identifier ); } } if (progress->identifier) { if (event == MULTIPART_EVENT_FILE_START) { multipart_event_file_start *e_data; e_data = (multipart_event_file_start*) event_data; read_bytes = e_data->post_bytes_processed; } else if (event == MULTIPART_EVENT_FILE_DATA) { multipart_event_file_data *e_data; e_data = (multipart_event_file_data*) event_data; read_bytes = e_data->post_bytes_processed; } else if (event == MULTIPART_EVENT_FILE_END) { multipart_event_file_end *e_data; e_data = (multipart_event_file_end*) event_data; read_bytes = e_data->post_bytes_processed; progress->files_uploaded++; } else if ( event == MULTIPART_EVENT_END ) { VCWD_UNLINK( progress->identifier ); efree( progress->identifier ); efree( progress->identifier_tmp ); efree( progress ); return 0; } time_t crtime = time(NULL); int d,dt,ds; if (progress->time_last > crtime) { /* just in case we encounter a fracture in time */ progress->time_start = progress->time_last = crtime; } dt = crtime - progress->time_last; ds = crtime - progress->time_start; d = read_bytes - progress->bytes_uploaded; if (dt) { progress->speed_last = d/dt; progress->time_last = crtime; progress->bytes_uploaded = read_bytes; progress->speed_average = ds ? read_bytes / ds : 0; progress->est_sec = progress->speed_average ? (progress->bytes_total - read_bytes) / progress->speed_average : -1; } if (dt || event >= MULTIPART_EVENT_FILE_END) { FILE *F; F = VCWD_FOPEN(progress->identifier_tmp, "wb"); if (F) { fprintf(F, "time_start=%d\ntime_last=%d\nspeed_average=%d\nspeed_last=%d\nbytes_uploaded=%d\nbytes_total=%d\nfiles_uploaded=%d\nest_sec=%d\n", progress->time_start, progress->time_last, progress->speed_average, progress->speed_last, progress->bytes_uploaded, progress->bytes_total, progress->files_uploaded, progress->est_sec ); fclose(F); VCWD_RENAME(progress->identifier_tmp,progress->identifier); } } } if (event == MULTIPART_EVENT_END ) { if (progress->identifier) { efree( progress->identifier ); } if (progress->identifier_tmp) { efree( progress->identifier_tmp ); } efree( progress ); } } /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(uploadprogress) { REGISTER_INI_ENTRIES(); php_rfc1867_callback = uploadprogress_php_rfc1867_file; /* add your stuff here */ return SUCCESS; } /* }}} */ /* {{{ PHP_MSHUTDOWN_FUNCTION */ PHP_MSHUTDOWN_FUNCTION(uploadprogress) { UNREGISTER_INI_ENTRIES(); php_rfc1867_callback = NULL; /* add your stuff here */ return SUCCESS; } /* }}} */ /* {{{ PHP_RINIT_FUNCTION */ PHP_RINIT_FUNCTION(uploadprogress) { /* add your stuff here */ return SUCCESS; } /* }}} */ /* {{{ PHP_RSHUTDOWN_FUNCTION */ PHP_RSHUTDOWN_FUNCTION(uploadprogress) { /* add your stuff here */ return SUCCESS; } /* }}} */ /* {{{ PHP_MINFO_FUNCTION */ PHP_MINFO_FUNCTION(uploadprogress) { char buffer[ 512 ] ; php_info_print_table_start() ; php_info_print_table_header( 2, "uploadprogress support", "enabled" ) ; snprintf( buffer, 512, "0.3.0-beta"); php_info_print_table_row( 2, "Version", buffer ) ; php_info_print_box_end(); /* add your stuff here */ } /* }}} */ /* {{{ proto bool uploadprogress_register(callback callback) */ PHP_FUNCTION(uploadprogress_get_info) { char * id; int id_lg; char method; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &id, &id_lg) == FAILURE) { return; } return uploadprogress_file_php_get_info( id, return_value ); RETURN_FALSE; } static char * uploadprogress_mk_filename(char * identifier, char * template) { char * x; char * filename; filename = emalloc( strlen(template) + strlen(identifier) + 3 ); x = strstr( template, "%s" ); if (x==NULL) { sprintf( filename, "%s/%s", template, identifier ); }else{ strcpy( filename, template ); strcpy( filename + (x - template), identifier ); strcat( filename, x+2 ); } return filename; } static void uploadprogress_file_php_get_info(char * id, zval * return_value) { char s[1024]; char * filename; FILE *F; TSRMLS_FETCH(); char * template = INI_STR("uploadprogress.file.filename_template"); if (strcmp(template, "") == 0) { return; } else { filename = uploadprogress_mk_filename( id, template ); if (!filename) return; F = VCWD_FOPEN(filename, "rb"); if (F) { array_init(return_value); while ( fgets(s, 1000, F) ) { char *k, *v, *e; e = strchr(s,'='); if (!e) continue; *e = 0; /* break the line into 2 parts */ v = e+1; k = s; /* trim spaces in front and after the name/value */ while (*k && *k <= 32) v++; while (*v && *v <= 32) v++; for (e=k; *e; e++) if (*e <= 32) { *e = 0; break; } for (e=v; *e; e++) if (*e <= 32) { *e = 0; break; } add_assoc_string( return_value, k, v, 1 ); } fclose(F); } if (filename) efree(filename); return; } } #endif /* HAVE_UPLOADPROGRESS */ /* * Local variables: * tab-width: 4 * c-basic-offset: 4 * End: * vim600: noet sw=4 ts=4 fdm=marker * vim<600: noet sw=4 ts=4 */