bastardize property proxy even more -- sorry that dev3 had been released with debug...
authorMichael Wallner <mike@php.net>
Wed, 18 Jan 2012 17:04:54 +0000 (17:04 +0000)
committerMichael Wallner <mike@php.net>
Wed, 18 Jan 2012 17:04:54 +0000 (17:04 +0000)
php_http_message.c
php_http_property_proxy.c
php_http_property_proxy.h
php_http_request_datashare.c
tests/properyproxy001.phpt [new file with mode: 0644]

index 066deca86566b3e640d6e92e0d9ab2f112e39c49..ead53476ebed117277e8fc0a842ddb2a10e8b91d 100644 (file)
@@ -1139,7 +1139,7 @@ static zval **php_http_message_object_get_prop_ptr(zval *object, zval *member, c
 
        if (SUCCESS == php_http_message_object_get_prophandler(Z_STRVAL_P(copy), Z_STRLEN_P(copy), &handler)) {
                zval_ptr_dtor(&copy);
-               return &php_http_property_proxy_init(NULL, object, member TSRMLS_CC)->myself;
+               return &php_http_property_proxy_init(NULL, object, member, NULL TSRMLS_CC)->myself;
        }
        zval_ptr_dtor(&copy);
 
index 8fae2f115d9eead34d0aa1fc629bd75181f90dbf..43ec7095c56f1054959122dc923e1da9013a0449 100644 (file)
 #include "php_http_api.h"
 
 #ifndef PHP_HTTP_PPDBG
-#      define PHP_HTTP_PPDBG 1
+#      define PHP_HTTP_PPDBG 0
 #endif
 
-php_http_property_proxy_t *php_http_property_proxy_init(php_http_property_proxy_t *proxy, zval *object, zval *member TSRMLS_DC)
+php_http_property_proxy_t *php_http_property_proxy_init(php_http_property_proxy_t *proxy, zval *object, zval *member, zval *parent TSRMLS_DC)
 {
        if (!proxy) {
                proxy = emalloc(sizeof(*proxy));
@@ -28,6 +28,10 @@ php_http_property_proxy_t *php_http_property_proxy_init(php_http_property_proxy_
        Z_ADDREF_P(object);
        proxy->object = object;
        proxy->member = php_http_ztyp(IS_STRING, member);
+       if (parent) {
+               Z_ADDREF_P(parent);
+               proxy->parent = parent;
+       }
 
 #if PHP_HTTP_PPDBG
        fprintf(stderr, "proxy_init: %s\n", Z_STRVAL_P(proxy->member));
@@ -40,6 +44,9 @@ void php_http_property_proxy_dtor(php_http_property_proxy_t *proxy)
        zval_ptr_dtor(&proxy->object);
        zval_ptr_dtor(&proxy->member);
        zval_ptr_dtor(&proxy->myself);
+       if (proxy->parent) {
+               zval_ptr_dtor(&proxy->parent);
+       }
 }
 
 void php_http_property_proxy_free(php_http_property_proxy_t **proxy)
@@ -101,21 +108,6 @@ void php_http_property_proxy_object_free(void *object TSRMLS_DC)
        efree(o);
 }
 
-static void php_http_property_proxy_object_set(zval **object, zval *value TSRMLS_DC)
-{
-       php_http_property_proxy_object_t *obj = zend_object_store_get_object(*object TSRMLS_CC);
-
-#if PHP_HTTP_PPDBG
-       fprintf(stderr, "proxy_set: %s\n", Z_STRVAL_P(obj->proxy->member));
-#endif
-       if (Z_TYPE_P(obj->proxy->object) == IS_OBJECT) {
-               zend_update_property(Z_OBJCE_P(obj->proxy->object), obj->proxy->object, Z_STRVAL_P(obj->proxy->member), Z_STRLEN_P(obj->proxy->member), value TSRMLS_CC);
-       } else {
-               Z_ADDREF_P(value);
-               zend_symtable_update(Z_ARRVAL_P(obj->proxy->object), Z_STRVAL_P(obj->proxy->member), Z_STRLEN_P(obj->proxy->member)+1, (void *) &value, sizeof(zval *), NULL);
-       }
-}
-
 static zval *php_http_property_proxy_object_get(zval *object TSRMLS_DC)
 {
        php_http_property_proxy_object_t *obj = zend_object_store_get_object(object TSRMLS_CC);
@@ -144,6 +136,27 @@ static zval *php_http_property_proxy_object_get(zval *object TSRMLS_DC)
        return NULL;
 }
 
+static void php_http_property_proxy_object_set(zval **object, zval *value TSRMLS_DC)
+{
+       php_http_property_proxy_object_t *obj = zend_object_store_get_object(*object TSRMLS_CC);
+       zval *target = obj->proxy->parent ? php_http_property_proxy_object_get(obj->proxy->parent TSRMLS_CC) : obj->proxy->object;
+
+#if PHP_HTTP_PPDBG
+       fprintf(stderr, "proxy_set: %s\n", Z_STRVAL_P(obj->proxy->member));
+#endif
+       if (Z_TYPE_P(target) == IS_OBJECT) {
+               zend_update_property(Z_OBJCE_P(target), target, Z_STRVAL_P(obj->proxy->member), Z_STRLEN_P(obj->proxy->member), value TSRMLS_CC);
+       } else {
+               Z_ADDREF_P(value);
+               zend_symtable_update(Z_ARRVAL_P(target), Z_STRVAL_P(obj->proxy->member), Z_STRLEN_P(obj->proxy->member)+1, (void *) &value, sizeof(zval *), NULL);
+       }
+       /* propagate */
+       if (obj->proxy->parent) {
+               php_http_property_proxy_object_set(&obj->proxy->parent, target TSRMLS_CC);
+               zval_ptr_dtor(&target);
+       }
+}
+
 static STATUS php_http_property_proxy_object_cast(zval *object, zval *return_value, int type TSRMLS_DC)
 {
        zval *old_value, *new_value;
@@ -162,17 +175,19 @@ static STATUS php_http_property_proxy_object_cast(zval *object, zval *return_val
 
 static zval *php_http_property_proxy_object_read_dimension(zval *object, zval *offset, int type TSRMLS_DC)
 {
-       zval *retval = NULL, *property = php_http_property_proxy_object_get(object TSRMLS_CC);
+       php_http_property_proxy_object_t *obj = zend_object_store_get_object(object TSRMLS_CC);
+       zval *retval = NULL, *property;
 
 #if PHP_HTTP_PPDBG
-       php_http_property_proxy_object_t *obj = zend_object_store_get_object(object TSRMLS_CC);
        zval *ocpy = php_http_ztyp(IS_STRING, offset);
        fprintf(stderr, "read_dimension: %s.%s (%d)\n", Z_STRVAL_P(obj->proxy->member), Z_STRVAL_P(ocpy), type);
        zval_ptr_dtor(&ocpy);
 #endif
+
+       property = php_http_property_proxy_object_get(object TSRMLS_CC);
        if (type != BP_VAR_R) {
                Z_ADDREF_P(property);
-               retval = php_http_property_proxy_init(NULL, property, offset TSRMLS_CC)->myself;
+               retval = php_http_property_proxy_init(NULL, property, offset, obj->proxy->myself TSRMLS_CC)->myself;
        } else if (Z_TYPE_P(property) == IS_ARRAY) {
                zval **data = NULL;
 
@@ -193,7 +208,7 @@ static zval *php_http_property_proxy_object_read_dimension(zval *object, zval *o
                }
        }
        zval_ptr_dtor(&property);
-if(retval)Z_SET_ISREF_P(retval);
+
        return retval;
 }
 
@@ -223,6 +238,7 @@ static void php_http_property_proxy_object_write_dimension(zval *object, zval *o
                                zval_ptr_dtor(&offset);
                        }
                        php_http_property_proxy_object_set(&object, property TSRMLS_CC);
+                       zval_ptr_dtor(&property);
                        break;
 
                default:
index 043d3ed9afa247c3bec94d089cb1592a5d1e2bf3..30b518e74929d38510fb03a8108d2e04b5d42457 100644 (file)
@@ -17,9 +17,10 @@ typedef struct php_http_property_proxy {
        zval *myself;
        zval *object;
        zval *member;
+       zval *parent;
 } php_http_property_proxy_t;
 
-PHP_HTTP_API php_http_property_proxy_t *php_http_property_proxy_init(php_http_property_proxy_t *proxy, zval *object, zval *member TSRMLS_DC);
+PHP_HTTP_API php_http_property_proxy_t *php_http_property_proxy_init(php_http_property_proxy_t *proxy, zval *object, zval *member, zval *parent TSRMLS_DC);
 PHP_HTTP_API void php_http_property_proxy_dtor(php_http_property_proxy_t *proxy);
 PHP_HTTP_API void php_http_property_proxy_free(php_http_property_proxy_t **proxy);
 
index 8312943877437045b95743bc07324f57ecc33cd3..ce3f1a34437f1e884fd90967076ef5c40e7a79df 100644 (file)
@@ -281,7 +281,7 @@ static zval **php_http_request_datashare_object_get_prop_ptr(zval *object, zval
        zend_property_info *pi;
 
        if ((pi = zend_get_property_info(php_http_request_datashare_class_entry, member, 1 TSRMLS_CC))) {
-               return &php_http_property_proxy_init(NULL, object, member TSRMLS_CC)->myself;
+               return &php_http_property_proxy_init(NULL, object, member, NULL TSRMLS_CC)->myself;
        }
 
        return zend_get_std_object_handlers()->get_property_ptr_ptr(object, member, literal_key TSRMLS_CC);
diff --git a/tests/properyproxy001.phpt b/tests/properyproxy001.phpt
new file mode 100644 (file)
index 0000000..3f9d70a
--- /dev/null
@@ -0,0 +1,94 @@
+--TEST--
+property proxy
+--FILE--
+<?php
+
+class m extends http\Message { 
+    function test() { 
+        $this->headers["bykey"] = 1; 
+        var_dump($this->headers); 
+
+        $h = &$this->headers; 
+        $h["by1ref"] = 2; 
+        var_dump($this->headers); 
+
+        $x = &$this->headers["byXref"];
+
+        $h = &$this->headers["by2ref"]; 
+        $h = 1; 
+        var_dump($this->headers);
+
+        $x = 2;
+        var_dump($this->headers);
+
+        $this->headers["bynext"][] = 1;
+        $this->headers["bynext"][] = 2;
+        $this->headers["bynext"][] = 3;
+        var_dump($this->headers);
+    }
+} 
+
+$m=new m; 
+$m->test(); 
+echo $m,"\n";
+
+?>
+DONE
+--EXPECTF--
+array(1) {
+  ["bykey"]=>
+  int(1)
+}
+array(2) {
+  ["bykey"]=>
+  int(1)
+  ["by1ref"]=>
+  int(2)
+}
+array(3) {
+  ["bykey"]=>
+  int(1)
+  ["by1ref"]=>
+  int(2)
+  ["by2ref"]=>
+  &int(1)
+}
+array(4) {
+  ["bykey"]=>
+  int(1)
+  ["by1ref"]=>
+  int(2)
+  ["by2ref"]=>
+  &int(1)
+  ["byXref"]=>
+  &int(2)
+}
+array(5) {
+  ["bykey"]=>
+  int(1)
+  ["by1ref"]=>
+  int(2)
+  ["by2ref"]=>
+  &int(1)
+  ["byXref"]=>
+  &int(2)
+  ["bynext"]=>
+  array(3) {
+    [0]=>
+    int(1)
+    [1]=>
+    int(2)
+    [2]=>
+    int(3)
+  }
+}
+bykey: 1
+by1ref: 2
+by2ref: 1
+byXref: 2
+bynext: 1
+bynext: 2
+bynext: 3
+
+DONE
+