wez             Wed Apr 28 04:23:23 2004 EDT

  Modified files:              
    /php-src/ext/com_dotnet     com_com.c com_extension.c com_handlers.c 
                                com_saproxy.c php_com_dotnet_internal.h 
  Log:
  Fix for Bug #28161 (and probably others that I can't find in the bug db;
  the search interface sucks).
  
  Expand the proxy object so it can handle psuedo array style properties.
  
  ASP/VB code like this:
  
        headObj.Attribute("RID") = rid 
  
  can be expressed like this in PHP:
  
        $headObj->Attribute['RID'] = $rid;
  
  In theory, this feature can be used for "multi dimensional" properties:
  
        headObj.Attribute("RID", "Foo") = rid;
  
  like this:
  
        $headObj->Attribute['RID']['Foo'] = $rid;
  
  
  
http://cvs.php.net/diff.php/php-src/ext/com_dotnet/com_com.c?r1=1.11&r2=1.12&ty=u
Index: php-src/ext/com_dotnet/com_com.c
diff -u php-src/ext/com_dotnet/com_com.c:1.11 php-src/ext/com_dotnet/com_com.c:1.12
--- php-src/ext/com_dotnet/com_com.c:1.11       Thu Feb 12 05:43:19 2004
+++ php-src/ext/com_dotnet/com_com.c    Wed Apr 28 04:23:22 2004
@@ -16,7 +16,7 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: com_com.c,v 1.11 2004/02/12 10:43:19 zeev Exp $ */
+/* $Id: com_com.c,v 1.12 2004/04/28 08:23:22 wez Exp $ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -333,6 +333,17 @@
                                spprintf(&msg, 0, "Parameter %d: %s", arg_err, desc);
                                LocalFree(desc);
                                break;
+
+                       case DISP_E_BADPARAMCOUNT:
+                               if ((disp_params->cArgs + disp_params->cNamedArgs == 
0) && (flags == DISPATCH_PROPERTYGET)) {
+                                       /* if getting a property and they are missing 
all parameters,
+                                        * we want to create a proxy object for them; 
so lets not create an
+                                        * exception here */
+                                       msg = NULL;
+                                       break;
+                               }
+                               /* else fall through */
+                               
                        default:
                                desc = php_win_err(hr);
                                spprintf(&msg, 0, "Error %s", desc);
@@ -557,6 +568,10 @@
                efree(vargs);
        }
 
+       /* a bit strange this, but... */
+       if (hr == DISP_E_BADPARAMCOUNT)
+               return hr;
+       
        return SUCCEEDED(hr) ? SUCCESS : FAILURE;
 }
 
http://cvs.php.net/diff.php/php-src/ext/com_dotnet/com_extension.c?r1=1.9&r2=1.10&ty=u
Index: php-src/ext/com_dotnet/com_extension.c
diff -u php-src/ext/com_dotnet/com_extension.c:1.9 
php-src/ext/com_dotnet/com_extension.c:1.10
--- php-src/ext/com_dotnet/com_extension.c:1.9  Thu Feb 12 05:43:19 2004
+++ php-src/ext/com_dotnet/com_extension.c      Wed Apr 28 04:23:22 2004
@@ -16,7 +16,7 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: com_extension.c,v 1.9 2004/02/12 10:43:19 zeev Exp $ */
+/* $Id: com_extension.c,v 1.10 2004/04/28 08:23:22 wez Exp $ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -197,18 +197,16 @@
        INIT_CLASS_ENTRY(ce, "com_safearray_proxy", NULL);
        php_com_saproxy_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
        php_com_saproxy_class_entry->ce_flags |= ZEND_ACC_FINAL;
-//     php_com_saproxy_class_entry->constructor->common.fn_flags |= 
ZEND_ACC_PROTECTED;
+       php_com_saproxy_class_entry->constructor->common.fn_flags |= 
ZEND_ACC_PROTECTED;
        php_com_saproxy_class_entry->get_iterator = php_com_saproxy_iter_get;
        
        INIT_CLASS_ENTRY(ce, "variant", NULL);
        ce.create_object = php_com_object_new;
-//     ce.get_iterator = php_com_iter_get;
        php_com_variant_class_entry = zend_register_internal_class(&ce TSRMLS_CC);
        php_com_variant_class_entry->get_iterator = php_com_iter_get;
 
        INIT_CLASS_ENTRY(ce, "com", NULL);
        ce.create_object = php_com_object_new;
-//     ce.get_iterator = php_com_iter_get;
        tmp = zend_register_internal_class_ex(&ce, php_com_variant_class_entry, 
"variant" TSRMLS_CC);
        tmp->get_iterator = php_com_iter_get;
 
@@ -217,7 +215,6 @@
 #if HAVE_MSCOREE_H
        INIT_CLASS_ENTRY(ce, "dotnet", NULL);
        ce.create_object = php_com_object_new;
-//     ce.get_iterator = php_com_iter_get;
        tmp = zend_register_internal_class_ex(&ce, php_com_variant_class_entry, 
"variant" TSRMLS_CC);
        tmp->get_iterator = php_com_iter_get;
 #endif
http://cvs.php.net/diff.php/php-src/ext/com_dotnet/com_handlers.c?r1=1.18&r2=1.19&ty=u
Index: php-src/ext/com_dotnet/com_handlers.c
diff -u php-src/ext/com_dotnet/com_handlers.c:1.18 
php-src/ext/com_dotnet/com_handlers.c:1.19
--- php-src/ext/com_dotnet/com_handlers.c:1.18  Mon Mar 22 17:47:05 2004
+++ php-src/ext/com_dotnet/com_handlers.c       Wed Apr 28 04:23:22 2004
@@ -16,7 +16,7 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: com_handlers.c,v 1.18 2004/03/22 22:47:05 wez Exp $ */
+/* $Id: com_handlers.c,v 1.19 2004/04/28 08:23:22 wez Exp $ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -34,6 +34,7 @@
        zval *return_value;
        php_com_dotnet_object *obj;
        VARIANT v;
+       HRESULT res;
 
        MAKE_STD_ZVAL(return_value);
        ZVAL_NULL(return_value);
@@ -46,10 +47,15 @@
                VariantInit(&v);
 
                convert_to_string_ex(&member);
-               if (SUCCESS == php_com_do_invoke(obj, Z_STRVAL_P(member), 
Z_STRLEN_P(member),
-                               DISPATCH_PROPERTYGET, &v, 0, NULL TSRMLS_CC)) {
+
+               res = php_com_do_invoke(obj, Z_STRVAL_P(member), Z_STRLEN_P(member),
+                               DISPATCH_PROPERTYGET, &v, 0, NULL TSRMLS_CC);
+
+               if (res == SUCCESS) {
                        php_com_zval_from_variant(return_value, &v, obj->code_page 
TSRMLS_CC);
                        VariantClear(&v);
+               } else if (res == DISP_E_BADPARAMCOUNT) {
+                       php_com_saproxy_create(object, return_value, member TSRMLS_CC);
                }
        } else {
                php_com_throw_exception(E_INVALIDARG, "this variant has no properties" 
TSRMLS_CC);
@@ -137,7 +143,7 @@
                                VariantClear(&v);
                        }
                } else {
-                       php_com_saproxy_create(object, return_value, Z_LVAL_P(offset) 
TSRMLS_CC);
+                       php_com_saproxy_create(object, return_value, offset TSRMLS_CC);
                }
 
        } else {
@@ -555,7 +561,6 @@
 void php_com_object_free_storage(void *object TSRMLS_DC)
 {
        php_com_dotnet_object *obj = (php_com_dotnet_object*)object;
-
        if (obj->typeinfo) {
                ITypeInfo_Release(obj->typeinfo);
                obj->typeinfo = NULL;
@@ -614,7 +619,6 @@
        obj->code_page = CP_ACP;
        obj->ce = ce;
 
-       
        retval.handle = zend_objects_store_put(obj, NULL, php_com_object_free_storage, 
php_com_object_clone TSRMLS_CC);
        retval.handlers = &php_com_object_handlers;
 
http://cvs.php.net/diff.php/php-src/ext/com_dotnet/com_saproxy.c?r1=1.8&r2=1.9&ty=u
Index: php-src/ext/com_dotnet/com_saproxy.c
diff -u php-src/ext/com_dotnet/com_saproxy.c:1.8 
php-src/ext/com_dotnet/com_saproxy.c:1.9
--- php-src/ext/com_dotnet/com_saproxy.c:1.8    Tue Apr 13 13:51:36 2004
+++ php-src/ext/com_dotnet/com_saproxy.c        Wed Apr 28 04:23:22 2004
@@ -16,11 +16,13 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: com_saproxy.c,v 1.8 2004/04/13 17:51:36 wez Exp $ */
+/* $Id: com_saproxy.c,v 1.9 2004/04/28 08:23:22 wez Exp $ */
 
 /* This module implements a SafeArray proxy which is used internally
  * by the engine when resolving multi-dimensional array accesses on
- * SafeArray types
+ * SafeArray types.
+ * In addition, the proxy is now able to handle properties of COM objects
+ * that smell like PHP arrays.
  * */
 
 #ifdef HAVE_CONFIG_H
@@ -43,7 +45,7 @@
        LONG dimensions;
        
        /* this is an array whose size_is(dimensions) */
-       LONG *indices;
+       zval **indices;
 
 } php_com_saproxy;
 
@@ -58,6 +60,17 @@
 
 #define SA_FETCH(zv)                   
(php_com_saproxy*)zend_object_store_get_object(zv TSRMLS_CC)
 
+static inline void clone_indices(php_com_saproxy *dest, php_com_saproxy *src, int 
ndims)
+{
+       int i;
+
+       for (i = 0; i < ndims; i++) {
+               MAKE_STD_ZVAL(dest->indices[i]);
+               *dest->indices[i] = *src->indices[i];
+               zval_copy_ctor(dest->indices[i]);
+       }
+}
+
 static zval *saproxy_property_read(zval *object, zval *member, int type TSRMLS_DC)
 {
        zval *return_value;
@@ -82,15 +95,50 @@
        UINT dims;
        SAFEARRAY *sa;
        LONG ubound, lbound;
+       int i;
+       HRESULT res;
        
        MAKE_STD_ZVAL(return_value);
        ZVAL_NULL(return_value);
        
-       if (!V_ISARRAY(&proxy->obj->v)) {
-               php_com_throw_exception(E_INVALIDARG, "proxied object is no longer a 
safe array!" TSRMLS_CC);
+       if (V_VT(&proxy->obj->v) == VT_DISPATCH) {
+               VARIANT v;
+               zval **args;
+
+               /* prop-get using first dimension as the property name,
+                * all subsequent dimensions and the offset as parameters */
+
+               args = safe_emalloc(proxy->dimensions + 1, sizeof(zval *), 0);
+
+               for (i = 1; i < proxy->dimensions; i++) {
+                       args[i-1] = proxy->indices[i];
+               }
+               args[i-1] = offset;
+
+               convert_to_string(proxy->indices[0]);
+               VariantInit(&v);
+
+               res = php_com_do_invoke(proxy->obj, Z_STRVAL_P(proxy->indices[0]),
+                               Z_STRLEN_P(proxy->indices[0]), 
DISPATCH_METHOD|DISPATCH_PROPERTYGET, &v,
+                               proxy->dimensions, args TSRMLS_CC);
+
+               if (res == SUCCESS) {
+                       php_com_zval_from_variant(return_value, &v, 
proxy->obj->code_page TSRMLS_CC);
+                       VariantClear(&v);
+               } else if (res == DISP_E_BADPARAMCOUNT) {
+                       /* return another proxy */
+                       php_com_saproxy_create(object, return_value, offset TSRMLS_CC);
+               }
+
+               return return_value;
+
+       } else if (!V_ISARRAY(&proxy->obj->v)) {
+               php_com_throw_exception(E_INVALIDARG, "invalid read from com proxy 
object" TSRMLS_CC);
                return return_value;
        }
 
+       /* the SafeArray case */
+       
        /* offset/index must be an integer */
        convert_to_long(offset);
        
@@ -123,7 +171,10 @@
                indices = do_alloca(dims * sizeof(LONG));
 
                /* copy indices from proxy */
-               memcpy(indices, proxy->indices, (dims-1) * sizeof(LONG));
+               for (i = 0; i < dims; i++) {
+                       convert_to_long(proxy->indices[i]);
+                       indices[i] = Z_LVAL_P(proxy->indices[i]);
+               }
 
                /* add user-supplied index */
                indices[dims-1] = Z_LVAL_P(offset);
@@ -148,7 +199,7 @@
                
        } else {
                /* return another proxy */
-               php_com_saproxy_create(object, return_value, Z_LVAL_P(offset) 
TSRMLS_CC);
+               php_com_saproxy_create(object, return_value, offset TSRMLS_CC);
        }
 
        return return_value;
@@ -156,7 +207,41 @@
 
 static void saproxy_write_dimension(zval *object, zval *offset, zval *value TSRMLS_DC)
 {
-       php_com_throw_exception(E_NOTIMPL, "writing to safearray not yet implemented" 
TSRMLS_CC);
+       php_com_saproxy *proxy = SA_FETCH(object);
+       UINT dims;
+       SAFEARRAY *sa;
+       LONG ubound, lbound;
+       int i;
+       HRESULT res;
+       VARIANT v;
+       
+       if (V_VT(&proxy->obj->v) == VT_DISPATCH) {
+               /* We do a prop-set using the first dimension as the property name,
+                * all subsequent dimensions and offset as parameters, with value as
+                * the final value */
+               zval **args = safe_emalloc(proxy->dimensions + 2, sizeof(zval *), 0);
+
+               for (i = 1; i < proxy->dimensions; i++) {
+                       args[i-1] = proxy->indices[i];
+               }
+               args[i-1] = offset;
+               args[i] = value;
+
+               convert_to_string(proxy->indices[0]);
+               VariantInit(&v);
+               if (SUCCESS == php_com_do_invoke(proxy->obj, 
Z_STRVAL_P(proxy->indices[0]),
+                                       Z_STRLEN_P(proxy->indices[0]), 
DISPATCH_PROPERTYPUT, &v, proxy->dimensions + 1,
+                                       args TSRMLS_CC)) {
+                       VariantClear(&v);
+               }
+
+               efree(args);
+               
+       } else if (V_ISARRAY(&proxy->obj->v)) {
+               php_com_throw_exception(E_NOTIMPL, "writing to safearray not yet 
implemented" TSRMLS_CC);
+       } else {
+               php_com_throw_exception(E_NOTIMPL, "invalid write to com proxy object" 
TSRMLS_CC);
+       }
 }
 
 static void saproxy_object_set(zval **property, zval *value TSRMLS_DC)
@@ -262,6 +347,13 @@
 static void saproxy_free_storage(void *object TSRMLS_DC)
 {
        php_com_saproxy *proxy = (php_com_saproxy *)object;
+       int i;
+
+       for (i = 0; i < proxy->dimensions; i++) {
+               if (proxy->indices) {
+                               FREE_ZVAL(proxy->indices[i]);
+               }
+       }
 
        zval_ptr_dtor(&proxy->zobj);
        efree(proxy->indices);
@@ -272,43 +364,45 @@
 {
        php_com_saproxy *proxy = (php_com_saproxy *)object;
        php_com_saproxy *cloneproxy;
+       int i;
 
        cloneproxy = emalloc(sizeof(*cloneproxy));
        memcpy(cloneproxy, proxy, sizeof(*cloneproxy));
 
        ZVAL_ADDREF(cloneproxy->zobj);
-       cloneproxy->indices = safe_emalloc(cloneproxy->dimensions, sizeof(LONG), 0);
-       memcpy(cloneproxy->indices, proxy->indices, cloneproxy->dimensions * 
sizeof(LONG));
+       cloneproxy->indices = safe_emalloc(cloneproxy->dimensions, sizeof(zval *), 0);
+       clone_indices(cloneproxy, proxy, proxy->dimensions);
 
        *clone_ptr = cloneproxy;
 }
 
-int php_com_saproxy_create(zval *com_object, zval *proxy_out, long index TSRMLS_DC)
+int php_com_saproxy_create(zval *com_object, zval *proxy_out, zval *index TSRMLS_DC)
 {
        php_com_saproxy *proxy, *rel = NULL;
-       php_com_dotnet_object *obj;
 
        proxy = ecalloc(1, sizeof(*proxy));
        proxy->dimensions = 1;
 
        if (Z_OBJCE_P(com_object) == php_com_saproxy_class_entry) {
                rel = SA_FETCH(com_object);
-               obj = rel->obj;
+               proxy->obj = rel->obj;
                proxy->zobj = rel->zobj;
                proxy->dimensions += rel->dimensions;
        } else {
-               obj = CDNO_FETCH(com_object);
+               proxy->obj = CDNO_FETCH(com_object);
                proxy->zobj = com_object;
        }
 
        ZVAL_ADDREF(proxy->zobj);
-       proxy->indices = safe_emalloc(proxy->dimensions, sizeof(LONG), 0);
+       proxy->indices = safe_emalloc(proxy->dimensions, sizeof(zval *), 0);
 
        if (rel) {
-               memcpy(proxy->indices, rel->indices, (proxy->dimensions-1) * 
sizeof(LONG));
+               clone_indices(proxy, rel, rel->dimensions);
        }
 
-       proxy->indices[proxy->dimensions-1] = index;
+       MAKE_STD_ZVAL(proxy->indices[proxy->dimensions-1]);
+       *proxy->indices[proxy->dimensions-1] = *index;
+       zval_copy_ctor(proxy->indices[proxy->dimensions-1]);
 
        Z_TYPE_P(proxy_out) = IS_OBJECT;
        Z_OBJ_HANDLE_P(proxy_out) = zend_objects_store_put(proxy, NULL, 
saproxy_free_storage, saproxy_clone TSRMLS_CC);
@@ -406,6 +500,7 @@
 {
        php_com_saproxy *proxy = SA_FETCH(object);
        php_com_saproxy_iter *I;
+       int i;
 
        I = ecalloc(1, sizeof(*I));
        I->iter.funcs = &saproxy_iter_funcs;
@@ -416,7 +511,10 @@
        ZVAL_ADDREF(I->proxy_obj);
 
        I->indices = safe_emalloc(proxy->dimensions + 1, sizeof(LONG), 0);
-       memcpy(I->indices, proxy->indices, proxy->dimensions * sizeof(LONG));
+       for (i = 0; i < proxy->dimensions; i++) {
+               convert_to_long(proxy->indices[i]);
+               I->indices[i] = Z_LVAL_P(proxy->indices[i]);
+       }
 
        SafeArrayGetLBound(V_ARRAY(&proxy->obj->v), proxy->dimensions, &I->imin);
        SafeArrayGetUBound(V_ARRAY(&proxy->obj->v), proxy->dimensions, &I->imax);
http://cvs.php.net/diff.php/php-src/ext/com_dotnet/php_com_dotnet_internal.h?r1=1.9&r2=1.10&ty=u
Index: php-src/ext/com_dotnet/php_com_dotnet_internal.h
diff -u php-src/ext/com_dotnet/php_com_dotnet_internal.h:1.9 
php-src/ext/com_dotnet/php_com_dotnet_internal.h:1.10
--- php-src/ext/com_dotnet/php_com_dotnet_internal.h:1.9        Wed Feb  4 06:14:30 
2004
+++ php-src/ext/com_dotnet/php_com_dotnet_internal.h    Wed Apr 28 04:23:22 2004
@@ -16,7 +16,7 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: php_com_dotnet_internal.h,v 1.9 2004/02/04 11:14:30 zeev Exp $ */
+/* $Id: php_com_dotnet_internal.h,v 1.10 2004/04/28 08:23:22 wez Exp $ */
 
 #ifndef PHP_COM_DOTNET_INTERNAL_H
 #define PHP_COM_DOTNET_INTERNAL_H
@@ -83,7 +83,7 @@
 
 /* com_saproxy.c */
 zend_object_iterator *php_com_saproxy_iter_get(zend_class_entry *ce, zval *object 
TSRMLS_DC);
-int php_com_saproxy_create(zval *com_object, zval *proxy_out, long index TSRMLS_DC);
+int php_com_saproxy_create(zval *com_object, zval *proxy_out, zval *index TSRMLS_DC);
 
 /* com_olechar.c */
 PHPAPI char *php_com_olestring_to_string(OLECHAR *olestring,

-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to