X-Git-Url: https://git.m6w6.name/?a=blobdiff_plain;f=http_message_object.c;h=7d4530da6067b3eee99b2f302e7019736e229983;hb=bbe81747963aa5b1bd27dff95f923b6b446f5a04;hp=b9fdc364b7a01768f06f13ec993a24716dc6c611;hpb=32e91737086db53bb1fd9ed9f79d693c43ec459f;p=m6w6%2Fext-http diff --git a/http_message_object.c b/http_message_object.c index b9fdc36..7d4530d 100644 --- a/http_message_object.c +++ b/http_message_object.c @@ -12,11 +12,6 @@ /* $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 */ /*