- fix ce
[m6w6/ext-http] / http_message_object.c
index a0077bdc1b8298a7317fe4d4d54ca6dfcfe37185..7d4530da6067b3eee99b2f302e7019736e229983 100644 (file)
@@ -6,17 +6,12 @@
     | modification, are permitted provided that the conditions mentioned |
     | in the accompanying LICENSE file are met.                          |
     +--------------------------------------------------------------------+
-    | Copyright (c) 2004-2005, Michael Wallner <mike@php.net>            |
+    | Copyright (c) 2004-2006, Michael Wallner <mike@php.net>            |
     +--------------------------------------------------------------------+
 */
 
 /* $Id$ */
 
-
-#ifdef HAVE_CONFIG_H
-#      include "config.h"
-#endif
-
 #include "php_http.h"
 
 #ifdef ZEND_ENGINE_2
@@ -99,6 +94,12 @@ HTTP_BEGIN_ARGS(unserialize, 0, 1)
        HTTP_ARG_VAL(serialized, 0)
 HTTP_END_ARGS;
 
+HTTP_EMPTY_ARGS(detach, 0);
+
+HTTP_BEGIN_ARGS(prepend, 0, 1)
+       HTTP_ARG_OBJ(HttpMessage, message, 0)
+HTTP_END_ARGS;
+
 #define http_message_object_declare_default_properties() _http_message_object_declare_default_properties(TSRMLS_C)
 static inline void _http_message_object_declare_default_properties(TSRMLS_D);
 #define http_message_object_read_prop _http_message_object_read_prop
@@ -141,6 +142,10 @@ zend_function_entry http_message_object_fe[] = {
 
        HTTP_MESSAGE_ME(fromString, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
        
+       HTTP_MESSAGE_ME(detach, ZEND_ACC_PUBLIC)
+       
+       HTTP_MESSAGE_ME(prepend, ZEND_ACC_PUBLIC)
+       
        EMPTY_FUNCTION_ENTRY
 };
 static zend_object_handlers http_message_object_handlers;
@@ -240,6 +245,14 @@ void _http_message_object_free(zend_object *object TSRMLS_DC)
                http_message_dtor(o->message);
                efree(o->message);
        }
+       if (o->parent.handle) {
+               zval p;
+               
+               INIT_PZVAL(&p);
+               p.type = IS_OBJECT;
+               p.value.obj = o->parent;
+               zend_objects_store_del_ref(&p TSRMLS_CC);
+       }
        efree(o);
 }
 
@@ -561,12 +574,12 @@ PHP_METHOD(HttpMessage, __construct)
 }
 /* }}} */
 
-/* {{{ proto static HttpMessage HttpMessage::fromString(string raw_message)
+/* {{{ proto static HttpMessage HttpMessage::fromString(string raw_message[, string class_name = "HttpMessage"])
  *
  * Create an HttpMessage object from a string. Kind of a static constructor.
  * 
  * Expects a string parameter containing a sinlge or several consecutive
- * HTTP messages.
+ * HTTP messages.  Accepts an optionsl string parameter specifying the class to use.
  * 
  * Returns an HttpMessage object on success or NULL on failure.
  * 
@@ -574,16 +587,27 @@ PHP_METHOD(HttpMessage, __construct)
  */
 PHP_METHOD(HttpMessage, fromString)
 {
-       char *string = NULL;
-       int length = 0;
+       char *string = NULL, *class_name = NULL;
+       int length = 0, class_length = 0;
        http_message *msg = NULL;
 
        RETVAL_NULL();
        
        SET_EH_THROW_HTTP();
-       if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &string, &length)) {
+       if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &string, &length, &class_name, &class_length)) {
                if ((msg = http_message_parse(string, length))) {
-                       ZVAL_OBJVAL(return_value, http_message_object_new_ex(http_message_object_ce, msg, NULL));
+                       zend_class_entry *ce = http_message_object_ce;
+                       
+                       if (class_name && *class_name) {
+                               ce = zend_fetch_class(class_name, class_length, ZEND_FETCH_CLASS_DEFAULT TSRMLS_CC);
+                               if (ce && !instanceof_function(ce, http_message_object_ce TSRMLS_CC)) {
+                                       http_error_ex(HE_WARNING, HTTP_E_RUNTIME, "Class %s does not extend HttpMessage", class_name);
+                                       ce = NULL;
+                               }
+                       }
+                       if (ce) {
+                               ZVAL_OBJVAL(return_value, http_message_object_new_ex(ce, msg, NULL));
+                       }
                }
        }
        SET_EH_NORMAL();
@@ -1063,6 +1087,83 @@ PHP_METHOD(HttpMessage, unserialize)
 }
 /* }}} */
 
+/* {{{ proto HttpMessage HttpMessage::detach(void)
+ *
+ * Returns a clone of an HttpMessage object detached from any parent messages.
+ */
+PHP_METHOD(HttpMessage, detach)
+{
+       http_info info;
+       http_message *msg;
+       getObject(http_message_object, obj);
+       
+       NO_ARGS;
+       
+       info.type = obj->message->type;
+       memcpy(&HTTP_INFO(&info), &HTTP_INFO(obj->message), sizeof(struct http_info));
+       
+       msg = http_message_new();
+       http_message_set_info(msg, &info);
+       
+       zend_hash_copy(&msg->hdrs, &obj->message->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
+       phpstr_append(&msg->body, PHPSTR_VAL(obj->message), PHPSTR_LEN(obj->message));
+       
+       ZVAL_OBJVAL(return_value, http_message_object_new_ex(Z_OBJCE_P(getThis()), msg, NULL));
+}
+/* }}} */
+
+/* {{{ proto void HttpMessage::prepend(HttpMessage message)
+ *
+ * Prepends message(s) to the HTTP message.
+ *
+ * Expects an HttpMessage object as parameter.
+ */
+PHP_METHOD(HttpMessage, prepend)
+{
+       zval *prepend;
+       zend_bool top = 1;
+       
+       if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|b", &prepend, http_message_object_ce, &top)) {
+               zval m;
+               http_message *save_parent_msg;
+               zend_object_value save_parent_obj;
+               getObject(http_message_object, obj);
+               getObjectEx(http_message_object, prepend_obj, prepend);
+               
+               INIT_PZVAL(&m);
+               m.type = IS_OBJECT;
+               
+               if (!top) {
+                       save_parent_obj = obj->parent;
+                       save_parent_msg = obj->message->parent;
+               } else {
+                       /* iterate to the most parent object */
+                       while (obj->parent.handle) {
+                               m.value.obj = obj->parent;
+                               obj = zend_object_store_get_object(&m TSRMLS_CC);
+                       }
+               }
+               
+               /* prepend */
+               obj->parent = prepend->value.obj;
+               obj->message->parent = prepend_obj->message;
+               
+               /* add ref */
+               zend_objects_store_add_ref(prepend TSRMLS_CC);
+               while (prepend_obj->parent.handle) {
+                       m.value.obj = prepend_obj->parent;
+                       zend_objects_store_add_ref(&m TSRMLS_CC);
+                       prepend_obj = zend_object_store_get_object(&m TSRMLS_CC);
+               }
+               
+               if (!top) {
+                       prepend_obj->parent = save_parent_obj;
+                       prepend_obj->message->parent = save_parent_msg;
+               }
+       }
+}
+/* }}} */
+
 #endif /* ZEND_ENGINE_2 */
 
 /*