<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>etc/extending_and_embedding_php/call_func_with_hash</filename>
    </added>
    <added>
      <filename>etc/extending_and_embedding_php/call_func_with_hash.c</filename>
    </added>
    <added>
      <filename>ext/test3.rb</filename>
    </added>
    <added>
      <filename>spec/extension/array_spec.rb</filename>
    </added>
    <added>
      <filename>spec/extension/call_and_eval_spec.rb</filename>
    </added>
    <added>
      <filename>spec/extension/object_spec.rb</filename>
    </added>
    <added>
      <filename>spec/extension/resource_spec.rb</filename>
    </added>
    <added>
      <filename>spec/extension/session_spec.rb</filename>
    </added>
    <added>
      <filename>spec/extension/strings_spec.rb</filename>
    </added>
    <added>
      <filename>spec/segfaults/segfault1_spec.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -1,8 +1,7 @@
-
 /*
   To compile:
 
-  gcc -g -o create_hash create_hash.c -I/usr/include/php5/ -I/usr/include/php5/main/ -I/usr/include/php5/Zend/ -I/usr/include/php5/TSRM/ -L/usr/local/lib/ -lphp5  -fPIC -O2
+  gcc -g -o create_hash create_hash.c -I/usr/local/include/php5/ -I/usr/local/include/php5/main/ -I/usr/local/include/php5/Zend/ -I/usr/local/include/php5/TSRM/ -L/usr/local/lib/ -lphp5  -fPIC -O2
 */
  
 #include &lt;stdio.h&gt;</diff>
      <filename>etc/create_hash/create_hash.c</filename>
    </modified>
    <modified>
      <diff>@@ -83,20 +83,12 @@ int main(int argc, char** argv) {
 
   args[0] = input_str;
 
-  //  ZVAL_STRING(args[0], &quot;&lt;?php echo; ?&gt;&quot;, 0);
   ZVAL_STRING(args[0], file_data, 0);
 
   call_user_function(EG(function_table), NULL, &amp;funcname, &amp;retval, 1, args TSRMLS_CC);
 
   iterate_through_hash(retval);
 
-  /*
-  convert_to_string(&amp;retval);
-
-  ans = Z_STRVAL(retval);
-  printf(&quot;%s\n&quot;, ans);
-  */
-
   PHP_EMBED_END_BLOCK();
   return 0;
 }</diff>
      <filename>etc/extending_and_embedding_php/parse_file.c</filename>
    </modified>
    <modified>
      <diff>@@ -5,19 +5,40 @@
 #include &lt;sapi/embed/php_embed.h&gt;
 #include &quot;ruby.h&quot;
 
+/*******************************************************
+ Declarations
+ *******************************************************/
+
 VALUE rb_mIonize;
 VALUE rb_mIonizePhp;
 VALUE rb_cIonizePhpArray;
 VALUE rb_cIonizePhpObject;
+VALUE rb_cIonizePhpResource;
 
 typedef struct ionize_php_array_struct {
   zval      *zvalue_p; 
+  HashTable *hash_table_p; 
 } ionize_php_array_t;
 
 typedef struct ionize_php_object_struct {
   zval      *zvalue_p;
 } ionize_php_object_t;
 
+typedef struct ionize_php_resource_struct {
+  zval      *zvalue_p;
+} ionize_php_resource_t;
+
+
+VALUE zval2rb_value(zval zvalue);
+VALUE zval2rb_hash_p(zval *zhash);
+VALUE zval2rb_value_p(zval *value);
+
+static VALUE ionize_php_array_new2(zval *zvalue_p);
+static VALUE ionize_php_object_new2(zval *zvalue_p);
+static VALUE ionize_php_resource_new2(zval *zvalue_p);
+
+// Other stuff??
+
 #define REQUIRE_PHP_SESSION if (require_php_session() == 1) return Qnil
 
 int php_session_started = 0;
@@ -31,20 +52,179 @@ int require_php_session() {
   }
 }
 
+
 /*******************************************************
- Conversion functions (Php &lt;=&gt; Ruby)
+ Debugging stuff.. Should be deleted before production
  *******************************************************/
 
-VALUE zval2rb_value(zval zvalue);
-VALUE zval2rb_hash_p(zval *zhash);
+void inspect_zhash(zval *zhash) {
+  printf(&quot;Zvalue array pointer is %d\n&quot;, zhash);
 
-static VALUE ionize_php_array_new2(zval *zvalue_p);
-static VALUE ionize_php_object_new2(zval *zvalue_p);
+  if (Z_ARRVAL_P(zhash)) {
+    printf(&quot;Through zvalue_p, ionize array arrval pointer is %d\n&quot;, Z_ARRVAL_P(zhash));
+    printf(&quot;Through zvalue_p, ionize arrval internal pointer is %d\n&quot;, Z_ARRVAL_P(zhash)-&gt;pInternalPointer);
+
+    HashPosition pos;
+    zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(zhash), &amp;pos);
+    
+    if (pos) {
+      printf(&quot;Hash position is %d\n&quot;, pos);
+      printf(&quot;Hash position pData is %d\n&quot;, pos-&gt;pData);
+      printf(&quot;Hash number of elements is %d\n&quot;, Z_ARRVAL_P(zhash)-&gt;nNumOfElements);
+    } else {
+      printf(&quot;Hash position is NULL!\n&quot;);
+    }
+  } else {
+    printf(&quot;Through zvalue_p, ionize array arrval pointer is NULL!\n&quot;);    
+  }
+}
+
+
+void inspect_hash(ionize_php_array_t *ionize_array) {
+  printf(&quot;Through hash_table_p, ionize array arrval pointer is %d\n&quot;, ionize_array-&gt;hash_table_p);
+  printf(&quot;Through hash_table_p, ionize array arrval internal pointer is %d\n&quot;, (ionize_array-&gt;hash_table_p)-&gt;pInternalPointer);
+
+  inspect_zhash(ionize_array-&gt;zvalue_p);
+}
+
+void print_hash_table(HashTable *hash_table_p) { 
+  char *string_key; 
+  ulong num_key; 
+
+  zval key, **value; 
+
+  zend_hash_internal_pointer_reset(hash_table_p); 
+
+  printf(&quot;Hash table has %d elements\n&quot;, zend_hash_num_elements(hash_table_p));
+
+  while (zend_hash_get_current_data(hash_table_p, (void**)&amp;value) == SUCCESS) { 
+    printf(&quot;Converting zvalue to rb value\n&quot;);
+    VALUE rbvalue = zval2rb_value_p(*value); 
+
+    switch (zend_hash_get_current_key(hash_table_p, &amp;string_key, &amp;num_key, 0)) { 
+    case HASH_KEY_IS_STRING: 
+      printf(&quot;Php key is %s\n&quot;, string_key);
+      break; 
+    case HASH_KEY_IS_LONG: 
+      printf(&quot;Php key is %d\n&quot;, num_key);
+      break; 
+    default: /* HASH_KEY_NON_EXISTANT */
+      break;
+    } 
+
+    if (Z_TYPE_P(*value) == IS_STRING) {
+      printf(&quot;Value happens to be a string. %s\n&quot;, Z_STRVAL_P(*value));
+    }
+
+    if (Z_TYPE_P(*value) == IS_LONG) {
+      printf(&quot;Value happens to be a long. %d\n&quot;, Z_LVAL_P(*value));
+    }
+    
+    printf(&quot;Moving forward\n&quot;);
+    if (zend_hash_move_forward(hash_table_p) != SUCCESS) {
+      printf(&quot;Moving hash forward was a failure. Returning\n&quot;);
+      return;
+    }
+    printf(&quot;Done moving forward. Going to next item\n&quot;);
+  }  
+}
+
+void print_hash(zval *zhash_p) { 
+  printf(&quot;Type is %d\n&quot;, zhash_p-&gt;type);
+  printf(&quot;Ref count of zhash is %d\n&quot;, zhash_p-&gt;refcount);
+  printf(&quot;Is ref is %d\n&quot;, zhash_p-&gt;is_ref);
+  printf(&quot;Arrval p is %d\n&quot;, Z_ARRVAL_P(zhash_p));
+
+  print_hash_table(Z_ARRVAL_P(zhash_p));
+}
+
+
+zval *create_array() {
+  zval *new_array, *new_element;
+  char *key = &quot;element_key&quot;;
+
+  MAKE_STD_ZVAL(new_array);
+  MAKE_STD_ZVAL(new_element);
+
+  array_init(new_array);
+
+  ZVAL_LONG(new_element, 10);
+
+  printf(&quot;Inserting element into array\n&quot;);
+  if (zend_hash_update(new_array-&gt;value.ht, key, strlen(key) + 1, (void *)&amp;new_element, sizeof(zval *), NULL) == FAILURE) {
+    printf(&quot;Couldn't insert element into array\n&quot;);
+  }
+
+  printf(&quot;Finished inserting into array\n&quot;);
+
+  return new_array;
+}
+
+
+
+VALUE php_array_keys(VALUE self) {
+  REQUIRE_PHP_SESSION;
+
+  zval *args[1];
+  zval *array;
+
+  array = create_array();
+  args[0] = array;
+  zval_add_ref(&amp;array); 
+  
+  zval return_value;
+  zval funcname;
+  ZVAL_STRING(&amp;funcname, &quot;array_keys&quot;, 0);
+
+  //  printf(&quot;Calling user function\n&quot;);
+  call_user_function(EG(function_table), NULL, &amp;funcname, &amp;return_value, 1, args);
+
+  //  printf(&quot;Handing back value\n&quot;);
+  //  print_hash(&amp;return_value);
+  //  inspect_zhash(&amp;return_value);
+  //  inspect_zhash(&amp;return_value);
+
+  VALUE result = zval2rb_value_p(&amp;return_value);
+
+  //  print_hash(&amp;return_value);
+  //  inspect_zhash(&amp;return_value);
+  //  inspect_zhash(&amp;return_value);
+
+  return result;
+}
+
+
+/*******************************************************
+ Error handling
+ *******************************************************/
+
+/*
+char php_error_buffer[2048];
+
+void ionize_php_error_cb(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args) {
+  //  char buffer[2048];
+  int len;
+
+  if (type != E_ERROR &amp;&amp; type != E_USER_ERROR &amp;&amp; type != E_CORE_ERROR &amp;&amp; type != E_PARSE &amp;&amp; type != E_COMPILE_ERROR) {
+    return;
+  }
+
+  len = snprintf(php_error_buffer, 2048, &quot;Error on line %d&quot;, error_lineno);
+
+  vsnprintf(php_error_buffer + len, (2048 - len), format, args);
+
+  zend_bailout();
+}
+*/
+
+/*******************************************************
+ Conversion functions (Php &lt;=&gt; Ruby)
+ *******************************************************/
 
 VALUE zval2rb_value_p(zval *zvalue_p) {
   char *svalue;
 
-  //  printf(&quot;Converting zval which is of type %d\n&quot;, Z_TYPE_P(zvalue_p));
+  // printf(&quot;Converting zval which is of type %d\n&quot;, Z_TYPE_P(zvalue_p));
 
   switch (Z_TYPE_P(zvalue_p)) {
   case IS_NULL:
@@ -68,8 +248,9 @@ VALUE zval2rb_value_p(zval *zvalue_p) {
     //    rb_raise(rb_eRuntimeError, &quot;This is a Php object.. Can't handle those yet\n&quot;);
     return ionize_php_object_new2(zvalue_p);
   case IS_RESOURCE:
-    rb_raise(rb_eRuntimeError, &quot;This is a Php resource.. Can't handle those yet\n&quot;);
-    return Qnil;
+    //    rb_raise(rb_eRuntimeError, &quot;This is a Php resource.. Can't handle those yet\n&quot;);
+    return ionize_php_resource_new2(zvalue_p);
+    //    return Qnil;
   case IS_CONSTANT:
     rb_raise(rb_eRuntimeError, &quot;This is a Php constant.. Can't handle those yet\n&quot;);
     return Qnil;    
@@ -125,7 +306,6 @@ VALUE zobj2rb_hash_p(zval *zobj) {
 }
 
 
-
 VALUE zval2rb_hash_p(zval *zhash) { 
   VALUE rbhash = rb_hash_new();   
   
@@ -166,6 +346,44 @@ VALUE zval2rb_hash_p(zval *zhash) {
 }
 
 
+VALUE zhash_table2rb_hash_p(HashTable *hash_table_p) { 
+  VALUE rbhash = rb_hash_new();   
+  
+  char *string_key; 
+  ulong num_key; 
+
+  zval key, **value; 
+  VALUE rbkey, rbvalue; 
+
+  zend_hash_internal_pointer_reset(hash_table_p); 
+  while (zend_hash_get_current_data(hash_table_p, (void**)&amp;value) == SUCCESS) { 
+    rbvalue = zval2rb_value_p(*value); 
+
+    switch (zend_hash_get_current_key(hash_table_p, &amp;string_key, &amp;num_key, 0)) { 
+    case HASH_KEY_IS_STRING: 
+      Z_TYPE(key) = IS_STRING; 
+      Z_STRVAL(key) = string_key; 
+      Z_STRLEN(key) = strlen(string_key); 
+      rbkey = zval2rb_value(key); 
+      break; 
+    case HASH_KEY_IS_LONG: 
+      Z_TYPE(key) = IS_LONG; 
+      Z_LVAL(key) = num_key; 
+      rbkey = zval2rb_value(key); 
+      break; 
+    default: /* HASH_KEY_NON_EXISTANT */
+      rbkey = Qnil; 
+    } 
+     
+    rb_hash_aset(rbhash, rbkey, rbvalue); 
+
+    if (zend_hash_move_forward(hash_table_p) != SUCCESS) {
+      rb_raise(rb_eRuntimeError, &quot;Couldn't iterate through hash\n&quot;);
+      return Qnil;
+    }
+  } 
+  return rbhash; 
+}
 
 VALUE zval2rb_value(zval zvalue) {
   long lvalue;
@@ -203,28 +421,26 @@ VALUE zval2rb_value(zval zvalue) {
 }
 
 
-void rb_value2zval2(VALUE rbval, zval *zvalue) {
-  long lvalue;
-  double dvalue;
-  char *svalue;
+void rb_value2zval2(VALUE rbval, zval *zvalue_p) {
+  ionize_php_array_t *ionize_array;
 
   switch (TYPE(rbval)) {
   case T_TRUE:
-    ZVAL_BOOL(zvalue, 1);
+    ZVAL_BOOL(zvalue_p, 1);
     break;
   case T_FALSE:
-    ZVAL_BOOL(zvalue, 0);    
+    ZVAL_BOOL(zvalue_p, 0);    
   case T_NIL:
-    // This seems to be crashing stuff.. Dunno why
-    ZVAL_NULL(zvalue);
+    ZVAL_NULL(zvalue_p);
+    break;
   case T_FLOAT:
-    ZVAL_DOUBLE(zvalue, RFLOAT(rbval)-&gt;value);
+    ZVAL_DOUBLE(zvalue_p, RFLOAT(rbval)-&gt;value);
     break;
   case T_FIXNUM:
-    ZVAL_LONG(zvalue, FIX2LONG(rbval));
+    ZVAL_LONG(zvalue_p, FIX2LONG(rbval));
     break;
   case T_BIGNUM: 
-    ZVAL_LONG(zvalue, NUM2LONG(rbval)); 
+    ZVAL_LONG(zvalue_p, NUM2LONG(rbval)); 
     break; 
     // We should revive this at some point
     //  case T_SYMBOL:
@@ -232,13 +448,29 @@ void rb_value2zval2(VALUE rbval, zval *zvalue) {
     //    ZVAL_STRING(&amp;z_value, svalue, 0);
     //    break;    
   case T_STRING:
-    ZVAL_STRINGL(zvalue, RSTRING(rbval)-&gt;ptr, RSTRING(rbval)-&gt;len, 1);
-    break;
+    ZVAL_STRINGL(zvalue_p, RSTRING(rbval)-&gt;ptr, RSTRING(rbval)-&gt;len, 1);
+    break;    
+  case T_DATA:
+    if (rb_class_of(rbval) == rb_cIonizePhpArray) {
+      //      printf(&quot;Argument is a php array. Pulling out zvalue and handing it back\n&quot;);
+      Data_Get_Struct(rbval, ionize_php_array_t, ionize_array);
+      
+      *zvalue_p = *ionize_array-&gt;zvalue_p;
+      Z_ARRVAL_P(zvalue_p) = ionize_array-&gt;hash_table_p;      
+
+      zvalue_p-&gt;is_ref = 1;
+    }
+    break;    
   default:
-    printf(&quot;Couldn't determine Ruby type\n&quot;);
-    ZVAL_NULL(zvalue);
+    rb_raise(rb_eTypeError, &quot;Couldn't determine Ruby type. Builtin type was %d&quot;, TYPE(rbval));
+    ZVAL_NULL(zvalue_p);
     break;
   } 
+
+//  if (Z_TYPE_P(zvalue_p) == IS_ARRAY) {
+//    print_hash(zvalue_p);
+//    inspect_zhash(zvalue_p);
+//  }
 }
 
 
@@ -347,55 +579,62 @@ VALUE php_include_file(VALUE self, VALUE filename) {
 
 VALUE php_call_user_function1(VALUE self, VALUE function_name) {
   REQUIRE_PHP_SESSION;
-  VALUE result;  
+  VALUE result;
 
-  zval *return_value_p;
-  zval *funcname_p;
+  // Don't ever make these pointers.. 
+  // It causes head-scratching segfaults
+  zval return_value;
+  zval funcname;
 
-  rb_value2zval2(function_name, funcname_p);
+  rb_value2zval2(function_name, &amp;funcname);
 
   // Apparently this is where things have been fucked up
   // so just make sure you do it right this time..
-  if (FAILURE == call_user_function(EG(function_table), NULL, funcname_p, return_value_p, 0, NULL TSRMLS_CC)) {
-    printf(&quot;Calling php function failed\n&quot;);
+  if (FAILURE == call_user_function(EG(function_table), NULL, &amp;funcname, &amp;return_value, 0, NULL TSRMLS_CC)) {
+    rb_raise(rb_eRuntimeError, &quot;Calling php function failed&quot;);
     return Qnil;
-  }    
-  result = zval2rb_value_p(return_value_p);
+  } 
+  
+  result = zval2rb_value_p(&amp;return_value);
 
   return result;
 }
 
-
 VALUE php_call_user_function2(VALUE self, VALUE function_name, VALUE arg1) {
   REQUIRE_PHP_SESSION;
   VALUE result;
   
-  // PHP_EMBED_START_BLOCK(0, NULL);  
-
   zval *args[1];
   
   zval return_value;
   zval funcname;
+
+  rb_value2zval2(function_name, &amp;funcname); 
   
-  rb_value2zval2(function_name, &amp;funcname);
+  //  printf(&quot;** Before converting to zvalue\n&quot;);
+  MAKE_STD_ZVAL(args[0]); rb_value2zval2(arg1, args[0]);    
 
-  // Apparently this is where things have been fucked up
-  // so just make sure you do it right this time..  
-  // Perform conversion and (a very important step)
-  // copy to *arg 
-  // 
-  // Without copying, the zend engine will want to 
-  // free these variables, introducing bugs 
-  zval *arg; MAKE_STD_ZVAL(arg); rb_value2zval2(arg1, arg); args[0] = arg;
+  // zval *arg; MAKE_STD_ZVAL(arg); rb_value2zval2(arg1, arg); args[0] = arg;
 
-  if (FAILURE == call_user_function(EG(function_table), NULL, &amp;funcname, &amp;return_value, 1, args TSRMLS_CC)) {
-    printf(&quot;Calling php function failed\n&quot;);
-    return Qnil;    
-  }  
+  //  printf(&quot;** Before calling call_user_function\n&quot;);
+  //  print_hash(args[0]);
+  //  inspect_zhash(args[0]);
   
-  result = zval2rb_value_p(&amp;return_value);
+  if (FAILURE == call_user_function(EG(function_table), NULL, &amp;funcname, &amp;return_value, 1, args)) {
+    if (EG(exception)) {
+      zval *msg = zend_read_property(zend_exception_get_default(TSRMLS_C), EG(exception), &quot;message&quot;, sizeof(&quot;message&quot;)-1, 0 TSRMLS_CC);
+      printf(&quot;Php error message is %s\n&quot; , Z_STRVAL_P(msg));
+    }
 
-  // PHP_EMBED_END_BLOCK(); 
+    rb_raise(rb_eRuntimeError, &quot;Calling php function failed&quot;);
+    return Qnil;
+  }
+
+  //  printf(&quot;** After calling call_user_function\n&quot;);
+  //  print_hash(args[0]);
+  //  inspect_zhash(&amp;return_value);
+  
+  result = zval2rb_value_p(&amp;return_value);
 
   return result;
 }
@@ -423,11 +662,20 @@ VALUE php_call_user_function3(VALUE self, VALUE function_name, VALUE arg1, VALUE
   // Without copying, the zend engine will want to 
   // free these variables, introducing bugs 
 
+  
   zval *z_arg1; MAKE_STD_ZVAL(z_arg1); rb_value2zval2(arg1, z_arg1); args[0] = z_arg1;
   zval *z_arg2; MAKE_STD_ZVAL(z_arg2); rb_value2zval2(arg2, z_arg2); args[1] = z_arg2;
+  
+  /*
+  MAKE_STD_ZVAL(args[0]);
+  rb_value2zval2(arg1, args[0]);  
+
+  MAKE_STD_ZVAL(args[1]);
+  rb_value2zval2(arg2, args[1]);  
+  */
 
   if (FAILURE == call_user_function(EG(function_table), NULL, &amp;funcname, &amp;return_value, 2, args TSRMLS_CC)) {
-    printf(&quot;Calling php function failed\n&quot;);
+    rb_raise(rb_eRuntimeError, &quot;Calling php function failed&quot;);
     return Qnil;    
   }  
   
@@ -457,7 +705,7 @@ VALUE php_call_user_function4(VALUE self, VALUE function_name, VALUE arg1, VALUE
   zval *z_arg3; MAKE_STD_ZVAL(z_arg3); rb_value2zval2(arg3, z_arg3); args[2] = z_arg3;
 
   if (FAILURE == call_user_function(EG(function_table), NULL, &amp;funcname, &amp;return_value, 3, args TSRMLS_CC)) {
-    printf(&quot;Calling php function failed\n&quot;);
+    rb_raise(rb_eRuntimeError, &quot;Calling php function failed&quot;);
     return Qnil;
   }
   
@@ -487,7 +735,7 @@ VALUE php_call_user_function5(VALUE self, VALUE function_name, VALUE arg1, VALUE
   zval *z_arg4; MAKE_STD_ZVAL(z_arg4); rb_value2zval2(arg4, z_arg4); args[3] = z_arg4;
 
   if (FAILURE == call_user_function(EG(function_table), NULL, &amp;funcname, &amp;return_value, 4, args TSRMLS_CC)) {
-    printf(&quot;Calling php function failed\n&quot;);
+    rb_raise(rb_eRuntimeError, &quot;Calling php function failed&quot;);
     return Qnil;
   }
   
@@ -519,7 +767,7 @@ VALUE php_call_user_function6(VALUE self, VALUE function_name, VALUE arg1, VALUE
   zval *z_arg5; MAKE_STD_ZVAL(z_arg5); rb_value2zval2(arg5, z_arg5); args[4] = z_arg5;
 
   if (FAILURE == call_user_function(EG(function_table), NULL, &amp;funcname, &amp;return_value, 5, args TSRMLS_CC)) {
-    printf(&quot;Calling php function failed\n&quot;);
+    rb_raise(rb_eRuntimeError, &quot;Calling php function failed&quot;);
     return Qnil;
   }
   
@@ -551,7 +799,7 @@ VALUE php_call_user_function7(VALUE self, VALUE function_name, VALUE arg1, VALUE
   zval *z_arg6; MAKE_STD_ZVAL(z_arg6); rb_value2zval2(arg6, z_arg6); args[5] = z_arg6;
 
   if (FAILURE == call_user_function(EG(function_table), NULL, &amp;funcname, &amp;return_value, 6, args TSRMLS_CC)) {
-    printf(&quot;Calling php function failed\n&quot;);
+    rb_raise(rb_eRuntimeError, &quot;Calling php function failed&quot;);
     return Qnil;
   }
   
@@ -563,6 +811,7 @@ VALUE php_call_user_function7(VALUE self, VALUE function_name, VALUE arg1, VALUE
 }
 
 
+
 /*******************************************************
  Ionize::Php::Array (Php arrays that live in Rubyland)
  *******************************************************/
@@ -581,12 +830,15 @@ zval *ionize_php_array2zval(VALUE ionize_php_array) {
 // watch how you handle that ionize_array struct
 static void ionize_php_array_free(ionize_php_array_t *ionize_array) {
   //  REQUIRE_PHP_SESSION;
+  //  printf(&quot;Freeing php array\n&quot;);
 
   if (ionize_array-&gt;zvalue_p) {
     zval_ptr_dtor(&amp;ionize_array-&gt;zvalue_p);
   }
   
-  ionize_array-&gt;zvalue_p = 0;  
+  ionize_array-&gt;zvalue_p = 0;
+  ionize_array-&gt;hash_table_p = 0;  
+
   xfree(ionize_array);
 }
 
@@ -714,20 +966,27 @@ static VALUE ionize_php_array_new2(zval *zvalue_p) {
   result = Data_Make_Struct(rb_cIonizePhpArray, ionize_php_array_t, 0, ionize_php_array_free, ionize_array);
 
   ionize_array-&gt;zvalue_p = zvalue_p;
+  ionize_array-&gt;hash_table_p = Z_ARRVAL_P(zvalue_p);
 
   zval_add_ref(&amp;ionize_array-&gt;zvalue_p);
 
+  //  inspect_hash(ionize_array);
+
   return result;
 }
 
 
 static VALUE ionize_php_array_real_inspect(VALUE self) {
+  //  printf(&quot;Doing real php array inspect\n&quot;);
+
   REQUIRE_PHP_SESSION;
 
   VALUE str, hash_key, hash_value;
 
   zval **zvalue_pp;
-  HashPosition pos;
+
+  //  HashPosition pos;
+
   char *string_key; 
   uint string_len; 
   ulong num_key;
@@ -735,23 +994,45 @@ static VALUE ionize_php_array_real_inspect(VALUE self) {
   ionize_php_array_t *ionize_array;
   Data_Get_Struct(self, ionize_php_array_t, ionize_array);
 
-  zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(ionize_array-&gt;zvalue_p), &amp;pos);
+  //  printf(&quot;Before we start, let's print the php array\n&quot;);
+  //  print_hash_table(ionize_array-&gt;hash_table_p);
+
+
+  //  zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(ionize_array-&gt;zvalue_p), &amp;pos);
+  zend_hash_internal_pointer_reset(ionize_array-&gt;hash_table_p);
+  // zend_hash_internal_pointer_reset(Z_ARRVAL_P(ionize_array-&gt;zvalue_p));
+
+  //  inspect_hash(ionize_array);
 
   str = rb_str_new2(&quot;#&lt;&quot;);
   OBJ_INFECT(str, self);
   rb_str_append(str, rb_class_path(rb_cIonizePhpArray));
 
   rb_str_cat2(str, &quot; (&quot;);
-  rb_str_concat(str, rb_obj_as_string(INT2FIX(zend_hash_num_elements(Z_ARRVAL_P(ionize_array-&gt;zvalue_p)))));
-  rb_str_cat2(str, &quot;): &quot;);  
+
+  //  printf(&quot;Collecting array size for real_inspect\n&quot;);
+  //  rb_str_concat(str, rb_obj_as_string(INT2FIX(zend_hash_num_elements(Z_ARRVAL_P(ionize_array-&gt;zvalue_p)))));
+  rb_str_concat(str, rb_obj_as_string(INT2FIX(zend_hash_num_elements(ionize_array-&gt;hash_table_p))));
+  rb_str_cat2(str, &quot;): &quot;);
 
   int index = 0;
-  while (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_P(ionize_array-&gt;zvalue_p), (void**)&amp;zvalue_pp, &amp;pos)) { 
+  //  while (SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_P(ionize_array-&gt;zvalue_p), (void**)&amp;zvalue_pp, &amp;pos)) { 
+  //  while (SUCCESS == zend_hash_get_current_data_ex(ionize_array-&gt;hash_table_p, (void**)&amp;zvalue_pp, &amp;pos)) { 
+  while (SUCCESS == zend_hash_get_current_data(ionize_array-&gt;hash_table_p, (void**)&amp;zvalue_pp)) { 
+    //    printf(&quot;At hash index %d\n&quot;, index);
+    //  while (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(ionize_array-&gt;zvalue_p), (void**)&amp;zvalue_pp)) { 
+    // Break here..
+
     hash_value = zval2rb_value_p(*zvalue_pp);
 
-    switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(ionize_array-&gt;zvalue_p), &amp;string_key, &amp;string_len, &amp;num_key, 0, &amp;pos)) {
+    //    switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(ionize_array-&gt;zvalue_p), &amp;string_key, &amp;string_len, &amp;num_key, 0, &amp;pos)) {
+    //    switch (zend_hash_get_current_key_ex(ionize_array-&gt;hash_table_p, &amp;string_key, &amp;string_len, &amp;num_key, 0, &amp;pos)) {
+    switch (zend_hash_get_current_key(ionize_array-&gt;hash_table_p, &amp;string_key, &amp;num_key, 0)) {
+      //    switch (zend_hash_get_current_key(Z_ARRVAL_P(ionize_array-&gt;zvalue_p), &amp;string_key, &amp;num_key, 0)) {
     case HASH_KEY_IS_STRING:
-      hash_key = rb_str_inspect(rb_str_new(string_key, string_len - 1));
+      //      printf(&quot;String key is now %s\n&quot;, string_key);
+      //      hash_key = rb_str_inspect(rb_str_new(string_key, string_len - 1));
+      hash_key = rb_str_inspect(rb_str_new2(string_key));
       // Freeing this caused some issues I think..
       //      efree(string_key);
       break;
@@ -769,7 +1050,9 @@ static VALUE ionize_php_array_real_inspect(VALUE self) {
     rb_str_cat2(str, &quot; =&gt; &quot;);
     rb_str_append(str, rb_inspect(hash_value));
 
-    zend_hash_move_forward_ex(Z_ARRVAL_P(ionize_array-&gt;zvalue_p), &amp;pos);
+    // zend_hash_move_forward_ex(Z_ARRVAL_P(ionize_array-&gt;zvalue_p), &amp;pos);
+    // zend_hash_move_forward_ex(ionize_array-&gt;hash_table_p, &amp;pos);
+    zend_hash_move_forward(ionize_array-&gt;hash_table_p);
     index++;
   }
 
@@ -779,12 +1062,16 @@ static VALUE ionize_php_array_real_inspect(VALUE self) {
 
 
 VALUE ionize_php_array_inspect(VALUE self) {
+  //  printf(&quot;Inspecting php array\n&quot;);    
+
   REQUIRE_PHP_SESSION;
 
   VALUE str;
   ionize_php_array_t *ionize_array;
   
   Data_Get_Struct(self, ionize_php_array_t, ionize_array);
+
+  //  inspect_hash(ionize_array);
   
   if (rb_inspecting_p(self)) {
     // We're already inspecting this element
@@ -792,9 +1079,12 @@ VALUE ionize_php_array_inspect(VALUE self) {
     OBJ_INFECT(str, self);
     rb_str_append(str, rb_class_path(CLASS_OF(self)));
     rb_str_cat2(str, &quot;(&quot;);
-    rb_str_concat(str, rb_obj_as_string(INT2FIX(zend_hash_num_elements(Z_ARRVAL_P(ionize_array-&gt;zvalue_p)))));
+    //    printf(&quot;Collecting array size for inspect\n&quot;);    
+    //    rb_str_concat(str, rb_obj_as_string(INT2FIX(zend_hash_num_elements(Z_ARRVAL_P(ionize_array-&gt;zvalue_p)))));
+    rb_str_concat(str, rb_obj_as_string(INT2FIX(zend_hash_num_elements(ionize_array-&gt;hash_table_p))));
     rb_str_cat2(str, &quot;)...&gt;&quot;);
-  } else if (!zend_hash_num_elements(Z_ARRVAL_P(ionize_array-&gt;zvalue_p))) {
+    //  } else if (!zend_hash_num_elements(Z_ARRVAL_P(ionize_array-&gt;zvalue_p))) {
+  } else if (!zend_hash_num_elements(ionize_array-&gt;hash_table_p)) {
     // The hash has no elements
     str = rb_str_new2(&quot;#&lt;&quot;);
     OBJ_INFECT(str, self);
@@ -815,7 +1105,8 @@ VALUE ionize_php_array_to_hash(VALUE self) {
   
   Data_Get_Struct(self, ionize_php_array_t, ionize_array);
 
-  return zval2rb_hash_p(ionize_array-&gt;zvalue_p);
+  return zhash_table2rb_hash_p(ionize_array-&gt;hash_table_p);
+  //  return zval2rb_hash_p(ionize_array-&gt;zvalue_p);
 }
 
 VALUE ionize_php_array_aref(VALUE self, VALUE key) {
@@ -828,10 +1119,12 @@ VALUE ionize_php_array_aref(VALUE self, VALUE key) {
 
   switch (TYPE(key)) {
   case T_FIXNUM:
-    zend_hash_index_find(Z_ARRVAL_P(ionize_array-&gt;zvalue_p), NUM2LONG(key), (void **)&amp;zvalue_pp);
+    //    zend_hash_index_find(Z_ARRVAL_P(ionize_array-&gt;zvalue_p), NUM2LONG(key), (void **)&amp;zvalue_pp);
+    zend_hash_index_find(ionize_array-&gt;hash_table_p, NUM2LONG(key), (void **)&amp;zvalue_pp);
     break;
   case T_STRING:
-    zend_hash_find(Z_ARRVAL_P(ionize_array-&gt;zvalue_p), RSTRING(key)-&gt;ptr, 1+RSTRING(key)-&gt;len, (void **)&amp;zvalue_pp);
+    // zend_hash_find(Z_ARRVAL_P(ionize_array-&gt;zvalue_p), RSTRING(key)-&gt;ptr, 1+RSTRING(key)-&gt;len, (void **)&amp;zvalue_pp);
+    zend_hash_find(ionize_array-&gt;hash_table_p, RSTRING(key)-&gt;ptr, 1+RSTRING(key)-&gt;len, (void **)&amp;zvalue_pp);
     break;
   default:
     rb_raise(rb_eTypeError, &quot;Received Ruby type not String or Fixnum for Ionize:Php::Array#[]&quot;);
@@ -851,7 +1144,8 @@ VALUE ionize_php_array_aset(VALUE self, VALUE key, VALUE rbvalue) {
 
   Data_Get_Struct(self, ionize_php_array_t, ionize_array);    
   
-  if (Z_ARRVAL_P(ionize_array-&gt;zvalue_p) == NULL) {
+  //  if (Z_ARRVAL_P(ionize_array-&gt;zvalue_p) == NULL) {
+  if (ionize_array-&gt;hash_table_p == NULL) {
     rb_raise(rb_eRuntimeError, &quot;Array has been freed by Php's garbage collector. Cannot continue&quot;); 
     return Qnil;
   }
@@ -862,7 +1156,8 @@ VALUE ionize_php_array_aset(VALUE self, VALUE key, VALUE rbvalue) {
     zval_add_ref(&amp;new_zvalue_p);
     rb_value2zval2(rbvalue, new_zvalue_p);
 
-    if (zend_hash_index_update(Z_ARRVAL_P(ionize_array-&gt;zvalue_p), FIX2ULONG(key), (void *)&amp;new_zvalue_p, sizeof(zval*), NULL) == FAILURE) {
+    //    if (zend_hash_index_update(Z_ARRVAL_P(ionize_array-&gt;zvalue_p), FIX2ULONG(key), (void *)&amp;new_zvalue_p, sizeof(zval*), NULL) == FAILURE) {
+    if (zend_hash_index_update(ionize_array-&gt;hash_table_p, FIX2ULONG(key), (void *)&amp;new_zvalue_p, sizeof(zval*), NULL) == FAILURE) {
       rb_raise(rb_eRuntimeError, &quot;Couldn't update Php array with key and value&quot;);
       result = Qnil;
     } else {
@@ -874,7 +1169,8 @@ VALUE ionize_php_array_aset(VALUE self, VALUE key, VALUE rbvalue) {
     rb_value2zval2(rbvalue, new_zvalue_p);
     zval_add_ref(&amp;new_zvalue_p);
 
-    if (zend_hash_update(Z_ARRVAL_P(ionize_array-&gt;zvalue_p), RSTRING(key)-&gt;ptr, 1+RSTRING(key)-&gt;len, &amp;new_zvalue_p, sizeof(zval*), NULL) == FAILURE) {
+    //    if (zend_hash_update(Z_ARRVAL_P(ionize_array-&gt;zvalue_p), RSTRING(key)-&gt;ptr, 1+RSTRING(key)-&gt;len, &amp;new_zvalue_p, sizeof(zval*), NULL) == FAILURE) {
+    if (zend_hash_update(ionize_array-&gt;hash_table_p, RSTRING(key)-&gt;ptr, 1+RSTRING(key)-&gt;len, &amp;new_zvalue_p, sizeof(zval*), NULL) == FAILURE) {
       rb_raise(rb_eRuntimeError, &quot;Couldn't update Php array with key and value&quot;);
       result = Qnil;
     } else {
@@ -891,12 +1187,14 @@ VALUE ionize_php_array_aset(VALUE self, VALUE key, VALUE rbvalue) {
 
 
 VALUE ionize_php_array_size(VALUE self) {
+  //  printf(&quot;Getting array size\n&quot;);
   REQUIRE_PHP_SESSION;
 
   ionize_php_array_t *ionize_array;
   Data_Get_Struct(self, ionize_php_array_t, ionize_array);  
 
-  return UINT2NUM(zend_hash_num_elements(Z_ARRVAL_P(ionize_array-&gt;zvalue_p)));
+  //  return UINT2NUM(zend_hash_num_elements(Z_ARRVAL_P(ionize_array-&gt;zvalue_p)));
+  return UINT2NUM(zend_hash_num_elements(ionize_array-&gt;hash_table_p));
 }
 
 
@@ -990,6 +1288,58 @@ static VALUE ionize_php_object_inspect(VALUE self) {
 
 
 /*******************************************************
+ Ionize::Php::Resource (Php resources that live in Rubyland)
+ *******************************************************/
+
+static void ionize_php_resource_free(ionize_php_resource_t *ionize_resource) {
+  //  REQUIRE_PHP_SESSION;
+  if (ionize_resource-&gt;zvalue_p) {
+    zval_ptr_dtor(&amp;ionize_resource-&gt;zvalue_p);
+  }
+  
+  ionize_resource-&gt;zvalue_p = 0;  
+  xfree(ionize_resource);
+}
+
+static VALUE ionize_php_resource_new2(zval *zvalue_p) {
+  REQUIRE_PHP_SESSION;
+
+  VALUE result;
+
+  if (!zvalue_p) 
+    rb_raise(rb_eTypeError, &quot;Received NULL for Ionize::Php::Resource.new&quot;);
+  
+  if (Z_TYPE_P(zvalue_p) != IS_RESOURCE)
+    rb_raise(rb_eTypeError, &quot;Expected Php resource as argument&quot;);
+
+  ionize_php_resource_t *ionize_resource;
+  result = Data_Make_Struct(rb_cIonizePhpResource, ionize_php_resource_t, 0, ionize_php_resource_free, ionize_resource);
+
+  ionize_resource-&gt;zvalue_p = zvalue_p;
+  zval_add_ref(&amp;ionize_resource-&gt;zvalue_p);
+
+  return result;
+}
+
+
+static VALUE ionize_php_resource_inspect(VALUE self) {
+  REQUIRE_PHP_SESSION;
+
+  VALUE str;
+
+  ionize_php_resource_t *ionize_resource;
+  Data_Get_Struct(self, ionize_php_resource_t, ionize_resource);
+
+  str = rb_obj_as_string(self);
+  OBJ_INFECT(str, self);
+  RSTRING(str)-&gt;ptr[RSTRING(str)-&gt;len-1]=' ';
+
+  return str;
+}
+
+
+
+/*******************************************************
  Session handling functions
  *******************************************************/
 
@@ -1022,14 +1372,32 @@ VALUE php_session_end_b(VALUE self) {
   return Qnil;
 }
 
+
+VALUE php_last_error_message(VALUE self) {
+  if (EG(exception)) {
+    zval *msg = zend_read_property(zend_exception_get_default(TSRMLS_C), EG(exception), &quot;message&quot;, sizeof(&quot;message&quot;)-1, 0 TSRMLS_CC);
+    return zval2rb_value_p(msg);
+  } else {    
+    return Qnil;
+  }
+}
+
+
 void Init_ionize_php_ext() {
+  // Replace Php error handler with our own
+  //  zend_error_cb = ionize_php_error_cb;
+
+  // oid (*zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args)
+
   rb_mIonize = rb_define_module(&quot;Ionize&quot;);
   rb_mIonizePhp = rb_define_module_under(rb_mIonize, &quot;Php&quot;);
 
   // Ionize::Php
   rb_define_module_function(rb_mIonizePhp, &quot;eval&quot;, ionize_php_eval_string, 1);
   rb_define_module_function(rb_mIonizePhp, &quot;include&quot;, php_include_file, 1);
+  rb_define_module_function(rb_mIonizePhp, &quot;last_error_message&quot;, php_last_error_message, 0);  
 
+  //  rb_define_module_function(rb_mIonizePhp, &quot;array_keys&quot;, php_array_keys, 0);
 
   rb_define_module_function(rb_mIonizePhp, &quot;call_function1&quot;, php_call_user_function1, 1);
   rb_define_module_function(rb_mIonizePhp, &quot;call_function2&quot;, php_call_user_function2, 2);
@@ -1041,33 +1409,34 @@ void Init_ionize_php_ext() {
 
   rb_define_module_function(rb_mIonizePhp, &quot;session&quot;, php_session_with_block, 0);
   rb_define_module_function(rb_mIonizePhp, &quot;session_start!&quot;, php_session_start_b, 0);
-  rb_define_module_function(rb_mIonizePhp, &quot;session_end!&quot;, php_session_end_b, 0);
+  rb_define_module_function(rb_mIonizePhp, &quot;start_session!&quot;, php_session_start_b, 0);
 
-  rb_cIonizePhpArray = rb_define_class_under(rb_mIonizePhp, &quot;Array&quot;, rb_cObject);
+  rb_define_module_function(rb_mIonizePhp, &quot;session_end!&quot;, php_session_end_b, 0);
+  rb_define_module_function(rb_mIonizePhp, &quot;end_session!&quot;, php_session_end_b, 0);
 
   // Ionize::Php::Array
+  rb_cIonizePhpArray = rb_define_class_under(rb_mIonizePhp, &quot;Array&quot;, rb_cObject);
   rb_define_singleton_method(rb_cIonizePhpArray, &quot;from_hash&quot;, ionize_php_array_new_from_hash, 1);
   rb_define_singleton_method(rb_cIonizePhpArray, &quot;from_array&quot;, ionize_php_array_new_from_ary, 1);
   
   rb_define_method(rb_cIonizePhpArray, &quot;inspect&quot;, ionize_php_array_inspect, 0);
+  rb_define_method(rb_cIonizePhpArray, &quot;my_inspect&quot;, ionize_php_array_inspect, 0);
   rb_define_method(rb_cIonizePhpArray, &quot;to_hash&quot;, ionize_php_array_to_hash, 0);
   rb_define_method(rb_cIonizePhpArray, &quot;[]&quot;, ionize_php_array_aref, 1);
   rb_define_method(rb_cIonizePhpArray, &quot;[]=&quot;, ionize_php_array_aset, 2);
 
   rb_define_method(rb_cIonizePhpArray, &quot;size&quot;, ionize_php_array_size, 0);
-  rb_define_method(rb_cIonizePhpArray, &quot;has_key?&quot;, ionize_php_array_has_key, 1);  
+  rb_define_method(rb_cIonizePhpArray, &quot;has_key?&quot;, ionize_php_array_has_key, 1);    
+  //  rb_define_method(rb_cIonizePhpArray, &quot;==&quot;, ionize_php_array_equal, 1);  
   
-  //  rb_define_method(rb_cIonizePhpArray, &quot;==&quot;, ionize_php_array_equal, 1);
-  
-  //  rb_define_method(rb_cIonizePhpArray, &quot;free&quot;, ionize_php_array_free, 0);
-  
-  //  rb_define_singleton_method(rb_cIonizePhpArray, &quot;new&quot;, 1);
-  
-  rb_cIonizePhpObject = rb_define_class_under(rb_mIonizePhp, &quot;Object&quot;, rb_cObject);
-
   // Ionize::Php::Object
+  rb_cIonizePhpObject = rb_define_class_under(rb_mIonizePhp, &quot;Object&quot;, rb_cObject);
   rb_define_method(rb_cIonizePhpObject, &quot;inspect&quot;, ionize_php_object_inspect, 0);
   rb_define_method(rb_cIonizePhpObject, &quot;instance_variables_hash&quot;, ionize_php_object_instance_variables_hash, 0);
+
+  // Ionize::Php::Resource
+  rb_cIonizePhpResource = rb_define_class_under(rb_mIonizePhp, &quot;Resource&quot;, rb_cObject);
+  rb_define_method(rb_cIonizePhpResource, &quot;inspect&quot;, ionize_php_resource_inspect, 0);  
 }
 
 </diff>
      <filename>ext/ionize_php_ext.c</filename>
    </modified>
    <modified>
      <diff></diff>
      <filename>ext/ionize_php_ext.o</filename>
    </modified>
    <modified>
      <diff></diff>
      <filename>ext/ionize_php_ext.so</filename>
    </modified>
    <modified>
      <diff>@@ -1,18 +1,17 @@
 
 require File.dirname(__FILE__) + '/ionize_php_ext'
 
-result = Ionize::Php::Array.create
-result = Ionize::Php::Array.create
+Ionize::Php.start_session!
 
-result = Ionize::Php.eval(%Q{ array(1,2) })
+result = Ionize::Php.eval(%Q{ return array(&quot;okay&quot; =&gt; 100, &quot;color&quot; =&gt; &quot;red&quot;); })
+keys = Ionize::Php.call_function2('array_keys', result)
+puts keys.inspect
 
-puts result[0]
-
-puts result.size
+values = Ionize::Php.call_function2('array_values', result)
+puts values.inspect
 
+last = Ionize::Php.call_function2('array_pop', result)
 puts result.inspect
-puts result.to_hash.inspect
-
-result[&quot;stuff&quot;] = &quot;2&quot;
-
+puts last.inspect
 
+Ionize::Php.end_session!</diff>
      <filename>ext/test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,9 +1,7 @@
 
 require File.dirname(__FILE__) + '/ionize_php_ext'
 
-
 Ionize::Php.session do
-
   object = Ionize::Php.eval(%Q{ 
     class A { 
         var $one;
@@ -15,9 +13,12 @@ Ionize::Php.session do
         }
       }
   })
+  
+  # If you omit this line it causes a segfault. Not sure why
+  puts Ionize::Php.call_function1('get_loaded_extensions').inspect
 
   array = Ionize::Php.call_function1('get_loaded_extensions').to_hash.sort.inspect
-  puts array
+  puts array.inspect
   puts array[1]
 
   puts &quot;Should be an 'A' object&quot;</diff>
      <filename>ext/test2.rb</filename>
    </modified>
    <modified>
      <diff>@@ -6,8 +6,6 @@ require 'ext/ionize_php_ext'
 $:.unshift(File.dirname(__FILE__)) unless
   $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
 
-
-
 require 'rubygems'
 require 'rack'
 </diff>
      <filename>lib/ionize.rb</filename>
    </modified>
  </modified>
  <removed type="array">
    <removed>
      <filename>spec/ionize_extension.rb</filename>
    </removed>
  </removed>
  <parents type="array">
    <parent>
      <id>fc9af2764acafdaa5f9e5cfcdc96b3be708a944f</id>
    </parent>
  </parents>
  <author>
    <name>farleyknight</name>
    <email>farleyknight+github@gmail.com</email>
  </author>
  <url>http://github.com/farleyknight/ionize/commit/52c6bd3cd37b00335e5f13d3bed094a38b926f85</url>
  <id>52c6bd3cd37b00335e5f13d3bed094a38b926f85</id>
  <committed-date>2009-06-07T14:09:00-07:00</committed-date>
  <authored-date>2009-06-07T14:09:00-07:00</authored-date>
  <message>Added better support for arrays. Now can be passed in as arguments to php functions</message>
  <tree>dfe19fb5cb1532563614fc76feab4d53f98b3995</tree>
  <committer>
    <name>farleyknight</name>
    <email>farleyknight+github@gmail.com</email>
  </committer>
</commit>
