New PHP5 APC - version 3.0.18, using PHP5 5.2.0-8+etch10,
[php5-apc.git] / apc_rfc1867.c
diff --git a/apc_rfc1867.c b/apc_rfc1867.c
new file mode 100644 (file)
index 0000000..af01870
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+  +----------------------------------------------------------------------+
+  | APC                                                                  |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 2006 The PHP Group                                     |
+  +----------------------------------------------------------------------+
+  | This source file is subject to version 3.01 of the PHP license,      |
+  | that is bundled with this package in the file LICENSE, and is        |
+  | available through the world-wide-web at the following url:           |
+  | http://www.php.net/license/3_01.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.               |
+  +----------------------------------------------------------------------+
+  | Authors: Rasmus Lerdorf <rasmus@php.net>                             |
+  +----------------------------------------------------------------------+
+
+   This software was contributed to PHP by Community Connect Inc. in 2002
+   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
+   Future revisions and derivatives of this source code must acknowledge
+   Community Connect Inc. as the original contributor of this module by
+   leaving this note intact in the source code.
+
+   All other licensing and usage conditions are those of the PHP Group.
+
+ */
+
+/* $Id: apc_rfc1867.c,v 3.12 2007/10/18 20:37:20 rasmus Exp $*/
+
+#include "apc.h"
+#include "apc_globals.h"
+#include "rfc1867.h"
+
+#ifdef PHP_WIN32
+#include "win32/time.h"
+#endif
+
+#ifdef MULTIPART_EVENT_FORMDATA
+extern int _apc_store(char *strkey, int strkey_len, const zval *val, const unsigned int ttl, const int exclusive TSRMLS_DC);
+
+static double my_time() {
+    struct timeval a;
+    double t;
+    gettimeofday(&a, NULL);
+    t = a.tv_sec + (a.tv_usec/1000000.00);
+    return t;
+}
+
+void apc_rfc1867_progress(unsigned int event, void *event_data, void **extra TSRMLS_DC) {
+    static char tracking_key[64];
+    static int  key_length = 0;
+    static size_t content_length = 0;
+    static char filename[128];
+    static char name[64];
+    static char *temp_filename=NULL;
+    static int cancel_upload = 0;
+    static double start_time;
+    static size_t bytes_processed = 0;
+    static size_t prev_bytes_processed = 0;
+    static int update_freq = 0;
+    static double rate;
+    zval *track = NULL;
+
+       switch (event) {
+               case MULTIPART_EVENT_START:
+                       {
+                multipart_event_start *data = (multipart_event_start *) event_data;
+                content_length = data->content_length;
+                *tracking_key = '\0';
+                *name = '\0';
+                cancel_upload = 0;
+                temp_filename = NULL;
+                *filename= '\0';
+                key_length = 0;
+                start_time = my_time();
+                bytes_processed = 0;
+                rate = 0;
+                update_freq = APCG(rfc1867_freq);
+                if(update_freq < 0) {  // frequency is a percentage, not bytes
+                    update_freq = content_length * APCG(rfc1867_freq) / 100; 
+                }
+                       }
+                       break;
+
+               case MULTIPART_EVENT_FORMDATA:
+                       {
+                int prefix_len = strlen(APCG(rfc1867_prefix));
+                multipart_event_formdata *data = (multipart_event_formdata *) event_data;
+                               if(data->name && !strncasecmp(data->name, APCG(rfc1867_name), strlen(APCG(rfc1867_name))) && data->value && data->length && data->length < sizeof(tracking_key) - prefix_len) {
+                    strlcat(tracking_key, APCG(rfc1867_prefix), 63);
+                    strlcat(tracking_key, *data->value, 63);
+                    key_length = data->length + prefix_len;
+                    bytes_processed = data->post_bytes_processed;
+                               }
+                       }
+                       break;
+
+               case MULTIPART_EVENT_FILE_START:
+            if(*tracking_key) {
+                multipart_event_file_start *data = (multipart_event_file_start *) event_data;
+
+                bytes_processed = data->post_bytes_processed;
+                strncpy(filename,*data->filename,127);
+                temp_filename = NULL;
+                strncpy(name,data->name,63);
+                ALLOC_INIT_ZVAL(track);
+                array_init(track);
+                add_assoc_long(track, "total", content_length);
+                add_assoc_long(track, "current", bytes_processed);
+                add_assoc_string(track, "filename", filename, 1);
+                add_assoc_string(track, "name", name, 1);
+                add_assoc_long(track, "done", 0);
+                add_assoc_double(track, "start_time", start_time);
+                _apc_store(tracking_key, key_length, track, 3600, 0 TSRMLS_CC);
+                zval_ptr_dtor(&track);
+            }
+            break;
+
+               case MULTIPART_EVENT_FILE_DATA:
+            if(*tracking_key) {
+                multipart_event_file_data *data = (multipart_event_file_data *) event_data;
+                bytes_processed = data->post_bytes_processed;
+                ALLOC_INIT_ZVAL(track);
+                array_init(track);
+                add_assoc_long(track, "total", content_length);
+                add_assoc_long(track, "current", bytes_processed);
+                add_assoc_string(track, "filename", filename, 1);
+                add_assoc_string(track, "name", name, 1);
+                add_assoc_long(track, "done", 0);
+                add_assoc_double(track, "start_time", start_time);
+                if(bytes_processed - prev_bytes_processed > update_freq) {
+                    _apc_store(tracking_key, key_length, track, 3600, 0 TSRMLS_CC);
+                    prev_bytes_processed = bytes_processed;
+                }
+                zval_ptr_dtor(&track);
+                       }
+                       break;
+
+               case MULTIPART_EVENT_FILE_END:
+            if(*tracking_key) {
+                multipart_event_file_end *data = (multipart_event_file_end *) event_data;
+                bytes_processed = data->post_bytes_processed;
+                cancel_upload = data->cancel_upload;
+                temp_filename = data->temp_filename;
+                ALLOC_INIT_ZVAL(track);
+                array_init(track);
+                add_assoc_long(track, "total", content_length);
+                add_assoc_long(track, "current", bytes_processed);
+                add_assoc_string(track, "filename", filename, 1);
+                add_assoc_string(track, "name", name, 1);
+                add_assoc_string(track, "temp_filename", temp_filename, 1);
+                add_assoc_long(track, "cancel_upload", cancel_upload);
+                add_assoc_long(track, "done", 0);
+                add_assoc_double(track, "start_time", start_time);
+                _apc_store(tracking_key, key_length, track, 3600, 0 TSRMLS_CC);
+                zval_ptr_dtor(&track);
+                       }
+                       break;
+
+               case MULTIPART_EVENT_END:
+            if(*tracking_key) {
+                double now = my_time(); 
+                multipart_event_end *data = (multipart_event_end *) event_data;
+                bytes_processed = data->post_bytes_processed;
+                if(now>start_time) rate = 8.0*bytes_processed/(now-start_time);
+                else rate = 8.0*bytes_processed;  /* Too quick */
+                ALLOC_INIT_ZVAL(track);
+                array_init(track);
+                add_assoc_long(track, "total", content_length);
+                add_assoc_long(track, "current", bytes_processed);
+                add_assoc_double(track, "rate", rate);
+                add_assoc_string(track, "filename", filename, 1);
+                add_assoc_string(track, "name", name, 1);
+                if(temp_filename) {
+                    add_assoc_string(track, "temp_filename", temp_filename, 1);
+                }
+                add_assoc_long(track, "cancel_upload", cancel_upload);
+                add_assoc_long(track, "done", 1);
+                add_assoc_double(track, "start_time", start_time);
+                _apc_store(tracking_key, key_length, track, 3600, 0 TSRMLS_CC);
+                zval_ptr_dtor(&track);
+                       }
+                       break;
+       }
+}
+
+#endif
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
+ * vim<600: expandtab sw=4 ts=4 sts=4
+ */