X-Git-Url: https://git.m6w6.name/?p=m6w6%2Fext-http;a=blobdiff_plain;f=http_message_object.c;h=8af5805076f966d5f4e34429f32176ed7f8b982a;hp=ad4d8277ef02d829f0c9878288ebee4937689efa;hb=e37040ebf8a470c77c7ae3498ee582ca20db259c;hpb=778163476c4500a8554c35c68dfc9c0cd33f82f8 diff --git a/http_message_object.c b/http_message_object.c index ad4d827..8af5805 100644 --- a/http_message_object.c +++ b/http_message_object.c @@ -123,8 +123,6 @@ HTTP_BEGIN_ARGS(prepend, 1) HTTP_END_ARGS; HTTP_EMPTY_ARGS(reverse); -#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 static zval *_http_message_object_read_prop(zval *object, zval *member, int type TSRMLS_DC); #define http_message_object_write_prop _http_message_object_write_prop @@ -132,6 +130,7 @@ static void _http_message_object_write_prop(zval *object, zval *member, zval *va #define http_message_object_get_props _http_message_object_get_props static HashTable *_http_message_object_get_props(zval *object TSRMLS_DC); +#define OBJ_PROP_CE http_message_object_ce zend_class_entry *http_message_object_ce; zend_function_entry http_message_object_fe[] = { HTTP_MESSAGE_ME(__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR) @@ -186,6 +185,7 @@ static zend_object_handlers http_message_object_handlers; PHP_MINIT_FUNCTION(http_message_object) { HTTP_REGISTER_CLASS_EX(HttpMessage, http_message_object, NULL, 0); + #ifndef WONKY # ifdef HAVE_SPL zend_class_implements(http_message_object_ce TSRMLS_CC, 3, spl_ce_Countable, zend_ce_serializable, zend_ce_iterator); @@ -195,25 +195,91 @@ PHP_MINIT_FUNCTION(http_message_object) #else zend_class_implements(http_message_object_ce TSRMLS_CC, 1, zend_ce_iterator); #endif - - HTTP_LONG_CONSTANT("HTTP_MSG_NONE", HTTP_MSG_NONE); - HTTP_LONG_CONSTANT("HTTP_MSG_REQUEST", HTTP_MSG_REQUEST); - HTTP_LONG_CONSTANT("HTTP_MSG_RESPONSE", HTTP_MSG_RESPONSE); - + http_message_object_handlers.clone_obj = _http_message_object_clone_obj; http_message_object_handlers.read_property = http_message_object_read_prop; http_message_object_handlers.write_property = http_message_object_write_prop; http_message_object_handlers.get_properties = http_message_object_get_props; http_message_object_handlers.get_property_ptr_ptr = NULL; + DCL_PROP(PROTECTED, long, type, HTTP_MSG_NONE); + DCL_PROP(PROTECTED, string, body, ""); + DCL_PROP(PROTECTED, string, requestMethod, ""); + DCL_PROP(PROTECTED, string, requestUrl, ""); + DCL_PROP(PROTECTED, string, responseStatus, ""); + DCL_PROP(PROTECTED, long, responseCode, 0); + DCL_PROP_N(PROTECTED, httpVersion); + DCL_PROP_N(PROTECTED, headers); + DCL_PROP_N(PROTECTED, parentMessage); + +#ifndef WONKY + DCL_CONST(long, "TYPE_NONE", HTTP_MSG_NONE); + DCL_CONST(long, "TYPE_REQUEST", HTTP_MSG_REQUEST); + DCL_CONST(long, "TYPE_RESPONSE", HTTP_MSG_RESPONSE); +#endif + + HTTP_LONG_CONSTANT("HTTP_MSG_NONE", HTTP_MSG_NONE); + HTTP_LONG_CONSTANT("HTTP_MSG_REQUEST", HTTP_MSG_REQUEST); + HTTP_LONG_CONSTANT("HTTP_MSG_RESPONSE", HTTP_MSG_RESPONSE); + return SUCCESS; } +void _http_message_object_reverse(zval *this_ptr, zval *return_value TSRMLS_DC) +{ + int i; + getObject(http_message_object, obj); + + /* count */ + http_message_count(i, obj->message); + + if (i > 1) { + zval o; + zend_object_value *ovalues = NULL; + http_message_object **objects = NULL; + int last = i - 1; + + objects = ecalloc(i, sizeof(http_message_object *)); + ovalues = ecalloc(i, sizeof(zend_object_value)); + + /* we are the first message */ + objects[0] = obj; + ovalues[0] = getThis()->value.obj; + + /* fetch parents */ + INIT_PZVAL(&o); + o.type = IS_OBJECT; + for (i = 1; obj->parent.handle; ++i) { + o.value.obj = obj->parent; + ovalues[i] = o.value.obj; + objects[i] = obj = zend_object_store_get_object(&o TSRMLS_CC); + } + + /* reorder parents */ + for (last = --i; i; --i) { + objects[i]->message->parent = objects[i-1]->message; + objects[i]->parent = ovalues[i-1]; + } + objects[0]->message->parent = NULL; + objects[0]->parent.handle = 0; + objects[0]->parent.handlers = NULL; + + /* add ref (why?) */ + Z_OBJ_ADDREF_P(getThis()); + RETVAL_OBJVAL(ovalues[last], 1); + + efree(objects); + efree(ovalues); + } else { + RETURN_ZVAL(getThis(), 1, 0); + } +} + void _http_message_object_prepend_ex(zval *this_ptr, zval *prepend, zend_bool top TSRMLS_DC) { zval m; - http_message *save_parent_msg; - zend_object_value save_parent_obj; + http_message *save_parent_msg = NULL; + zend_object_value save_parent_obj = {0, NULL}; getObject(http_message_object, obj); getObjectEx(http_message_object, prepend_obj, prepend); @@ -288,27 +354,6 @@ zend_object_value _http_message_object_clone_obj(zval *this_ptr TSRMLS_DC) return http_message_object_new_ex(Z_OBJCE_P(this_ptr), http_message_dup(obj->message), NULL); } -static inline void _http_message_object_declare_default_properties(TSRMLS_D) -{ - zend_class_entry *ce = http_message_object_ce; - -#ifndef WONKY - DCL_CONST(long, "TYPE_NONE", HTTP_MSG_NONE); - DCL_CONST(long, "TYPE_REQUEST", HTTP_MSG_REQUEST); - DCL_CONST(long, "TYPE_RESPONSE", HTTP_MSG_RESPONSE); -#endif - - DCL_PROP(PROTECTED, long, type, HTTP_MSG_NONE); - DCL_PROP(PROTECTED, string, body, ""); - DCL_PROP(PROTECTED, string, requestMethod, ""); - DCL_PROP(PROTECTED, string, requestUrl, ""); - DCL_PROP(PROTECTED, string, responseStatus, ""); - DCL_PROP(PROTECTED, long, responseCode, 0); - DCL_PROP_N(PROTECTED, httpVersion); - DCL_PROP_N(PROTECTED, headers); - DCL_PROP_N(PROTECTED, parentMessage); -} - void _http_message_object_free(zend_object *object TSRMLS_DC) { http_message_object *o = (http_message_object *) object; @@ -551,7 +596,7 @@ static HashTable *_http_message_object_get_props(zval *object TSRMLS_DC) getObjectEx(http_message_object, obj, object); http_message *msg = obj->message; HashTable *props = OBJ_PROP(obj); - zval array; + zval array, *parent; INIT_ZARR(array, props); @@ -606,6 +651,14 @@ static HashTable *_http_message_object_get_props(zval *object TSRMLS_DC) zend_hash_copy(Z_ARRVAL_P(headers), &msg->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *)); ASSOC_PROP(array, zval, "headers", headers); ASSOC_STRINGL(array, "body", PHPSTR_VAL(msg), PHPSTR_LEN(msg)); + + MAKE_STD_ZVAL(parent); + if (msg->parent) { + ZVAL_OBJVAL(parent, obj->parent, 1); + } else { + ZVAL_NULL(parent); + } + ASSOC_PROP(array, zval, "parentMessage", parent); return OBJ_PROP(obj); } @@ -1080,22 +1133,24 @@ PHP_METHOD(HttpMessage, setHttpVersion) /* {{{ proto HttpMessage HttpMessage::getParentMessage() * * Get parent Message. - * + * * Returns the parent HttpMessage on success, or NULL if there's none. + * + * Throws HttpRuntimeException. */ PHP_METHOD(HttpMessage, getParentMessage) { - NO_ARGS; - - IF_RETVAL_USED { + SET_EH_THROW_HTTP(); + NO_ARGS { getObject(http_message_object, obj); if (obj->message->parent) { RETVAL_OBJVAL(obj->parent, 1); } else { - RETVAL_NULL(); + http_error(HE_WARNING, HTTP_E_RUNTIME, "HttpMessage does not have a parent message"); } } + SET_EH_NORMAL(); } /* }}} */ @@ -1357,11 +1412,13 @@ PHP_METHOD(HttpMessage, detach) } /* }}} */ -/* {{{ proto void HttpMessage::prepend(HttpMessage message) +/* {{{ proto void HttpMessage::prepend(HttpMessage message[, bool top = true]) * * Prepends message(s) to the HTTP message. * * Expects an HttpMessage object as parameter. + * + * Throws HttpInvalidParamException if the message is located within the same message chain. */ PHP_METHOD(HttpMessage, prepend) { @@ -1369,6 +1426,20 @@ PHP_METHOD(HttpMessage, prepend) zend_bool top = 1; if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|b", &prepend, http_message_object_ce, &top)) { + http_message *msg[2]; + getObject(http_message_object, obj); + getObjectEx(http_message_object, prepend_obj, prepend); + + /* safety check */ + for (msg[0] = obj->message; msg[0]; msg[0] = msg[0]->parent) { + for (msg[1] = prepend_obj->message; msg[1]; msg[1] = msg[1]->parent) { + if (msg[0] == msg[1]) { + http_error(HE_THROW, HTTP_E_INVALID_PARAM, "Cannot prepend a message located within the same message chain"); + return; + } + } + } + http_message_object_prepend_ex(getThis(), prepend, top); } } @@ -1382,53 +1453,8 @@ PHP_METHOD(HttpMessage, prepend) */ PHP_METHOD(HttpMessage, reverse) { - int i; - getObject(http_message_object, obj); - - NO_ARGS; - - /* count */ - http_message_count(i, obj->message); - - if (i > 1) { - zval o; - zend_object_value *ovalues = NULL; - http_message_object **objects = NULL; - int last = i - 1; - - objects = ecalloc(i, sizeof(http_message_object *)); - ovalues = ecalloc(i, sizeof(zend_object_value)); - - /* we are the first message */ - objects[0] = obj; - ovalues[0] = getThis()->value.obj; - - /* fetch parents */ - INIT_PZVAL(&o); - o.type = IS_OBJECT; - for (i = 1; obj->parent.handle; ++i) { - o.value.obj = obj->parent; - ovalues[i] = o.value.obj; - objects[i] = obj = zend_object_store_get_object(&o TSRMLS_CC); - } - - /* reorder parents */ - for (last = --i; i; --i) { - objects[i]->message->parent = objects[i-1]->message; - objects[i]->parent = ovalues[i-1]; - } - objects[0]->message->parent = NULL; - objects[0]->parent.handle = 0; - objects[0]->parent.handlers = NULL; - - /* add ref (why?) */ - Z_OBJ_ADDREF_P(getThis()); - RETVAL_OBJVAL(ovalues[last], 1); - - efree(objects); - efree(ovalues); - } else { - RETURN_ZVAL(getThis(), 1, 0); + NO_ARGS { + http_message_object_reverse(getThis(), return_value); } } /* }}} */