[PATCH] upload-progress-tracking
| From: | Doru Petrescu | Date: | Thu, 20 Nov 2003 11:02:37 +0000 |
| Subject: | [PATCH] upload-progress-tracking | ||
| Groups: | php.internals | ||
| Request: | Send a blank email to internals+get-5611@lists.php.net to get a copy of this message | ||
Hi,
This is a patch that implements a hooking mechanism into the
rfc1867_post_handler() function that process post content of type
multipart/form-data, for example when uploading files. This will allow
execution of a callback routine while php reads and process the incoming data.
This happens before the actual script is loaded and executed. This will make
possible for an extension to register a callback, that will do something
interesting like an upload-progress-meter for the incoming uploads.
This wishes to be a better approach to do U-P-M than my previous patch, that
was inserting ugly code directly into rfc1867_post_handler() function. This
new implementation provides separation of code, and a standard hooking
mechanism, whatever you need to do.
This patch define a new configuration option 'upload_progress_tracking'
(default off). You will have to turn it ON, in order for U-P-M to work. This
is intended to reduce the number of wasted cpu cycles when this feature is not
needed. You should turn this on only for the directories/files that actually
need and use this.
Security considerations: data received from client is checked for valid
characters and valid length before doing anything else with it.
What can be done with this ? well... this was intended to be a way to do
an upload progress meter, but you can do a lot of other things, even RUN PHP
CODE while data is uploaded. I have a quick&dirt patch available if anyone want
to play with ...
See the attached README file for more technical details.
BTW, patch is against php-4.3.4
--
Best regards,
Doru Petrescu
Senior Software Engineer
Astral Telecom Bucuresti
Attachment: [text/x-patch] patch.upload_progress_tracking_callback_v1.txt
What is this ? ============== This is a patch that implements a hooking mechanism into the rfc1867_post_handler() function that process post content of type multipart/form-data, for example when uploading files. This will allow execution of a callback routine while php reads and process the incoming data. This happens before the actual script is loaded and executed. This will make possible for an extension to register a callback, that will do something interesting like an upload-progress-meter for the incoming uploads. This wishes to be a better approach to do U-P-M than my previous patch, that was inserting ugly code directly into rfc1867_post_handler() function. This new implementation provides separation of code, and a standard hooking mechanism, whatever you need to do. This patch define a new configuration option 'upload_progress_tracking' (default off). You will have to turn it ON, in order for U-P-M to work. This is intended to reduce the number of wasted cpu cycles when this feature is not needed. You should turn this on only for the directories/files that actually need and use this. Security considerations: data received from client is checked for valid characters and valid length before doing anything else with it. How to use Upload-Progress-Tracking: =================================== First you have to enable it. Use: upload_progress_tracking = On or php_value upload_progress_tracking 1 Then you will need to load and configure a PHP extension that do something useful the progress tracking info. See the Upload-Progress-Meter extension for more details on this. All being set on the server side, you need a web page with an upload form, with a special HIDDEN parameter, named UPLOAD_IDENTIFIER, that will have every time a different random value. You can use either javascript or php script to generate its random value. Valid characters for its value are: a..z A..Z 0..9 . (dot) and _ (underline). Valid length is 16-32. under 16 it will be ignored, over 32 it will be truncated to 32. If it is missing, have invalid chars, or is to short, it will be ignored, and upload-tracking-info will not be provided for this upload. See the Upload-Progress-Meter extension for an working example. What the Callback: ================== prototype for the callback: void upload_progress_callback( void *pointer, int read_bytes, int total_bytes, int what_happened ) 1. first time call, to initialize: upload_progress_callback( &tmp_pointer, 0, total, 0 ) tmp_pointer is an INPUT/OUTPUT parameter! on INPUT: tmp_pointer = (char*) UPLOAD_IDENTIFIER. his value was pre-checked for valid chars ( a..z A..Z 0..9 . and _ ) and valid length (16..32) on OUTPUT: tmp_pointer will return the value of the 'progress' opaque pointer, that will be used by the callback to store its data. it is the callback responsibility to alloc any storage space it requires, and to free it at the end. on INIT call, read_bytes parameter will have a ZERO value, while total_bytes will have a greater than zero value. on any other call read_bytes will have a greater than zero value guaranteed! 2. regular update data call: upload_progress_callback( progress, read, total, what_happened ) progress: the opaque pointer returned by the previous init call read: the new number of bytes read so far. this will always be greater than zero, but might not always be greater than the last value received total: total number of bytes. this value will not change what_happened: - a NEGATIVE value (UPLOAD_DONE) means end-of-upload. this is the last call. - a POSITIVE value (UPLOAD_GOT_A_NEW_FILE) means we've just seen another file uploaded, more might come. just ++nr_of_uploaded_files_counter. - a ZERO value (UPLOAD_UPDATE) means nothing unusual, just the regular update. When the upload finish, either because of an error (read<total), or normally (read=total), you need to free any resources you previously allocated (like the progress opaque pointer) Just make sure you do not free it before you receive the UPLOAD_DONE signal, or SIGSEGV will kill us all! Puting this to work: ==================== Any extension that will use this, need to put this at the top of the file: extern int upload_progress_register_callback( void* ); and define a callback like this: /* begin C code */ void my_callback(void *pointer, int read, int total, int whats_new) { if (total==0) { /* INIT time */ void ** tmp_pointer = pointer; /* this is actualy (void**) this time. see NOTES */ void * progress; char identifier = (char*) pointer; /* allocate an internal structure to keep track of things */ progress = malloc(); *tmp_pointer = progress; /* initialize everything ... */ return; }else{ if (whats_new < 0) { /* last call. its free() time ... */ free( pointer ); return; }else{ /* regular UPDATE call */ if (whats_new>0) { nr_uploaded_files++; } /* do_stuff... compute upload speed ... whatever */ return; } } } /* end of C code */
Attachment: [text/x-patch] patch.upload_progress_tracking_callback_v1.txt
What is this ? ============== This is a patch that implements a hooking mechanism into the rfc1867_post_handler() function that process post content of type multipart/form-data, for example when uploading files. This will allow execution of a callback routine while php reads and process the incoming data. This happens before the actual script is loaded and executed. This will make possible for an extension to register a callback, that will do something interesting like an upload-progress-meter for the incoming uploads. This wishes to be a better approach to do U-P-M than my previous patch, that was inserting ugly code directly into rfc1867_post_handler() function. This new implementation provides separation of code, and a standard hooking mechanism, whatever you need to do. This patch define a new configuration option 'upload_progress_tracking' (default off). You will have to turn it ON, in order for U-P-M to work. This is intended to reduce the number of wasted cpu cycles when this feature is not needed. You should turn this on only for the directories/files that actually need and use this. Security considerations: data received from client is checked for valid characters and valid length before doing anything else with it. How to use Upload-Progress-Tracking: =================================== First you have to enable it. Use: upload_progress_tracking = On or php_value upload_progress_tracking 1 Then you will need to load and configure a PHP extension that do something useful the progress tracking info. See the Upload-Progress-Meter extension for more details on this. All being set on the server side, you need a web page with an upload form, with a special HIDDEN parameter, named UPLOAD_IDENTIFIER, that will have every time a different random value. You can use either javascript or php script to generate its random value. Valid characters for its value are: a..z A..Z 0..9 . (dot) and _ (underline). Valid length is 16-32. under 16 it will be ignored, over 32 it will be truncated to 32. If it is missing, have invalid chars, or is to short, it will be ignored, and upload-tracking-info will not be provided for this upload. See the Upload-Progress-Meter extension for an working example. What the Callback: ================== prototype for the callback: void upload_progress_callback( void *pointer, int read_bytes, int total_bytes, int what_happened ) 1. first time call, to initialize: upload_progress_callback( &tmp_pointer, 0, total, 0 ) tmp_pointer is an INPUT/OUTPUT parameter! on INPUT: tmp_pointer = (char*) UPLOAD_IDENTIFIER. his value was pre-checked for valid chars ( a..z A..Z 0..9 . and _ ) and valid length (16..32) on OUTPUT: tmp_pointer will return the value of the 'progress' opaque pointer, that will be used by the callback to store its data. it is the callback responsibility to alloc any storage space it requires, and to free it at the end. on INIT call, read_bytes parameter will have a ZERO value, while total_bytes will have a greater than zero value. on any other call read_bytes will have a greater than zero value guaranteed! 2. regular update data call: upload_progress_callback( progress, read, total, what_happened ) progress: the opaque pointer returned by the previous init call read: the new number of bytes read so far. this will always be greater than zero, but might not always be greater than the last value received total: total number of bytes. this value will not change what_happened: - a NEGATIVE value (UPLOAD_DONE) means end-of-upload. this is the last call. - a POSITIVE value (UPLOAD_GOT_A_NEW_FILE) means we've just seen another file uploaded, more might come. just ++nr_of_uploaded_files_counter. - a ZERO value (UPLOAD_UPDATE) means nothing unusual, just the regular update. When the upload finish, either because of an error (read<total), or normally (read=total), you need to free any resources you previously allocated (like the progress opaque pointer) Just make sure you do not free it before you receive the UPLOAD_DONE signal, or SIGSEGV will kill us all! Puting this to work: ==================== Any extension that will use this, need to put this at the top of the file: extern int upload_progress_register_callback( void* ); and define a callback like this: /* begin C code */ void my_callback(void *pointer, int read, int total, int whats_new) { if (total==0) { /* INIT time */ void ** tmp_pointer = pointer; /* this is actualy (void**) this time. see NOTES */ void * progress; char identifier = (char*) pointer; /* allocate an internal structure to keep track of things */ progress = malloc(); *tmp_pointer = progress; /* initialize everything ... */ return; }else{ if (whats_new < 0) { /* last call. its free() time ... */ free( pointer ); return; }else{ /* regular UPDATE call */ if (whats_new>0) { nr_uploaded_files++; } /* do_stuff... compute upload speed ... whatever */ return; } } } /* end of C code */