]> granicus.if.org Git - php/commitdiff
- Added support for parsing recordsets.
authorAndrei Zmievski <andrei@php.net>
Sun, 18 Nov 2001 01:16:03 +0000 (01:16 +0000)
committerAndrei Zmievski <andrei@php.net>
Sun, 18 Nov 2001 01:16:03 +0000 (01:16 +0000)
- Fixed a bug that sometimes would corrupt top-level element
  if it was a scalar one.

NEWS
ext/wddx/wddx.c

diff --git a/NEWS b/NEWS
index 0027504c2ee1796821d39081d4b323c870761e1f..7f6c1b55c8ead57933d467c1803a89645181395c 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,9 @@
 PHP 4.0                                                                    NEWS
 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 ?? ??? 200?, Version 4.2.0-dev
+- Fixed a bug in WDDX deserialization that would sometimes corrupt the root
+  element if it was a scalar one. (Andrei)
+- Added support for parsing recordsets contained in WDDX packets. (Andrei)
 - Renamed key_exists tp array_key_exists. (Derick)
 - Fix ImageColorsForIndex() and ImageColorAt() to work for TrueColor
   images. (Rasmus)
index 5e39ddfd6cc5bfc6ec5571a5df30381c5a34ebb8..315f21b0f70b9b0e358d12ca8a0d5a247421d6ba 100644 (file)
@@ -31,6 +31,7 @@
 #include "ext/standard/info.h"
 #include "ext/standard/php_smart_str.h"
 #include "ext/standard/html.h"
+#include "ext/standard/php_string.h"
 
 #define WDDX_BUF_LEN                   256
 #define PHP_CLASS_NAME_VAR             "php_class_name"
 #define EL_STRUCT                              "struct"
 #define EL_VALUE                               "value"
 #define EL_VAR                                 "var"
-#define EL_VAR_NAME                            "name"
+#define EL_NAME                                "name"
 #define EL_VERSION                             "version"
+#define EL_RECORDSET                   "recordset"
+#define EL_FIELD                               "field"
 
 #define php_wddx_deserialize(a,b) \
        php_wddx_deserialize_ex((a)->value.str.val, (a)->value.str.len, (b))
@@ -72,7 +75,9 @@ typedef struct {
                ST_NUMBER,
                ST_STRING,
                ST_BINARY,
-               ST_STRUCT
+               ST_STRUCT,
+               ST_RECORDSET,
+               ST_FIELD
        } type;
        char *varname;
 } st_entry;
@@ -80,6 +85,7 @@ typedef struct {
 typedef struct {
        int top, max;
        char *varname;
+       zend_bool done;
        void **elements;
 } wddx_stack;
 
@@ -129,6 +135,7 @@ static int wddx_stack_init(wddx_stack *stack)
        } else {
                stack->max = STACK_BLOCK_SIZE;
                stack->varname = NULL;
+               stack->done = 0;
                return SUCCESS;
        }
 }
@@ -382,7 +389,7 @@ static void php_wddx_serialize_string(wddx_packet *packet, zval *var)
                                        break;
 
                                default:
-                                       if (iscntrl((int)*p)) {
+                                       if (iscntrl((int)*p) && *p != '\n') {
                                                FLUSH_BUF();
                                                sprintf(control_buf, WDDX_CHAR, *p);
                                                php_wddx_add_chunk(packet, control_buf);
@@ -712,12 +719,14 @@ static void php_wddx_push_element(void *user_data, const char *name, const char
                wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry));
        } else if (!strcmp(name, EL_CHAR)) {
                int i;
-               char tmp_buf[2];
                
-               for (i=0; atts[i]; i++) {
-                       if (!strcmp(atts[i], EL_CHAR_CODE) && atts[i+1]) {
-                               sprintf(tmp_buf, "%c", (char)strtol(atts[i+1], NULL, 16));
+               for (i = 0; atts[i]; i++) {
+                       if (!strcmp(atts[i], EL_CHAR_CODE) && atts[++i] && atts[i][0]) {
+                               char tmp_buf[2];
+
+                               sprintf(tmp_buf, "%c", (char)strtol(atts[i], NULL, 16));
                                php_wddx_process_data(user_data, tmp_buf, strlen(tmp_buf));
+                               break;
                        }
                }
        } else if (!strcmp(name, EL_NUMBER)) {
@@ -731,8 +740,8 @@ static void php_wddx_push_element(void *user_data, const char *name, const char
        } else if (!strcmp(name, EL_BOOLEAN)) {
                int i;
 
-               for (i=0; atts[i]; i++) {
-                       if (!strcmp(atts[i], EL_VALUE) && atts[i+1]) {
+               for (i = 0; atts[i]; i++) {
+                       if (!strcmp(atts[i], EL_VALUE) && atts[++i] && atts[i][0]) {
                                ent.type = ST_BOOLEAN;
                                SET_STACK_VARNAME;
 
@@ -740,7 +749,8 @@ static void php_wddx_push_element(void *user_data, const char *name, const char
                                INIT_PZVAL(ent.data);
                                Z_TYPE_P(ent.data) = IS_BOOL;
                                wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry));
-                               php_wddx_process_data(user_data, atts[i+1], strlen(atts[i+1]));
+                               php_wddx_process_data(user_data, atts[i], strlen(atts[i]));
+                               break;
                        }
                }
        } else if (!strcmp(name, EL_NULL)) {
@@ -771,14 +781,83 @@ static void php_wddx_push_element(void *user_data, const char *name, const char
        } else if (!strcmp(name, EL_VAR)) {
                int i;
                
-               for (i=0; atts[i]; i++) {
-                       if (!strcmp(atts[i], EL_VAR_NAME) && atts[i+1]) {
-                               char *decoded_value;
+               for (i = 0; atts[i]; i++) {
+                       if (!strcmp(atts[i], EL_NAME) && atts[++i] && atts[i][0]) {
+                               char *decoded;
+                               int decoded_len;
+                               decoded = xml_utf8_decode(atts[i], strlen(atts[i]), &decoded_len, "ISO-8859-1");
+                               stack->varname = decoded;
+                               break;
+                       }
+               }
+       } else if (!strcmp(name, EL_RECORDSET)) {
+               int i;
+
+               ent.type = ST_RECORDSET;
+               SET_STACK_VARNAME;
+               MAKE_STD_ZVAL(ent.data);
+               array_init(ent.data);
+
+               for (i = 0; atts[i]; i++) {
+                       if (!strcmp(atts[i], "fieldNames") && atts[++i] && atts[i][0]) {
+                               zval *tmp;
+                               char *key;
+                               char *p1, *p2, *endp;
+                               char *decoded;
+                               int decoded_len;
+
+                               decoded = xml_utf8_decode(atts[i], strlen(atts[i]), &decoded_len, "ISO-8859-1");
+                               endp = (char *)decoded + decoded_len;
+                               p1 = (char *)decoded;
+                               while ((p2 = php_memnstr(p1, ",", sizeof(",")-1, endp)) != NULL) {
+                                       key = estrndup(p1, p2 - p1);
+                                       MAKE_STD_ZVAL(tmp);
+                                       array_init(tmp);
+                                       add_assoc_zval_ex(ent.data, key, p2 - p1 + 1, tmp);
+                                       p1 = p2 + sizeof(",")-1;
+                                       efree(key);
+                               }
+
+                               if (p1 <= endp) {
+                                       MAKE_STD_ZVAL(tmp);
+                                       array_init(tmp);
+                                       add_assoc_zval_ex(ent.data, p1, endp - p1 + 1, tmp);
+                               }
+
+                               efree(decoded);
+                               break;
+                       }
+               }
+
+               wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry));
+       } else if (!strcmp(name, EL_FIELD)) {
+               int i;
+               st_entry ent;
+
+               ent.type = ST_FIELD;
+               ent.varname = NULL;
+               ent.data = NULL;
+
+               for (i = 0; atts[i]; i++) {
+                       if (!strcmp(atts[i], EL_NAME) && atts[++i] && atts[i][0]) {
+                               char *decoded;
                                int decoded_len;
-                               decoded_value = xml_utf8_decode(atts[i+1],strlen(atts[i+1]),&decoded_len,"ISO-8859-1");
-                               stack->varname = decoded_value;
+                               st_entry *recordset;
+                               zval **field;
+                               decoded = xml_utf8_decode(atts[i], strlen(atts[i]), &decoded_len, "ISO-8859-1");
+                               if (wddx_stack_top(stack, (void**)&recordset) == SUCCESS &&
+                                       recordset->type == ST_RECORDSET &&
+                                       zend_hash_find(Z_ARRVAL_P(recordset->data), decoded, decoded_len+1, (void**)&field) == SUCCESS) {
+                                       ent.data = *field;
+                               }
+                               
+                               efree(decoded);
+                               break;
                        }
                }
+
+               wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry));
        }
 }
 /* }}} */
@@ -802,7 +881,7 @@ static void php_wddx_pop_element(void *user_data, const char *name)
        if (!strcmp(name, EL_STRING) || !strcmp(name, EL_NUMBER) ||
                !strcmp(name, EL_BOOLEAN) || !strcmp(name, EL_NULL) ||
                !strcmp(name, EL_ARRAY) || !strcmp(name, EL_STRUCT) ||
-               !strcmp(name, EL_BINARY)) {
+               !strcmp(name, EL_RECORDSET) || !strcmp(name, EL_BINARY)) {
                wddx_stack_top(stack, (void**)&ent1);
 
                if (!strcmp(name, EL_BINARY)) {
@@ -833,6 +912,14 @@ static void php_wddx_pop_element(void *user_data, const char *name)
                if (stack->top > 1) {
                        stack->top--;
                        wddx_stack_top(stack, (void**)&ent2);
+                       
+                       /* if non-existent field */
+                       if (ent2->type == ST_FIELD && ent2->data == NULL) {
+                               zval_ptr_dtor(&ent1->data);
+                               efree(ent1);
+                               return;
+                       }
+                       
                        if (Z_TYPE_P(ent2->data) == IS_ARRAY || Z_TYPE_P(ent2->data) == IS_OBJECT) {
                                target_hash = HASH_OF(ent2->data);
 
@@ -871,8 +958,7 @@ static void php_wddx_pop_element(void *user_data, const char *name)
                                                
                                                /* Clean up class name var entry */
                                                zval_ptr_dtor(&ent1->data);
-                                       }
-                                       else
+                                       } else
                                                zend_hash_update(target_hash,
                                                                                 ent1->varname, strlen(ent1->varname)+1,
                                                                                 &ent1->data, sizeof(zval *), NULL);
@@ -884,9 +970,15 @@ static void php_wddx_pop_element(void *user_data, const char *name)
                                }
                        }
                        efree(ent1);
-               }
+               } else
+                       stack->done = 1;
        } else if (!strcmp(name, EL_VAR) && stack->varname) {
                efree(stack->varname);
+       } else if (!strcmp(name, EL_FIELD)) {
+               st_entry *ent;
+               wddx_stack_top(stack, (void **)&ent);
+               efree(ent);
+               stack->top--;
        }
 }
 /* }}} */
@@ -897,28 +989,28 @@ static void php_wddx_process_data(void *user_data, const char *s, int len)
 {
        st_entry *ent;
        wddx_stack *stack = (wddx_stack *)user_data;
-       char *decoded_value;
+       char *decoded;
        int decoded_len;
        TSRMLS_FETCH();
 
-       if (!wddx_stack_is_empty(stack)) {
+       if (!wddx_stack_is_empty(stack) && !stack->done) {
                wddx_stack_top(stack, (void**)&ent);
                switch (Z_TYPE_P(ent)) {
                        case ST_STRING: 
-                               decoded_value = xml_utf8_decode(s,len,&decoded_len,"ISO-8859-1");
+                               decoded = xml_utf8_decode(s, len, &decoded_len, "ISO-8859-1");
 
                                if (Z_STRLEN_P(ent->data) == 0) {
-                                       Z_STRVAL_P(ent->data) = estrndup(decoded_value, decoded_len);
+                                       Z_STRVAL_P(ent->data) = estrndup(decoded, decoded_len);
                                        Z_STRLEN_P(ent->data) = decoded_len;
                                } else {
                                        Z_STRVAL_P(ent->data) = erealloc(Z_STRVAL_P(ent->data),
                                                        Z_STRLEN_P(ent->data) + decoded_len + 1);
-                                       strncpy(Z_STRVAL_P(ent->data)+Z_STRLEN_P(ent->data), decoded_value, decoded_len);
+                                       strncpy(Z_STRVAL_P(ent->data)+Z_STRLEN_P(ent->data), decoded, decoded_len);
                                        Z_STRLEN_P(ent->data) += decoded_len;
                                        Z_STRVAL_P(ent->data)[Z_STRLEN_P(ent->data)] = '\0';
                                }
 
-                               efree(decoded_value);
+                               efree(decoded);
                                break;
 
                        case ST_BINARY: