LTP GCOV extension - code coverage report
Current view: directory - ext/http - http_message_object.c
Test: PHP Code Coverage
Date: 2007-04-10 Instrumented lines: 598
Code covered: 49.5 % Executed lines: 296
Legend: not executed executed

       1                 : /*
       2                 :     +--------------------------------------------------------------------+
       3                 :     | PECL :: http                                                       |
       4                 :     +--------------------------------------------------------------------+
       5                 :     | Redistribution and use in source and binary forms, with or without |
       6                 :     | modification, are permitted provided that the conditions mentioned |
       7                 :     | in the accompanying LICENSE file are met.                          |
       8                 :     +--------------------------------------------------------------------+
       9                 :     | Copyright (c) 2004-2007, Michael Wallner <mike@php.net>            |
      10                 :     +--------------------------------------------------------------------+
      11                 : */
      12                 : 
      13                 : /* $Id: http_message_object.c,v 1.112 2007/02/22 11:04:37 mike Exp $ */
      14                 : 
      15                 : #define HTTP_WANT_SAPI
      16                 : #define HTTP_WANT_CURL
      17                 : #define HTTP_WANT_MAGIC
      18                 : #include "php_http.h"
      19                 : 
      20                 : #ifdef ZEND_ENGINE_2
      21                 : 
      22                 : #include "zend_interfaces.h"
      23                 : #include "ext/standard/url.h"
      24                 : 
      25                 : #include "php_http_api.h"
      26                 : #include "php_http_send_api.h"
      27                 : #include "php_http_url_api.h"
      28                 : #include "php_http_message_api.h"
      29                 : #include "php_http_message_object.h"
      30                 : #include "php_http_exception_object.h"
      31                 : #include "php_http_response_object.h"
      32                 : #include "php_http_request_method_api.h"
      33                 : #include "php_http_request_api.h"
      34                 : #include "php_http_request_object.h"
      35                 : #include "php_http_headers_api.h"
      36                 : 
      37                 : #if defined(HTTP_HAVE_SPL) && !defined(WONKY)
      38                 : /* SPL doesn't install its headers */
      39                 : extern PHPAPI zend_class_entry *spl_ce_Countable;
      40                 : #endif
      41                 : 
      42                 : #define HTTP_BEGIN_ARGS(method, req_args)       HTTP_BEGIN_ARGS_EX(HttpMessage, method, 0, req_args)
      43                 : #define HTTP_EMPTY_ARGS(method)                         HTTP_EMPTY_ARGS_EX(HttpMessage, method, 0)
      44                 : #define HTTP_MESSAGE_ME(method, visibility)     PHP_ME(HttpMessage, method, HTTP_ARGS(HttpMessage, method), visibility)
      45                 : 
      46                 : HTTP_BEGIN_ARGS(__construct, 0)
      47                 :         HTTP_ARG_VAL(message, 0)
      48                 : HTTP_END_ARGS;
      49                 : 
      50                 : HTTP_BEGIN_ARGS(factory, 0)
      51                 :         HTTP_ARG_VAL(message, 0)
      52                 :         HTTP_ARG_VAL(class_name, 0)
      53                 : HTTP_END_ARGS;
      54                 : 
      55                 : HTTP_BEGIN_ARGS(fromEnv, 1)
      56                 :         HTTP_ARG_VAL(type, 0)
      57                 :         HTTP_ARG_VAL(class_name, 0)
      58                 : HTTP_END_ARGS;
      59                 : 
      60                 : HTTP_EMPTY_ARGS(getBody);
      61                 : HTTP_BEGIN_ARGS(setBody, 1)
      62                 :         HTTP_ARG_VAL(body, 0)
      63                 : HTTP_END_ARGS;
      64                 : 
      65                 : HTTP_BEGIN_ARGS(getHeader, 1)
      66                 :         HTTP_ARG_VAL(header, 0)
      67                 : HTTP_END_ARGS;
      68                 : 
      69                 : HTTP_EMPTY_ARGS(getHeaders);
      70                 : HTTP_BEGIN_ARGS(setHeaders, 1)
      71                 :         HTTP_ARG_VAL(headers, 0)
      72                 : HTTP_END_ARGS;
      73                 : 
      74                 : HTTP_BEGIN_ARGS(addHeaders, 1)
      75                 :         HTTP_ARG_VAL(headers, 0)
      76                 :         HTTP_ARG_VAL(append, 0)
      77                 : HTTP_END_ARGS;
      78                 : 
      79                 : HTTP_EMPTY_ARGS(getType);
      80                 : HTTP_BEGIN_ARGS(setType, 1)
      81                 :         HTTP_ARG_VAL(type, 0)
      82                 : HTTP_END_ARGS;
      83                 : 
      84                 : HTTP_EMPTY_ARGS(getInfo);
      85                 : HTTP_BEGIN_ARGS(setInfo, 1)
      86                 :         HTTP_ARG_VAL(http_info, 0)
      87                 : HTTP_END_ARGS;
      88                 : 
      89                 : HTTP_EMPTY_ARGS(getResponseCode);
      90                 : HTTP_BEGIN_ARGS(setResponseCode, 1)
      91                 :         HTTP_ARG_VAL(response_code, 0)
      92                 : HTTP_END_ARGS;
      93                 : 
      94                 : HTTP_EMPTY_ARGS(getResponseStatus);
      95                 : HTTP_BEGIN_ARGS(setResponseStatus, 1)
      96                 :         HTTP_ARG_VAL(response_status, 0)
      97                 : HTTP_END_ARGS;
      98                 : 
      99                 : HTTP_EMPTY_ARGS(getRequestMethod);
     100                 : HTTP_BEGIN_ARGS(setRequestMethod, 1)
     101                 :         HTTP_ARG_VAL(request_method, 0)
     102                 : HTTP_END_ARGS;
     103                 : 
     104                 : HTTP_EMPTY_ARGS(getRequestUrl);
     105                 : HTTP_BEGIN_ARGS(setRequestUrl, 1)
     106                 :         HTTP_ARG_VAL(url, 0)
     107                 : HTTP_END_ARGS;
     108                 : 
     109                 : HTTP_EMPTY_ARGS(getHttpVersion);
     110                 : HTTP_BEGIN_ARGS(setHttpVersion, 1)
     111                 :         HTTP_ARG_VAL(http_version, 0)
     112                 : HTTP_END_ARGS;
     113                 : 
     114                 : HTTP_BEGIN_ARGS(guessContentType, 1)
     115                 :         HTTP_ARG_VAL(magic_file, 0)
     116                 :         HTTP_ARG_VAL(magic_mode, 0)
     117                 : HTTP_END_ARGS;
     118                 : 
     119                 : HTTP_EMPTY_ARGS(getParentMessage);
     120                 : HTTP_EMPTY_ARGS(send);
     121                 : HTTP_BEGIN_ARGS(toString, 0)
     122                 :         HTTP_ARG_VAL(include_parent, 0)
     123                 : HTTP_END_ARGS;
     124                 : 
     125                 : HTTP_EMPTY_ARGS(toMessageTypeObject);
     126                 : 
     127                 : HTTP_EMPTY_ARGS(count);
     128                 : 
     129                 : HTTP_EMPTY_ARGS(serialize);
     130                 : HTTP_BEGIN_ARGS(unserialize, 1)
     131                 :         HTTP_ARG_VAL(serialized, 0)
     132                 : HTTP_END_ARGS;
     133                 : 
     134                 : HTTP_EMPTY_ARGS(rewind);
     135                 : HTTP_EMPTY_ARGS(valid);
     136                 : HTTP_EMPTY_ARGS(key);
     137                 : HTTP_EMPTY_ARGS(current);
     138                 : HTTP_EMPTY_ARGS(next);
     139                 : 
     140                 : HTTP_EMPTY_ARGS(detach);
     141                 : HTTP_BEGIN_ARGS(prepend, 1)
     142                 :         HTTP_ARG_OBJ(HttpMessage, message, 0)
     143                 : HTTP_END_ARGS;
     144                 : HTTP_EMPTY_ARGS(reverse);
     145                 : 
     146                 : #define http_message_object_read_prop _http_message_object_read_prop
     147                 : static zval *_http_message_object_read_prop(zval *object, zval *member, int type TSRMLS_DC);
     148                 : #define http_message_object_write_prop _http_message_object_write_prop
     149                 : static void _http_message_object_write_prop(zval *object, zval *member, zval *value TSRMLS_DC);
     150                 : #define http_message_object_get_props _http_message_object_get_props
     151                 : static HashTable *_http_message_object_get_props(zval *object TSRMLS_DC);
     152                 : 
     153                 : #define THIS_CE http_message_object_ce
     154                 : zend_class_entry *http_message_object_ce;
     155                 : zend_function_entry http_message_object_fe[] = {
     156                 :         HTTP_MESSAGE_ME(__construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
     157                 :         HTTP_MESSAGE_ME(getBody, ZEND_ACC_PUBLIC)
     158                 :         HTTP_MESSAGE_ME(setBody, ZEND_ACC_PUBLIC)
     159                 :         HTTP_MESSAGE_ME(getHeader, ZEND_ACC_PUBLIC)
     160                 :         HTTP_MESSAGE_ME(getHeaders, ZEND_ACC_PUBLIC)
     161                 :         HTTP_MESSAGE_ME(setHeaders, ZEND_ACC_PUBLIC)
     162                 :         HTTP_MESSAGE_ME(addHeaders, ZEND_ACC_PUBLIC)
     163                 :         HTTP_MESSAGE_ME(getType, ZEND_ACC_PUBLIC)
     164                 :         HTTP_MESSAGE_ME(setType, ZEND_ACC_PUBLIC)
     165                 :         HTTP_MESSAGE_ME(getInfo, ZEND_ACC_PUBLIC)
     166                 :         HTTP_MESSAGE_ME(setInfo, ZEND_ACC_PUBLIC)
     167                 :         HTTP_MESSAGE_ME(getResponseCode, ZEND_ACC_PUBLIC)
     168                 :         HTTP_MESSAGE_ME(setResponseCode, ZEND_ACC_PUBLIC)
     169                 :         HTTP_MESSAGE_ME(getResponseStatus, ZEND_ACC_PUBLIC)
     170                 :         HTTP_MESSAGE_ME(setResponseStatus, ZEND_ACC_PUBLIC)
     171                 :         HTTP_MESSAGE_ME(getRequestMethod, ZEND_ACC_PUBLIC)
     172                 :         HTTP_MESSAGE_ME(setRequestMethod, ZEND_ACC_PUBLIC)
     173                 :         HTTP_MESSAGE_ME(getRequestUrl, ZEND_ACC_PUBLIC)
     174                 :         HTTP_MESSAGE_ME(setRequestUrl, ZEND_ACC_PUBLIC)
     175                 :         HTTP_MESSAGE_ME(getHttpVersion, ZEND_ACC_PUBLIC)
     176                 :         HTTP_MESSAGE_ME(setHttpVersion, ZEND_ACC_PUBLIC)
     177                 :         HTTP_MESSAGE_ME(guessContentType, ZEND_ACC_PUBLIC)
     178                 :         HTTP_MESSAGE_ME(getParentMessage, ZEND_ACC_PUBLIC)
     179                 :         HTTP_MESSAGE_ME(send, ZEND_ACC_PUBLIC)
     180                 :         HTTP_MESSAGE_ME(toString, ZEND_ACC_PUBLIC)
     181                 :         HTTP_MESSAGE_ME(toMessageTypeObject, ZEND_ACC_PUBLIC)
     182                 : 
     183                 :         /* implements Countable */
     184                 :         HTTP_MESSAGE_ME(count, ZEND_ACC_PUBLIC)
     185                 :         
     186                 :         /* implements Serializable */
     187                 :         HTTP_MESSAGE_ME(serialize, ZEND_ACC_PUBLIC)
     188                 :         HTTP_MESSAGE_ME(unserialize, ZEND_ACC_PUBLIC)
     189                 :         
     190                 :         /* implements Iterator */
     191                 :         HTTP_MESSAGE_ME(rewind, ZEND_ACC_PUBLIC)
     192                 :         HTTP_MESSAGE_ME(valid, ZEND_ACC_PUBLIC)
     193                 :         HTTP_MESSAGE_ME(current, ZEND_ACC_PUBLIC)
     194                 :         HTTP_MESSAGE_ME(key, ZEND_ACC_PUBLIC)
     195                 :         HTTP_MESSAGE_ME(next, ZEND_ACC_PUBLIC)
     196                 : 
     197                 :         ZEND_MALIAS(HttpMessage, __toString, toString, HTTP_ARGS(HttpMessage, toString), ZEND_ACC_PUBLIC)
     198                 : 
     199                 :         HTTP_MESSAGE_ME(factory, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
     200                 :         ZEND_MALIAS(HttpMessage, fromString, factory, HTTP_ARGS(HttpMessage, factory), ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
     201                 :         HTTP_MESSAGE_ME(fromEnv, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
     202                 :         
     203                 :         HTTP_MESSAGE_ME(detach, ZEND_ACC_PUBLIC)
     204                 :         HTTP_MESSAGE_ME(prepend, ZEND_ACC_PUBLIC)
     205                 :         HTTP_MESSAGE_ME(reverse, ZEND_ACC_PUBLIC)
     206                 : 
     207                 :         EMPTY_FUNCTION_ENTRY
     208                 : };
     209                 : static zend_object_handlers http_message_object_handlers;
     210                 : 
     211                 : PHP_MINIT_FUNCTION(http_message_object)
     212             220 : {
     213             220 :         HTTP_REGISTER_CLASS_EX(HttpMessage, http_message_object, NULL, 0);
     214                 :         
     215                 : #ifndef WONKY
     216                 : #       ifdef HTTP_HAVE_SPL
     217             220 :         zend_class_implements(http_message_object_ce TSRMLS_CC, 3, spl_ce_Countable, zend_ce_serializable, zend_ce_iterator);
     218                 : #       else
     219                 :         zend_class_implements(http_message_object_ce TSRMLS_CC, 2, zend_ce_serializable, zend_ce_iterator);
     220                 : #       endif
     221                 : #else
     222                 :         zend_class_implements(http_message_object_ce TSRMLS_CC, 1, zend_ce_iterator);
     223                 : #endif
     224                 :         
     225             220 :         http_message_object_handlers.clone_obj = _http_message_object_clone_obj;
     226             220 :         http_message_object_handlers.read_property = http_message_object_read_prop;
     227             220 :         http_message_object_handlers.write_property = http_message_object_write_prop;
     228             220 :         http_message_object_handlers.get_properties = http_message_object_get_props;
     229             220 :         http_message_object_handlers.get_property_ptr_ptr = NULL;
     230                 :         
     231             220 :         zend_declare_property_long(THIS_CE, ZEND_STRS("type")-1, HTTP_MSG_NONE, ZEND_ACC_PROTECTED TSRMLS_CC);
     232             220 :         zend_declare_property_string(THIS_CE, ZEND_STRS("body")-1, "", ZEND_ACC_PROTECTED TSRMLS_CC);
     233             220 :         zend_declare_property_string(THIS_CE, ZEND_STRS("requestMethod")-1, "", ZEND_ACC_PROTECTED TSRMLS_CC);
     234             220 :         zend_declare_property_string(THIS_CE, ZEND_STRS("requestUrl")-1, "", ZEND_ACC_PROTECTED TSRMLS_CC);
     235             220 :         zend_declare_property_string(THIS_CE, ZEND_STRS("responseStatus")-1, "", ZEND_ACC_PROTECTED TSRMLS_CC);
     236             220 :         zend_declare_property_long(THIS_CE, ZEND_STRS("responseCode")-1, 0, ZEND_ACC_PROTECTED TSRMLS_CC);
     237             220 :         zend_declare_property_null(THIS_CE, ZEND_STRS("httpVersion")-1, ZEND_ACC_PROTECTED TSRMLS_CC);
     238             220 :         zend_declare_property_null(THIS_CE, ZEND_STRS("headers")-1, ZEND_ACC_PROTECTED TSRMLS_CC);
     239             220 :         zend_declare_property_null(THIS_CE, ZEND_STRS("parentMessage")-1, ZEND_ACC_PROTECTED TSRMLS_CC);
     240                 :         
     241                 : #ifndef WONKY
     242             220 :         zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_NONE")-1, HTTP_MSG_NONE TSRMLS_CC);
     243             220 :         zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_REQUEST")-1, HTTP_MSG_REQUEST TSRMLS_CC);
     244             220 :         zend_declare_class_constant_long(THIS_CE, ZEND_STRS("TYPE_RESPONSE")-1, HTTP_MSG_RESPONSE TSRMLS_CC);
     245                 : #endif
     246                 :         
     247             220 :         HTTP_LONG_CONSTANT("HTTP_MSG_NONE", HTTP_MSG_NONE);
     248             220 :         HTTP_LONG_CONSTANT("HTTP_MSG_REQUEST", HTTP_MSG_REQUEST);
     249             220 :         HTTP_LONG_CONSTANT("HTTP_MSG_RESPONSE", HTTP_MSG_RESPONSE);
     250                 :         
     251             220 :         return SUCCESS;
     252                 : }
     253                 : 
     254                 : void _http_message_object_reverse(zval *this_ptr, zval *return_value TSRMLS_DC)
     255               2 : {
     256                 :         int i;
     257               2 :         getObject(http_message_object, obj);
     258                 :         
     259                 :         /* count */
     260               2 :         http_message_count(i, obj->message);
     261                 :         
     262               2 :         if (i > 1) {
     263                 :                 zval o;
     264               2 :                 zend_object_value *ovalues = NULL;
     265               2 :                 http_message_object **objects = NULL;
     266               2 :                 int last = i - 1;
     267                 :                 
     268               2 :                 objects = ecalloc(i, sizeof(http_message_object *));
     269               2 :                 ovalues = ecalloc(i, sizeof(zend_object_value));
     270                 :         
     271                 :                 /* we are the first message */
     272               2 :                 objects[0] = obj;
     273               2 :                 ovalues[0] = getThis()->value.obj;
     274                 :         
     275                 :                 /* fetch parents */
     276               2 :                 INIT_PZVAL(&o);
     277               2 :                 o.type = IS_OBJECT;
     278              12 :                 for (i = 1; obj->parent.handle; ++i) {
     279              10 :                         o.value.obj = obj->parent;
     280              10 :                         ovalues[i] = o.value.obj;
     281              10 :                         objects[i] = obj = zend_object_store_get_object(&o TSRMLS_CC);
     282                 :                 }
     283                 :                 
     284                 :                 /* reorder parents */
     285              12 :                 for (last = --i; i; --i) {
     286              10 :                         objects[i]->message->parent = objects[i-1]->message;
     287              10 :                         objects[i]->parent = ovalues[i-1];
     288                 :                 }
     289               2 :                 objects[0]->message->parent = NULL;
     290               2 :                 objects[0]->parent.handle = 0;
     291               2 :                 objects[0]->parent.handlers = NULL;
     292                 :                 
     293                 :                 /* add ref (why?) */
     294               2 :                 Z_OBJ_ADDREF_P(getThis());
     295               2 :                 RETVAL_OBJVAL(ovalues[last], 1);
     296                 :                 
     297               2 :                 efree(objects);
     298               2 :                 efree(ovalues);
     299                 :         } else {
     300               0 :                 RETURN_ZVAL(getThis(), 1, 0);
     301                 :         }
     302                 : }
     303                 : 
     304                 : void _http_message_object_prepend_ex(zval *this_ptr, zval *prepend, zend_bool top TSRMLS_DC)
     305               3 : {
     306                 :         zval m;
     307               3 :         http_message *save_parent_msg = NULL;
     308               3 :         zend_object_value save_parent_obj = {0, NULL};
     309               3 :         getObject(http_message_object, obj);
     310               3 :         getObjectEx(http_message_object, prepend_obj, prepend);
     311                 :                 
     312               3 :         INIT_PZVAL(&m);
     313               3 :         m.type = IS_OBJECT;
     314                 :                 
     315               3 :         if (!top) {
     316               1 :                 save_parent_obj = obj->parent;
     317               1 :                 save_parent_msg = obj->message->parent;
     318                 :         } else {
     319                 :                 /* iterate to the most parent object */
     320               6 :                 while (obj->parent.handle) {
     321               2 :                         m.value.obj = obj->parent;
     322               2 :                         obj = zend_object_store_get_object(&m TSRMLS_CC);
     323                 :                 }
     324                 :         }
     325                 :                 
     326                 :         /* prepend */
     327               3 :         obj->parent = prepend->value.obj;
     328               3 :         obj->message->parent = prepend_obj->message;
     329                 :                 
     330                 :         /* add ref */
     331               3 :         zend_objects_store_add_ref(prepend TSRMLS_CC);
     332               8 :         while (prepend_obj->parent.handle) {
     333               2 :                 m.value.obj = prepend_obj->parent;
     334               2 :                 zend_objects_store_add_ref(&m TSRMLS_CC);
     335               2 :                 prepend_obj = zend_object_store_get_object(&m TSRMLS_CC);
     336                 :         }
     337                 :                 
     338               3 :         if (!top) {
     339               1 :                 prepend_obj->parent = save_parent_obj;
     340               1 :                 prepend_obj->message->parent = save_parent_msg;
     341                 :         }
     342               3 : }
     343                 : 
     344                 : zend_object_value _http_message_object_new(zend_class_entry *ce TSRMLS_DC)
     345               8 : {
     346               8 :         return http_message_object_new_ex(ce, NULL, NULL);
     347                 : }
     348                 : 
     349                 : zend_object_value _http_message_object_new_ex(zend_class_entry *ce, http_message *msg, http_message_object **ptr TSRMLS_DC)
     350             144 : {
     351                 :         zend_object_value ov;
     352                 :         http_message_object *o;
     353                 : 
     354             144 :         o = ecalloc(1, sizeof(http_message_object));
     355             144 :         o->zo.ce = ce;
     356                 :         
     357             144 :         if (ptr) {
     358               3 :                 *ptr = o;
     359                 :         }
     360                 : 
     361             144 :         if (msg) {
     362             136 :                 o->message = msg;
     363             136 :                 if (msg->parent) {
     364              39 :                         o->parent = http_message_object_new_ex(ce, msg->parent, NULL);
     365                 :                 }
     366                 :         }
     367                 : 
     368             144 :         ALLOC_HASHTABLE(OBJ_PROP(o));
     369             144 :         zend_hash_init(OBJ_PROP(o), zend_hash_num_elements(&ce->default_properties), NULL, ZVAL_PTR_DTOR, 0);
     370             144 :         zend_hash_copy(OBJ_PROP(o), &ce->default_properties, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
     371                 : 
     372             144 :         ov.handle = putObject(http_message_object, o);
     373             144 :         ov.handlers = &http_message_object_handlers;
     374                 : 
     375             144 :         return ov;
     376                 : }
     377                 : 
     378                 : zend_object_value _http_message_object_clone_obj(zval *this_ptr TSRMLS_DC)
     379               0 : {
     380                 :         zend_object_value new_ov;
     381               0 :         http_message_object *new_obj = NULL;
     382               0 :         getObject(http_message_object, old_obj);
     383                 :         
     384               0 :         new_ov = http_message_object_new_ex(old_obj->zo.ce, http_message_dup(old_obj->message), &new_obj);
     385               0 :         zend_objects_clone_members(&new_obj->zo, new_ov, &old_obj->zo, Z_OBJ_HANDLE_P(this_ptr) TSRMLS_CC);
     386                 :         
     387               0 :         return new_ov;
     388                 : }
     389                 : 
     390                 : void _http_message_object_free(zend_object *object TSRMLS_DC)
     391             144 : {
     392             144 :         http_message_object *o = (http_message_object *) object;
     393                 : 
     394             144 :         if (o->message) {
     395             144 :                 http_message_dtor(o->message);
     396             144 :                 efree(o->message);
     397                 :         }
     398             144 :         if (o->parent.handle) {
     399                 :                 zval p;
     400                 :                 
     401              49 :                 INIT_PZVAL(&p);
     402              49 :                 p.type = IS_OBJECT;
     403              49 :                 p.value.obj = o->parent;
     404              49 :                 zend_objects_store_del_ref(&p TSRMLS_CC);
     405                 :         }
     406             144 :         freeObject(o);
     407             144 : }
     408                 : 
     409                 : static zval *_http_message_object_read_prop(zval *object, zval *member, int type TSRMLS_DC)
     410               2 : {
     411               2 :         getObjectEx(http_message_object, obj, object);
     412               2 :         http_message *msg = obj->message;
     413                 :         zval *return_value;
     414                 : #ifdef WONKY
     415                 :         ulong h = zend_hash_func(Z_STRVAL_P(member), Z_STRLEN_P(member)+1);
     416                 : #else
     417               2 :         zend_property_info *pinfo = zend_get_property_info(obj->zo.ce, member, 1 TSRMLS_CC);
     418                 :         
     419               2 :         if (!pinfo || ACC_PROP_PUBLIC(pinfo->flags)) {
     420               0 :                 return zend_get_std_object_handlers()->read_property(object, member, type TSRMLS_CC);
     421                 :         }
     422                 : #endif
     423                 : 
     424               2 :         if (type == BP_VAR_W) {
     425               1 :                 zend_error(E_ERROR, "Cannot access HttpMessage properties by reference or array key/index");
     426               0 :                 return NULL;
     427                 :         }
     428                 :         
     429               1 :         ALLOC_ZVAL(return_value);
     430               1 :         return_value->refcount = 0;
     431               1 :         return_value->is_ref = 0;
     432                 : 
     433                 : #ifdef WONKY
     434                 :         switch (h)
     435                 : #else
     436               1 :         switch (pinfo->h)
     437                 : #endif
     438                 :         {
     439                 :                 case HTTP_MSG_PROPHASH_TYPE:
     440                 :                 case HTTP_MSG_CHILD_PROPHASH_TYPE:
     441               0 :                         RETVAL_LONG(msg->type);
     442               0 :                         break;
     443                 : 
     444                 :                 case HTTP_MSG_PROPHASH_HTTP_VERSION:
     445                 :                 case HTTP_MSG_CHILD_PROPHASH_HTTP_VERSION:
     446               0 :                         RETVAL_DOUBLE(msg->http.version);
     447               0 :                         break;
     448                 : 
     449                 :                 case HTTP_MSG_PROPHASH_BODY:
     450                 :                 case HTTP_MSG_CHILD_PROPHASH_BODY:
     451               0 :                         phpstr_fix(PHPSTR(msg));
     452               0 :                         RETVAL_PHPSTR(PHPSTR(msg), 0, 1);
     453               0 :                         break;
     454                 : 
     455                 :                 case HTTP_MSG_PROPHASH_HEADERS:
     456                 :                 case HTTP_MSG_CHILD_PROPHASH_HEADERS:
     457               1 :                         array_init(return_value);
     458               1 :                         zend_hash_copy(Z_ARRVAL_P(return_value), &msg->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
     459               1 :                         break;
     460                 : 
     461                 :                 case HTTP_MSG_PROPHASH_PARENT_MESSAGE:
     462                 :                 case HTTP_MSG_CHILD_PROPHASH_PARENT_MESSAGE:
     463               0 :                         if (msg->parent) {
     464               0 :                                 RETVAL_OBJVAL(obj->parent, 1);
     465                 :                         } else {
     466               0 :                                 RETVAL_NULL();
     467                 :                         }
     468               0 :                         break;
     469                 : 
     470                 :                 case HTTP_MSG_PROPHASH_REQUEST_METHOD:
     471                 :                 case HTTP_MSG_CHILD_PROPHASH_REQUEST_METHOD:
     472               0 :                         if (HTTP_MSG_TYPE(REQUEST, msg) && msg->http.info.request.method) {
     473               0 :                                 RETVAL_STRING(msg->http.info.request.method, 1);
     474                 :                         } else {
     475               0 :                                 RETVAL_NULL();
     476                 :                         }
     477               0 :                         break;
     478                 : 
     479                 :                 case HTTP_MSG_PROPHASH_REQUEST_URL:
     480                 :                 case HTTP_MSG_CHILD_PROPHASH_REQUEST_URL:
     481               0 :                         if (HTTP_MSG_TYPE(REQUEST, msg) && msg->http.info.request.url) {
     482               0 :                                 RETVAL_STRING(msg->http.info.request.url, 1);
     483                 :                         } else {
     484               0 :                                 RETVAL_NULL();
     485                 :                         }
     486               0 :                         break;
     487                 : 
     488                 :                 case HTTP_MSG_PROPHASH_RESPONSE_CODE:
     489                 :                 case HTTP_MSG_CHILD_PROPHASH_RESPONSE_CODE:
     490               0 :                         if (HTTP_MSG_TYPE(RESPONSE, msg)) {
     491               0 :                                 RETVAL_LONG(msg->http.info.response.code);
     492                 :                         } else {
     493               0 :                                 RETVAL_NULL();
     494                 :                         }
     495               0 :                         break;
     496                 :                 
     497                 :                 case HTTP_MSG_PROPHASH_RESPONSE_STATUS:
     498                 :                 case HTTP_MSG_CHILD_PROPHASH_RESPONSE_STATUS:
     499               0 :                         if (HTTP_MSG_TYPE(RESPONSE, msg) && msg->http.info.response.status) {
     500               0 :                                 RETVAL_STRING(msg->http.info.response.status, 1);
     501                 :                         } else {
     502               0 :                                 RETVAL_NULL();
     503                 :                         }
     504               0 :                         break;
     505                 :                 
     506                 :                 default:
     507                 : #ifdef WONKY
     508                 :                         return zend_get_std_object_handlers()->read_property(object, member, type TSRMLS_CC);
     509                 : #else
     510               0 :                         RETVAL_NULL();
     511                 : #endif
     512                 :         }
     513                 : 
     514               1 :         return return_value;
     515                 : }
     516                 : 
     517                 : static void _http_message_object_write_prop(zval *object, zval *member, zval *value TSRMLS_DC)
     518               0 : {
     519               0 :         getObjectEx(http_message_object, obj, object);
     520               0 :         http_message *msg = obj->message;
     521               0 :         zval *cpy = NULL;
     522                 : #ifdef WONKY
     523                 :         ulong h = zend_hash_func(Z_STRVAL_P(member), Z_STRLEN_P(member) + 1);
     524                 : #else
     525               0 :         zend_property_info *pinfo = zend_get_property_info(obj->zo.ce, member, 1 TSRMLS_CC);
     526                 :         
     527               0 :         if (!pinfo || ACC_PROP_PUBLIC(pinfo->flags)) {
     528               0 :                 zend_get_std_object_handlers()->write_property(object, member, value TSRMLS_CC);
     529               0 :                 return;
     530                 :         }
     531                 : #endif
     532                 :         
     533               0 :         cpy = zval_copy(Z_TYPE_P(value), value);
     534                 :         
     535                 : #ifdef WONKY
     536                 :         switch (h)
     537                 : #else
     538               0 :         switch (pinfo->h)
     539                 : #endif
     540                 :         {
     541                 :                 case HTTP_MSG_PROPHASH_TYPE:
     542                 :                 case HTTP_MSG_CHILD_PROPHASH_TYPE:
     543               0 :                         convert_to_long(cpy);
     544               0 :                         http_message_set_type(msg, Z_LVAL_P(cpy));
     545               0 :                         break;
     546                 : 
     547                 :                 case HTTP_MSG_PROPHASH_HTTP_VERSION:
     548                 :                 case HTTP_MSG_CHILD_PROPHASH_HTTP_VERSION:
     549               0 :                         convert_to_double(cpy);
     550               0 :                         msg->http.version = Z_DVAL_P(cpy);
     551               0 :                         break;
     552                 : 
     553                 :                 case HTTP_MSG_PROPHASH_BODY:
     554                 :                 case HTTP_MSG_CHILD_PROPHASH_BODY:
     555               0 :                         convert_to_string(cpy);
     556               0 :                         phpstr_dtor(PHPSTR(msg));
     557               0 :                         phpstr_from_string_ex(PHPSTR(msg), Z_STRVAL_P(cpy), Z_STRLEN_P(cpy));
     558               0 :                         break;
     559                 : 
     560                 :                 case HTTP_MSG_PROPHASH_HEADERS:
     561                 :                 case HTTP_MSG_CHILD_PROPHASH_HEADERS:
     562               0 :                         convert_to_array(cpy);
     563               0 :                         zend_hash_clean(&msg->hdrs);
     564               0 :                         zend_hash_copy(&msg->hdrs, Z_ARRVAL_P(cpy), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
     565               0 :                         break;
     566                 : 
     567                 :                 case HTTP_MSG_PROPHASH_PARENT_MESSAGE:
     568                 :                 case HTTP_MSG_CHILD_PROPHASH_PARENT_MESSAGE:
     569               0 :                         if (Z_TYPE_P(value) == IS_OBJECT && instanceof_function(Z_OBJCE_P(value), http_message_object_ce TSRMLS_CC)) {
     570               0 :                                 if (msg->parent) {
     571                 :                                         zval tmp;
     572               0 :                                         tmp.value.obj = obj->parent;
     573               0 :                                         Z_OBJ_DELREF(tmp);
     574                 :                                 }
     575               0 :                                 Z_OBJ_ADDREF_P(value);
     576               0 :                                 obj->parent = value->value.obj;
     577                 :                         }
     578               0 :                         break;
     579                 : 
     580                 :                 case HTTP_MSG_PROPHASH_REQUEST_METHOD:
     581                 :                 case HTTP_MSG_CHILD_PROPHASH_REQUEST_METHOD:
     582               0 :                         if (HTTP_MSG_TYPE(REQUEST, msg)) {
     583               0 :                                 convert_to_string(cpy);
     584               0 :                                 STR_SET(msg->http.info.request.method, estrndup(Z_STRVAL_P(cpy), Z_STRLEN_P(cpy)));
     585                 :                         }
     586               0 :                         break;
     587                 : 
     588                 :                 case HTTP_MSG_PROPHASH_REQUEST_URL:
     589                 :                 case HTTP_MSG_CHILD_PROPHASH_REQUEST_URL:
     590               0 :                         if (HTTP_MSG_TYPE(REQUEST, msg)) {
     591               0 :                                 convert_to_string(cpy);
     592               0 :                                 STR_SET(msg->http.info.request.url, estrndup(Z_STRVAL_P(cpy), Z_STRLEN_P(cpy)));
     593                 :                         }
     594               0 :                         break;
     595                 : 
     596                 :                 case HTTP_MSG_PROPHASH_RESPONSE_CODE:
     597                 :                 case HTTP_MSG_CHILD_PROPHASH_RESPONSE_CODE:
     598               0 :                         if (HTTP_MSG_TYPE(RESPONSE, msg)) {
     599               0 :                                 convert_to_long(cpy);
     600               0 :                                 msg->http.info.response.code = Z_LVAL_P(cpy);
     601                 :                         }
     602               0 :                         break;
     603                 :                 
     604                 :                 case HTTP_MSG_PROPHASH_RESPONSE_STATUS:
     605                 :                 case HTTP_MSG_CHILD_PROPHASH_RESPONSE_STATUS:
     606               0 :                         if (HTTP_MSG_TYPE(RESPONSE, msg)) {
     607               0 :                                 convert_to_string(cpy);
     608               0 :                                 STR_SET(msg->http.info.response.status, estrndup(Z_STRVAL_P(cpy), Z_STRLEN_P(cpy)));
     609                 :                         }
     610                 :                         break;
     611                 :                 
     612                 :                 default:
     613                 : #ifdef WONKY
     614                 :                         zend_get_std_object_handlers()->write_property(object, member, value TSRMLS_CC);
     615                 : #endif
     616                 :                         break;
     617                 :         }
     618               0 :         zval_free(&cpy);
     619                 : }
     620                 : 
     621                 : static HashTable *_http_message_object_get_props(zval *object TSRMLS_DC)
     622               1 : {
     623                 :         zval *headers;
     624               1 :         getObjectEx(http_message_object, obj, object);
     625               1 :         http_message *msg = obj->message;
     626               1 :         HashTable *props = OBJ_PROP(obj);
     627                 :         zval array, *parent;
     628                 :         
     629               1 :         INIT_ZARR(array, props);
     630                 : 
     631                 : #define ASSOC_PROP(array, ptype, name, val) \
     632                 :         { \
     633                 :                 char *m_prop_name; \
     634                 :                 int m_prop_len; \
     635                 :                 zend_mangle_property_name(&m_prop_name, &m_prop_len, "*", 1, name, lenof(name), 0); \
     636                 :                 add_assoc_ ##ptype## _ex(&array, m_prop_name, sizeof(name)+3, val); \
     637                 :                 efree(m_prop_name); \
     638                 :         }
     639                 : #define ASSOC_STRING(array, name, val) ASSOC_STRINGL(array, name, val, strlen(val))
     640                 : #define ASSOC_STRINGL(array, name, val, len) \
     641                 :         { \
     642                 :                 char *m_prop_name; \
     643                 :                 int m_prop_len; \
     644                 :                 zend_mangle_property_name(&m_prop_name, &m_prop_len, "*", 1, name, lenof(name), 0); \
     645                 :                 add_assoc_stringl_ex(&array, m_prop_name, sizeof(name)+3, val, len, 1); \
     646                 :                 efree(m_prop_name); \
     647                 :         }
     648                 : 
     649               1 :         ASSOC_PROP(array, long, "type", msg->type);
     650               1 :         ASSOC_PROP(array, double, "httpVersion", msg->http.version);
     651                 : 
     652               1 :         switch (msg->type) {
     653                 :                 case HTTP_MSG_REQUEST:
     654               0 :                         ASSOC_PROP(array, long, "responseCode", 0);
     655               0 :                         ASSOC_STRINGL(array, "responseStatus", "", 0);
     656               0 :                         ASSOC_STRING(array, "requestMethod", STR_PTR(msg->http.info.request.method));
     657               0 :                         ASSOC_STRING(array, "requestUrl", STR_PTR(msg->http.info.request.url));
     658               0 :                         break;
     659                 : 
     660                 :                 case HTTP_MSG_RESPONSE:
     661               1 :                         ASSOC_PROP(array, long, "responseCode", msg->http.info.response.code);
     662               1 :                         ASSOC_STRING(array, "responseStatus", STR_PTR(msg->http.info.response.status));
     663               1 :                         ASSOC_STRINGL(array, "requestMethod", "", 0);
     664               1 :                         ASSOC_STRINGL(array, "requestUrl", "", 0);
     665               1 :                         break;
     666                 : 
     667                 :                 case HTTP_MSG_NONE:
     668                 :                 default:
     669               0 :                         ASSOC_PROP(array, long, "responseCode", 0);
     670               0 :                         ASSOC_STRINGL(array, "responseStatus", "", 0);
     671               0 :                         ASSOC_STRINGL(array, "requestMethod", "", 0);
     672               0 :                         ASSOC_STRINGL(array, "requestUrl", "", 0);
     673                 :                         break;
     674                 :         }
     675                 : 
     676               1 :         MAKE_STD_ZVAL(headers);
     677               1 :         array_init(headers);
     678               1 :         zend_hash_copy(Z_ARRVAL_P(headers), &msg->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
     679               1 :         ASSOC_PROP(array, zval, "headers", headers);
     680               1 :         ASSOC_STRINGL(array, "body", PHPSTR_VAL(msg), PHPSTR_LEN(msg));
     681                 :         
     682               1 :         MAKE_STD_ZVAL(parent);
     683               1 :         if (msg->parent) {
     684               0 :                 ZVAL_OBJVAL(parent, obj->parent, 1);
     685                 :         } else {
     686               1 :                 ZVAL_NULL(parent);
     687                 :         }
     688               1 :         ASSOC_PROP(array, zval, "parentMessage", parent);
     689                 : 
     690               1 :         return OBJ_PROP(obj);
     691                 : }
     692                 : 
     693                 : /* ### USERLAND ### */
     694                 : 
     695                 : /* {{{ proto void HttpMessage::__construct([string message])
     696                 :         Create a new HttpMessage object instance. */
     697                 : PHP_METHOD(HttpMessage, __construct)
     698               8 : {
     699               8 :         int length = 0;
     700               8 :         char *message = NULL;
     701                 :         
     702               8 :         getObject(http_message_object, obj);
     703                 :         
     704               8 :         SET_EH_THROW_HTTP();
     705               8 :         if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &message, &length) && message && length) {
     706               7 :                 http_message *msg = obj->message;
     707                 :                 
     708               7 :                 http_message_dtor(msg);
     709               7 :                 if ((obj->message = http_message_parse_ex(msg, message, length))) {
     710               7 :                         if (obj->message->parent) {
     711               7 :                                 obj->parent = http_message_object_new_ex(Z_OBJCE_P(getThis()), obj->message->parent, NULL);
     712                 :                         }
     713                 :                 } else {
     714               0 :                         obj->message = http_message_init(msg);
     715                 :                 }
     716                 :         }
     717               8 :         if (!obj->message) {
     718               1 :                 obj->message = http_message_new();
     719                 :         }
     720               8 :         SET_EH_NORMAL();
     721               8 : }
     722                 : /* }}} */
     723                 : 
     724                 : /* {{{ proto static HttpMessage HttpMessage::factory([string raw_message[, string class_name = "HttpMessage"]])
     725                 :         Create a new HttpMessage object instance. */
     726                 : PHP_METHOD(HttpMessage, factory)
     727               3 : {
     728               3 :         char *string = NULL, *cn = NULL;
     729               3 :         int length = 0, cl = 0;
     730               3 :         http_message *msg = NULL;
     731                 :         zend_object_value ov;
     732               3 :         http_message_object *obj = NULL;
     733                 : 
     734               3 :         RETVAL_NULL();
     735                 :         
     736               3 :         SET_EH_THROW_HTTP();
     737               3 :         if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|ss", &string, &length, &cn, &cl)) {
     738               3 :                 if (length) {
     739               3 :                         msg = http_message_parse(string, length);
     740                 :                 }
     741               3 :                 if ((msg || !length) && SUCCESS == http_object_new(&ov, cn, cl, _http_message_object_new_ex, http_message_object_ce, msg, &obj)) {
     742               3 :                         RETVAL_OBJVAL(ov, 0);
     743                 :                 }
     744               3 :                 if (obj && !obj->message) {
     745               0 :                         obj->message = http_message_new();
     746                 :                 }
     747                 :         }
     748               3 :         SET_EH_NORMAL();
     749               3 : }
     750                 : /* }}} */
     751                 : 
     752                 : /* {{{ proto static HttpMessage HttpMessage::fromEnv(int type[, string class_name = "HttpMessage"])
     753                 :         Create a new HttpMessage object from environment representing either current request or response */
     754                 : PHP_METHOD(HttpMessage, fromEnv)
     755               0 : {
     756               0 :         char *cn = NULL;
     757               0 :         int cl = 0;
     758                 :         long type;
     759               0 :         http_message_object *obj = NULL;
     760                 :         zend_object_value ov;
     761                 :         
     762               0 :         RETVAL_NULL();
     763               0 :         SET_EH_THROW_HTTP();
     764               0 :         if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|s", &type, &cn, &cl)) {
     765               0 :                 if (SUCCESS == http_object_new(&ov, cn, cl, _http_message_object_new_ex, http_message_object_ce, http_message_init_env(NULL, type), &obj)) {
     766               0 :                         RETVAL_OBJVAL(ov, 0);
     767                 :                 }
     768               0 :                 if (obj && !obj->message) {
     769               0 :                         obj->message = http_message_new();
     770                 :                 }
     771                 :         }
     772               0 :         SET_EH_NORMAL();
     773               0 : }
     774                 : /* }}} */
     775                 : 
     776                 : /* {{{ proto string HttpMessage::getBody()
     777                 :         Get the body of the parsed HttpMessage. */
     778                 : PHP_METHOD(HttpMessage, getBody)
     779               6 : {
     780               6 :         NO_ARGS;
     781                 : 
     782               6 :         if (return_value_used) {
     783               6 :                 getObject(http_message_object, obj);
     784               6 :                 RETURN_PHPSTR(&obj->message->body, PHPSTR_FREE_NOT, 1);
     785                 :         }
     786                 : }
     787                 : /* }}} */
     788                 : 
     789                 : /* {{{ proto void HttpMessage::setBody(string body)
     790                 :         Set the body of the HttpMessage. NOTE: Don't forget to update any headers accordingly. */
     791                 : PHP_METHOD(HttpMessage, setBody)
     792               0 : {
     793                 :         char *body;
     794                 :         int len;
     795               0 :         getObject(http_message_object, obj);
     796                 :         
     797               0 :         if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &body, &len)) {
     798               0 :                 phpstr_dtor(PHPSTR(obj->message));
     799               0 :                 phpstr_from_string_ex(PHPSTR(obj->message), body, len);              
     800                 :         }
     801               0 : }
     802                 : /* }}} */
     803                 : 
     804                 : /* {{{ proto string HttpMessage::getHeader(string header)
     805                 :         Get message header. */
     806                 : PHP_METHOD(HttpMessage, getHeader)
     807               2 : {
     808                 :         zval *header;
     809                 :         char *orig_header, *nice_header;
     810                 :         int header_len;
     811               2 :         getObject(http_message_object, obj);
     812                 :         
     813               2 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &orig_header, &header_len)) {
     814               0 :                 RETURN_FALSE;
     815                 :         }
     816                 :         
     817               2 :         nice_header = pretty_key(estrndup(orig_header, header_len), header_len, 1, 1);
     818               2 :         if ((header = http_message_header_ex(obj->message, nice_header, header_len + 1, 0))) {
     819               2 :                 RETVAL_ZVAL(header, 1, 1);
     820                 :         }
     821               2 :         efree(nice_header);
     822                 : }
     823                 : /* }}} */
     824                 : 
     825                 : /* {{{ proto array HttpMessage::getHeaders()
     826                 :         Get Message Headers. */
     827                 : PHP_METHOD(HttpMessage, getHeaders)
     828               2 : {
     829               2 :         NO_ARGS;
     830                 : 
     831               2 :         if (return_value_used) {
     832               2 :                 getObject(http_message_object, obj);
     833                 : 
     834               2 :                 array_init(return_value);
     835               2 :                 array_copy(&obj->message->hdrs, Z_ARRVAL_P(return_value));
     836                 :         }
     837               2 : }
     838                 : /* }}} */
     839                 : 
     840                 : /* {{{ proto void HttpMessage::setHeaders(array headers)
     841                 :         Sets new headers. */
     842                 : PHP_METHOD(HttpMessage, setHeaders)
     843               0 : {
     844               0 :         zval *new_headers = NULL;
     845               0 :         getObject(http_message_object, obj);
     846                 : 
     847               0 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/!", &new_headers)) {
     848               0 :                 return;
     849                 :         }
     850                 : 
     851               0 :         zend_hash_clean(&obj->message->hdrs);
     852               0 :         if (new_headers) {
     853               0 :                 array_copy(Z_ARRVAL_P(new_headers), &obj->message->hdrs);
     854                 :         }
     855                 : }
     856                 : /* }}} */
     857                 : 
     858                 : /* {{{ proto void HttpMessage::addHeaders(array headers[, bool append = false])
     859                 :         Add headers. If append is true, headers with the same name will be separated, else overwritten. */
     860                 : PHP_METHOD(HttpMessage, addHeaders)
     861               1 : {
     862                 :         zval *new_headers;
     863               1 :         zend_bool append = 0;
     864               1 :         getObject(http_message_object, obj);
     865                 : 
     866               1 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|b", &new_headers, &append)) {
     867               0 :                 return;
     868                 :         }
     869                 : 
     870               1 :         array_join(Z_ARRVAL_P(new_headers), &obj->message->hdrs, append, ARRAY_JOIN_STRONLY|ARRAY_JOIN_PRETTIFY);
     871                 : }
     872                 : /* }}} */
     873                 : 
     874                 : /* {{{ proto int HttpMessage::getType()
     875                 :         Get Message Type. (HTTP_MSG_NONE|HTTP_MSG_REQUEST|HTTP_MSG_RESPONSE) */
     876                 : PHP_METHOD(HttpMessage, getType)
     877               0 : {
     878               0 :         NO_ARGS;
     879                 : 
     880               0 :         if (return_value_used) {
     881               0 :                 getObject(http_message_object, obj);
     882               0 :                 RETURN_LONG(obj->message->type);
     883                 :         }
     884                 : }
     885                 : /* }}} */
     886                 : 
     887                 : /* {{{ proto void HttpMessage::setType(int type)
     888                 :         Set Message Type. (HTTP_MSG_NONE|HTTP_MSG_REQUEST|HTTP_MSG_RESPONSE) */
     889                 : PHP_METHOD(HttpMessage, setType)
     890               0 : {
     891                 :         long type;
     892               0 :         getObject(http_message_object, obj);
     893                 : 
     894               0 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &type)) {
     895               0 :                 return;
     896                 :         }
     897               0 :         http_message_set_type(obj->message, type);
     898                 : }
     899                 : /* }}} */
     900                 : 
     901                 : /* {{{ proto string HttpMessage::getInfo(void)
     902                 :         Get the HTTP request/response line */
     903                 : PHP_METHOD(HttpMessage, getInfo)
     904               0 : {
     905               0 :         NO_ARGS;
     906                 :         
     907               0 :         if (return_value_used) {
     908               0 :                 getObject(http_message_object, obj);
     909                 :                 
     910               0 :                 switch (obj->message->type) {
     911                 :                         case HTTP_MSG_REQUEST:
     912               0 :                                 Z_STRLEN_P(return_value) = spprintf(&Z_STRVAL_P(return_value), 0, HTTP_INFO_REQUEST_FMT_ARGS(&obj->message->http, ""));
     913               0 :                                 break;
     914                 :                         case HTTP_MSG_RESPONSE:
     915               0 :                                 Z_STRLEN_P(return_value) = spprintf(&Z_STRVAL_P(return_value), 0, HTTP_INFO_RESPONSE_FMT_ARGS(&obj->message->http, ""));
     916               0 :                                 break;
     917                 :                         default:
     918               0 :                                 RETURN_NULL();
     919                 :                                 break;
     920                 :                 }
     921               0 :                 Z_TYPE_P(return_value) = IS_STRING;
     922                 :         }
     923                 : }
     924                 : /* }}} */
     925                 : 
     926                 : /* {{{ proto bool HttpMessage::setInfo(string http_info)
     927                 :         Set type and request or response info with a standard HTTP request or response line */
     928                 : PHP_METHOD(HttpMessage, setInfo)
     929               0 : {
     930                 :         char *str;
     931                 :         int len;
     932                 :         http_info inf;
     933                 :         
     934               0 :         if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &len) && SUCCESS == http_info_parse_ex(str, &inf, 0)) {
     935               0 :                 getObject(http_message_object, obj);
     936                 :                 
     937               0 :                 http_message_set_info(obj->message, &inf);
     938               0 :                 http_info_dtor(&inf);
     939               0 :                 RETURN_TRUE;
     940                 :         }
     941               0 :         RETURN_FALSE;
     942                 : }
     943                 : /* }}} */
     944                 : 
     945                 : /* {{{ proto int HttpMessage::getResponseCode()
     946                 :         Get the Response Code of the Message. */
     947                 : PHP_METHOD(HttpMessage, getResponseCode)
     948               6 : {
     949               6 :         NO_ARGS;
     950                 : 
     951               6 :         if (return_value_used) {
     952               6 :                 getObject(http_message_object, obj);
     953               6 :                 HTTP_CHECK_MESSAGE_TYPE_RESPONSE(obj->message, RETURN_FALSE);
     954               6 :                 RETURN_LONG(obj->message->http.info.response.code);
     955                 :         }
     956                 : }
     957                 : /* }}} */
     958                 : 
     959                 : /* {{{ proto bool HttpMessage::setResponseCode(int code)
     960                 :         Set the response code of an HTTP Response Message. */
     961                 : PHP_METHOD(HttpMessage, setResponseCode)
     962               0 : {
     963                 :         long code;
     964               0 :         getObject(http_message_object, obj);
     965                 : 
     966               0 :         HTTP_CHECK_MESSAGE_TYPE_RESPONSE(obj->message, RETURN_FALSE);
     967                 : 
     968               0 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &code)) {
     969               0 :                 RETURN_FALSE;
     970                 :         }
     971               0 :         if (code < 100 || code > 599) {
     972               0 :                 http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Invalid response code (100-599): %ld", code);
     973               0 :                 RETURN_FALSE;
     974                 :         }
     975                 : 
     976               0 :         obj->message->http.info.response.code = code;
     977               0 :         RETURN_TRUE;
     978                 : }
     979                 : /* }}} */
     980                 : 
     981                 : /* {{{ proto string HttpMessage::getResponseStatus()
     982                 :         Get the Response Status of the message (i.e. the string following the response code). */
     983                 : PHP_METHOD(HttpMessage, getResponseStatus)
     984               1 : {
     985               1 :         NO_ARGS;
     986                 :         
     987               1 :         if (return_value_used) {
     988               1 :                 getObject(http_message_object, obj);
     989               1 :                 HTTP_CHECK_MESSAGE_TYPE_RESPONSE(obj->message, RETURN_FALSE);
     990               1 :                 if (obj->message->http.info.response.status) {
     991               1 :                         RETURN_STRING(obj->message->http.info.response.status, 1);
     992                 :                 } else {
     993               0 :                         RETURN_EMPTY_STRING();
     994                 :                 }
     995                 :         }
     996                 : }
     997                 : /* }}} */
     998                 : 
     999                 : /* {{{ proto bool HttpMessage::setResponseStatus(string status)
    1000                 :         Set the Response Status of the HTTP message (i.e. the string following the response code). */
    1001                 : PHP_METHOD(HttpMessage, setResponseStatus)
    1002               0 : {
    1003                 :         char *status;
    1004                 :         int status_len;
    1005               0 :         getObject(http_message_object, obj);
    1006                 :         
    1007               0 :         HTTP_CHECK_MESSAGE_TYPE_RESPONSE(obj->message, RETURN_FALSE);
    1008                 :         
    1009               0 :         if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &status, &status_len)) {
    1010               0 :                 RETURN_FALSE;
    1011                 :         }
    1012               0 :         STR_SET(obj->message->http.info.response.status, estrndup(status, status_len));
    1013               0 :         RETURN_TRUE;
    1014                 : }
    1015                 : /* }}} */
    1016                 : 
    1017                 : /* {{{ proto string HttpMessage::getRequestMethod()
    1018                 :         Get the Request Method of the Message. */
    1019                 : PHP_METHOD(HttpMessage, getRequestMethod)
    1020               0 : {
    1021               0 :         NO_ARGS;
    1022                 : 
    1023               0 :         if (return_value_used) {
    1024               0 :                 getObject(http_message_object, obj);
    1025               0 :                 HTTP_CHECK_MESSAGE_TYPE_REQUEST(obj->message, RETURN_FALSE);
    1026               0 :                 if (obj->message->http.info.request.method) {
    1027               0 :                         RETURN_STRING(obj->message->http.info.request.method, 1);
    1028                 :                 } else {
    1029               0 :                         RETURN_EMPTY_STRING();
    1030                 :                 }
    1031                 :         }
    1032                 : }
    1033                 : /* }}} */
    1034                 : 
    1035                 : /* {{{ proto bool HttpMessage::setRequestMethod(string method)
    1036                 :         Set the Request Method of the HTTP Message. */
    1037                 : PHP_METHOD(HttpMessage, setRequestMethod)
    1038               0 : {
    1039                 :         char *method;
    1040                 :         int method_len;
    1041               0 :         getObject(http_message_object, obj);
    1042                 : 
    1043               0 :         HTTP_CHECK_MESSAGE_TYPE_REQUEST(obj->message, RETURN_FALSE);
    1044                 : 
    1045               0 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &method, &method_len)) {
    1046               0 :                 RETURN_FALSE;
    1047                 :         }
    1048               0 :         if (method_len < 1) {
    1049               0 :                 http_error(HE_WARNING, HTTP_E_INVALID_PARAM, "Cannot set HttpMessage::requestMethod to an empty string");
    1050               0 :                 RETURN_FALSE;
    1051                 :         }
    1052               0 :         if (!http_request_method_exists(1, 0, method)) {
    1053               0 :                 http_error_ex(HE_WARNING, HTTP_E_REQUEST_METHOD, "Unknown request method: %s", method);
    1054               0 :                 RETURN_FALSE;
    1055                 :         }
    1056                 : 
    1057               0 :         STR_SET(obj->message->http.info.request.method, estrndup(method, method_len));
    1058               0 :         RETURN_TRUE;
    1059                 : }
    1060                 : /* }}} */
    1061                 : 
    1062                 : /* {{{ proto string HttpMessage::getRequestUrl()
    1063                 :         Get the Request URL of the Message. */
    1064                 : PHP_METHOD(HttpMessage, getRequestUrl)
    1065               0 : {
    1066               0 :         NO_ARGS;
    1067                 : 
    1068               0 :         if (return_value_used) {
    1069               0 :                 getObject(http_message_object, obj);
    1070               0 :                 HTTP_CHECK_MESSAGE_TYPE_REQUEST(obj->message, RETURN_FALSE);
    1071               0 :                 if (obj->message->http.info.request.url) {
    1072               0 :                         RETURN_STRING(obj->message->http.info.request.url, 1);
    1073                 :                 } else {
    1074               0 :                         RETURN_EMPTY_STRING();
    1075                 :                 }
    1076                 :         }
    1077                 : }
    1078                 : /* }}} */
    1079                 : 
    1080                 : /* {{{ proto bool HttpMessage::setRequestUrl(string url)
    1081                 :         Set the Request URL of the HTTP Message. */
    1082                 : PHP_METHOD(HttpMessage, setRequestUrl)
    1083               0 : {
    1084                 :         char *URI;
    1085                 :         int URIlen;
    1086               0 :         getObject(http_message_object, obj);
    1087                 : 
    1088               0 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &URI, &URIlen)) {
    1089               0 :                 RETURN_FALSE;
    1090                 :         }
    1091               0 :         HTTP_CHECK_MESSAGE_TYPE_REQUEST(obj->message, RETURN_FALSE);
    1092               0 :         if (URIlen < 1) {
    1093               0 :                 http_error(HE_WARNING, HTTP_E_INVALID_PARAM, "Cannot set HttpMessage::requestUrl to an empty string");
    1094               0 :                 RETURN_FALSE;
    1095                 :         }
    1096                 : 
    1097               0 :         STR_SET(obj->message->http.info.request.url, estrndup(URI, URIlen));
    1098               0 :         RETURN_TRUE;
    1099                 : }
    1100                 : /* }}} */
    1101                 : 
    1102                 : /* {{{ proto string HttpMessage::getHttpVersion()
    1103                 :         Get the HTTP Protocol Version of the Message. */
    1104                 : PHP_METHOD(HttpMessage, getHttpVersion)
    1105               0 : {
    1106               0 :         NO_ARGS;
    1107                 : 
    1108               0 :         if (return_value_used) {
    1109               0 :                 char ver[4] = {0};
    1110               0 :                 getObject(http_message_object, obj);
    1111                 : 
    1112               0 :                 sprintf(ver, "%1.1lf", obj->message->http.version);
    1113               0 :                 RETURN_STRINGL(ver, 3, 1);
    1114                 :         }
    1115                 : }
    1116                 : /* }}} */
    1117                 : 
    1118                 : /* {{{ proto bool HttpMessage::setHttpVersion(string version)
    1119                 :         Set the HTTP Protocol version of the Message. */
    1120                 : PHP_METHOD(HttpMessage, setHttpVersion)
    1121               0 : {
    1122                 :         char v[4];
    1123                 :         zval *zv;
    1124               0 :         getObject(http_message_object, obj);
    1125                 : 
    1126               0 :         if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/", &zv)) {
    1127               0 :                 return;
    1128                 :         }
    1129                 : 
    1130               0 :         convert_to_double(zv);
    1131               0 :         sprintf(v, "%1.1lf", Z_DVAL_P(zv));
    1132               0 :         if (strcmp(v, "1.0") && strcmp(v, "1.1")) {
    1133               0 :                 http_error_ex(HE_WARNING, HTTP_E_INVALID_PARAM, "Invalid HTTP protocol version (1.0 or 1.1): %s", v);
    1134               0 :                 RETURN_FALSE;
    1135                 :         }
    1136                 : 
    1137               0 :         obj->message->http.version = Z_DVAL_P(zv);
    1138               0 :         RETURN_TRUE;
    1139                 : }
    1140                 : /* }}} */
    1141                 : 
    1142                 : /* {{{ proto string HttpMessage::guessContentType(string magic_file[, int magic_mode = MAGIC_MIME])
    1143                 :         Attempts to guess the content type of supplied payload through libmagic. */
    1144                 : PHP_METHOD(HttpMessage, guessContentType)
    1145               0 : {
    1146                 : #ifdef HTTP_HAVE_MAGIC
    1147                 :         char *magic_file, *ct = NULL;
    1148                 :         int magic_file_len;
    1149                 :         long magic_mode = MAGIC_MIME;
    1150                 :         
    1151                 :         RETVAL_FALSE;
    1152                 :         SET_EH_THROW_HTTP();
    1153                 :         if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &magic_file, &magic_file_len, &magic_mode)) {
    1154                 :                 getObject(http_message_object, obj);
    1155                 :                 if ((ct = http_guess_content_type(magic_file, magic_mode, PHPSTR_VAL(&obj->message->body), PHPSTR_LEN(&obj->message->body), SEND_DATA))) {
    1156                 :                         RETVAL_STRING(ct, 0);
    1157                 :                 }
    1158                 :         }
    1159                 :         SET_EH_NORMAL();
    1160                 : #else
    1161               0 :         http_error(HE_THROW, HTTP_E_RUNTIME, "Cannot guess Content-Type; libmagic not available");
    1162               0 :         RETURN_FALSE;
    1163                 : #endif
    1164                 : }
    1165                 : /* }}} */
    1166                 : 
    1167                 : /* {{{ proto HttpMessage HttpMessage::getParentMessage()
    1168                 :         Get parent Message. */
    1169                 : PHP_METHOD(HttpMessage, getParentMessage)
    1170               6 : {
    1171               6 :         SET_EH_THROW_HTTP();
    1172               6 :         NO_ARGS {
    1173               6 :                 getObject(http_message_object, obj);
    1174                 : 
    1175               6 :                 if (obj->message->parent) {
    1176               5 :                         RETVAL_OBJVAL(obj->parent, 1);
    1177                 :                 } else {
    1178               1 :                         http_error(HE_WARNING, HTTP_E_RUNTIME, "HttpMessage does not have a parent message");
    1179                 :                 }
    1180                 :         }
    1181               6 :         SET_EH_NORMAL();
    1182               6 : }
    1183                 : /* }}} */
    1184                 : 
    1185                 : /* {{{ proto bool HttpMessage::send()
    1186                 :         Send the Message according to its type as Response or Request. */
    1187                 : PHP_METHOD(HttpMessage, send)
    1188               0 : {
    1189               0 :         getObject(http_message_object, obj);
    1190                 : 
    1191               0 :         NO_ARGS;
    1192                 : 
    1193               0 :         RETURN_SUCCESS(http_message_send(obj->message));
    1194                 : }
    1195                 : /* }}} */
    1196                 : 
    1197                 : /* {{{ proto string HttpMessage::toString([bool include_parent = false])
    1198                 :         Get the string representation of the Message. */
    1199                 : PHP_METHOD(HttpMessage, toString)
    1200              16 : {
    1201              16 :         if (return_value_used) {
    1202                 :                 char *string;
    1203                 :                 size_t length;
    1204              16 :                 zend_bool include_parent = 0;
    1205              16 :                 getObject(http_message_object, obj);
    1206                 : 
    1207              16 :                 if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &include_parent)) {
    1208               0 :                         RETURN_FALSE;
    1209                 :                 }
    1210                 : 
    1211              16 :                 if (include_parent) {
    1212               9 :                         http_message_serialize(obj->message, &string, &length);
    1213                 :                 } else {
    1214               7 :                         http_message_tostring(obj->message, &string, &length);
    1215                 :                 }
    1216              16 :                 RETURN_STRINGL(string, length, 0);
    1217                 :         }
    1218                 : }
    1219                 : /* }}} */
    1220                 : 
    1221                 : /* {{{ proto HttpRequest|HttpResponse HttpMessage::toMessageTypeObject(void)
    1222                 :         Creates an object regarding to the type of the message. Returns either an HttpRequest or HttpResponse object on success, or NULL on failure. */
    1223                 : PHP_METHOD(HttpMessage, toMessageTypeObject)
    1224               0 : {
    1225               0 :         SET_EH_THROW_HTTP();
    1226                 :         
    1227               0 :         NO_ARGS;
    1228                 :         
    1229               0 :         if (return_value_used) {
    1230               0 :                 getObject(http_message_object, obj);
    1231                 :                 
    1232               0 :                 switch (obj->message->type) {
    1233                 :                         case HTTP_MSG_REQUEST:
    1234                 :                         {
    1235                 : #ifdef HTTP_HAVE_CURL
    1236                 :                                 int method;
    1237                 :                                 char *url;
    1238               0 :                                 zval body, *array, *headers, *host = http_message_header(obj->message, "Host");
    1239               0 :                                 php_url hurl, *purl = php_url_parse(obj->message->http.info.request.url);
    1240                 :                                 
    1241               0 :                                 MAKE_STD_ZVAL(array);
    1242               0 :                                 array_init(array);
    1243                 :                                 
    1244               0 :                                 memset(&hurl, 0, sizeof(php_url));
    1245               0 :                                 hurl.host = host ? Z_STRVAL_P(host) : NULL;
    1246               0 :                                 zval_ptr_dtor(&host);
    1247               0 :                                 http_build_url(HTTP_URL_REPLACE, purl, &hurl, NULL, &url, NULL);
    1248               0 :                                 php_url_free(purl);
    1249               0 :                                 add_assoc_string(array, "url", url, 0);
    1250                 :                                 
    1251               0 :                                 if (    (method = http_request_method_exists(1, 0, obj->message->http.info.request.method)) ||
    1252                 :                                                 (method = http_request_method_register(obj->message->http.info.request.method, strlen(obj->message->http.info.request.method)))) {
    1253               0 :                                         add_assoc_long(array, "method", method);
    1254                 :                                 }
    1255                 :                                 
    1256               0 :                                 if (10 == (int) (obj->message->http.version * 10)) {
    1257               0 :                                         add_assoc_long(array, "protocol", CURL_HTTP_VERSION_1_0);
    1258                 :                                 }
    1259                 :                                 
    1260               0 :                                 MAKE_STD_ZVAL(headers);
    1261               0 :                                 array_init(headers);
    1262               0 :                                 array_copy(&obj->message->hdrs, Z_ARRVAL_P(headers));
    1263               0 :                                 add_assoc_zval(array, "headers", headers);
    1264                 :                                 
    1265               0 :                                 object_init_ex(return_value, http_request_object_ce);
    1266               0 :                                 zend_call_method_with_1_params(&return_value, http_request_object_ce, NULL, "setoptions", NULL, array);
    1267               0 :                                 zval_ptr_dtor(&array);
    1268                 :                                 
    1269               0 :                                 INIT_PZVAL(&body);
    1270               0 :                                 ZVAL_STRINGL(&body, PHPSTR_VAL(obj->message), PHPSTR_LEN(obj->message), 0);
    1271               0 :                                 zend_call_method_with_1_params(&return_value, http_request_object_ce, NULL, "setrawpostdata", NULL, &body);
    1272                 : #else
    1273                 :                                 http_error(HE_WARNING, HTTP_E_RUNTIME, "Cannot transform HttpMessage to HttpRequest (missing curl support)");
    1274                 : #endif
    1275               0 :                                 break;
    1276                 :                         }
    1277                 :                         
    1278                 :                         case HTTP_MSG_RESPONSE:
    1279                 :                         {
    1280                 : #ifndef WONKY
    1281                 :                                 HashPosition pos1, pos2;
    1282               0 :                                 HashKey key = initHashKey(0);
    1283                 :                                 zval **header, **h, *body;
    1284                 :                                 
    1285               0 :                                 if (obj->message->http.info.response.code) {
    1286               0 :                                         http_send_status(obj->message->http.info.response.code);
    1287                 :                                 }
    1288                 :                                 
    1289               0 :                                 object_init_ex(return_value, http_response_object_ce);
    1290                 :                                 
    1291               0 :                                 FOREACH_HASH_KEYVAL(pos1, &obj->message->hdrs, key, header) {
    1292               0 :                                         if (key.type == HASH_KEY_IS_STRING) {
    1293                 :                                                 zval *zkey;
    1294                 :                                                 
    1295               0 :                                                 MAKE_STD_ZVAL(zkey);
    1296               0 :                                                 ZVAL_STRINGL(zkey, key.str, key.len - 1, 1);
    1297                 :                                                 
    1298               0 :                                                 switch (Z_TYPE_PP(header)) {
    1299                 :                                                         case IS_ARRAY:
    1300                 :                                                         case IS_OBJECT:
    1301               0 :                                                                 FOREACH_HASH_VAL(pos2, HASH_OF(*header), h) {
    1302               0 :                                                                         ZVAL_ADDREF(*h);
    1303               0 :                                                                         zend_call_method_with_2_params(&return_value, http_response_object_ce, NULL, "setheader", NULL, zkey, *h);
    1304               0 :                                                                         zval_ptr_dtor(h);
    1305                 :                                                                 }
    1306               0 :                                                                 break;
    1307                 :                                                         
    1308                 :                                                         default:
    1309               0 :                                                                 ZVAL_ADDREF(*header);
    1310               0 :                                                                 zend_call_method_with_2_params(&return_value, http_response_object_ce, NULL, "setheader", NULL, zkey, *header);
    1311               0 :                                                                 zval_ptr_dtor(header);
    1312                 :                                                                 break;
    1313                 :                                                 }
    1314               0 :                                                 zval_ptr_dtor(&zkey);
    1315                 :                                         }
    1316                 :                                 }
    1317                 :                                 
    1318               0 :                                 MAKE_STD_ZVAL(body);
    1319               0 :                                 ZVAL_STRINGL(body, PHPSTR_VAL(obj->message), PHPSTR_LEN(obj->message), 1);
    1320               0 :                                 zend_call_method_with_1_params(&return_value, http_response_object_ce, NULL, "setdata", NULL, body);
    1321               0 :                                 zval_ptr_dtor(&body);
    1322                 : #else
    1323                 :                                 http_error(HE_WARNING, HTTP_E_RUNTIME, "Cannot transform HttpMessage to HttpResponse (need PHP 5.1+)");
    1324                 : #endif
    1325               0 :                                 break;
    1326                 :                         }
    1327                 :                         
    1328                 :                         default:
    1329               0 :                                 http_error(HE_WARNING, HTTP_E_MESSAGE_TYPE, "HttpMessage is neither of type HttpMessage::TYPE_REQUEST nor HttpMessage::TYPE_RESPONSE");
    1330                 :                                 break;
    1331                 :                 }
    1332                 :         }
    1333               0 :         SET_EH_NORMAL();
    1334               0 : }
    1335                 : /* }}} */
    1336                 : 
    1337                 : /* {{{ proto int HttpMessage::count()
    1338                 :         Implements Countable::count(). Returns the number of parent messages + 1. */
    1339                 : PHP_METHOD(HttpMessage, count)
    1340               3 : {
    1341               3 :         NO_ARGS {
    1342                 :                 long i;
    1343               3 :                 getObject(http_message_object, obj);
    1344                 :                 
    1345               3 :                 http_message_count(i, obj->message);
    1346               3 :                 RETURN_LONG(i);
    1347                 :         }
    1348                 : }
    1349                 : /* }}} */
    1350                 : 
    1351                 : /* {{{ proto string HttpMessage::serialize()
    1352                 :         Implements Serializable::serialize(). Returns the serialized representation of the HttpMessage. */
    1353                 : PHP_METHOD(HttpMessage, serialize)
    1354               1 : {
    1355               1 :         NO_ARGS {
    1356                 :                 char *string;
    1357                 :                 size_t length;
    1358               1 :                 getObject(http_message_object, obj);
    1359                 :                 
    1360               1 :                 http_message_serialize(obj->message, &string, &length);
    1361               1 :                 RETURN_STRINGL(string, length, 0);
    1362                 :         }
    1363                 : }
    1364                 : /* }}} */
    1365                 : 
    1366                 : /* {{{ proto void HttpMessage::unserialize(string serialized)
    1367                 :         Implements Serializable::unserialize(). Re-constructs the HttpMessage based upon the serialized string. */
    1368                 : PHP_METHOD(HttpMessage, unserialize)
    1369               1 : {
    1370                 :         int length;
    1371                 :         char *serialized;
    1372               1 :         getObject(http_message_object, obj);
    1373                 :         
    1374               1 :         if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &serialized, &length)) {
    1375                 :                 http_message *msg;
    1376                 :                 
    1377               1 :                 http_message_dtor(obj->message);
    1378               1 :                 if ((msg = http_message_parse_ex(obj->message, serialized, (size_t) length))) {
    1379               1 :                         obj->message = msg;
    1380                 :                 } else {
    1381               0 :                         http_error(HE_ERROR, HTTP_E_RUNTIME, "Could not unserialize HttpMessage");
    1382               0 :                         http_message_init(obj->message);
    1383                 :                 }
    1384                 :         }
    1385               1 : }
    1386                 : /* }}} */
    1387                 : 
    1388                 : /* {{{ proto HttpMessage HttpMessage::detach(void)
    1389                 :         Returns a clone of an HttpMessage object detached from any parent messages. */
    1390                 : PHP_METHOD(HttpMessage, detach)
    1391               2 : {
    1392                 :         http_info info;
    1393                 :         http_message *msg;
    1394               2 :         getObject(http_message_object, obj);
    1395                 :         
    1396               2 :         NO_ARGS;
    1397                 :         
    1398               2 :         info.type = obj->message->type;
    1399               2 :         memcpy(&HTTP_INFO(&info), &HTTP_INFO(obj->message), sizeof(struct http_info));
    1400                 :         
    1401               2 :         msg = http_message_new();
    1402               2 :         http_message_set_info(msg, &info);
    1403                 :         
    1404               2 :         zend_hash_copy(&msg->hdrs, &obj->message->hdrs, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
    1405               2 :         phpstr_append(&msg->body, PHPSTR_VAL(obj->message), PHPSTR_LEN(obj->message));
    1406                 :         
    1407               2 :         RETVAL_OBJVAL(http_message_object_new_ex(Z_OBJCE_P(getThis()), msg, NULL), 0);
    1408               2 : }
    1409                 : /* }}} */
    1410                 : 
    1411                 : /* {{{ proto void HttpMessage::prepend(HttpMessage message[, bool top = true])
    1412                 :         Prepends message(s) to the HTTP message. Throws HttpInvalidParamException if the message is located within the same message chain. */
    1413                 : PHP_METHOD(HttpMessage, prepend)
    1414               2 : {
    1415                 :         zval *prepend;
    1416               2 :         zend_bool top = 1;
    1417                 :         
    1418               2 :         if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|b", &prepend, http_message_object_ce, &top)) {
    1419                 :                 http_message *msg[2];
    1420               2 :                 getObject(http_message_object, obj);
    1421               2 :                 getObjectEx(http_message_object, prepend_obj, prepend);
    1422                 :                 
    1423                 :                 /* safety check */
    1424               8 :                 for (msg[0] = obj->message; msg[0]; msg[0] = msg[0]->parent) {
    1425              14 :                         for (msg[1] = prepend_obj->message; msg[1]; msg[1] = msg[1]->parent) {
    1426               8 :                                 if (msg[0] == msg[1]) {
    1427               0 :                                         http_error(HE_THROW, HTTP_E_INVALID_PARAM, "Cannot prepend a message located within the same message chain");
    1428               0 :                                         return;
    1429                 :                                 }
    1430                 :                         }
    1431                 :                 }
    1432                 :                 
    1433               2 :                 http_message_object_prepend_ex(getThis(), prepend, top);
    1434                 :         }
    1435                 : }
    1436                 : /* }}} */
    1437                 : 
    1438                 : /* {{{ proto HttpMessage HttpMessage::reverse()
    1439                 :         Reorders the message chain in reverse order. Returns the most parent HttpMessage object. */
    1440                 : PHP_METHOD(HttpMessage, reverse)
    1441               2 : {
    1442               2 :         NO_ARGS {
    1443               2 :                 http_message_object_reverse(getThis(), return_value);
    1444                 :         }
    1445               2 : }
    1446                 : /* }}} */
    1447                 : 
    1448                 : /* {{{ proto void HttpMessage::rewind(void)
    1449                 :         Implements Iterator::rewind(). */
    1450                 : PHP_METHOD(HttpMessage, rewind)
    1451               1 : {
    1452               1 :         NO_ARGS {
    1453               1 :                 getObject(http_message_object, obj);
    1454                 :                 
    1455               1 :                 if (obj->iterator) {
    1456               0 :                         zval_ptr_dtor(&obj->iterator);
    1457                 :                 }
    1458               1 :                 ZVAL_ADDREF(getThis());
    1459               1 :                 obj->iterator = getThis();
    1460                 :         }
    1461               1 : }
    1462                 : /* }}} */
    1463                 : 
    1464                 : /* {{{ proto bool HttpMessage::valid(void)
    1465                 :         Implements Iterator::valid(). */
    1466                 : PHP_METHOD(HttpMessage, valid)
    1467               5 : {
    1468               5 :         NO_ARGS {
    1469               5 :                 getObject(http_message_object, obj);
    1470                 :                 
    1471               5 :                 RETURN_BOOL(obj->iterator != NULL);
    1472                 :         }
    1473                 : }
    1474                 : /* }}} */
    1475                 : 
    1476                 : /* {{{ proto void HttpMessage::next(void)
    1477                 :         Implements Iterator::next(). */
    1478                 : PHP_METHOD(HttpMessage, next)
    1479               4 : {
    1480               4 :         NO_ARGS {
    1481               4 :                 getObject(http_message_object, obj);
    1482               4 :                 getObjectEx(http_message_object, itr, obj->iterator);
    1483                 :                 
    1484               7 :                 if (itr && itr->parent.handle) {
    1485               3 :                         zval *old = obj->iterator;
    1486               3 :                         MAKE_STD_ZVAL(obj->iterator);
    1487               3 :                         ZVAL_OBJVAL(obj->iterator, itr->parent, 1);
    1488               3 :                         zval_ptr_dtor(&old);
    1489                 :                 } else {
    1490               1 :                         zval_ptr_dtor(&obj->iterator);
    1491               1 :                         obj->iterator = NULL;
    1492                 :                 }
    1493                 :         }
    1494               4 : }
    1495                 : /* }}} */
    1496                 : 
    1497                 : /* {{{ proto int HttpMessage::key(void)
    1498                 :         Implements Iterator::key(). */
    1499                 : PHP_METHOD(HttpMessage, key)
    1500               0 : {
    1501               0 :         NO_ARGS {
    1502               0 :                 getObject(http_message_object, obj);
    1503                 :                 
    1504               0 :                 RETURN_LONG(obj->iterator ? obj->iterator->value.obj.handle:0);
    1505                 :         }
    1506                 : }
    1507                 : /* }}} */
    1508                 : 
    1509                 : /* {{{ proto HttpMessage HttpMessage::current(void)
    1510                 :         Implements Iterator::current(). */
    1511                 : PHP_METHOD(HttpMessage, current)
    1512               4 : {
    1513               4 :         NO_ARGS {
    1514               4 :                 getObject(http_message_object, obj);
    1515                 :                 
    1516               4 :                 if (obj->iterator) {
    1517               4 :                         RETURN_ZVAL(obj->iterator, 1, 0);
    1518                 :                 }
    1519                 :         }
    1520                 : }
    1521                 : /* }}} */
    1522                 : 
    1523                 : #endif /* ZEND_ENGINE_2 */
    1524                 : 
    1525                 : /*
    1526                 :  * Local variables:
    1527                 :  * tab-width: 4
    1528                 :  * c-basic-offset: 4
    1529                 :  * End:
    1530                 :  * vim600: noet sw=4 ts=4 fdm=marker
    1531                 :  * vim<600: noet sw=4 ts=4
    1532                 :  */
    1533                 : 

Generated by: LTP GCOV extension version 1.5