]> granicus.if.org Git - php/commitdiff
Tons of changes for Tidy 2.0 -- output buffering, multiple documents,
authorJohn Coggeshall <john@php.net>
Sun, 14 Dec 2003 06:02:33 +0000 (06:02 +0000)
committerJohn Coggeshall <john@php.net>
Sun, 14 Dec 2003 06:02:33 +0000 (06:02 +0000)
dual nature ($a->parse_file() and $a = tidy_parse_file()), etc.

ext/tidy/TODO
ext/tidy/package.xml
ext/tidy/php_tidy.h
ext/tidy/tidy.c

index 699c207dcb44bd18d738ada5b6466b3344816c98..8a13162cc0d44129ba7fa8a2ff71780ed5413058 100644 (file)
@@ -1,3 +1,3 @@
 TODO
 
-    - Implement get_nodes() method
+Do the docs.
index 266cc5d7c669151f4677c7076fcbbe0f4f9b66ac..9117d87cb77883e148e1a3c5044d2adcb4251d40 100644 (file)
@@ -14,7 +14,7 @@
    <user>iliaa</user>
    <name>Ilia Alshanetsky</name>
    <email>ilia@php.net</email>
-   <role>lead</role>
+   <role>developer</role>
   </maintainer>
  </maintainers>
  <description>
@@ -44,6 +44,7 @@ but also traverse the document tree using the Zend Engine 2 OO semantics.
    <file role="doc" name="examples/cleanhtml.php"/>
    <file role="doc" name="examples/dumpit.php"/>
    <file role="doc" name="examples/urlgrab.php"/>
+   <file role="doc" name="libtidy.txt"/>
    
    <file role="test" name="tests/001.phpt"/>
    <file role="test" name="tests/002.phpt"/>
@@ -59,6 +60,6 @@ but also traverse the document tree using the Zend Engine 2 OO semantics.
   </deps>
  </release>
 </package>
-<!--
+!--
 vim:et:ts=1:sw=1
 -->
index e170d37086ea00690f4ca75c146019b06e328e32..929d8dca2c5fe13c93e4830b1be9186a5b22ac91 100644 (file)
@@ -1,6 +1,6 @@
 /*
   +----------------------------------------------------------------------+
-  | PHP Version 4                                                        |
+  | PHP Version 5                                                        |
   +----------------------------------------------------------------------+
   | Copyright (c) 1997-2003 The PHP Group                                |
   +----------------------------------------------------------------------+
@@ -12,8 +12,7 @@
   | obtain it through the world-wide-web, please send a note to          |
   | license@php.net so we can mail you a copy immediately.               |
   +----------------------------------------------------------------------+
-  | Author: John Coggeshall  <john@php.net>                              |
-  |         Ilia Alshanetsky <ilia@php.net>                             |
+  | Author: John Coggeshall <john@php.net>                               |
   +----------------------------------------------------------------------+
 */
 
 #ifndef PHP_TIDY_H
 #define PHP_TIDY_H
 
+#include "tidyenum.h"
+#include "tidy.h"
+#include "buffio.h"
+
 extern zend_module_entry tidy_module_entry;
 #define phpext_tidy_ptr &tidy_module_entry
 
@@ -35,47 +38,31 @@ extern zend_module_entry tidy_module_entry;
 #include "TSRM.h"
 #endif
 
-#include "tidyenum.h"
-#include "tidy.h"
-#include "buffio.h"
-
-#ifdef ZTS
-#define TG(v) TSRMG(tidy_globals_id, zend_tidy_globals *, v)
-#else
-#define TG(v) (tidy_globals.v)
-#endif
-
-#ifndef TRUE
-#define TRUE 1
-#define FALSE 0
-#endif
-
-#define TIDY_RV_FALSE(__t) __t->type = IS_BOOL; __t->value.lval = FALSE
-#define TIDY_RV_TRUE(__t) __t->type = IS_BOOL; __t->value.lval = TRUE
+#define PHP_TIDY_MODULE_VERSION        "2.0-dev"
 
 #define REMOVE_NEWLINE(_z) _z->value.str.val[_z->value.str.len-1] = '\0'; _z->value.str.len--;
 
-#define TIDY_TAG_CONST(tag) REGISTER_LONG_CONSTANT("TIDY_TAG_" #tag, TidyTag_##tag, CONST_CS | CONST_PERSISTENT)
-#define TIDY_ATTR_CONST(attr) REGISTER_LONG_CONSTANT("TIDY_ATTR_" #attr, TidyAttr_##attr, CONST_CS | CONST_PERSISTENT)
-#define TIDY_NODE_CONST(name, type) REGISTER_LONG_CONSTANT("TIDY_NODETYPE_" #name, TidyNode_##type, CONST_CS | CONST_PERSISTENT)
-
-#define PHP_ME_MAPPING(name, func_name, arg_types) \
-       ZEND_NAMED_FE(name, ZEND_FN(func_name), arg_types)
+#define TIDYDOC_FROM_OBJECT(tdoc, object) \
+       { \
+               PHPTidyObj *obj = (PHPTidyObj*) zend_object_store_get_object(object TSRMLS_CC); \
+               tdoc = obj->ptdoc; \
+       }
 
-#define PHP_NODE_METHOD(name)    PHP_FUNCTION(tnm_ ##name)
-#define PHP_ATTR_METHOD(name)    PHP_FUNCTION(tam_ ##name)
-#define PHP_NODE_ME(name, param)      PHP_ME_MAPPING(name, tnm_ ##name, param)
-#define PHP_ATTR_ME(name, param)      PHP_ME_MAPPING(name, tam_ ##name, param)
+#define Z_OBJ_P(zval_p) zend_objects_get_address(zval_p TSRMLS_CC)
 
+#define TIDY_METHOD_MAP(name, func_name, arg_types) \
+       ZEND_NAMED_FE(name, ZEND_FN(func_name), arg_types)
 
+#define TIDY_THROW(message) \
+       PG(suppress_errors) = 0; \
+       EG(exception) = zend_throw_exception(tidy_ce_exception, message, 0 TSRMLS_CC);
 
-#define TIDY_REGISTER_OBJECT(_type, _object, _ptr) \
-       { \
-               tidy_object *obj; \
-               obj = (tidy_object*)zend_object_store_get_object(_object TSRMLS_CC); \
-               obj->type = is_ ## _type; \
-               obj->u._type = _ptr; \
-       }
+#define TIDY_NODE_METHOD(name)    PHP_FUNCTION(tnm_ ##name)
+#define TIDY_NODE_ME(name, param)      TIDY_METHOD_MAP(name, tnm_ ##name, param)
+#define TIDY_DOC_METHOD(name)     PHP_FUNCTION(tdm_ ##name)
+#define TIDY_DOC_ME(name, param)  TIDY_METHOD_MAP(name, tdm_ ##name, param)
+#define TIDY_ATTR_METHOD(name)    PHP_FUNCTION(tam_ ##name)
+#define TIDY_ATTR_ME(name, param) TIDY_METHOD_MAP(name, tam_ ##name, param)
 
 #define REGISTER_TIDY_CLASS(name, parent) \
        { \
@@ -88,62 +75,122 @@ extern zend_module_entry tidy_module_entry;
                tidy_object_handlers_ ## name.clone_obj = NULL; \
     }
 
-#define GET_THIS_CONTAINER() \
-    PHPTidyObj *obj; \
-    { \
-        zval *object = getThis(); \
-        obj = (PHPTidyObj *)zend_object_store_get_object(object TSRMLS_CC); \
-    }
+#define TIDY_TAG_CONST(tag) REGISTER_LONG_CONSTANT("TIDY_TAG_" #tag, TidyTag_##tag, CONST_CS | CONST_PERSISTENT)
+#define TIDY_ATTR_CONST(attr) REGISTER_LONG_CONSTANT("TIDY_ATTR_" #attr, TidyAttr_##attr, CONST_CS | CONST_PERSISTENT)
+#define TIDY_NODE_CONST(name, type) REGISTER_LONG_CONSTANT("TIDY_NODETYPE_" #name, TidyNode_##type, CONST_CS | CONST_PERSISTENT)
 
-#define INSTANCIATE_NODE(_zval, _container, _node) \
-       tidy_instanciate(tidy_ce_node, _zval TSRMLS_CC); \
-       _container = (PHPTidyObj *) zend_object_store_get_object(_zval TSRMLS_CC); \
-       _container->node = _node; \
-       _container->attr = NULL; \
-       _container->type = is_node; \
-       tidy_add_default_properities(_container, is_node TSRMLS_CC);
-
-#define INSTANCIATE_ATTR(_zval, _container, _attr) \
-       tidy_instanciate(tidy_ce_attr, _zval TSRMLS_CC); \
-       _container = (PHPTidyObj *) zend_object_store_get_object(_zval TSRMLS_CC); \
-       _container->node = NULL; \
-       _container->attr = _attr; \
-       _container->type = is_attr; \
-       tidy_add_default_properities(_container, is_attr TSRMLS_CC);
-
-#define PHP_NODE_METHOD_IS_TYPE(_type, _const) \
-PHP_NODE_METHOD(is_ ##_type) \
-{ \
-       GET_THIS_CONTAINER(); \
-       if(tidyNodeGetType(obj->node) == _const) {\
-               RETURN_TRUE; \
-       } else { \
-               RETURN_FALSE; \
-       } \
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+
+#define ADD_PROPERITY_STRING(_table, _key, _string) \
+       { \
+               zval *tmp; \
+               MAKE_STD_ZVAL(tmp); \
+               if(_string) { \
+                       ZVAL_STRING(tmp, (char *)_string, 1); \
+               } else { \
+                       ZVAL_EMPTY_STRING(tmp); \
+               } \
+               zend_hash_update(_table, #_key, sizeof(#_key), (void *)&tmp, sizeof(zval *), NULL); \
+       }
+
+#define ADD_PROPERITY_LONG(_table, _key, _long) \
+       { \
+               zval *tmp; \
+               MAKE_STD_ZVAL(tmp); \
+               ZVAL_LONG(tmp, _long); \
+               zend_hash_update(_table, #_key, sizeof(#_key), (void *)&tmp, sizeof(zval *), NULL); \
+       }
+
+#define ADD_PROPERITY_NULL(_table, _key) \
+       { \
+               zval *tmp; \
+               MAKE_STD_ZVAL(tmp); \
+               ZVAL_NULL(tmp); \
+               zend_hash_update(_table, #_key, sizeof(#_key), (void *)&tmp, sizeof(zval *), NULL); \
+       }
+
+#define TIDY_PARSED_CHECK(_obj) \
+if(!_obj->ptdoc->parsed) { \
+       php_error_docref(NULL TSRMLS_CC, E_WARNING, "A document must be parsed before executing this function."); \
+       RETURN_FALSE; \
+} 
+
+#define TIDY_PARSED_REPAIR_CHECK(_obj) \
+TIDY_PARSED_CHECK(_obj); \
+if(!_obj->ptdoc->repaired) { \
+    php_error_docref(NULL TSRMLS_CC, E_WARNING, "You must clean and repair the document before executing this function."); \
+    RETURN_FALSE; \
 }
 
+#define TIDY_SAFE_MODE_CHECK(filename) \
+if ((PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(filename TSRMLS_CC)) { \
+       RETURN_FALSE; \
+} \
+
+#define TIDY_SET_DEFAULT_CONFIG(_doc) \
+       if (TG(default_config) && TG(default_config)[0]) { \
+               if (tidyLoadConfig(_doc, TG(default_config)) < 0) { \
+                       zend_error(E_ERROR, "Unable to load Tidy configuration file at '%s'.", TG(default_config)); \
+               } \
+       }
+
+typedef struct _PHPTidyDoc PHPTidyDoc;
+typedef struct _PHPTidyObj PHPTidyObj;
+
 typedef enum {
     is_node,
-    is_attr
+    is_attr,
+    is_doc,
+    is_exception
 } tidy_obj_type;
 
+typedef enum {
+    is_root_node,
+    is_html_node,
+    is_head_node,
+    is_body_node
+} tidy_base_nodetypes;
+
 struct _PHPTidyDoc {
-    
     TidyDoc     doc;
     TidyBuffer  *errbuf;
     zend_bool   parsed;
+    zend_bool   repaired;
+    unsigned int ref_count;
 };
 
-typedef struct _PHPTidyDoc PHPTidyDoc;
-typedef struct _PHPTidyObj PHPTidyObj;
-
 struct _PHPTidyObj {
     zend_object         std;
     TidyNode            node;
     TidyAttr            attr;
     tidy_obj_type       type;
+    
+    PHPTidyDoc          *ptdoc;
 };
 
+static char *php_tidy_file_to_mem(char *, zend_bool TSRMLS_DC);
+static void tidy_object_dtor(void *, zend_object_handle  TSRMLS_DC);
+static zend_object_value tidy_object_new_node(zend_class_entry * TSRMLS_DC);
+static zend_object_value tidy_object_new_attr(zend_class_entry * TSRMLS_DC);
+static zend_object_value tidy_object_new_doc(zend_class_entry * TSRMLS_DC);
+static zend_object_value tidy_object_new_exception(zend_class_entry * TSRMLS_DC);
+static zend_class_entry *tidy_get_ce_node(zval * TSRMLS_DC);
+static zend_class_entry *tidy_get_ce_attr(zval * TSRMLS_DC);
+static zend_class_entry *tidy_get_ce_doc(zval * TSRMLS_DC);
+static zval * tidy_instanciate(zend_class_entry *, zval * TSRMLS_DC);
+static int tidy_doc_cast_handler(zval *, zval *, int, int TSRMLS_DC);
+static int tidy_node_cast_handler(zval *, zval *, int, int TSRMLS_DC);
+static void tidy_doc_update_properties(PHPTidyObj * TSRMLS_DC);
+static void tidy_add_default_properities(PHPTidyObj *, tidy_obj_type TSRMLS_DC);
+static void *php_tidy_get_opt_val(PHPTidyDoc *, TidyOption, TidyOptionType * TSRMLS_DC);
+static void php_tidy_create_node(INTERNAL_FUNCTION_PARAMETERS, tidy_base_nodetypes);
+
+void _php_tidy_register_nodetypes(INIT_FUNC_ARGS);
+void _php_tidy_register_tags(INIT_FUNC_ARGS);
+void _php_tidy_register_attributes(INIT_FUNC_ARGS);
 
 PHP_MINIT_FUNCTION(tidy);
 PHP_MSHUTDOWN_FUNCTION(tidy);
@@ -151,6 +198,9 @@ PHP_RINIT_FUNCTION(tidy);
 PHP_RSHUTDOWN_FUNCTION(tidy);
 PHP_MINFO_FUNCTION(tidy);
 
+PHP_FUNCTION(tidy_reset_config);
+PHP_FUNCTION(tidy_restore_config);
+PHP_FUNCTION(tidy_snapshot_config);
 PHP_FUNCTION(tidy_setopt);
 PHP_FUNCTION(tidy_getopt);
 PHP_FUNCTION(tidy_parse_string);
@@ -177,42 +227,28 @@ PHP_FUNCTION(tidy_load_config_enc);
 PHP_FUNCTION(tidy_set_encoding);
 PHP_FUNCTION(tidy_save_config);
 
+PHP_FUNCTION(ob_tidyhandler);
+
 PHP_FUNCTION(tidy_get_root);
 PHP_FUNCTION(tidy_get_html);
 PHP_FUNCTION(tidy_get_head);
 PHP_FUNCTION(tidy_get_body);
 
-PHP_NODE_METHOD(__construct);
-PHP_NODE_METHOD(attributes);
-PHP_NODE_METHOD(children);
-
-PHP_NODE_METHOD(has_children);
-PHP_NODE_METHOD(has_siblings);
-PHP_NODE_METHOD(is_comment);
-PHP_NODE_METHOD(is_html);
-PHP_NODE_METHOD(is_xhtml);
-PHP_NODE_METHOD(is_xml);
-PHP_NODE_METHOD(is_text);
-PHP_NODE_METHOD(is_jste);
-PHP_NODE_METHOD(is_asp);
-PHP_NODE_METHOD(is_php);
-
-PHP_NODE_METHOD(next);
-PHP_NODE_METHOD(prev);
-PHP_NODE_METHOD(get_attr);
-PHP_NODE_METHOD(get_nodes);
-
-/* resource dtor */
-void dtor_TidyDoc(zend_rsrc_list_entry * TSRMLS_DC);
-
-/* constant register helpers */
-void _php_tidy_register_nodetypes(INIT_FUNC_ARGS);
-void _php_tidy_register_tags(INIT_FUNC_ARGS);
-void _php_tidy_register_attributes(INIT_FUNC_ARGS);
+TIDY_ATTR_METHOD(__construct);
+
+TIDY_NODE_METHOD(__construct);
+TIDY_NODE_METHOD(has_children);
+TIDY_NODE_METHOD(has_siblings);
+TIDY_NODE_METHOD(is_comment);
+TIDY_NODE_METHOD(is_html);
+TIDY_NODE_METHOD(is_xhtml);
+TIDY_NODE_METHOD(is_xml);
+TIDY_NODE_METHOD(is_text);
+TIDY_NODE_METHOD(is_jste);
+TIDY_NODE_METHOD(is_asp);
+TIDY_NODE_METHOD(is_php);
 
 ZEND_BEGIN_MODULE_GLOBALS(tidy)
-       PHPTidyDoc *tdoc;
-       zend_bool used;
        char *default_config;
 ZEND_END_MODULE_GLOBALS(tidy)
 
@@ -222,9 +258,6 @@ ZEND_END_MODULE_GLOBALS(tidy)
 #define TG(v) (tidy_globals.v)
 #endif
 
-
-
-
 #endif
 
 
index baaf38f1d073f033490d4c79c1f5698da82e04fb..d5b54776b515945870dee4a8c36bdf0885b2cc41 100644 (file)
@@ -1,6 +1,6 @@
 /*
   +----------------------------------------------------------------------+
-  | PHP Version 4                                                        |
+  | PHP Version 5                                                        |
   +----------------------------------------------------------------------+
   | Copyright (c) 1997-2003 The PHP Group                                |
   +----------------------------------------------------------------------+
@@ -13,7 +13,6 @@
   | license@php.net so we can mail you a copy immediately.               |
   +----------------------------------------------------------------------+
   | Author: John Coggeshall <john@php.net>                               |
-  |         Ilia Alshanetsky <ilia@php.net>                                                             |
   +----------------------------------------------------------------------+
 */
 
 #include "Zend/zend_API.h"
 #include "Zend/zend_hash.h"
 #include "safe_mode.h"
+#include "zend_default_classes.h"
+#include "zend_object_handlers.h"
 
-ZEND_DECLARE_MODULE_GLOBALS(tidy);
-
-#define TIDY_PARSED_CHECK() \
-if(!TG(tdoc)->parsed) { \
-       php_error_docref(NULL TSRMLS_CC, E_WARNING, "A document must be parsed before executing this function."); \
-       RETURN_FALSE; \
-} \
+ZEND_DECLARE_MODULE_GLOBALS(tidy)
 
-#define TIDY_SAFE_MODE_CHECK(filename) \
-if ((PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(filename TSRMLS_CC)) { \
-       RETURN_FALSE; \
-} \
+PHP_INI_BEGIN()
+STD_PHP_INI_ENTRY("tidy.default_config",       "",     PHP_INI_SYSTEM,         OnUpdateString,         default_config,         zend_tidy_globals,      tidy_globals)
+PHP_INI_ENTRY("tidy.clean_output",     "0",    PHP_INI_SYSTEM,         NULL)
+PHP_INI_END()
 
 function_entry tidy_functions[] = {
        PHP_FE(tidy_setopt,             NULL)
@@ -69,62 +64,62 @@ function_entry tidy_functions[] = {
        PHP_FE(tidy_load_config_enc,    NULL)
        PHP_FE(tidy_set_encoding,       NULL)
        PHP_FE(tidy_save_config,        NULL)
-
-#ifdef ZEND_ENGINE_2
        PHP_FE(tidy_get_root,           NULL)
        PHP_FE(tidy_get_head,           NULL)
        PHP_FE(tidy_get_html,           NULL)
        PHP_FE(tidy_get_body,           NULL)
-#endif
-
+       PHP_FE(tidy_reset_config,       NULL)
+       PHP_FE(tidy_snapshot_config, NULL)
+       PHP_FE(tidy_restore_config, NULL)
+       PHP_FE(ob_tidyhandler,          NULL)
        {NULL, NULL, NULL}
 };
 
-#ifdef ZEND_ENGINE_2
-#include "zend_default_classes.h"
-
-static void tidy_object_dtor(void *object, zend_object_handle handle TSRMLS_DC);
-static void tidy_object_new(zend_class_entry *class_type, zend_object_handlers *handlers, zend_object_value *retval TSRMLS_DC);
-
-static zend_object_value tidy_object_new_node(zend_class_entry *class_type TSRMLS_DC);
-static zend_object_value tidy_object_new_attr(zend_class_entry *class_type TSRMLS_DC);
-static zend_object_value tidy_object_new_exception(zend_class_entry *class_type TSRMLS_DC);
-
-static zend_class_entry *tidy_get_ce_node(zval *object TSRMLS_DC);
-static zend_class_entry *tidy_get_ce_attr(zval *object TSRMLS_DC);
-
-static zval * tidy_instanciate(zend_class_entry *pce, zval *object TSRMLS_DC);
-
-zend_class_entry *tidy_ce_node, *tidy_ce_attr,
-                                *tidy_ce_exception;
-                 
-static zend_object_handlers tidy_object_handlers_node;
-static zend_object_handlers tidy_object_handlers_attr;
-static zend_object_handlers tidy_object_handlers_exception;
+function_entry tidy_funcs_doc[] = {
+       TIDY_METHOD_MAP(setopt, tidy_setopt, NULL)
+       TIDY_METHOD_MAP(getopt, tidy_getopt, NULL)
+       TIDY_METHOD_MAP(parse_string, tidy_parse_string, NULL)
+       TIDY_METHOD_MAP(parse_file, tidy_parse_file, NULL)
+       TIDY_METHOD_MAP(clean_repair, tidy_clean_repair, NULL)
+       TIDY_METHOD_MAP(repair_string, tidy_repair_string, NULL)
+       TIDY_METHOD_MAP(repair_file, tidy_repair_file, NULL)
+       TIDY_METHOD_MAP(diagnose, tidy_diagnose, NULL)
+       TIDY_METHOD_MAP(get_release, tidy_get_release, NULL)
+       TIDY_METHOD_MAP(get_config, tidy_get_config, NULL)
+       TIDY_METHOD_MAP(get_status, tidy_get_status, NULL)
+       TIDY_METHOD_MAP(get_html_ver, tidy_get_html_ver, NULL)
+       TIDY_METHOD_MAP(is_xhtml, tidy_is_xhtml, NULL)
+       TIDY_METHOD_MAP(is_xml, tidy_is_xml, NULL)
+       TIDY_METHOD_MAP(load_config, tidy_load_config, NULL)
+       TIDY_METHOD_MAP(load_config_enc, tidy_load_config_enc, NULL)
+       TIDY_METHOD_MAP(set_encoding, tidy_set_encoding, NULL)
+       TIDY_METHOD_MAP(save_config, tidy_save_config, NULL)
+       TIDY_METHOD_MAP(root, tidy_get_root, NULL)
+       TIDY_METHOD_MAP(head, tidy_get_head, NULL)
+       TIDY_METHOD_MAP(html, tidy_get_html, NULL)
+       TIDY_METHOD_MAP(body, tidy_get_body, NULL)
+       TIDY_METHOD_MAP(reset_config, tidy_reset_config, NULL)
+       TIDY_METHOD_MAP(snapshot_config, tidy_snapshot_config, NULL)
+       TIDY_METHOD_MAP(restore_config, tidy_restore_config, NULL)
+       {NULL, NULL, NULL}
+};
 
 function_entry tidy_funcs_node[] = {
        
-       PHP_NODE_ME(__construct, NULL)
-       PHP_NODE_ME(attributes, NULL)
-       PHP_NODE_ME(children, NULL)
-       
-       PHP_NODE_ME(has_children, NULL)
-       PHP_NODE_ME(has_siblings, NULL)
-       PHP_NODE_ME(is_comment, NULL)
-       PHP_NODE_ME(is_html, NULL)
-       PHP_NODE_ME(is_text, NULL)
-       PHP_NODE_ME(is_jste, NULL)
-       PHP_NODE_ME(is_asp, NULL)
-       PHP_NODE_ME(is_php, NULL)
-       
-       PHP_NODE_ME(next, NULL)
-       PHP_NODE_ME(prev, NULL)
-       PHP_NODE_ME(get_attr, NULL)
-       /*PHP_NODE_ME(get_nodes, NULL) TODO */
+       TIDY_NODE_ME(__construct, NULL)
+       TIDY_NODE_ME(has_children, NULL)
+       TIDY_NODE_ME(has_siblings, NULL)
+       TIDY_NODE_ME(is_comment, NULL)
+       TIDY_NODE_ME(is_html, NULL)
+       TIDY_NODE_ME(is_text, NULL)
+       TIDY_NODE_ME(is_jste, NULL)
+       TIDY_NODE_ME(is_asp, NULL)
+       TIDY_NODE_ME(is_php, NULL)
        {NULL, NULL, NULL}
 };
 
 function_entry tidy_funcs_attr[] = {
+       TIDY_ATTR_ME(__construct, NULL)
        {NULL, NULL, NULL}
 };
 
@@ -132,7 +127,13 @@ function_entry tidy_funcs_exception[] = {
        {NULL, NULL, NULL}
 };
 
-#endif
+zend_class_entry *tidy_ce_doc, *tidy_ce_node,
+                 *tidy_ce_attr, *tidy_ce_exception;
+
+static zend_object_handlers tidy_object_handlers_doc;
+static zend_object_handlers tidy_object_handlers_node;
+static zend_object_handlers tidy_object_handlers_attr;
+static zend_object_handlers tidy_object_handlers_exception;
 
 zend_module_entry tidy_module_entry = {
 #if ZEND_MODULE_API_NO >= 20010901
@@ -142,100 +143,39 @@ zend_module_entry tidy_module_entry = {
        tidy_functions,
        PHP_MINIT(tidy),
        PHP_MSHUTDOWN(tidy),
-       PHP_RINIT(tidy),
-       NULL,
+       PHP_RINIT(tidy),        
+       PHP_RSHUTDOWN(tidy),
        PHP_MINFO(tidy),
 #if ZEND_MODULE_API_NO >= 20010901
-       "1.0",
+       PHP_TIDY_MODULE_VERSION,
 #endif
        STANDARD_MODULE_PROPERTIES
 };
 
+
 #ifdef COMPILE_DL_TIDY
 ZEND_GET_MODULE(tidy)
 #endif
 
-/* {{{ PHP_INI
- */
-PHP_INI_BEGIN()
-STD_PHP_INI_ENTRY("tidy.default_config",       "",     PHP_INI_SYSTEM,         OnUpdateString,         default_config,         zend_tidy_globals,      tidy_globals)
-PHP_INI_END()
-/* }}} */
-
-static void tidy_globals_ctor(zend_tidy_globals *g TSRMLS_DC)
+/* Wrappers so tidy can use the PHP memory management */
+void *php_tidy_malloc(size_t len)
 {
-       g->used = 0;
-       g->tdoc = pemalloc(sizeof(PHPTidyDoc), 1);
-       g->tdoc->doc = tidyCreate();
-       g->tdoc->parsed = 0;
-       g->tdoc->errbuf = pemalloc(sizeof(TidyBuffer), 1);
-       tidyBufInit(g->tdoc->errbuf);
-
-       if(tidySetErrorBuffer(g->tdoc->doc, g->tdoc->errbuf) != 0) {
-               zend_error(E_ERROR, "Could not set Tidy error buffer");
-       }
-
-       tidyOptSetBool(g->tdoc->doc, TidyForceOutput, yes);
-       tidyOptSetBool(g->tdoc->doc, TidyMark, no);
-
-       /* remember settings so that we can restore them */
-       tidyOptSnapshot(g->tdoc->doc);
+       return emalloc(len);
 }
 
-static void tidy_globals_dtor(zend_tidy_globals *g TSRMLS_DC)
+void *php_tidy_realloc(void *buf, size_t len)
 {
-       tidyBufFree(g->tdoc->errbuf);
-       pefree(g->tdoc->errbuf, 1);
-       tidyRelease(g->tdoc->doc);
-       pefree(g->tdoc, 1);
-       g->used = 0;
+       return erealloc(buf, len);
 }
 
-static void *php_tidy_get_opt_val(TidyOption opt, TidyOptionType *type TSRMLS_DC)
+void php_tidy_free(void *buf)
 {
-       *type = tidyOptGetType(opt);
-
-       switch (*type) {
-               case TidyString: {
-                       char *val = (char *) tidyOptGetValue(TG(tdoc)->doc, tidyOptGetId(opt));
-                       if (val) {
-                               return (void *) estrdup(val);
-                       } else {
-                               return (void *) estrdup("");
-                       }
-               }
-                       break;
-
-               case TidyInteger:
-                       return (void *) tidyOptGetInt(TG(tdoc)->doc, tidyOptGetId(opt));
-                       break;
-
-               case TidyBoolean:
-                       return (void *) tidyOptGetBool(TG(tdoc)->doc, tidyOptGetId(opt));
-                       break;
-       }
-
-       /* should not happen */
-       return NULL;
+       efree(buf);
 }
 
-static char *php_tidy_file_to_mem(char *filename, zend_bool use_include_path TSRMLS_DC)
+void php_tidy_panic(ctmbstr msg)
 {
-       php_stream *stream;
-       int len;
-       char *data = NULL;
-
-       if (!(stream = php_stream_open_wrapper(filename, "rb", (use_include_path ? USE_PATH : 0) | ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL))) {
-               return NULL;
-       }
-       if ((len = php_stream_copy_to_mem(stream, &data, PHP_STREAM_COPY_ALL, 0)) > 0) {
-               /* noop */
-       } else if (len == 0) {
-               data = estrdup("");
-       }
-       php_stream_close(stream);
-
-       return data;
+       php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not allocate memory for tidy! (Reason: %s)", (char *)msg);
 }
 
 static void php_tidy_quick_repair(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_file)
@@ -243,11 +183,28 @@ static void php_tidy_quick_repair(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_fil
        char *data=NULL, *cfg_file=NULL, *arg1;
        int cfg_file_len, arg1_len;
        zend_bool use_include_path = 0;
+       zval *object = getThis();
+       PHPTidyObj *obj;
+       
+       if(object) {
+       
+               if(zend_parse_parameters(1 TSRMLS_CC, "s|sb", &arg1, &arg1_len, &cfg_file, &cfg_file_len, &use_include_path) == FAILURE) {
+                       RETURN_FALSE;
+               }
+               
+       } else {
+               
+               if(zend_parse_parameters(1 TSRMLS_CC, "Os|sb", &object, tidy_ce_doc,
+                                                                &arg1, &arg1_len, &cfg_file, &cfg_file_len, &use_include_path) == FAILURE) {
+                       return;
+               }
+               
+               tidy_instanciate(tidy_ce_doc, return_value TSRMLS_CC);
 
-       if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|sb", &arg1, &arg1_len, &cfg_file, &cfg_file_len, &use_include_path) == FAILURE) {
-               RETURN_FALSE;
        }
 
+       obj = (PHPTidyObj *) zend_object_store_get_object(return_value TSRMLS_CC);
+
        if (is_file) {
                if (!(data = php_tidy_file_to_mem(arg1, use_include_path TSRMLS_CC))) {
                        RETURN_FALSE;
@@ -258,23 +215,22 @@ static void php_tidy_quick_repair(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_fil
 
        if (cfg_file && cfg_file[0]) {
                TIDY_SAFE_MODE_CHECK(cfg_file);
-               if(tidyLoadConfig(TG(tdoc)->doc, cfg_file) < 0) {
+               if(tidyLoadConfig(obj->ptdoc->doc, cfg_file) < 0) {
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not load configuration file '%s'", cfg_file);
                        RETVAL_FALSE;
                }
-               TG(used) = 1;
        }
 
        if (data) {
-               if(tidyParseString(TG(tdoc)->doc, data) < 0) {
-                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "[Tidy error] %s", TG(tdoc)->errbuf->bp);
+               if(tidyParseString(obj->ptdoc->doc, data) < 0) {
+                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "[Tidy error] %s", obj->ptdoc->errbuf->bp);
                        RETVAL_FALSE;
                } else {
-                       TG(tdoc)->parsed = TRUE;
-                       if (tidyCleanAndRepair(TG(tdoc)->doc) >= 0) {
+                       obj->ptdoc->parsed = TRUE;
+                       if (tidyCleanAndRepair(obj->ptdoc->doc) >= 0) {
                                TidyBuffer output = {0};
 
-                               tidySaveBuffer (TG(tdoc)->doc, &output);
+                               tidySaveBuffer (obj->ptdoc->doc, &output);
                                RETVAL_STRING(output.bp, 1);
                                tidyBufFree(&output);
                        } else {
@@ -288,179 +244,717 @@ static void php_tidy_quick_repair(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_fil
        }
 }
 
-PHP_MINIT_FUNCTION(tidy)
+static char *php_tidy_file_to_mem(char *filename, zend_bool use_include_path TSRMLS_DC)
 {
-       REGISTER_INI_ENTRIES();
-
-#ifdef ZEND_ENGINE_2
-       REGISTER_TIDY_CLASS(node, NULL);
-       REGISTER_TIDY_CLASS(attr, NULL);
-       REGISTER_TIDY_CLASS(exception, zend_exception_get_default());
-
-       tidy_object_handlers_node.get_class_entry = tidy_get_ce_node;
-       tidy_object_handlers_attr.get_class_entry = tidy_get_ce_attr;
-#endif
-
-       _php_tidy_register_tags(INIT_FUNC_ARGS_PASSTHRU);
-       _php_tidy_register_attributes(INIT_FUNC_ARGS_PASSTHRU);
-       _php_tidy_register_nodetypes(INIT_FUNC_ARGS_PASSTHRU);
+       php_stream *stream;
+       int len;
+       char *data = NULL;
 
-       ZEND_INIT_MODULE_GLOBALS(tidy, tidy_globals_ctor, tidy_globals_dtor);
+       if (!(stream = php_stream_open_wrapper(filename, "rb", (use_include_path ? USE_PATH : 0) | ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL))) {
+               return NULL;
+       }
+       if ((len = php_stream_copy_to_mem(stream, &data, PHP_STREAM_COPY_ALL, 0)) > 0) {
+               /* noop */
+       } else if (len == 0) {
+               data = estrdup("");
+       }
+       php_stream_close(stream);
 
-       return SUCCESS;
+       return data;
 }
 
-PHP_MSHUTDOWN_FUNCTION(tidy)
+static void tidy_object_dtor(void *object, zend_object_handle handle TSRMLS_DC)
 {
-#ifndef ZTS
-        tidy_globals_dtor(&tidy_globals TSRMLS_CC);
-#endif
-       return SUCCESS;
-}
+       PHPTidyObj *intern = (PHPTidyObj *)object;
 
-PHP_RINIT_FUNCTION(tidy)
-{
-       if (TG(used) && tidyOptDiffThanSnapshot((TG(tdoc))->doc)) {
-               tidyOptResetToSnapshot((TG(tdoc))->doc);
-               TG(used) = 0;
-       }
-       /* if a user provided a default configuration file, use it */
-       if (TG(default_config) && TG(default_config)[0]) {
-               if (tidyLoadConfig((TG(tdoc))->doc, TG(default_config)) < 0) {
-                       zend_error(E_ERROR, "Unable to load Tidy configuration file at '%s'.", TG(default_config));
-               }
-               TG(used) = 1;
+       zend_hash_destroy(intern->std.properties);
+       FREE_HASHTABLE(intern->std.properties);
+       
+       intern->ptdoc->ref_count--;
+       
+       if(intern->ptdoc->ref_count <= 0) {
+               
+               tidyBufFree(intern->ptdoc->errbuf);
+               efree(intern->ptdoc->errbuf);
+               tidyRelease(intern->ptdoc->doc);
+               efree(intern->ptdoc);
        }
-       return SUCCESS;
+       
+       efree(object);
 }
 
-PHP_MINFO_FUNCTION(tidy)
+static void tidy_object_new(zend_class_entry *class_type, zend_object_handlers *handlers,
+                                                       zend_object_value *retval, tidy_obj_type objtype TSRMLS_DC)
 {
-       TidyIterator itOpt = tidyGetOptionList(TG(tdoc)->doc);
-       void *opt_value;
-       TidyOptionType optt;
-       char buf[255];
-
-       php_info_print_table_start();
-       php_info_print_table_header(2, "Tidy support", "enabled");
-       php_info_print_table_row(2, "libTidy Build Date", (char *)tidyReleaseDate());
-       php_info_print_table_end();
-
-       DISPLAY_INI_ENTRIES();
+       PHPTidyObj *intern;
+       zval *tmp;
 
-       php_info_print_table_start();
-       php_info_print_table_header(2, "Tidy Configuration Directive", "Value");
-       while (itOpt) {
-               TidyOption opt = tidyGetNextOption(TG(tdoc)->doc, &itOpt);
+       intern = emalloc(sizeof(PHPTidyObj));
+       memset(intern, 0, sizeof(PHPTidyObj));
+       intern->std.ce = class_type;
 
-               opt_value = php_tidy_get_opt_val(opt, &optt TSRMLS_CC);
-               switch (optt) {
-                       case TidyString:
-                               php_info_print_table_row(2, (char *)tidyOptGetName(opt), (char*)opt_value);
-                               efree(opt_value);
-                               break;
+       ALLOC_HASHTABLE(intern->std.properties);
+       zend_hash_init(intern->std.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
+       zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
 
-                       case TidyInteger:
-                               sprintf(buf, "%d", (int)opt_value);
-                               php_info_print_table_row(2, (char *)tidyOptGetName(opt), (char*)buf);
-                               break;
+       switch(objtype) {
+               
+               case is_node:
+                       break;
+               case is_attr:
+                       break;
+               case is_doc:
 
-                       case TidyBoolean:
-                               php_info_print_table_row(2, (char *)tidyOptGetName(opt), (opt_value ? "TRUE" : "FALSE"));
-                               break;
-               }
+                       tidySetMallocCall(php_tidy_malloc);
+                       tidySetReallocCall(php_tidy_realloc);
+                       tidySetFreeCall(php_tidy_free);
+                       tidySetPanicCall(php_tidy_panic);
+                       
+                       intern->ptdoc = emalloc(sizeof(PHPTidyDoc));
+                       intern->ptdoc->doc = tidyCreate();
+                       intern->ptdoc->parsed = FALSE;
+                       intern->ptdoc->repaired = FALSE;
+                       intern->ptdoc->ref_count = 1;
+                       intern->ptdoc->errbuf = emalloc(sizeof(TidyBuffer));
+                       tidyBufInit(intern->ptdoc->errbuf);
+               
+                       if(tidySetErrorBuffer(intern->ptdoc->doc, intern->ptdoc->errbuf) != 0) {
+                               zend_error(E_ERROR, "Could not set Tidy error buffer");
+                       }
+       
+                       
+                       tidyOptSetBool(intern->ptdoc->doc, TidyForceOutput, yes);
+                       tidyOptSetBool(intern->ptdoc->doc, TidyMark, no);
+       
+                       TIDY_SET_DEFAULT_CONFIG(intern->ptdoc->doc);
+                       
+                       tidy_add_default_properities(intern, is_doc TSRMLS_CC);
+                       break;
+               default:
+                       break;                  
        }
-       php_info_print_table_end();
+       
+       retval->handle = zend_objects_store_put(intern, tidy_object_dtor, NULL TSRMLS_CC);
+       retval->handlers = handlers;
 }
 
-/* {{{ proto bool tidy_parse_string(string input)
-   Parse a document stored in a string */
-PHP_FUNCTION(tidy_parse_string)
+static zend_object_value tidy_object_new_node(zend_class_entry *class_type TSRMLS_DC)
 {
-       char *input;
-       int input_len;
+       zend_object_value retval;
+       tidy_object_new(class_type, &tidy_object_handlers_node, &retval, is_node TSRMLS_CC);
+       return retval;
+}
 
-       if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &input, &input_len) == FAILURE) {
-               RETURN_FALSE;
-       }
+static zend_object_value tidy_object_new_attr(zend_class_entry *class_type TSRMLS_DC)
+{
+       zend_object_value retval;
+       tidy_object_new(class_type, &tidy_object_handlers_attr, &retval, is_attr TSRMLS_CC);
+       return retval;
+       
+}
 
-       if(tidyParseString(TG(tdoc)->doc, input) < 0) {
-               php_error_docref(NULL TSRMLS_CC, E_WARNING, "[Tidy error] %s", TG(tdoc)->errbuf->bp);
-               RETURN_FALSE;
-       }
+static zend_object_value tidy_object_new_doc(zend_class_entry *class_type TSRMLS_DC)
+{
+       zend_object_value retval;
+       tidy_object_new(class_type, &tidy_object_handlers_doc, &retval, is_doc TSRMLS_CC);
+       return retval;
+       
+}
 
-       TG(tdoc)->parsed = TRUE;
-       RETURN_TRUE;
+static zend_object_value tidy_object_new_exception(zend_class_entry *class_type TSRMLS_DC)
+{
+       zend_object_value retval;
+       tidy_object_new(class_type, &tidy_object_handlers_exception, &retval, is_exception TSRMLS_CC);
+       return retval;
+       
 }
-/* }}} */
 
-/* {{{ proto string tidy_get_error_buffer([boolean detailed])
-   Return warnings and errors which occured parsing the specified document*/
-PHP_FUNCTION(tidy_get_error_buffer)
+static zend_class_entry *tidy_get_ce_node(zval *object TSRMLS_DC)
 {
-       zend_bool detailed = 0;
+       return tidy_ce_node;
+}
 
-       if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &detailed) == FAILURE) {
-               RETURN_FALSE;
-       }
+static zend_class_entry *tidy_get_ce_attr(zval *object TSRMLS_DC)
+{
+       return tidy_ce_attr;
+}
 
-       TIDY_PARSED_CHECK();
+static zend_class_entry *tidy_get_ce_doc(zval *object TSRMLS_DC)
+{
+       return tidy_ce_doc;
+}
 
-       if (detailed) {
-               tidyErrorSummary(TG(tdoc)->doc);
+static zval * tidy_instanciate(zend_class_entry *pce, zval *object TSRMLS_DC)
+{
+       if (!object) {
+               ALLOC_ZVAL(object);
        }
-
-       RETVAL_STRING(TG(tdoc)->errbuf->bp, 1);
-       tidyBufClear(TG(tdoc)->errbuf); 
+       Z_TYPE_P(object) = IS_OBJECT;
+       object_init_ex(object, pce);
+       object->refcount = 1;
+       object->is_ref = 1;
+       return object;
 }
-/* }}} */
 
-/* {{{ proto string tidy_get_output() 
-   Return a string representing the parsed tidy markup */
-PHP_FUNCTION(tidy_get_output)
+static int tidy_doc_cast_handler(zval *in, zval *out, int type, int free TSRMLS_DC)
 {
        TidyBuffer output = {0};
+       PHPTidyObj *obj;
 
-       if (ZEND_NUM_ARGS()) {
-               WRONG_PARAM_COUNT;
+       switch(type) {
+               case IS_LONG:
+                       ZVAL_LONG(out, 0);
+                       break;
+               case IS_DOUBLE:
+                       ZVAL_DOUBLE(out, 0);
+                       break;
+               case IS_BOOL:
+                       ZVAL_BOOL(out, TRUE);
+                       break;
+               case IS_STRING:
+                       obj = (PHPTidyObj *)zend_object_store_get_object(in TSRMLS_CC);
+                       tidySaveBuffer (obj->ptdoc->doc, &output);
+                       ZVAL_STRINGL(out, output.bp, output.size, TRUE);
+                       tidyBufFree(&output);
+                       break;
+               default:
+                       return FAILURE;
        }
-
-       TIDY_PARSED_CHECK();
-
-       tidySaveBuffer (TG(tdoc)->doc, &output);
-
-       RETVAL_STRING(output.bp, 1);
-
-       tidyBufFree(&output);
+       
+       return SUCCESS;
 }
-/* }}} */
 
-/* {{{ proto boolean tidy_parse_file(string file [, bool use_include_path])
-   Parse markup in file or URI */
-PHP_FUNCTION(tidy_parse_file)
+static int tidy_node_cast_handler(zval *in, zval *out, int type, int free TSRMLS_DC)
 {
-       char *inputfile;
-       int input_len;
-       zend_bool use_include_path = 0;
-       char *contents;
+       TidyBuffer buf = {0};
+       PHPTidyObj *obj;
 
-       if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &inputfile, &input_len) == FAILURE) {
+       switch(type) {
+               case IS_LONG:
+                       ZVAL_LONG(out, 0);
+                       break;
+               case IS_DOUBLE:
+                       ZVAL_DOUBLE(out, 0);
+                       break;
+               case IS_BOOL:
+                       ZVAL_BOOL(out, TRUE);
+                       break;
+               case IS_STRING:
+                       obj = (PHPTidyObj *)zend_object_store_get_object(in TSRMLS_CC);
+                       tidyNodeGetText(obj->ptdoc->doc, obj->node, &buf);
+                       buf.bp[buf.size-1] = '\0';
+                       ZVAL_STRINGL(out, buf.bp, buf.size, TRUE);
+                       tidyBufFree(&buf);
+                       break;
+               default:
+                       return FAILURE;
+       }
+       
+       return SUCCESS;
+}
+
+static void tidy_doc_update_properties(PHPTidyObj *obj TSRMLS_DC)
+{
+
+       zval *temp;
+               
+       if(obj->ptdoc->parsed) {
+               TidyBuffer output = {0};
+                       
+               tidySaveBuffer (obj->ptdoc->doc, &output);
+               
+               if(output.size) {
+                       MAKE_STD_ZVAL(temp);
+                       ZVAL_STRINGL(temp, output.bp, output.size, TRUE);
+                       zend_hash_update(obj->std.properties, "value", sizeof("value"), (void *)&temp, sizeof(zval *), NULL);
+                       
+               }
+               
+               tidyBufFree(&output);
+               
+               if(obj->ptdoc->errbuf->size) {
+                       MAKE_STD_ZVAL(temp);
+                       ZVAL_STRINGL(temp, obj->ptdoc->errbuf->bp, obj->ptdoc->errbuf->size, TRUE);
+                       zend_hash_update(obj->std.properties, "error_buf", sizeof("error_buf"), (void *)&temp, sizeof(zval *), NULL);
+               }
+               
+       }
+               
+}
+
+
+static void tidy_globals_ctor(zend_tidy_globals *g TSRMLS_DC)
+{
+}
+
+/*
+static void tidy_globals_dtor(zend_tidy_globals *g TSRMLS_DC)
+{
+}
+*/
+
+static void tidy_add_default_properities(PHPTidyObj *obj, tidy_obj_type type TSRMLS_DC)
+{
+       
+       TidyBuffer buf;
+       TidyAttr        tempattr;
+       TidyNode        tempnode;
+       zval *attribute, *children, *temp;
+       PHPTidyObj *newobj;
+       
+       switch(type) {
+               
+               case is_node:
+                       
+                       memset(&buf, 0, sizeof(buf));
+                       tidyNodeGetText(obj->ptdoc->doc, obj->node, &buf);
+                       buf.bp[buf.size-1] = '\0';
+                       ADD_PROPERITY_STRING(obj->std.properties, value, buf.bp);
+                       tidyBufFree(&buf);
+
+                       ADD_PROPERITY_STRING(obj->std.properties, name, tidyNodeGetName(obj->node));
+                       ADD_PROPERITY_LONG(obj->std.properties, type, tidyNodeGetType(obj->node));
+                       
+                       switch(tidyNodeGetType(obj->node)) {
+                               
+                               case TidyNode_Root:
+                               case TidyNode_DocType:
+                               case TidyNode_Text:
+                               case TidyNode_Comment:
+                                       break;
+                               default:
+                                       ADD_PROPERITY_LONG(obj->std.properties, id, tidyNodeGetId(obj->node));
+                       }
+                       
+                       
+                       tempattr = tidyAttrFirst(obj->node);
+                       MAKE_STD_ZVAL(attribute);
+                       
+                       if(tempattr) {
+                               char *name, *val;
+                               array_init(attribute);
+               
+                               do {
+                                       name = (char *)tidyAttrName(tempattr);
+                                       val = (char *)tidyAttrValue(tempattr);
+                                       if(name && val) {
+                                               add_assoc_string(attribute, name, val, TRUE);
+                                       }
+                               } while((tempattr = tidyAttrNext(tempattr)));
+                               
+                               
+                       } else {
+                               ZVAL_NULL(attribute);
+                       }
+                       zend_hash_update(obj->std.properties, "attribute", sizeof("attribute"), (void *)&attribute, sizeof(zval *), NULL);
+                       
+                       tempnode = tidyGetChild(obj->node);
+               
+                       MAKE_STD_ZVAL(children);
+                       if(tempnode) {
+                               array_init(children);
+                               do {
+                                       
+                                       MAKE_STD_ZVAL(temp);
+                                       tidy_instanciate(tidy_ce_node, temp TSRMLS_CC);
+                                       newobj = (PHPTidyObj *) zend_object_store_get_object(temp TSRMLS_CC);
+                                       newobj->attr = NULL;
+                                       newobj->node = tempnode;
+                                       newobj->type = is_node;
+                                       newobj->ptdoc = obj->ptdoc;
+                                       newobj->ptdoc->ref_count++;
+                                       
+                                       tidy_add_default_properities(newobj, is_node TSRMLS_DC);
+                                       add_next_index_zval(children, temp);
+                                                                       
+                               } while((tempnode = tidyGetNext(tempnode)));
+                               
+                       } else {
+                               ZVAL_NULL(children);
+                       }
+                       
+                       zend_hash_update(obj->std.properties, "child", sizeof("child"), (void *)&children, sizeof(zval *), NULL);
+                       
+            break;
+               case is_attr:
+                       ADD_PROPERITY_STRING(obj->std.properties, name, tidyAttrName(obj->attr));
+                       ADD_PROPERITY_STRING(obj->std.properties, value, tidyAttrValue(obj->attr));
+                       ADD_PROPERITY_LONG(obj->std.properties, id, tidyAttrGetId(obj->attr));
+                       break;
+               
+               case is_doc:
+                       ADD_PROPERITY_NULL(obj->std.properties, error_buf);
+                       ADD_PROPERITY_NULL(obj->std.properties, value);
+                       break;
+               case is_exception:
+               default:
+                       break;
+       }
+}
+
+static void *php_tidy_get_opt_val(PHPTidyDoc *ptdoc, TidyOption opt, TidyOptionType *type TSRMLS_DC)
+{
+       *type = tidyOptGetType(opt);
+
+       switch (*type) {
+               case TidyString: {
+                       char *val = (char *) tidyOptGetValue(ptdoc->doc, tidyOptGetId(opt));
+                       if (val) {
+                               return (void *) estrdup(val);
+                       } else {
+                               return (void *) estrdup("");
+                       }
+               }
+                       break;
+
+               case TidyInteger:
+                       return (void *) tidyOptGetInt(ptdoc->doc, tidyOptGetId(opt));
+                       break;
+
+               case TidyBoolean:
+                       return (void *) tidyOptGetBool(ptdoc->doc, tidyOptGetId(opt));
+                       break;
+       }
+
+       /* should not happen */
+       return NULL;
+}
+
+static void php_tidy_create_node(INTERNAL_FUNCTION_PARAMETERS, tidy_base_nodetypes node)
+{
+       
+       zval *object = getThis();
+       PHPTidyObj *obj, *newobj;
+
+       if(object) {
+           
+               if(ZEND_NUM_ARGS()) {
+                       WRONG_PARAM_COUNT;
+               }
+
+       } else {
+               
+               if(zend_parse_method_parameters(1 TSRMLS_CC, NULL, "O", &object, tidy_ce_doc) == FAILURE) {
+                       RETURN_FALSE;
+               }
+               
+       }
+
+       obj = (PHPTidyObj *) zend_object_store_get_object(object TSRMLS_CC);
+
+       TIDY_PARSED_CHECK(obj);
+
+       tidy_instanciate(tidy_ce_node, return_value TSRMLS_CC);
+       newobj = (PHPTidyObj *) zend_object_store_get_object(return_value TSRMLS_CC);
+       newobj->attr = NULL;
+       newobj->type = is_node;
+       newobj->ptdoc = obj->ptdoc;
+       newobj->ptdoc->ref_count++;
+
+       switch(node) {
+               
+               case is_root_node:
+                       newobj->node = tidyGetRoot(newobj->ptdoc->doc);
+                       break;
+               case is_html_node:
+                       newobj->node = tidyGetHtml(newobj->ptdoc->doc);
+                       break;
+               case is_head_node:
+                       newobj->node = tidyGetHead(newobj->ptdoc->doc);
+                       break;
+               case is_body_node:
+                       newobj->node = tidyGetBody(newobj->ptdoc->doc);
+                       
+                       break;
+       }
+       
+       tidy_add_default_properities(newobj, is_node TSRMLS_CC);
+
+}
+
+static void php_tidy_parse_file(INTERNAL_FUNCTION_PARAMETERS)
+{
+       char *inputfile;
+       int input_len;
+       zend_bool use_include_path = 0;
+       char *contents;
+       
+       zend_bool is_object = FALSE;
+       
+       zval *object = getThis();
+       PHPTidyObj *obj;
+       
+       if(zend_parse_parameters(1 TSRMLS_CC, "s|b", &inputfile, &input_len, &use_include_path) == FAILURE) {
+               RETURN_FALSE;
+       }       
+       
+       if(object) {
+       
+               is_object = TRUE;
+               obj = (PHPTidyObj *)zend_object_store_get_object(object TSRMLS_CC);
+               
+               if(obj->ptdoc->parsed) { 
+                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot parse two documents with the same tidy instance"); 
+                       RETURN_FALSE; 
+               }
+               
+       } else {
+               
+               tidy_instanciate(tidy_ce_doc, return_value TSRMLS_CC);
+               obj = (PHPTidyObj *) zend_object_store_get_object(return_value TSRMLS_CC);
+
+       }
+       
+       if (!(contents = php_tidy_file_to_mem(inputfile, use_include_path TSRMLS_CC))) {
                RETURN_FALSE;
        }
+               
+       if(tidyParseString(obj->ptdoc->doc, contents) < 0) {
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "[Tidy error] %s", obj->ptdoc->errbuf->bp);
+               RETVAL_FALSE;
+       } else {
+                               
+               obj->ptdoc->parsed = TRUE;
+               tidy_doc_update_properties(obj TSRMLS_DC);
+               
+               if(is_object) {
+                       RETVAL_TRUE;
+               } 
+
+       }
+       
+       efree(contents);
+       
+}
+
+PHP_MINIT_FUNCTION(tidy)
+{
+       REGISTER_INI_ENTRIES();
+       REGISTER_TIDY_CLASS(doc,        NULL);
+       REGISTER_TIDY_CLASS(node,       NULL);
+       REGISTER_TIDY_CLASS(attr,               NULL);
+       REGISTER_TIDY_CLASS(exception, zend_exception_get_default());
+
+       tidy_object_handlers_doc.get_class_entry = tidy_get_ce_doc;
+       tidy_object_handlers_node.get_class_entry = tidy_get_ce_node;
+       tidy_object_handlers_attr.get_class_entry = tidy_get_ce_attr;
+       
+       tidy_object_handlers_doc.cast_object = tidy_doc_cast_handler;
+       tidy_object_handlers_node.cast_object = tidy_node_cast_handler;
+       
+       ZEND_INIT_MODULE_GLOBALS(tidy, tidy_globals_ctor, tidy_globals_dtor);
+
+       _php_tidy_register_tags(INIT_FUNC_ARGS_PASSTHRU);
+       _php_tidy_register_attributes(INIT_FUNC_ARGS_PASSTHRU);
+       _php_tidy_register_nodetypes(INIT_FUNC_ARGS_PASSTHRU);
+       
+       return SUCCESS;
+}
+
+
+PHP_MSHUTDOWN_FUNCTION(tidy)
+{
+       return SUCCESS;
+}
+
+PHP_RINIT_FUNCTION(tidy)
+{
+       if (INI_BOOL("tidy.clean_output") == TRUE) {
+               
+        if (php_start_ob_buffer_named("ob_tidyhandler", 0, 1 TSRMLS_CC) == FAILURE) {
+            zend_error(E_NOTICE, "Unable to use Tidy for output buffering.");
+        }
+    }
+
+       return SUCCESS;
+}
+
+
+
+PHP_RSHUTDOWN_FUNCTION(tidy)
+{
+       return SUCCESS;
+}
+
+
+PHP_MINFO_FUNCTION(tidy)
+{
+       php_info_print_table_start();
+       php_info_print_table_header(2, "tidy support", "enabled");
+       php_info_print_table_end();
+
+}
+
+TIDY_ATTR_METHOD(__construct)
+{
+}
+
+PHP_FUNCTION(ob_tidyhandler)
+{
+       char *input;
+       int input_len;
+       long mode; 
+       TidyBuffer output = {0}, errbuf = {0};
+       TidyDoc doc;
+       
+       if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &input, &input_len, &mode) == FAILURE) {
+               WRONG_PARAM_COUNT;
+       }
+
+       doc  = tidyCreate();
+       tidyBufInit(&errbuf);
+       tidyBufInit(&output);
+       
+       tidyOptSetBool(doc, TidyForceOutput, yes);
+       tidyOptSetBool(doc, TidyMark, no);
+       
+       if(tidySetErrorBuffer(doc, &errbuf) != 0) {
+               zend_error(E_ERROR, "Could not set Tidy error buffer");
+       }
+       
+       TIDY_SET_DEFAULT_CONFIG(doc);
+       
+       if(input_len > 1) {
+               if(tidyParseString(doc, input) < 0) {
+                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "[Tidy error] %s", errbuf.bp);
+               }
+               
+               if(tidyCleanAndRepair(doc) < 0) {
+                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "[Tidy error] %s", errbuf.bp);
+               }
+               
+               tidySaveBuffer (doc, &output);
+               RETVAL_STRING(output.bp, 1);
+       } else {
+               RETVAL_NULL();
+       }
+       
+       tidyRelease(doc);
+       tidyBufFree(&output);
+       tidyBufFree(&errbuf);
+}
+
+/* {{{ proto bool tidy_parse_string(string input)
+   Parse a document stored in a string */
+PHP_FUNCTION(tidy_parse_string)
+{
+       char *input;
+       int input_len;
+       
+       zend_bool is_object = FALSE;
+       
+       zval *object = getThis();
+       PHPTidyObj *obj;
+       
+       if(object) {
+           
+               
+               if(zend_parse_parameters(1 TSRMLS_CC, "s", &input, &input_len) == FAILURE) {
+                       RETURN_FALSE;
+               }
+       
+               is_object = TRUE;
+               obj = (PHPTidyObj *)zend_object_store_get_object(object TSRMLS_CC);
+               
+               if(obj->ptdoc->parsed) { 
+                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot parse two documents with the same tidy instance"); 
+                       RETURN_FALSE; 
+               }
+               
+       } else {
+               
+               if(zend_parse_parameters(1 TSRMLS_CC, "s", &input, &input_len) == FAILURE) {
+                       return;
+               }
+               
+               tidy_instanciate(tidy_ce_doc, return_value TSRMLS_CC);
+               obj = (PHPTidyObj *) zend_object_store_get_object(return_value TSRMLS_CC);
+
+       }
+               
+       if(tidyParseString(obj->ptdoc->doc, input) < 0) {
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "[Tidy error] %s", obj->ptdoc->errbuf->bp);
+               return;
+       }
+       
+       obj->ptdoc->parsed = TRUE;
+       
+       tidy_doc_update_properties(obj TSRMLS_DC);
+       
+       if(is_object) {
+               
+               RETURN_TRUE;
+               
+       }
+}
+/* }}} */
 
-       if (!(contents = php_tidy_file_to_mem(inputfile, use_include_path TSRMLS_CC))) {
-               RETURN_FALSE;
+/* {{{ proto string tidy_get_error_buffer([boolean detailed])
+   Return warnings and errors which occured parsing the specified document*/
+PHP_FUNCTION(tidy_get_error_buffer)
+{
+       zval *object = getThis();
+       PHPTidyObj *obj;
+       
+       if(object) {
+           
+               if(ZEND_NUM_ARGS()) {
+                       WRONG_PARAM_COUNT;
+               }
+       
+       } else {
+               
+               if(zend_parse_method_parameters(1 TSRMLS_CC, NULL, "O", &object, tidy_ce_doc) == FAILURE) {
+                       RETURN_FALSE;
+               }
+               
        }
        
-       if(tidyParseString(TG(tdoc)->doc, contents) < 0) {
-               php_error_docref(NULL TSRMLS_CC, E_WARNING, "[Tidy error] %s", TG(tdoc)->errbuf->bp);
-               RETVAL_FALSE;
+       obj = (PHPTidyObj *) zend_object_store_get_object(object TSRMLS_CC);
+       
+       RETURN_STRING(obj->ptdoc->errbuf->bp, 1);
+}
+/* }}} */
+
+/* {{{ proto string tidy_get_output() 
+   Return a string representing the parsed tidy markup */
+PHP_FUNCTION(tidy_get_output)
+{
+       zval *object = getThis();
+       PHPTidyObj *obj;
+       TidyBuffer output = {0};
+       
+       if(object) {
+           
+               if(ZEND_NUM_ARGS()) {
+                       WRONG_PARAM_COUNT;
+               }
+       
        } else {
-               TG(tdoc)->parsed = TRUE;
-               RETVAL_TRUE;
+               
+               if(zend_parse_method_parameters(1 TSRMLS_CC, NULL, "O", &object, tidy_ce_doc) == FAILURE) {
+                       RETURN_FALSE;
+               }
+               
        }
+       
+       obj = (PHPTidyObj *) zend_object_store_get_object(object TSRMLS_CC);
+       
+       TIDY_PARSED_CHECK(obj);
+       
+       tidySaveBuffer (obj->ptdoc->doc, &output);
+       
+       RETVAL_STRING(output.bp, 1);
+       
+       tidyBufFree(&output);
+}
+/* }}} */
 
-       efree(contents);
+/* {{{ proto boolean tidy_parse_file(string file [, bool use_include_path])
+   Parse markup in file or URI */
+PHP_FUNCTION(tidy_parse_file)
+{
+       php_tidy_parse_file(INTERNAL_FUNCTION_PARAM_PASSTHRU);
 }
 /* }}} */
 
@@ -468,16 +962,32 @@ PHP_FUNCTION(tidy_parse_file)
    Execute configured cleanup and repair operations on parsed markup */
 PHP_FUNCTION(tidy_clean_repair)
 {
-       if(ZEND_NUM_ARGS()) {
-               WRONG_PARAM_COUNT;
+       zval *object = getThis();
+       PHPTidyObj *obj;
+       
+       if(object) {
+           
+               if(ZEND_NUM_ARGS()) {
+                       WRONG_PARAM_COUNT;
+               }
+       
+       } else {
+               
+               if(zend_parse_method_parameters(1 TSRMLS_CC, NULL, "O", &object, tidy_ce_doc) == FAILURE) {
+                       RETURN_FALSE;
+               }
+               
        }
-
-       TIDY_PARSED_CHECK();
-
-       if (tidyCleanAndRepair(TG(tdoc)->doc) >= 0) {
+       
+       obj = (PHPTidyObj *) zend_object_store_get_object(object TSRMLS_CC);
+       
+       TIDY_PARSED_CHECK(obj);
+       if (tidyCleanAndRepair(obj->ptdoc->doc) >= 0) {
+               obj->ptdoc->repaired = TRUE;
+               tidy_doc_update_properties(obj TSRMLS_DC);
                RETURN_TRUE;
        }
-
+       
        RETURN_FALSE;
 }
 /* }}} */
@@ -486,7 +996,7 @@ PHP_FUNCTION(tidy_clean_repair)
    Repair a string using an optionally provided configuration file */
 PHP_FUNCTION(tidy_repair_string)
 {
-       php_tidy_quick_repair(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+       php_tidy_quick_repair(INTERNAL_FUNCTION_PARAM_PASSTHRU, FALSE);
 }
 /* }}} */
 
@@ -494,7 +1004,7 @@ PHP_FUNCTION(tidy_repair_string)
    Repair a file using an optionally provided configuration file */
 PHP_FUNCTION(tidy_repair_file)
 {
-       php_tidy_quick_repair(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
+       php_tidy_quick_repair(INTERNAL_FUNCTION_PARAM_PASSTHRU, TRUE);
 }
 /* }}} */
 
@@ -502,16 +1012,32 @@ PHP_FUNCTION(tidy_repair_file)
     Run configured diagnostics on parsed and repaired markup. */
 PHP_FUNCTION(tidy_diagnose)
 {
-       if(ZEND_NUM_ARGS()) {
-               WRONG_PARAM_COUNT;
+       zval *object = getThis();
+       PHPTidyObj *obj;
+       
+       if(object) {
+           
+               if(ZEND_NUM_ARGS()) {
+                       WRONG_PARAM_COUNT;
+               }
+       
+       } else {
+               
+               if(zend_parse_method_parameters(1 TSRMLS_CC, NULL, "O", &object, tidy_ce_doc) == FAILURE) {
+                       RETURN_FALSE;
+               }
+               
        }
-
-       TIDY_PARSED_CHECK();
-
-       if (tidyRunDiagnostics(TG(tdoc)->doc) >= 0) {
+       
+       obj = (PHPTidyObj *) zend_object_store_get_object(object TSRMLS_CC);
+       
+       TIDY_PARSED_REPAIR_CHECK(obj);
+       
+       if (tidyRunDiagnostics(obj->ptdoc->doc) >= 0) {
+               tidy_doc_update_properties(obj TSRMLS_DC);
                RETURN_TRUE;
        }
-
+       
        RETURN_FALSE;    
 }
 /* }}} */
@@ -523,58 +1049,63 @@ PHP_FUNCTION(tidy_get_release)
        if(ZEND_NUM_ARGS()) {
                WRONG_PARAM_COUNT;
        }
-
+       
        RETURN_STRING((char *)tidyReleaseDate(), 1);    
 }
 /* }}} */
 
-/* {{{ proto string tidy_reset_config()
-    Restore Tidy configuration to default values */
-PHP_FUNCTION(tidy_reset_config)
-{
-       if(ZEND_NUM_ARGS()) {
-               WRONG_PARAM_COUNT;
-       }
-
-       RETURN_BOOL(tidyOptResetToSnapshot(TG(tdoc)->doc));
-}
-/* }}} */
-
 /* {{{ proto array tidy_get_config()
     Get current Tidy configuarion */
 PHP_FUNCTION(tidy_get_config)
 {
-       TidyIterator itOpt = tidyGetOptionList(TG(tdoc)->doc);
+       TidyIterator itOpt;
        char *opt_name;
        void *opt_value;
        TidyOptionType optt;
-
-       if(ZEND_NUM_ARGS()) {
-               WRONG_PARAM_COUNT;
+       
+       zval *object = getThis();
+       PHPTidyObj *obj;
+       
+       if(object) {
+           
+               if(ZEND_NUM_ARGS()) {
+                       WRONG_PARAM_COUNT;
+               }
+       
+       } else {
+               
+               if(zend_parse_method_parameters(1 TSRMLS_CC, NULL, "O", &object, tidy_ce_doc) == FAILURE) {
+                       RETURN_FALSE;
+               }
+               
        }
-
+       
+       obj = (PHPTidyObj *) zend_object_store_get_object(object TSRMLS_CC);
+       
+       itOpt = tidyGetOptionList(obj->ptdoc->doc);
+       
        array_init(return_value);
-
+       
        while (itOpt) {
-               TidyOption opt = tidyGetNextOption(TG(tdoc)->doc, &itOpt);
-
+               TidyOption opt = tidyGetNextOption(obj->ptdoc->doc, &itOpt);
+       
                opt_name = (char *)tidyOptGetName(opt);
-               opt_value = php_tidy_get_opt_val(opt, &optt TSRMLS_CC);
+               opt_value = php_tidy_get_opt_val(obj->ptdoc, opt, &optt TSRMLS_CC);
                switch (optt) {
                        case TidyString:
                                add_assoc_string(return_value, opt_name, (char*)opt_value, 0);
                                break;
-
+       
                        case TidyInteger:
                                add_assoc_long(return_value, opt_name, (long)opt_value);
                                break;
-
+       
                        case TidyBoolean:
                                add_assoc_bool(return_value, opt_name, (long)opt_value);
                                break;
                }
        }
-
+       
        return;
 }
 /* }}} */
@@ -584,11 +1115,26 @@ PHP_FUNCTION(tidy_get_config)
     Get status of specfied document. */
 PHP_FUNCTION(tidy_get_status)
 {
-       if(ZEND_NUM_ARGS()) {
-               WRONG_PARAM_COUNT;
+       zval *object = getThis();
+       PHPTidyObj *obj;
+       
+       if(object) {
+           
+               if(ZEND_NUM_ARGS()) {
+                       WRONG_PARAM_COUNT;
+               }
+       
+       } else {
+               
+               if(zend_parse_method_parameters(1 TSRMLS_CC, NULL, "O", &object, tidy_ce_doc) == FAILURE) {
+                       RETURN_FALSE;
+               }
+               
        }
-
-       RETURN_LONG(tidyStatus(TG(tdoc)->doc));
+       
+       obj = (PHPTidyObj *) zend_object_store_get_object(object TSRMLS_CC);
+       
+       RETURN_LONG(tidyStatus(obj->ptdoc->doc));
 }
 /* }}} */
 
@@ -596,13 +1142,28 @@ PHP_FUNCTION(tidy_get_status)
     Get the Detected HTML version for the specified document. */
 PHP_FUNCTION(tidy_get_html_ver)
 {
-       if(ZEND_NUM_ARGS()) {
-               WRONG_PARAM_COUNT;
+       zval *object = getThis();
+       PHPTidyObj *obj;
+       
+       if(object) {
+           
+               if(ZEND_NUM_ARGS()) {
+                       WRONG_PARAM_COUNT;
+               }
+       
+       } else {
+               
+               if(zend_parse_method_parameters(1 TSRMLS_CC, NULL, "O", &object, tidy_ce_doc) == FAILURE) {
+                       RETURN_FALSE;
+               }
+               
        }
-
-       TIDY_PARSED_CHECK();
-
-       RETURN_LONG(tidyDetectedHtmlVersion(TG(tdoc)->doc));
+       
+       obj = (PHPTidyObj *) zend_object_store_get_object(object TSRMLS_CC);
+       
+       TIDY_PARSED_CHECK(obj);
+       
+       RETURN_LONG(tidyDetectedHtmlVersion(obj->ptdoc->doc));
 }
 /* }}} */
 
@@ -610,13 +1171,28 @@ PHP_FUNCTION(tidy_get_html_ver)
     Indicates if the document is a XHTML document. */
 PHP_FUNCTION(tidy_is_xhtml)
 {
-       if(ZEND_NUM_ARGS()) {
-               WRONG_PARAM_COUNT;
+       zval *object = getThis();
+       PHPTidyObj *obj;
+       
+       if(object) {
+           
+               if(ZEND_NUM_ARGS()) {
+                       WRONG_PARAM_COUNT;
+               }
+       
+       } else {
+               
+               if(zend_parse_method_parameters(1 TSRMLS_CC, NULL, "O", &object, tidy_ce_doc) == FAILURE) {
+                       RETURN_FALSE;
+               }
+               
        }
-
-       TIDY_PARSED_CHECK();
-
-       RETURN_BOOL(tidyDetectedXhtml(TG(tdoc)->doc));
+       
+       obj = (PHPTidyObj *) zend_object_store_get_object(object TSRMLS_CC);
+       
+       TIDY_PARSED_CHECK(obj);
+       
+       RETURN_BOOL(tidyDetectedXhtml(obj->ptdoc->doc));
 }
 /* }}} */
 
@@ -624,13 +1200,28 @@ PHP_FUNCTION(tidy_is_xhtml)
     Indicates if the document is a generic (non HTML/XHTML) XML document. */
 PHP_FUNCTION(tidy_is_xml)
 {
-       if(ZEND_NUM_ARGS()) {
-               WRONG_PARAM_COUNT;
+       zval *object = getThis();
+       PHPTidyObj *obj;
+       
+       if(object) {
+           
+               if(ZEND_NUM_ARGS()) {
+                       WRONG_PARAM_COUNT;
+               }
+       
+       } else {
+               
+               if(zend_parse_method_parameters(1 TSRMLS_CC, NULL, "O", &object, tidy_ce_doc) == FAILURE) {
+                       RETURN_FALSE;
+               }
+               
        }
-
-       TIDY_PARSED_CHECK();
-
-       RETURN_BOOL(tidyDetectedGenericXml(TG(tdoc)->doc));
+       
+       obj = (PHPTidyObj *) zend_object_store_get_object(object TSRMLS_CC);
+       
+       TIDY_PARSED_CHECK(obj);
+       
+       RETURN_BOOL(tidyDetectedGenericXml(obj->ptdoc->doc));
 }
 /* }}} */
 
@@ -638,13 +1229,28 @@ PHP_FUNCTION(tidy_is_xml)
     Returns the Number of Tidy errors encountered for specified document. */
 PHP_FUNCTION(tidy_error_count)
 {
-       if(ZEND_NUM_ARGS()) {
-               WRONG_PARAM_COUNT;
+       zval *object = getThis();
+       PHPTidyObj *obj;
+       
+       if(object) {
+           
+               if(ZEND_NUM_ARGS()) {
+                       WRONG_PARAM_COUNT;
+               }
+       
+       } else {
+               
+               if(zend_parse_method_parameters(1 TSRMLS_CC, NULL, "O", &object, tidy_ce_doc) == FAILURE) {
+                       RETURN_FALSE;
+               }
+               
        }
-
-       TIDY_PARSED_CHECK();
-
-       RETURN_LONG(tidyErrorCount(TG(tdoc)->doc));
+       
+       obj = (PHPTidyObj *) zend_object_store_get_object(object TSRMLS_CC);
+       
+       TIDY_PARSED_CHECK(obj);
+       
+       RETURN_LONG(tidyErrorCount(obj->ptdoc->doc));
 }
 /* }}} */
 
@@ -652,13 +1258,28 @@ PHP_FUNCTION(tidy_error_count)
     Returns the Number of Tidy warnings encountered for specified document. */
 PHP_FUNCTION(tidy_warning_count)
 {
-       if(ZEND_NUM_ARGS()) {
-               WRONG_PARAM_COUNT;
+       zval *object = getThis();
+       PHPTidyObj *obj;
+       
+       if(object) {
+           
+               if(ZEND_NUM_ARGS()) {
+                       WRONG_PARAM_COUNT;
+               }
+       
+       } else {
+               
+               if(zend_parse_method_parameters(1 TSRMLS_CC, NULL, "O", &object, tidy_ce_doc) == FAILURE) {
+                       RETURN_FALSE;
+               }
+               
        }
-
-       TIDY_PARSED_CHECK();
-
-       RETURN_LONG(tidyWarningCount(TG(tdoc)->doc));
+       
+       obj = (PHPTidyObj *) zend_object_store_get_object(object TSRMLS_CC);
+       
+       TIDY_PARSED_CHECK(obj);
+       
+       RETURN_LONG(tidyWarningCount(obj->ptdoc->doc));
 }
 /* }}} */
 
@@ -666,13 +1287,28 @@ PHP_FUNCTION(tidy_warning_count)
     Returns the Number of Tidy accessibility warnings encountered for specified document. */
 PHP_FUNCTION(tidy_access_count)
 {
-       if(ZEND_NUM_ARGS()) {
-               WRONG_PARAM_COUNT;
+       zval *object = getThis();
+       PHPTidyObj *obj;
+       
+       if(object) {
+           
+               if(ZEND_NUM_ARGS()) {
+                       WRONG_PARAM_COUNT;
+               }
+       
+       } else {
+               
+               if(zend_parse_method_parameters(1 TSRMLS_CC, NULL, "O", &object, tidy_ce_doc) == FAILURE) {
+                       RETURN_FALSE;
+               }
+               
        }
-
-       TIDY_PARSED_CHECK();
-
-       RETURN_LONG(tidyAccessWarningCount(TG(tdoc)->doc));     
+       
+       obj = (PHPTidyObj *) zend_object_store_get_object(object TSRMLS_CC);
+       
+       TIDY_PARSED_CHECK(obj);
+       
+       RETURN_LONG(tidyAccessWarningCount(obj->ptdoc->doc));   
 }
 /* }}} */
 
@@ -680,13 +1316,28 @@ PHP_FUNCTION(tidy_access_count)
     Returns the Number of Tidy configuration errors encountered for specified document. */
 PHP_FUNCTION(tidy_config_count)
 {
-       if(ZEND_NUM_ARGS()) {
-               WRONG_PARAM_COUNT;
+       zval *object = getThis();
+       PHPTidyObj *obj;
+       
+       if(object) {
+           
+               if(ZEND_NUM_ARGS()) {
+                       WRONG_PARAM_COUNT;
+               }
+       
+       } else {
+               
+               if(zend_parse_method_parameters(1 TSRMLS_CC, NULL, "O", &object, tidy_ce_doc) == FAILURE) {
+                       RETURN_FALSE;
+               }
+               
        }
-
-       TIDY_PARSED_CHECK();
-
-       RETURN_LONG(tidyConfigErrorCount(TG(tdoc)->doc));       
+       
+       obj = (PHPTidyObj *) zend_object_store_get_object(object TSRMLS_CC);
+       
+       TIDY_PARSED_CHECK(obj);
+       
+       RETURN_LONG(tidyConfigErrorCount(obj->ptdoc->doc));     
 }
 /* }}} */
 
@@ -696,19 +1347,33 @@ PHP_FUNCTION(tidy_load_config)
 {
        char *filename;
        int filename_len;
-
-       if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
-               RETURN_FALSE;
+       
+       zval *object = getThis();
+       PHPTidyObj *obj;
+       
+       if(object) {
+           
+               if(zend_parse_parameters(1 TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
+                       RETURN_FALSE;
+               }
+       
+       } else {
+               
+               if(zend_parse_method_parameters(1 TSRMLS_CC, NULL, "Os", &object, tidy_ce_doc, &filename, &filename_len) == FAILURE) {
+                       RETURN_FALSE;
+               }
+               
        }
-
+       
        TIDY_SAFE_MODE_CHECK(filename);
-
-       if(tidyLoadConfig(TG(tdoc)->doc, filename) < 0) {
+       
+       obj = (PHPTidyObj *) zend_object_store_get_object(object TSRMLS_CC);
+               
+       if(tidyLoadConfig(obj->ptdoc->doc, filename) < 0) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not load configuration file '%s'", filename);
                RETURN_FALSE;
        }
-
-       TG(used) = 1;
+       
        RETURN_TRUE;
 }
 /* }}} */
@@ -718,21 +1383,37 @@ PHP_FUNCTION(tidy_load_config)
 PHP_FUNCTION(tidy_load_config_enc)
 {
        char *filename, *encoding;
-       int enc_len, file_len;
-
-       if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &filename, &file_len, &encoding, &enc_len) == FAILURE) {
-               RETURN_FALSE;
+       int file_len, enc_len;
+       
+       zval *object = getThis();
+       PHPTidyObj *obj;
+       
+       if(object) {
+           
+               if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &filename, &file_len, &encoding, &enc_len) == FAILURE) {
+                       RETURN_FALSE;
+               }
+       
+       } else {
+               
+               if(zend_parse_method_parameters(1 TSRMLS_CC, NULL, "Oss", &object, tidy_ce_doc,
+                                                                               &filename, &file_len, &encoding, &enc_len) == FAILURE) {
+                       RETURN_FALSE;
+               }
+               
        }
-
+       
        TIDY_SAFE_MODE_CHECK(filename);
-
-       if(tidyLoadConfigEnc(TG(tdoc)->doc, filename, encoding) < 0) {
+       
+       obj = (PHPTidyObj *) zend_object_store_get_object(object TSRMLS_CC);
+               
+       if(tidyLoadConfigEnc(obj->ptdoc->doc, filename, encoding) < 0) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not load configuration file '%s' using encoding '%s'", filename, encoding);
                RETURN_FALSE;
        }
-
-       TG(used) = 1;
+       
        RETURN_TRUE;
+       
 }
 /* }}} */
 
@@ -742,41 +1423,165 @@ PHP_FUNCTION(tidy_load_config_enc)
     utf16be, utf16, big5 and shiftjis. */
 PHP_FUNCTION(tidy_set_encoding)
 {
+       zval *object = getThis();
+       PHPTidyObj *obj;
        char *encoding;
        int enc_len;
-
-       if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &encoding, &enc_len) == FAILURE) {
-               RETURN_FALSE;
+       
+       if(object) {
+           
+               if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &encoding, &enc_len) == FAILURE) {
+                       RETURN_FALSE;
+               }
+       
+       } else {
+               
+               if(zend_parse_method_parameters(1 TSRMLS_CC, NULL, "Os", &object, tidy_ce_doc, &encoding, &enc_len) == FAILURE) {
+                       RETURN_FALSE;
+               }
+               
        }
-
-       if(tidySetCharEncoding(TG(tdoc)->doc, encoding) < 0) {
+       
+       obj = (PHPTidyObj *) zend_object_store_get_object(object TSRMLS_CC);
+               
+       if(tidySetCharEncoding(obj->ptdoc->doc, encoding) < 0) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not set encoding '%s'", encoding);
                RETURN_FALSE;
        }
-
-       TG(used) = 1;
+       
        RETURN_TRUE;
 }
 /* }}} */
+   
+/* {{{ proto boolean tidy_snapshot_config()
+   Take a snapshot of the configuration for this document so it can be modified
+   and later restored. */
+PHP_FUNCTION(tidy_snapshot_config)
+{
+       zval *object = getThis();
+       PHPTidyObj *obj;
+       
+       if(object) {
+           
+               if(ZEND_NUM_ARGS()) {
+                       WRONG_PARAM_COUNT;
+               }
+       
+       } else {
+               
+               if(zend_parse_method_parameters(1 TSRMLS_CC, NULL, "O", &object, tidy_ce_doc) == FAILURE) {
+                       RETURN_FALSE;
+               }
+               
+       }
+
+       obj = (PHPTidyObj *) zend_object_store_get_object(object TSRMLS_CC);
+       
+       if(tidyOptSnapshot(obj->ptdoc->doc)) {
+               RETURN_TRUE;
+       } else {
+               RETURN_FALSE;
+       }
+}
+
+/* {{{ proto boolean tidy_restore_config()
+   Restore the configuration for the document to the last snapshot */
+PHP_FUNCTION(tidy_restore_config)
+{
+       zval *object = getThis();
+       PHPTidyObj *obj;
+       
+       if(object) {
+           
+               if(ZEND_NUM_ARGS()) {
+                       WRONG_PARAM_COUNT;
+               }
+       
+       } else {
+               
+               if(zend_parse_method_parameters(1 TSRMLS_CC, NULL, "O", &object, tidy_ce_doc) == FAILURE) {
+                       RETURN_FALSE;
+               }
+               
+       }
 
+       obj = (PHPTidyObj *) zend_object_store_get_object(object TSRMLS_CC);
+       
+       if(tidyOptResetToSnapshot(obj->ptdoc->doc)) {
+               RETURN_TRUE;
+       } else {
+               RETURN_FALSE;
+       }
+}
+
+/* {{{ proto boolean tidy_restore_config(boolean ignore_default)
+   Reset the configuration for the document to default config */
+PHP_FUNCTION(tidy_reset_config)
+{
+       zval *object = getThis();
+       PHPTidyObj *obj;
+       
+       if(object) {
+           
+               if(ZEND_NUM_ARGS()) {
+                       WRONG_PARAM_COUNT;
+               }
+       
+       } else {
+               
+               if(zend_parse_method_parameters(1 TSRMLS_CC, NULL, "O", &object, tidy_ce_doc) == FAILURE) {
+                       RETURN_FALSE;
+               }
+               
+       }
+
+       obj = (PHPTidyObj *) zend_object_store_get_object(object TSRMLS_CC);
+       
+       if(tidyOptResetAllToDefault(obj->ptdoc->doc)) {
+               if (TG(default_config) && TG(default_config)[0]) { 
+                       if (tidyLoadConfig(obj->ptdoc->doc, TG(default_config)) < 0) { 
+                               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to load Tidy configuration file at '%s'.", TG(default_config));
+                               RETURN_FALSE;
+                       } 
+               }
+               RETURN_TRUE;
+       } else {
+               RETURN_FALSE;
+       }
+}
+       
 /* {{{ proto boolean tidy_save_config(string filename)
     Save current settings to named file. Only non-default values are written. */
 PHP_FUNCTION(tidy_save_config)
 {
+       zval *object = getThis();
+       PHPTidyObj *obj;
        char *filename;
        int file_len;
-
-       if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &file_len) == FAILURE) {
-               RETURN_FALSE;
+       
+       if(object) {
+           
+               if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &file_len) == FAILURE) {
+                       RETURN_FALSE;
+               }
+       
+       } else {
+               
+               if(zend_parse_method_parameters(1 TSRMLS_CC, NULL, "Os", &object, tidy_ce_doc, &filename, &file_len) == FAILURE) {
+                       RETURN_FALSE;
+               }
+               
        }
-
+       
        TIDY_SAFE_MODE_CHECK(filename);
-
-       if(tidyOptSaveFile(TG(tdoc)->doc, filename) < 0) {
+       
+       obj = (PHPTidyObj *) zend_object_store_get_object(object TSRMLS_CC);
+       
+       if(tidyOptSaveFile(obj->ptdoc->doc, filename) < 0) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not write tidy configuration file '%s'", filename);
                RETURN_FALSE;
        }
-
+       
        RETURN_TRUE;
 }
 /* }}} */
@@ -785,42 +1590,61 @@ PHP_FUNCTION(tidy_save_config)
     Updates the configuration settings for the specified tidy document. */
 PHP_FUNCTION(tidy_setopt)
 {
+       zval *object = getThis();
+       PHPTidyObj *obj;
+       
        zval *value;
        char *optname;
        int optname_len;
        TidyOption opt;
-
-       if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &optname, &optname_len, &value) == FAILURE) {
-               RETURN_FALSE;
+       
+       if(object) {
+           
+               if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &optname, &optname_len, &value) == FAILURE) {
+                       RETURN_FALSE;
+               }
+       
+       } else {
+               
+               if(zend_parse_method_parameters(1 TSRMLS_CC, NULL, "Osz", &object, tidy_ce_doc, &optname, &optname_len, &value) == FAILURE) {
+                       RETURN_FALSE;
+               }
+               
        }
 
-       opt = tidyGetOptionByName(TG(tdoc)->doc, optname);
+       obj = (PHPTidyObj *) zend_object_store_get_object(object TSRMLS_CC);
+
+       opt = tidyGetOptionByName(obj->ptdoc->doc, optname);
+       
        if (!opt) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown Tidy Configuration Option '%s'", optname);
                RETURN_FALSE;
        }
-           
+       
+       if(tidyOptIsReadOnly(opt)) {
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Attempted to set read-only option '%s'", optname);
+               RETURN_FALSE;
+       }
+       
        switch(tidyOptGetType(opt)) {
+               
                case TidyString:
                        convert_to_string_ex(&value);
-                       if(tidyOptSetValue(TG(tdoc)->doc, tidyOptGetId(opt), Z_STRVAL_P(value))) {
-                               TG(used) = 1;
+                       if(tidyOptSetValue(obj->ptdoc->doc, tidyOptGetId(opt), Z_STRVAL_P(value))) {
                                RETURN_TRUE;
                        } 
                        break;
                        
                case TidyInteger:
                        convert_to_long_ex(&value);
-                       if(tidyOptSetInt(TG(tdoc)->doc, tidyOptGetId(opt), Z_LVAL_P(value))) {
-                               TG(used) = 1;
+                       if(tidyOptSetInt(obj->ptdoc->doc, tidyOptGetId(opt), Z_LVAL_P(value))) {
                                RETURN_TRUE;
                        } 
                        break;
                        
                case TidyBoolean:
                        convert_to_long_ex(&value);
-                       if(tidyOptSetBool(TG(tdoc)->doc,  tidyOptGetId(opt), Z_LVAL_P(value))) {
-                               TG(used) = 1;
+                       if(tidyOptSetBool(obj->ptdoc->doc,  tidyOptGetId(opt), Z_LVAL_P(value))) {
                                RETURN_TRUE;
                        } 
                        break;
@@ -829,206 +1653,80 @@ PHP_FUNCTION(tidy_setopt)
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to determine type of Tidy configuration constant to set");
                        break;
        }
-       RETURN_FALSE;
-}
-/* }}} */
-
-/* {{{ proto mixed tidy_getopt(string option)
-    Returns the value of the specified configuration option for the tidy document. */
-PHP_FUNCTION(tidy_getopt)
-{
-       char *optname;
-       void *optval;
-       int optname_len;
-       TidyOption opt;
-       TidyOptionType optt;
-           
-       if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &optname, &optname_len) == FAILURE) {
-               RETURN_FALSE;
-       }
-
-       opt = tidyGetOptionByName(TG(tdoc)->doc, optname);
-       if (!opt) {
-               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown Tidy Configuration Option '%s'", optname);
-               RETURN_FALSE;
-       }
-           
-       optval = php_tidy_get_opt_val(opt, &optt TSRMLS_CC);
-       switch (optt) {
-               case TidyString:
-                       RETVAL_STRING((char *)optval, 0);
-                       break;
-
-               case TidyInteger:
-                       RETURN_LONG((long)optval);
-                       break;
-
-               case TidyBoolean:
-                       if (optval) {
-                               RETURN_TRUE;
-                       } else {
-                               RETURN_NULL();
-                       }
-                       break;
-                           
-               default:
-                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to determine type of Tidy configuration constant to get");
-                       break;
-       }
-
-       RETURN_FALSE;
-}
-/* }}} */
-   
-#ifdef ZEND_ENGINE_2
-static void tidy_object_dtor(void *object, zend_object_handle handle TSRMLS_DC)
-{
-       PHPTidyObj *intern = (PHPTidyObj *)object;
-
-       zend_hash_destroy(intern->std.properties);
-       FREE_HASHTABLE(intern->std.properties);
-       
-       efree(object);
-}
-
-static void tidy_object_new(zend_class_entry *class_type, zend_object_handlers *handlers, zend_object_value *retval TSRMLS_DC)
-{
-       PHPTidyObj *intern;
-       zval *tmp;
-
-       intern = emalloc(sizeof(PHPTidyObj));
-       memset(intern, 0, sizeof(PHPTidyObj));
-       intern->std.ce = class_type;
-
-       ALLOC_HASHTABLE(intern->std.properties);
-       zend_hash_init(intern->std.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
-       zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
-
-       retval->handle = zend_objects_store_put(intern, tidy_object_dtor, NULL TSRMLS_CC);
-       retval->handlers = handlers;
-}
-
-static zend_object_value tidy_object_new_node(zend_class_entry *class_type TSRMLS_DC)
-{
-       zend_object_value retval;
-       tidy_object_new(class_type, &tidy_object_handlers_node, &retval TSRMLS_CC);
-       return retval;
-}
-
-static zend_object_value tidy_object_new_attr(zend_class_entry *class_type TSRMLS_DC)
-{
-       zend_object_value retval;
-       tidy_object_new(class_type, &tidy_object_handlers_attr, &retval TSRMLS_CC);
-       return retval;
-       
-}
-
-static zend_object_value tidy_object_new_exception(zend_class_entry *class_type TSRMLS_DC)
-{
-       zend_object_value retval;
-       tidy_object_new(class_type, &tidy_object_handlers_exception, &retval TSRMLS_CC);
-       return retval;
        
+       RETURN_FALSE;
 }
+/* }}} */
 
-static zend_class_entry *tidy_get_ce_node(zval *object TSRMLS_DC)
-{
-       return tidy_ce_node;
-}
-
-static zend_class_entry *tidy_get_ce_attr(zval *object TSRMLS_DC)
-{
-       return tidy_ce_attr;
-}
-
-static zval * tidy_instanciate(zend_class_entry *pce, zval *object TSRMLS_DC)
+/* {{{ proto mixed tidy_getopt(string option)
+    Returns the value of the specified configuration option for the tidy document. */
+PHP_FUNCTION(tidy_getopt)
 {
-       if (!object) {
-               ALLOC_ZVAL(object);
+       zval *object = getThis();
+       PHPTidyObj *obj;
+       char *optname;
+       void *optval;
+       int optname_len;
+       TidyOption opt;
+       TidyOptionType optt;
+       
+       if(object) {
+           
+               if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &optname, &optname_len) == FAILURE) {
+                       RETURN_FALSE;
+               }
+       
+       } else {
+               
+               if(zend_parse_method_parameters(1 TSRMLS_CC, NULL, "Os", &object, tidy_ce_doc, &optname, &optname_len) == FAILURE) {
+                       RETURN_FALSE;
+               }
+               
        }
-       Z_TYPE_P(object) = IS_OBJECT;
-       object_init_ex(object, pce);
-       object->refcount = 1;
-       object->is_ref = 1;
-       return object;
-}
 
-#define ADD_PROPERITY_STRING(_table, _key, _string) \
-       { \
-               zval *tmp; \
-               MAKE_STD_ZVAL(tmp); \
-               if(_string) { \
-                       ZVAL_STRING(tmp, (char *)_string, 1); \
-               } else { \
-                       ZVAL_EMPTY_STRING(tmp); \
-               } \
-               zend_hash_update(_table, #_key, sizeof(#_key), (void *)&tmp, sizeof(zval *), NULL); \
-       }
+       obj = (PHPTidyObj *) zend_object_store_get_object(object TSRMLS_CC);
+       
 
-#define ADD_PROPERITY_LONG(_table, _key, _long) \
-       { \
-               zval *tmp; \
-               MAKE_STD_ZVAL(tmp); \
-               ZVAL_LONG(tmp, _long); \
-               zend_hash_update(_table, #_key, sizeof(#_key), (void *)&tmp, sizeof(zval *), NULL); \
+       opt = tidyGetOptionByName(obj->ptdoc->doc, optname);
+       if (!opt) {
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown Tidy Configuration Option '%s'", optname);
+               RETURN_FALSE;
        }
+           
+       optval = php_tidy_get_opt_val(obj->ptdoc, opt, &optt TSRMLS_CC);
+       switch (optt) {
+               case TidyString:
+                       RETVAL_STRING((char *)optval, 0);
+                       break;
 
-static void tidy_add_default_properities(PHPTidyObj *obj, tidy_obj_type type TSRMLS_DC) {
-       
-       TidyBuffer buf;
-       
-       switch(type) {
-               
-               case is_node:
-                       memset(&buf, 0, sizeof(buf));
-                       tidyNodeGetText(TG(tdoc)->doc, obj->node, &buf);
-                       ADD_PROPERITY_STRING(obj->std.properties, value, buf.bp);
-                       tidyBufFree(&buf);
-
-/* fprintf(stderr, "type: %d\n",tidyNodeGetType(obj->node)); */
+               case TidyInteger:
+                       RETURN_LONG((long)optval);
+                       break;
 
-                       ADD_PROPERITY_STRING(obj->std.properties, name, tidyNodeGetName(obj->node));
-                       ADD_PROPERITY_LONG(obj->std.properties, type, tidyNodeGetType(obj->node));
-                       switch(tidyNodeGetType(obj->node)) {
-                               
-                               case TidyNode_Root:
-                               case TidyNode_DocType:
-                               case TidyNode_Text:
-                               case TidyNode_Comment:
-                                       break;
-                               default:
-                                       ADD_PROPERITY_LONG(obj->std.properties, id, tidyNodeGetId(obj->node));
+               case TidyBoolean:
+                       if (optval) {
+                               RETURN_TRUE;
+                       } else {
+                               RETURN_NULL();
                        }
-                       
-            break;
-               case is_attr:
-                       ADD_PROPERITY_STRING(obj->std.properties, name, tidyAttrName(obj->attr));
-                       ADD_PROPERITY_STRING(obj->std.properties, value, tidyAttrValue(obj->attr));
-                       ADD_PROPERITY_LONG(obj->std.properties, id, tidyAttrGetId(obj->attr));
+                       break;
+                           
+               default:
+                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to determine type of Tidy configuration constant to get");
                        break;
        }
-       
+
+       RETURN_FALSE;
+
 }
+/* }}} */
+
 /* {{{ proto TidyNode tidy_get_root()
     Returns a TidyNode Object representing the root of the tidy parse tree */
 PHP_FUNCTION(tidy_get_root)
 {
-       PHPTidyObj      *obj;
-       
-       if(ZEND_NUM_ARGS()) {
-               WRONG_PARAM_COUNT;
-       }
-
-       TIDY_PARSED_CHECK();
-       
-       tidy_instanciate(tidy_ce_node, return_value TSRMLS_CC);
-       obj = (PHPTidyObj *) zend_object_store_get_object(return_value TSRMLS_CC);
-       obj->node = tidyGetRoot(TG(tdoc)->doc);
-       obj->attr = NULL;
-       obj->type = is_node;
+       php_tidy_create_node(INTERNAL_FUNCTION_PARAM_PASSTHRU, is_root_node);
        
-       tidy_add_default_properities(obj, is_node TSRMLS_CC);
-               
 }
 /* }}} */
 
@@ -1036,21 +1734,7 @@ PHP_FUNCTION(tidy_get_root)
     Returns a TidyNode Object starting from the <HTML> tag of the tidy parse tree */
 PHP_FUNCTION(tidy_get_html)
 {
-       PHPTidyObj      *obj;
-       
-       if(ZEND_NUM_ARGS()) {
-               WRONG_PARAM_COUNT;
-       }
-
-       TIDY_PARSED_CHECK();
-       
-       tidy_instanciate(tidy_ce_node, return_value TSRMLS_CC);
-       obj = (PHPTidyObj *) zend_object_store_get_object(return_value TSRMLS_CC);
-       obj->node = tidyGetHtml(TG(tdoc)->doc);
-       obj->attr = NULL;
-       obj->type = is_node;
-       
-       tidy_add_default_properities(obj, is_node TSRMLS_CC);
+       php_tidy_create_node(INTERNAL_FUNCTION_PARAM_PASSTHRU, is_html_node);   
 }
 /* }}} */
 
@@ -1058,21 +1742,7 @@ PHP_FUNCTION(tidy_get_html)
     Returns a TidyNode Object starting from the <HEAD> tag of the tidy parse tree */
 PHP_FUNCTION(tidy_get_head)
 {
-       PHPTidyObj      *obj;
-       
-       if(ZEND_NUM_ARGS()) {
-               WRONG_PARAM_COUNT;
-       }
-
-       TIDY_PARSED_CHECK();
-       
-       tidy_instanciate(tidy_ce_node, return_value TSRMLS_CC);
-       obj = (PHPTidyObj *) zend_object_store_get_object(return_value TSRMLS_CC);
-       obj->node = tidyGetHead(TG(tdoc)->doc);
-       obj->attr = NULL;
-       obj->type = is_node;
-       
-       tidy_add_default_properities(obj, is_node TSRMLS_CC);
+       php_tidy_create_node(INTERNAL_FUNCTION_PARAM_PASSTHRU, is_head_node);
 }
 /* }}} */
 
@@ -1080,87 +1750,29 @@ PHP_FUNCTION(tidy_get_head)
     Returns a TidyNode Object starting from the <BODY> tag of the tidy parse tree */
 PHP_FUNCTION(tidy_get_body)
 {
-       PHPTidyObj      *obj;
-       
-       if(ZEND_NUM_ARGS()) {
-               WRONG_PARAM_COUNT;
-       }
-
-       TIDY_PARSED_CHECK();
-       
-       tidy_instanciate(tidy_ce_node, return_value TSRMLS_CC);
-       obj = (PHPTidyObj *) zend_object_store_get_object(return_value TSRMLS_CC);
-       obj->node = tidyGetBody(TG(tdoc)->doc);
-       obj->attr = NULL;
-       obj->type = is_node;
-       
-       tidy_add_default_properities(obj, is_node TSRMLS_CC);
+       php_tidy_create_node(INTERNAL_FUNCTION_PARAM_PASSTHRU, is_body_node);
 }
 /* }}} */
 
 /* {{{ proto void tidy_node::tidy_node()
    Constructor. */
-PHP_NODE_METHOD(__construct)
-{
-}
-/* }}} */
-
-/* {{{ proto tidy_attr tidy_node::attributes()
-   Returns an array of attribute objects for node */
-PHP_NODE_METHOD(attributes)
-{
-       TidyAttr        tempattr;
-       zval *object;
-       PHPTidyObj      *objtemp;
-       GET_THIS_CONTAINER();
-       
-       tempattr = tidyAttrFirst(obj->node);
-                       
-       if(tempattr) {
-               array_init(return_value);
-               
-               do {
-                       
-                       MAKE_STD_ZVAL(object);
-                       INSTANCIATE_ATTR(object, objtemp, tempattr);
-                       add_next_index_zval(return_value, object);
-                                       
-               } while((tempattr = tidyAttrNext(tempattr)));
-       }
-}
-/* }}} */
-
-
-
-/* {{{ proto tidy_node tidy_node::children()
-   Returns an array of child nodes */
-PHP_NODE_METHOD(children)
+TIDY_NODE_METHOD(__construct)
 {
-       TidyNode tempnode;
-       zval *object;
-       PHPTidyObj      *objtemp;
-       GET_THIS_CONTAINER();
-       
-       tempnode = tidyGetChild(obj->node);
-                       
-       if(tempnode) {
-               array_init(return_value);
-               do {
-               
-                       MAKE_STD_ZVAL(object);
-                       INSTANCIATE_NODE(object, objtemp, tempnode);
-                       add_next_index_zval(return_value, object);
-                                                       
-               } while((tempnode = tidyGetNext(tempnode)));
-       }
 }
 /* }}} */
 
 /* {{{ proto boolean tidy_node::has_children()
    Returns true if this node has children */
-PHP_NODE_METHOD(has_children)
+TIDY_NODE_METHOD(has_children)
 {
-       GET_THIS_CONTAINER();
+       zval *object = getThis();
+       PHPTidyObj *obj;
+
+       if(ZEND_NUM_ARGS()) {
+               WRONG_PARAM_COUNT;
+       }
+               
+       obj = (PHPTidyObj *) zend_object_store_get_object(object TSRMLS_CC);
        
        if(tidyGetChild(obj->node)) {
                RETURN_TRUE;
@@ -1173,9 +1785,16 @@ PHP_NODE_METHOD(has_children)
 
 /* {{{ proto boolean tidy_node::has_siblings()
    Returns true if this node has siblings */
-PHP_NODE_METHOD(has_siblings)
+TIDY_NODE_METHOD(has_siblings)
 {
-       GET_THIS_CONTAINER();
+       zval *object = getThis();
+       PHPTidyObj *obj;
+
+       if(ZEND_NUM_ARGS()) {
+               WRONG_PARAM_COUNT;
+       }
+               
+       obj = (PHPTidyObj *) zend_object_store_get_object(object TSRMLS_CC);
        
        if(tidyGetNext(obj->node)) {
                RETURN_TRUE;
@@ -1188,9 +1807,17 @@ PHP_NODE_METHOD(has_siblings)
    
 /* {{{ proto boolean tidy_node::is_comment()
    Returns true if this node represents a comment */
-PHP_NODE_METHOD(is_comment)
+TIDY_NODE_METHOD(is_comment)
 {
-       GET_THIS_CONTAINER();
+       zval *object = getThis();
+       PHPTidyObj *obj;
+
+       if(ZEND_NUM_ARGS()) {
+               WRONG_PARAM_COUNT;
+       }
+               
+       obj = (PHPTidyObj *) zend_object_store_get_object(object TSRMLS_CC);
+       
        if(tidyNodeGetType(obj->node) == TidyNode_Comment) {
                RETURN_TRUE;
        } else {
@@ -1202,13 +1829,21 @@ PHP_NODE_METHOD(is_comment)
    
 /* {{{ proto boolean tidy_node::is_html()
    Returns true if this node is part of a HTML document */
-PHP_NODE_METHOD(is_html)
+TIDY_NODE_METHOD(is_html)
 {
-       GET_THIS_CONTAINER();
+       zval *object = getThis();
+       PHPTidyObj *obj;
+
+       if(ZEND_NUM_ARGS()) {
+               WRONG_PARAM_COUNT;
+       }
+               
+       obj = (PHPTidyObj *) zend_object_store_get_object(object TSRMLS_CC);
        
        if(tidyNodeGetType(obj->node) & (TidyNode_Start | TidyNode_End | TidyNode_StartEnd)) {
                RETURN_TRUE;
        }
+       
        RETURN_FALSE;
        
 }
@@ -1216,10 +1851,18 @@ PHP_NODE_METHOD(is_html)
    
 /* {{{ proto boolean tidy_node::is_xhtml()
    Returns true if this node is part of a XHTML document */ 
-PHP_NODE_METHOD(is_xhtml)
+TIDY_NODE_METHOD(is_xhtml)
 {
-       GET_THIS_CONTAINER();
-       if(tidyDetectedXhtml(TG(tdoc)->doc)) {
+       zval *object = getThis();
+       PHPTidyObj *obj;
+
+       if(ZEND_NUM_ARGS()) {
+               WRONG_PARAM_COUNT;
+       }
+               
+       obj = (PHPTidyObj *) zend_object_store_get_object(object TSRMLS_CC);
+       
+       if(tidyDetectedXhtml(obj->ptdoc->doc)) {
                RETURN_TRUE;
        } else {
                RETURN_FALSE;
@@ -1229,10 +1872,18 @@ PHP_NODE_METHOD(is_xhtml)
    
 /* {{{ proto boolean tidy_node::is_xml()
    Returns true if this node is part of a XML document */
-PHP_NODE_METHOD(is_xml)
+TIDY_NODE_METHOD(is_xml)
 {
-       GET_THIS_CONTAINER();
-       if(tidyDetectedGenericXml(TG(tdoc)->doc)) {
+       zval *object = getThis();
+       PHPTidyObj *obj;
+
+       if(ZEND_NUM_ARGS()) {
+               WRONG_PARAM_COUNT;
+       }
+               
+       obj = (PHPTidyObj *) zend_object_store_get_object(object TSRMLS_CC);
+       
+       if(tidyDetectedGenericXml(obj->ptdoc->doc)) {
                RETURN_TRUE;
        } else {
                RETURN_FALSE;
@@ -1242,9 +1893,17 @@ PHP_NODE_METHOD(is_xml)
 
 /* {{{ proto boolean tidy_node::is_text()
    Returns true if this node represents text (no markup) */
-PHP_NODE_METHOD(is_text)
+TIDY_NODE_METHOD(is_text)
 {
-       GET_THIS_CONTAINER();
+       zval *object = getThis();
+       PHPTidyObj *obj;
+
+       if(ZEND_NUM_ARGS()) {
+               WRONG_PARAM_COUNT;
+       }
+               
+       obj = (PHPTidyObj *) zend_object_store_get_object(object TSRMLS_CC);
+       
        if(tidyNodeGetType(obj->node) == TidyNode_Text) {
                RETURN_TRUE;
        } else {
@@ -1256,9 +1915,17 @@ PHP_NODE_METHOD(is_text)
    
 /* {{{ proto boolean tidy_node::is_jste()
    Returns true if this node is JSTE */
-PHP_NODE_METHOD(is_jste)
+TIDY_NODE_METHOD(is_jste)
 {
-       GET_THIS_CONTAINER();
+       zval *object = getThis();
+       PHPTidyObj *obj;
+
+       if(ZEND_NUM_ARGS()) {
+               WRONG_PARAM_COUNT;
+       }
+               
+       obj = (PHPTidyObj *) zend_object_store_get_object(object TSRMLS_CC);
+       
        if(tidyNodeGetType(obj->node) == TidyNode_Jste) {
                RETURN_TRUE;
        } else {
@@ -1269,9 +1936,17 @@ PHP_NODE_METHOD(is_jste)
 
 /* {{{ proto boolean tidy_node::is_asp()
    Returns true if this node is ASP */
-PHP_NODE_METHOD(is_asp)
+TIDY_NODE_METHOD(is_asp)
 {
-       GET_THIS_CONTAINER();
+       zval *object = getThis();
+       PHPTidyObj *obj;
+
+       if(ZEND_NUM_ARGS()) {
+               WRONG_PARAM_COUNT;
+       }
+               
+       obj = (PHPTidyObj *) zend_object_store_get_object(object TSRMLS_CC);
+       
        if(tidyNodeGetType(obj->node) == TidyNode_Asp) {
                RETURN_TRUE;
        } else {
@@ -1282,107 +1957,25 @@ PHP_NODE_METHOD(is_asp)
    
 /* {{{ proto boolean tidy_node::is_jsp()
    Returns true if this node is JSP */
-PHP_NODE_METHOD(is_php)
-{
-       GET_THIS_CONTAINER();
-       if(tidyNodeGetType(obj->node) == TidyNode_Php) {
-               RETURN_TRUE;
-       } else {
-               RETURN_FALSE;
-       }
-}
-/* }}} */
-
-/* {{{ proto tidy_node tidy_node::next()
-   Returns the next sibling to this node */
-PHP_NODE_METHOD(next)
+TIDY_NODE_METHOD(is_php)
 {
-       PHPTidyObj      *obj;
-       
-       if(ZEND_NUM_ARGS()) {
-               WRONG_PARAM_COUNT;
-       }
+       zval *object = getThis();
+       PHPTidyObj *obj;
 
-       TIDY_PARSED_CHECK();
-       
-       tidy_instanciate(tidy_ce_node, return_value TSRMLS_CC);
-       obj = (PHPTidyObj *) zend_object_store_get_object(return_value TSRMLS_CC);
-       obj->node = tidyGetNext(obj->node);
-       obj->attr = NULL;
-       obj->type = is_node;
-       
-       tidy_add_default_properities(obj, is_node TSRMLS_CC);
-}
-/* }}} */
-   
-/* {{{ proto tidy_node tidy_node::prev()
-   Returns the previous sibiling to this node */
-PHP_NODE_METHOD(prev)
-{
-       PHPTidyObj      *obj;
-       
        if(ZEND_NUM_ARGS()) {
                WRONG_PARAM_COUNT;
        }
-
-       TIDY_PARSED_CHECK();
-       
-       tidy_instanciate(tidy_ce_node, return_value TSRMLS_CC);
-       obj = (PHPTidyObj *) zend_object_store_get_object(return_value TSRMLS_CC);
-       obj->node = tidyGetPrev(obj->node);
-       obj->attr = NULL;
-       obj->type = is_node;
-       
-       tidy_add_default_properities(obj, is_node TSRMLS_CC);
-}
-/* }}} */
-   
-/* {{{ proto tidy_attr tidy_node::get_attr(int attrib_id)
-   Return the attribute with the provided attribute id */
-PHP_NODE_METHOD(get_attr)
-{
-       TidyAttr tempattr;
-       long param;
-       GET_THIS_CONTAINER();
-       
-       if(ZEND_NUM_ARGS() != 1) {
-               WRONG_PARAM_COUNT;
-       }
-
-       TIDY_PARSED_CHECK();
-
-       if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &param) == FAILURE) {
-               RETURN_FALSE;
-       }
-       
-       for(tempattr = tidyAttrFirst(obj->node); tempattr; tempattr = tidyAttrNext(tempattr)) {
                
-               if(tidyAttrGetId(tempattr) == param) {
-       
-                       tidy_instanciate(tidy_ce_node, return_value TSRMLS_CC);
-       
-                       obj = (PHPTidyObj *) zend_object_store_get_object(return_value TSRMLS_CC);
-                       obj->node = NULL;
-                       obj->attr = tempattr;
-                       obj->type = is_attr;
+       obj = (PHPTidyObj *) zend_object_store_get_object(object TSRMLS_CC);
        
-                       tidy_add_default_properities(obj, is_attr TSRMLS_CC);
-               }
+       if(tidyNodeGetType(obj->node) == TidyNode_Php) {
+               RETURN_TRUE;
+       } else {
+               RETURN_FALSE;
        }
-               
-}
-/* }}} */
-
-/* {{{ proto tidy_node tidy_node::get_nodes(int node_id)
-   Return an array of nodes under this node with the specified id */
-PHP_NODE_METHOD(get_nodes)
-{
-       /* TODO */
 }
 /* }}} */
 
-#endif /* ZEND_ENGINE_2 */
-   
 void _php_tidy_register_nodetypes(INIT_FUNC_ARGS)
 {
     
@@ -1688,3 +2281,4 @@ void _php_tidy_register_attributes(INIT_FUNC_ARGS)
     TIDY_ATTR_CONST(XMLNS);
         
 }
+