xref: /PHP-5.3/ext/tidy/tidy.c (revision a2045ff3)
1 /*
2   +----------------------------------------------------------------------+
3   | PHP Version 5                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1997-2013 The PHP Group                                |
6   +----------------------------------------------------------------------+
7   | This source file is subject to version 3.01 of the PHP license,      |
8   | that is bundled with this package in the file LICENSE, and is        |
9   | available through the world-wide-web at the following url:           |
10   | http://www.php.net/license/3_01.txt                                  |
11   | If you did not receive a copy of the PHP license and are unable to   |
12   | obtain it through the world-wide-web, please send a note to          |
13   | license@php.net so we can mail you a copy immediately.               |
14   +----------------------------------------------------------------------+
15   | Author: John Coggeshall <john@php.net>                               |
16   +----------------------------------------------------------------------+
17 */
18 
19 /* $Id$ */
20 
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 
25 #include "php.h"
26 #include "php_tidy.h"
27 
28 #if HAVE_TIDY
29 
30 #include "php_ini.h"
31 #include "ext/standard/info.h"
32 #include "safe_mode.h"
33 
34 #include "tidy.h"
35 #include "buffio.h"
36 
37 /* compatibility with older versions of libtidy */
38 #ifndef TIDY_CALL
39 #define TIDY_CALL
40 #endif
41 
42 #define PHP_TIDY_MODULE_VERSION	"2.0"
43 
44 /* {{{ ext/tidy macros
45 */
46 #define TIDY_SET_CONTEXT \
47     zval *object = getThis();
48 
49 #define TIDY_FETCH_OBJECT	\
50 	PHPTidyObj *obj;	\
51 	TIDY_SET_CONTEXT; \
52 	if (object) {	\
53 		if (zend_parse_parameters_none() == FAILURE) {	\
54 			return;	\
55 		}	\
56 	} else {	\
57 		if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, NULL, "O", &object, tidy_ce_doc) == FAILURE) {	\
58 			RETURN_FALSE;	\
59 		}	\
60 	}	\
61 	obj = (PHPTidyObj *) zend_object_store_get_object(object TSRMLS_CC);	\
62 
63 #define TIDY_FETCH_ONLY_OBJECT	\
64 	PHPTidyObj *obj;	\
65 	TIDY_SET_CONTEXT; \
66 	if (zend_parse_parameters_none() == FAILURE) {	\
67 		return;	\
68 	}	\
69 	obj = (PHPTidyObj *) zend_object_store_get_object(object TSRMLS_CC);	\
70 
71 #define TIDY_APPLY_CONFIG_ZVAL(_doc, _val) \
72     if(_val) { \
73         if(Z_TYPE_PP(_val) == IS_ARRAY) { \
74             _php_tidy_apply_config_array(_doc, HASH_OF(*_val) TSRMLS_CC); \
75         } else { \
76             convert_to_string_ex(_val); \
77             TIDY_SAFE_MODE_CHECK(Z_STRVAL_PP(_val)); \
78             switch (tidyLoadConfig(_doc, Z_STRVAL_PP(_val))) { \
79               case -1: \
80                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not load configuration file '%s'", Z_STRVAL_PP(_val)); \
81                 break; \
82               case 1: \
83                 php_error_docref(NULL TSRMLS_CC, E_NOTICE, "There were errors while parsing the configuration file '%s'", Z_STRVAL_PP(_val)); \
84                 break; \
85             } \
86         } \
87     }
88 
89 #define REGISTER_TIDY_CLASS(classname, name, parent, __flags) \
90 	{ \
91 		zend_class_entry ce; \
92 		INIT_CLASS_ENTRY(ce, # classname, tidy_funcs_ ## name); \
93 		ce.create_object = tidy_object_new_ ## name; \
94 		tidy_ce_ ## name = zend_register_internal_class_ex(&ce, parent, NULL TSRMLS_CC); \
95 		tidy_ce_ ## name->ce_flags |= __flags;  \
96 		memcpy(&tidy_object_handlers_ ## name, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); \
97 		tidy_object_handlers_ ## name.clone_obj = NULL; \
98 	}
99 
100 #define TIDY_TAG_CONST(tag) REGISTER_LONG_CONSTANT("TIDY_TAG_" #tag, TidyTag_##tag, CONST_CS | CONST_PERSISTENT)
101 #define TIDY_NODE_CONST(name, type) REGISTER_LONG_CONSTANT("TIDY_NODETYPE_" #name, TidyNode_##type, CONST_CS | CONST_PERSISTENT)
102 
103 #ifndef TRUE
104 #define TRUE 1
105 #endif
106 
107 #ifndef FALSE
108 #define FALSE 0
109 #endif
110 
111 #define ADD_PROPERTY_STRING(_table, _key, _string) \
112 	{ \
113 		zval *tmp; \
114 		MAKE_STD_ZVAL(tmp); \
115 		if (_string) { \
116 			ZVAL_STRING(tmp, (char *)_string, 1); \
117 		} else { \
118 			ZVAL_EMPTY_STRING(tmp); \
119 		} \
120 		zend_hash_update(_table, #_key, sizeof(#_key), (void *)&tmp, sizeof(zval *), NULL); \
121 	}
122 
123 #define ADD_PROPERTY_STRINGL(_table, _key, _string, _len) \
124    { \
125        zval *tmp; \
126        MAKE_STD_ZVAL(tmp); \
127        if (_string) { \
128            ZVAL_STRINGL(tmp, (char *)_string, _len, 1); \
129        } else { \
130            ZVAL_EMPTY_STRING(tmp); \
131        } \
132        zend_hash_update(_table, #_key, sizeof(#_key), (void *)&tmp, sizeof(zval *), NULL); \
133    }
134 
135 #define ADD_PROPERTY_LONG(_table, _key, _long) \
136 	{ \
137 		zval *tmp; \
138 		MAKE_STD_ZVAL(tmp); \
139 		ZVAL_LONG(tmp, _long); \
140 		zend_hash_update(_table, #_key, sizeof(#_key), (void *)&tmp, sizeof(zval *), NULL); \
141 	}
142 
143 #define ADD_PROPERTY_NULL(_table, _key) \
144 	{ \
145 		zval *tmp; \
146 		MAKE_STD_ZVAL(tmp); \
147 		ZVAL_NULL(tmp); \
148 		zend_hash_update(_table, #_key, sizeof(#_key), (void *)&tmp, sizeof(zval *), NULL); \
149 	}
150 
151 #define ADD_PROPERTY_BOOL(_table, _key, _bool) \
152     { \
153        zval *tmp; \
154        MAKE_STD_ZVAL(tmp); \
155        ZVAL_BOOL(tmp, _bool); \
156        zend_hash_update(_table, #_key, sizeof(#_key), (void *)&tmp, sizeof(zval *), NULL); \
157    }
158 
159 #define TIDY_SAFE_MODE_CHECK(filename) \
160 if ((PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(filename TSRMLS_CC)) { \
161 	RETURN_FALSE; \
162 } \
163 
164 #define TIDY_SET_DEFAULT_CONFIG(_doc) \
165 	if (TG(default_config) && TG(default_config)[0]) { \
166 		if (tidyLoadConfig(_doc, TG(default_config)) < 0) { \
167 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to load Tidy configuration file at '%s'.", TG(default_config)); \
168 		} \
169 	}
170 /* }}} */
171 
172 /* {{{ ext/tidy structs
173 */
174 typedef struct _PHPTidyDoc PHPTidyDoc;
175 typedef struct _PHPTidyObj PHPTidyObj;
176 
177 typedef enum {
178 	is_node,
179 	is_doc
180 } tidy_obj_type;
181 
182 typedef enum {
183 	is_root_node,
184 	is_html_node,
185 	is_head_node,
186 	is_body_node
187 } tidy_base_nodetypes;
188 
189 struct _PHPTidyDoc {
190 	TidyDoc     doc;
191 	TidyBuffer  *errbuf;
192 	unsigned int ref_count;
193 	unsigned int initialized:1;
194 };
195 
196 struct _PHPTidyObj {
197 	zend_object         std;
198 	TidyNode            node;
199 	tidy_obj_type       type;
200 	PHPTidyDoc          *ptdoc;
201 };
202 /* }}} */
203 
204 /* {{{ ext/tidy prototypes
205 */
206 static char *php_tidy_file_to_mem(char *, zend_bool, int * TSRMLS_DC);
207 static void tidy_object_free_storage(void * TSRMLS_DC);
208 static zend_object_value tidy_object_new_node(zend_class_entry * TSRMLS_DC);
209 static zend_object_value tidy_object_new_doc(zend_class_entry * TSRMLS_DC);
210 static zval * tidy_instanciate(zend_class_entry *, zval * TSRMLS_DC);
211 static int tidy_doc_cast_handler(zval *, zval *, int TSRMLS_DC);
212 static int tidy_node_cast_handler(zval *, zval *, int TSRMLS_DC);
213 static void tidy_doc_update_properties(PHPTidyObj * TSRMLS_DC);
214 static void tidy_add_default_properties(PHPTidyObj *, tidy_obj_type TSRMLS_DC);
215 static void *php_tidy_get_opt_val(PHPTidyDoc *, TidyOption, TidyOptionType * TSRMLS_DC);
216 static void php_tidy_create_node(INTERNAL_FUNCTION_PARAMETERS, tidy_base_nodetypes);
217 static int _php_tidy_set_tidy_opt(TidyDoc, char *, zval * TSRMLS_DC);
218 static int _php_tidy_apply_config_array(TidyDoc doc, HashTable *ht_options TSRMLS_DC);
219 static void _php_tidy_register_nodetypes(INIT_FUNC_ARGS);
220 static void _php_tidy_register_tags(INIT_FUNC_ARGS);
221 
222 static PHP_MINIT_FUNCTION(tidy);
223 static PHP_MSHUTDOWN_FUNCTION(tidy);
224 static PHP_RINIT_FUNCTION(tidy);
225 static PHP_MINFO_FUNCTION(tidy);
226 
227 static PHP_FUNCTION(tidy_getopt);
228 static PHP_FUNCTION(tidy_parse_string);
229 static PHP_FUNCTION(tidy_parse_file);
230 static PHP_FUNCTION(tidy_clean_repair);
231 static PHP_FUNCTION(tidy_repair_string);
232 static PHP_FUNCTION(tidy_repair_file);
233 static PHP_FUNCTION(tidy_diagnose);
234 static PHP_FUNCTION(tidy_get_output);
235 static PHP_FUNCTION(tidy_get_error_buffer);
236 static PHP_FUNCTION(tidy_get_release);
237 static PHP_FUNCTION(tidy_get_config);
238 static PHP_FUNCTION(tidy_get_status);
239 static PHP_FUNCTION(tidy_get_html_ver);
240 #if HAVE_TIDYOPTGETDOC
241 static PHP_FUNCTION(tidy_get_opt_doc);
242 #endif
243 static PHP_FUNCTION(tidy_is_xhtml);
244 static PHP_FUNCTION(tidy_is_xml);
245 static PHP_FUNCTION(tidy_error_count);
246 static PHP_FUNCTION(tidy_warning_count);
247 static PHP_FUNCTION(tidy_access_count);
248 static PHP_FUNCTION(tidy_config_count);
249 
250 static PHP_FUNCTION(ob_tidyhandler);
251 
252 static PHP_FUNCTION(tidy_get_root);
253 static PHP_FUNCTION(tidy_get_html);
254 static PHP_FUNCTION(tidy_get_head);
255 static PHP_FUNCTION(tidy_get_body);
256 
257 static TIDY_DOC_METHOD(__construct);
258 static TIDY_DOC_METHOD(parseFile);
259 static TIDY_DOC_METHOD(parseString);
260 
261 static TIDY_NODE_METHOD(hasChildren);
262 static TIDY_NODE_METHOD(hasSiblings);
263 static TIDY_NODE_METHOD(isComment);
264 static TIDY_NODE_METHOD(isHtml);
265 static TIDY_NODE_METHOD(isText);
266 static TIDY_NODE_METHOD(isJste);
267 static TIDY_NODE_METHOD(isAsp);
268 static TIDY_NODE_METHOD(isPhp);
269 static TIDY_NODE_METHOD(getParent);
270 static TIDY_NODE_METHOD(__construct);
271 /* }}} */
272 
273 ZEND_DECLARE_MODULE_GLOBALS(tidy)
274 
275 PHP_INI_BEGIN()
276 STD_PHP_INI_ENTRY("tidy.default_config",	"",	PHP_INI_SYSTEM,		OnUpdateString,		default_config,		zend_tidy_globals,	tidy_globals)
277 PHP_INI_ENTRY("tidy.clean_output",     "0",    PHP_INI_PERDIR,         NULL)
278 PHP_INI_END()
279 
280 /* {{{ arginfo */
281 ZEND_BEGIN_ARG_INFO_EX(arginfo_tidy_parse_string, 0, 0, 1)
282 	ZEND_ARG_INFO(0, input)
283 	ZEND_ARG_INFO(0, config_options)
284 	ZEND_ARG_INFO(0, encoding)
285 ZEND_END_ARG_INFO()
286 
287 ZEND_BEGIN_ARG_INFO_EX(arginfo_tidy_get_error_buffer, 0, 0, 0)
288 	ZEND_ARG_INFO(0, detailed)
289 ZEND_END_ARG_INFO()
290 
291 ZEND_BEGIN_ARG_INFO(arginfo_tidy_get_output, 0)
292 ZEND_END_ARG_INFO()
293 
294 ZEND_BEGIN_ARG_INFO_EX(arginfo_tidy_parse_file, 0, 0, 1)
295 	ZEND_ARG_INFO(0, file)
296 	ZEND_ARG_INFO(0, config_options)
297 	ZEND_ARG_INFO(0, encoding)
298 	ZEND_ARG_INFO(0, use_include_path)
299 ZEND_END_ARG_INFO()
300 
301 ZEND_BEGIN_ARG_INFO(arginfo_tidy_clean_repair, 0)
302 ZEND_END_ARG_INFO()
303 
304 ZEND_BEGIN_ARG_INFO_EX(arginfo_tidy_repair_string, 0, 0, 1)
305 	ZEND_ARG_INFO(0, data)
306 	ZEND_ARG_INFO(0, config_file)
307 	ZEND_ARG_INFO(0, encoding)
308 ZEND_END_ARG_INFO()
309 
310 ZEND_BEGIN_ARG_INFO_EX(arginfo_tidy_repair_file, 0, 0, 1)
311 	ZEND_ARG_INFO(0, filename)
312 	ZEND_ARG_INFO(0, config_file)
313 	ZEND_ARG_INFO(0, encoding)
314 	ZEND_ARG_INFO(0, use_include_path)
315 ZEND_END_ARG_INFO()
316 
317 ZEND_BEGIN_ARG_INFO(arginfo_tidy_diagnose, 0)
318 ZEND_END_ARG_INFO()
319 
320 ZEND_BEGIN_ARG_INFO(arginfo_tidy_get_release, 0)
321 ZEND_END_ARG_INFO()
322 
323 #if HAVE_TIDYOPTGETDOC
324 ZEND_BEGIN_ARG_INFO_EX(arginfo_tidy_get_opt_doc, 0, 0, 2)
325 	ZEND_ARG_INFO(0, resource)
326 	ZEND_ARG_INFO(0, optname)
327 ZEND_END_ARG_INFO()
328 #endif
329 
330 ZEND_BEGIN_ARG_INFO(arginfo_tidy_get_config, 0)
331 ZEND_END_ARG_INFO()
332 
333 ZEND_BEGIN_ARG_INFO(arginfo_tidy_get_status, 0)
334 ZEND_END_ARG_INFO()
335 
336 ZEND_BEGIN_ARG_INFO(arginfo_tidy_get_html_ver, 0)
337 ZEND_END_ARG_INFO()
338 
339 ZEND_BEGIN_ARG_INFO(arginfo_tidy_is_xhtml, 0)
340 ZEND_END_ARG_INFO()
341 
342 ZEND_BEGIN_ARG_INFO(arginfo_tidy_is_xml, 0)
343 ZEND_END_ARG_INFO()
344 
345 ZEND_BEGIN_ARG_INFO(arginfo_tidy_error_count, 0)
346 ZEND_END_ARG_INFO()
347 
348 ZEND_BEGIN_ARG_INFO(arginfo_tidy_warning_count, 0)
349 ZEND_END_ARG_INFO()
350 
351 ZEND_BEGIN_ARG_INFO(arginfo_tidy_access_count, 0)
352 ZEND_END_ARG_INFO()
353 
354 ZEND_BEGIN_ARG_INFO(arginfo_tidy_config_count, 0)
355 ZEND_END_ARG_INFO()
356 
357 ZEND_BEGIN_ARG_INFO_EX(arginfo_tidy_getopt, 0, 0, 1)
358 	ZEND_ARG_INFO(0, option)
359 ZEND_END_ARG_INFO()
360 
361 ZEND_BEGIN_ARG_INFO(arginfo_tidy_get_root, 0)
362 ZEND_END_ARG_INFO()
363 
364 ZEND_BEGIN_ARG_INFO(arginfo_tidy_get_html, 0)
365 ZEND_END_ARG_INFO()
366 
367 ZEND_BEGIN_ARG_INFO(arginfo_tidy_get_head, 0)
368 ZEND_END_ARG_INFO()
369 
370 ZEND_BEGIN_ARG_INFO_EX(arginfo_tidy_get_body, 0, 0, 1)
371 	ZEND_ARG_INFO(0, tidy)
372 ZEND_END_ARG_INFO()
373 
374 ZEND_BEGIN_ARG_INFO_EX(arginfo_ob_tidyhandler, 0, 0, 1)
375 	ZEND_ARG_INFO(0, input)
376 	ZEND_ARG_INFO(0, mode)
377 ZEND_END_ARG_INFO()
378 /* }}} */
379 
380 static const zend_function_entry tidy_functions[] = {
381 	PHP_FE(tidy_getopt,             arginfo_tidy_getopt)
382 	PHP_FE(tidy_parse_string,       arginfo_tidy_parse_string)
383 	PHP_FE(tidy_parse_file,         arginfo_tidy_parse_file)
384 	PHP_FE(tidy_get_output,         arginfo_tidy_get_output)
385 	PHP_FE(tidy_get_error_buffer,   arginfo_tidy_get_error_buffer)
386 	PHP_FE(tidy_clean_repair,       arginfo_tidy_clean_repair)
387 	PHP_FE(tidy_repair_string,	arginfo_tidy_repair_string)
388 	PHP_FE(tidy_repair_file,	arginfo_tidy_repair_file)
389 	PHP_FE(tidy_diagnose,           arginfo_tidy_diagnose)
390 	PHP_FE(tidy_get_release,	arginfo_tidy_get_release)
391 	PHP_FE(tidy_get_config,		arginfo_tidy_get_config)
392 	PHP_FE(tidy_get_status,		arginfo_tidy_get_status)
393 	PHP_FE(tidy_get_html_ver,	arginfo_tidy_get_html_ver)
394 	PHP_FE(tidy_is_xhtml,		arginfo_tidy_is_xhtml)
395 	PHP_FE(tidy_is_xml,		arginfo_tidy_is_xml)
396 	PHP_FE(tidy_error_count,	arginfo_tidy_error_count)
397 	PHP_FE(tidy_warning_count,	arginfo_tidy_warning_count)
398 	PHP_FE(tidy_access_count,	arginfo_tidy_access_count)
399 	PHP_FE(tidy_config_count,	arginfo_tidy_config_count)
400 #if HAVE_TIDYOPTGETDOC
401 	PHP_FE(tidy_get_opt_doc,	arginfo_tidy_get_opt_doc)
402 #endif
403 	PHP_FE(tidy_get_root,		arginfo_tidy_get_root)
404 	PHP_FE(tidy_get_head,		arginfo_tidy_get_head)
405 	PHP_FE(tidy_get_html,		arginfo_tidy_get_html)
406 	PHP_FE(tidy_get_body,		arginfo_tidy_get_body)
407 	PHP_FE(ob_tidyhandler,		arginfo_ob_tidyhandler)
408 	PHP_FE_END
409 };
410 
411 static const zend_function_entry tidy_funcs_doc[] = {
412 	TIDY_METHOD_MAP(getOpt, tidy_getopt, NULL)
413 	TIDY_METHOD_MAP(cleanRepair, tidy_clean_repair, NULL)
414 	TIDY_DOC_ME(parseFile, NULL)
415 	TIDY_DOC_ME(parseString, NULL)
416 	TIDY_METHOD_MAP(repairString, tidy_repair_string, NULL)
417 	TIDY_METHOD_MAP(repairFile, tidy_repair_file, NULL)
418 	TIDY_METHOD_MAP(diagnose, tidy_diagnose, NULL)
419 	TIDY_METHOD_MAP(getRelease, tidy_get_release, NULL)
420 	TIDY_METHOD_MAP(getConfig, tidy_get_config, NULL)
421 	TIDY_METHOD_MAP(getStatus, tidy_get_status, NULL)
422 	TIDY_METHOD_MAP(getHtmlVer, tidy_get_html_ver, NULL)
423 #if HAVE_TIDYOPTGETDOC
424 	TIDY_METHOD_MAP(getOptDoc, tidy_get_opt_doc, NULL)
425 #endif
426 	TIDY_METHOD_MAP(isXhtml, tidy_is_xhtml, NULL)
427 	TIDY_METHOD_MAP(isXml, tidy_is_xml, NULL)
428 	TIDY_METHOD_MAP(root, tidy_get_root, NULL)
429 	TIDY_METHOD_MAP(head, tidy_get_head, NULL)
430 	TIDY_METHOD_MAP(html, tidy_get_html, NULL)
431 	TIDY_METHOD_MAP(body, tidy_get_body, NULL)
432 	TIDY_DOC_ME(__construct, NULL)
433 	PHP_FE_END
434 };
435 
436 static const zend_function_entry tidy_funcs_node[] = {
437 	TIDY_NODE_ME(hasChildren, NULL)
438 	TIDY_NODE_ME(hasSiblings, NULL)
439 	TIDY_NODE_ME(isComment, NULL)
440 	TIDY_NODE_ME(isHtml, NULL)
441 	TIDY_NODE_ME(isText, NULL)
442 	TIDY_NODE_ME(isJste, NULL)
443 	TIDY_NODE_ME(isAsp, NULL)
444 	TIDY_NODE_ME(isPhp, NULL)
445 	TIDY_NODE_ME(getParent, NULL)
446 	TIDY_NODE_PRIVATE_ME(__construct, NULL)
447 	PHP_FE_END
448 };
449 
450 static zend_class_entry *tidy_ce_doc, *tidy_ce_node;
451 
452 static zend_object_handlers tidy_object_handlers_doc;
453 static zend_object_handlers tidy_object_handlers_node;
454 
455 zend_module_entry tidy_module_entry = {
456 	STANDARD_MODULE_HEADER,
457 	"tidy",
458 	tidy_functions,
459 	PHP_MINIT(tidy),
460 	PHP_MSHUTDOWN(tidy),
461 	PHP_RINIT(tidy),
462 	NULL,
463 	PHP_MINFO(tidy),
464 	PHP_TIDY_MODULE_VERSION,
465 	PHP_MODULE_GLOBALS(tidy),
466 	NULL,
467 	NULL,
468 	NULL,
469 	STANDARD_MODULE_PROPERTIES_EX
470 };
471 
472 #ifdef COMPILE_DL_TIDY
ZEND_GET_MODULE(tidy)473 ZEND_GET_MODULE(tidy)
474 #endif
475 
476 static void* TIDY_CALL php_tidy_malloc(size_t len)
477 {
478 	return emalloc(len);
479 }
480 
php_tidy_realloc(void * buf,size_t len)481 static void* TIDY_CALL php_tidy_realloc(void *buf, size_t len)
482 {
483 	return erealloc(buf, len);
484 }
485 
php_tidy_free(void * buf)486 static void TIDY_CALL php_tidy_free(void *buf)
487 {
488 	efree(buf);
489 }
490 
php_tidy_panic(ctmbstr msg)491 static void TIDY_CALL php_tidy_panic(ctmbstr msg)
492 {
493 	TSRMLS_FETCH();
494 	php_error_docref(NULL TSRMLS_CC, E_ERROR, "Could not allocate memory for tidy! (Reason: %s)", (char *)msg);
495 }
496 
_php_tidy_set_tidy_opt(TidyDoc doc,char * optname,zval * value TSRMLS_DC)497 static int _php_tidy_set_tidy_opt(TidyDoc doc, char *optname, zval *value TSRMLS_DC)
498 {
499 	TidyOption opt = tidyGetOptionByName(doc, optname);
500 	zval conv = *value;
501 
502 	if (!opt) {
503 		php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Unknown Tidy Configuration Option '%s'", optname);
504 		return FAILURE;
505 	}
506 
507 	if (tidyOptIsReadOnly(opt)) {
508 		php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Attempting to set read-only option '%s'", optname);
509 		return FAILURE;
510 	}
511 
512 	switch(tidyOptGetType(opt)) {
513 		case TidyString:
514 			if (Z_TYPE(conv) != IS_STRING) {
515 				zval_copy_ctor(&conv);
516 				convert_to_string(&conv);
517 			}
518 			if (tidyOptSetValue(doc, tidyOptGetId(opt), Z_STRVAL(conv))) {
519 				if (Z_TYPE(conv) != Z_TYPE_P(value)) {
520 					zval_dtor(&conv);
521 				}
522 				return SUCCESS;
523 			}
524 			if (Z_TYPE(conv) != Z_TYPE_P(value)) {
525 				zval_dtor(&conv);
526 			}
527 			break;
528 
529 		case TidyInteger:
530 			if (Z_TYPE(conv) != IS_LONG) {
531 				zval_copy_ctor(&conv);
532 				convert_to_long(&conv);
533 			}
534 			if (tidyOptSetInt(doc, tidyOptGetId(opt), Z_LVAL(conv))) {
535 				return SUCCESS;
536 			}
537 			break;
538 
539 		case TidyBoolean:
540 			if (Z_TYPE(conv) != IS_LONG) {
541 				zval_copy_ctor(&conv);
542 				convert_to_long(&conv);
543 			}
544 			if (tidyOptSetBool(doc, tidyOptGetId(opt), Z_LVAL(conv))) {
545 				return SUCCESS;
546 			}
547 			break;
548 
549 		default:
550 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to determine type of configuration option");
551 			break;
552 	}
553 
554 	return FAILURE;
555 }
556 
php_tidy_quick_repair(INTERNAL_FUNCTION_PARAMETERS,zend_bool is_file)557 static void php_tidy_quick_repair(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_file)
558 {
559 	char *data=NULL, *arg1, *enc = NULL;
560 	int arg1_len, enc_len = 0, data_len = 0;
561 	zend_bool use_include_path = 0;
562 	TidyDoc doc;
563 	TidyBuffer *errbuf;
564 	zval **config = NULL;
565 
566 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|Zsb", &arg1, &arg1_len, &config, &enc, &enc_len, &use_include_path) == FAILURE) {
567 		RETURN_FALSE;
568 	}
569 
570 	if (is_file) {
571 		if (strlen(arg1) != arg1_len) {
572 			RETURN_FALSE;
573 		}
574 		if (!(data = php_tidy_file_to_mem(arg1, use_include_path, &data_len TSRMLS_CC))) {
575 			RETURN_FALSE;
576 		}
577 	} else {
578 		data = arg1;
579 		data_len = arg1_len;
580 	}
581 
582 	doc = tidyCreate();
583 	errbuf = emalloc(sizeof(TidyBuffer));
584 	tidyBufInit(errbuf);
585 
586 	if (tidySetErrorBuffer(doc, errbuf) != 0) {
587 		tidyBufFree(errbuf);
588 		efree(errbuf);
589 		tidyRelease(doc);
590 		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Could not set Tidy error buffer");
591 	}
592 
593 	tidyOptSetBool(doc, TidyForceOutput, yes);
594 	tidyOptSetBool(doc, TidyMark, no);
595 
596 	TIDY_SET_DEFAULT_CONFIG(doc);
597 
598 	if (config) {
599 		TIDY_APPLY_CONFIG_ZVAL(doc, config);
600 	}
601 
602 	if(enc_len) {
603 		if (tidySetCharEncoding(doc, enc) < 0) {
604 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not set encoding '%s'", enc);
605 			RETVAL_FALSE;
606 		}
607 	}
608 
609 	if (data) {
610 		TidyBuffer buf;
611 
612 		tidyBufInit(&buf);
613 		tidyBufAppend(&buf, data, data_len);
614 
615 		if (tidyParseBuffer(doc, &buf) < 0) {
616 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errbuf->bp);
617 			RETVAL_FALSE;
618 		} else {
619 			if (tidyCleanAndRepair(doc) >= 0) {
620 				TidyBuffer output;
621 				tidyBufInit(&output);
622 
623 				tidySaveBuffer (doc, &output);
624 				RETVAL_STRINGL((char*)output.bp, output.size ? output.size-1 : 0, 1);
625 				tidyBufFree(&output);
626 			} else {
627 				RETVAL_FALSE;
628 			}
629 		}
630 
631 		tidyBufFree(&buf);
632 	}
633 
634 	if (is_file) {
635 		efree(data);
636 	}
637 
638 	tidyBufFree(errbuf);
639 	efree(errbuf);
640 	tidyRelease(doc);
641 }
642 
php_tidy_file_to_mem(char * filename,zend_bool use_include_path,int * len TSRMLS_DC)643 static char *php_tidy_file_to_mem(char *filename, zend_bool use_include_path, int *len TSRMLS_DC)
644 {
645 	php_stream *stream;
646 	char *data = NULL;
647 
648 	if (!(stream = php_stream_open_wrapper(filename, "rb", (use_include_path ? USE_PATH : 0) | ENFORCE_SAFE_MODE, NULL))) {
649 		return NULL;
650 	}
651 	if ((*len = (int) php_stream_copy_to_mem(stream, &data, PHP_STREAM_COPY_ALL, 0)) == 0) {
652 		data = estrdup("");
653 		*len = 0;
654 	}
655 	php_stream_close(stream);
656 
657 	return data;
658 }
659 
tidy_object_free_storage(void * object TSRMLS_DC)660 static void tidy_object_free_storage(void *object TSRMLS_DC)
661 {
662 	PHPTidyObj *intern = (PHPTidyObj *)object;
663 
664 	zend_object_std_dtor(&intern->std TSRMLS_CC);
665 
666 	if (intern->ptdoc) {
667 		intern->ptdoc->ref_count--;
668 
669 		if (intern->ptdoc->ref_count <= 0) {
670 			tidyBufFree(intern->ptdoc->errbuf);
671 			efree(intern->ptdoc->errbuf);
672 			tidyRelease(intern->ptdoc->doc);
673 			efree(intern->ptdoc);
674 		}
675 	}
676 
677 	efree(object);
678 }
679 
tidy_object_new(zend_class_entry * class_type,zend_object_handlers * handlers,zend_object_value * retval,tidy_obj_type objtype TSRMLS_DC)680 static void tidy_object_new(zend_class_entry *class_type, zend_object_handlers *handlers,
681 							zend_object_value *retval, tidy_obj_type objtype TSRMLS_DC)
682 {
683 	PHPTidyObj *intern;
684 	zval *tmp;
685 
686 	intern = emalloc(sizeof(PHPTidyObj));
687 	memset(intern, 0, sizeof(PHPTidyObj));
688 	zend_object_std_init(&intern->std, class_type TSRMLS_CC);
689 
690 	zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_property_ctor, (void *) &tmp, sizeof(zval *));
691 
692 	switch(objtype) {
693 		case is_node:
694 			break;
695 
696 		case is_doc:
697 			tidySetMallocCall(php_tidy_malloc);
698 			tidySetReallocCall(php_tidy_realloc);
699 			tidySetFreeCall(php_tidy_free);
700 			tidySetPanicCall(php_tidy_panic);
701 
702 			intern->ptdoc = emalloc(sizeof(PHPTidyDoc));
703 			intern->ptdoc->doc = tidyCreate();
704 			intern->ptdoc->ref_count = 1;
705 			intern->ptdoc->initialized = 0;
706 			intern->ptdoc->errbuf = emalloc(sizeof(TidyBuffer));
707 			tidyBufInit(intern->ptdoc->errbuf);
708 
709 			if (tidySetErrorBuffer(intern->ptdoc->doc, intern->ptdoc->errbuf) != 0) {
710 				tidyBufFree(intern->ptdoc->errbuf);
711 				efree(intern->ptdoc->errbuf);
712 				tidyRelease(intern->ptdoc->doc);
713 				efree(intern->ptdoc);
714 				efree(intern);
715 				php_error_docref(NULL TSRMLS_CC, E_ERROR, "Could not set Tidy error buffer");
716 			}
717 
718 			tidyOptSetBool(intern->ptdoc->doc, TidyForceOutput, yes);
719 			tidyOptSetBool(intern->ptdoc->doc, TidyMark, no);
720 
721 			TIDY_SET_DEFAULT_CONFIG(intern->ptdoc->doc);
722 
723 			tidy_add_default_properties(intern, is_doc TSRMLS_CC);
724 			break;
725 
726 		default:
727 			break;
728 	}
729 
730 	retval->handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) tidy_object_free_storage, NULL TSRMLS_CC);
731 	retval->handlers = handlers;
732 }
733 
tidy_object_new_node(zend_class_entry * class_type TSRMLS_DC)734 static zend_object_value tidy_object_new_node(zend_class_entry *class_type TSRMLS_DC)
735 {
736 	zend_object_value retval;
737 	tidy_object_new(class_type, &tidy_object_handlers_node, &retval, is_node TSRMLS_CC);
738 	return retval;
739 }
740 
tidy_object_new_doc(zend_class_entry * class_type TSRMLS_DC)741 static zend_object_value tidy_object_new_doc(zend_class_entry *class_type TSRMLS_DC)
742 {
743 	zend_object_value retval;
744 	tidy_object_new(class_type, &tidy_object_handlers_doc, &retval, is_doc TSRMLS_CC);
745 	return retval;
746 }
747 
tidy_instanciate(zend_class_entry * pce,zval * object TSRMLS_DC)748 static zval * tidy_instanciate(zend_class_entry *pce, zval *object TSRMLS_DC)
749 {
750 	if (!object) {
751 		ALLOC_ZVAL(object);
752 	}
753 
754 	Z_TYPE_P(object) = IS_OBJECT;
755 	object_init_ex(object, pce);
756 	Z_SET_REFCOUNT_P(object, 1);
757 	Z_SET_ISREF_P(object);
758 	return object;
759 }
760 
tidy_doc_cast_handler(zval * in,zval * out,int type TSRMLS_DC)761 static int tidy_doc_cast_handler(zval *in, zval *out, int type TSRMLS_DC)
762 {
763 	TidyBuffer output;
764 	PHPTidyObj *obj;
765 
766 	switch(type) {
767 		case IS_LONG:
768 			ZVAL_LONG(out, 0);
769 			break;
770 
771 		case IS_DOUBLE:
772 			ZVAL_DOUBLE(out, 0);
773 			break;
774 
775 		case IS_BOOL:
776 			ZVAL_BOOL(out, TRUE);
777 			break;
778 
779 		case IS_STRING:
780 			obj = (PHPTidyObj *)zend_object_store_get_object(in TSRMLS_CC);
781 			tidyBufInit(&output);
782 			tidySaveBuffer (obj->ptdoc->doc, &output);
783 			ZVAL_STRINGL(out, (char*)output.bp, output.size ? output.size-1 : 0, TRUE);
784 			tidyBufFree(&output);
785 			break;
786 
787 		default:
788 			return FAILURE;
789 	}
790 
791 	return SUCCESS;
792 }
793 
tidy_node_cast_handler(zval * in,zval * out,int type TSRMLS_DC)794 static int tidy_node_cast_handler(zval *in, zval *out, int type TSRMLS_DC)
795 {
796 	TidyBuffer buf;
797 	PHPTidyObj *obj;
798 
799 	switch(type) {
800 		case IS_LONG:
801 			ZVAL_LONG(out, 0);
802 			break;
803 
804 		case IS_DOUBLE:
805 			ZVAL_DOUBLE(out, 0);
806 			break;
807 
808 		case IS_BOOL:
809 			ZVAL_BOOL(out, TRUE);
810 			break;
811 
812 		case IS_STRING:
813 			obj = (PHPTidyObj *)zend_object_store_get_object(in TSRMLS_CC);
814 			tidyBufInit(&buf);
815 			if (obj->ptdoc) {
816 				tidyNodeGetText(obj->ptdoc->doc, obj->node, &buf);
817 			}
818 			ZVAL_STRINGL(out, (char*)buf.bp, buf.size ? buf.size-1 : 0, TRUE);
819 			tidyBufFree(&buf);
820 			break;
821 
822 		default:
823 			return FAILURE;
824 	}
825 
826 	return SUCCESS;
827 }
828 
tidy_doc_update_properties(PHPTidyObj * obj TSRMLS_DC)829 static void tidy_doc_update_properties(PHPTidyObj *obj TSRMLS_DC)
830 {
831 
832 	TidyBuffer output;
833 	zval *temp;
834 
835 	tidyBufInit(&output);
836 	tidySaveBuffer (obj->ptdoc->doc, &output);
837 
838 	if (output.size) {
839 		MAKE_STD_ZVAL(temp);
840 		ZVAL_STRINGL(temp, (char*)output.bp, output.size-1, TRUE);
841 		zend_hash_update(obj->std.properties, "value", sizeof("value"), (void *)&temp, sizeof(zval *), NULL);
842 	}
843 
844 	tidyBufFree(&output);
845 
846 	if (obj->ptdoc->errbuf->size) {
847 		MAKE_STD_ZVAL(temp);
848 		ZVAL_STRINGL(temp, (char*)obj->ptdoc->errbuf->bp, obj->ptdoc->errbuf->size-1, TRUE);
849 		zend_hash_update(obj->std.properties, "errorBuffer", sizeof("errorBuffer"), (void *)&temp, sizeof(zval *), NULL);
850 	}
851 }
852 
tidy_add_default_properties(PHPTidyObj * obj,tidy_obj_type type TSRMLS_DC)853 static void tidy_add_default_properties(PHPTidyObj *obj, tidy_obj_type type TSRMLS_DC)
854 {
855 
856 	TidyBuffer buf;
857 	TidyAttr	tempattr;
858 	TidyNode	tempnode;
859 	zval *attribute, *children, *temp;
860 	PHPTidyObj *newobj;
861 
862 	switch(type) {
863 
864 		case is_node:
865 			tidyBufInit(&buf);
866 			tidyNodeGetText(obj->ptdoc->doc, obj->node, &buf);
867 			ADD_PROPERTY_STRINGL(obj->std.properties, value, buf.bp, buf.size-1);
868 			tidyBufFree(&buf);
869 
870 			ADD_PROPERTY_STRING(obj->std.properties, name, tidyNodeGetName(obj->node));
871 			ADD_PROPERTY_LONG(obj->std.properties, type, tidyNodeGetType(obj->node));
872 			ADD_PROPERTY_LONG(obj->std.properties, line, tidyNodeLine(obj->node));
873 			ADD_PROPERTY_LONG(obj->std.properties, column, tidyNodeColumn(obj->node));
874 			ADD_PROPERTY_BOOL(obj->std.properties, proprietary, tidyNodeIsProp(obj->ptdoc->doc, obj->node));
875 
876 			switch(tidyNodeGetType(obj->node)) {
877 				case TidyNode_Root:
878 				case TidyNode_DocType:
879 				case TidyNode_Text:
880 				case TidyNode_Comment:
881 					break;
882 
883 				default:
884 					ADD_PROPERTY_LONG(obj->std.properties, id, tidyNodeGetId(obj->node));
885 			}
886 
887 			tempattr = tidyAttrFirst(obj->node);
888 			MAKE_STD_ZVAL(attribute);
889 
890 			if (tempattr) {
891 				char *name, *val;
892 				array_init(attribute);
893 
894 				do {
895 					name = (char *)tidyAttrName(tempattr);
896 					val = (char *)tidyAttrValue(tempattr);
897 					if (name && val) {
898 						add_assoc_string(attribute, name, val, TRUE);
899 					}
900 				} while((tempattr = tidyAttrNext(tempattr)));
901 			} else {
902 				ZVAL_NULL(attribute);
903 			}
904 			zend_hash_update(obj->std.properties, "attribute", sizeof("attribute"), (void *)&attribute, sizeof(zval *), NULL);
905 
906 			tempnode = tidyGetChild(obj->node);
907 
908 			MAKE_STD_ZVAL(children);
909 			if (tempnode) {
910 				array_init(children);
911 				do {
912 					MAKE_STD_ZVAL(temp);
913 					tidy_instanciate(tidy_ce_node, temp TSRMLS_CC);
914 					newobj = (PHPTidyObj *) zend_object_store_get_object(temp TSRMLS_CC);
915 					newobj->node = tempnode;
916 					newobj->type = is_node;
917 					newobj->ptdoc = obj->ptdoc;
918 					newobj->ptdoc->ref_count++;
919 
920 					tidy_add_default_properties(newobj, is_node TSRMLS_CC);
921 					add_next_index_zval(children, temp);
922 
923 				} while((tempnode = tidyGetNext(tempnode)));
924 
925 			} else {
926 				ZVAL_NULL(children);
927 			}
928 
929 			zend_hash_update(obj->std.properties, "child", sizeof("child"), (void *)&children, sizeof(zval *), NULL);
930 
931 			break;
932 
933 		case is_doc:
934 			ADD_PROPERTY_NULL(obj->std.properties, errorBuffer);
935 			ADD_PROPERTY_NULL(obj->std.properties, value);
936 			break;
937 	}
938 }
939 
php_tidy_get_opt_val(PHPTidyDoc * ptdoc,TidyOption opt,TidyOptionType * type TSRMLS_DC)940 static void *php_tidy_get_opt_val(PHPTidyDoc *ptdoc, TidyOption opt, TidyOptionType *type TSRMLS_DC)
941 {
942 	*type = tidyOptGetType(opt);
943 
944 	switch (*type) {
945 		case TidyString: {
946 			char *val = (char *) tidyOptGetValue(ptdoc->doc, tidyOptGetId(opt));
947 			if (val) {
948 				return (void *) estrdup(val);
949 			} else {
950 				return (void *) estrdup("");
951 			}
952 		}
953 			break;
954 
955 		case TidyInteger:
956 			return (void *) tidyOptGetInt(ptdoc->doc, tidyOptGetId(opt));
957 			break;
958 
959 		case TidyBoolean:
960 			return (void *) tidyOptGetBool(ptdoc->doc, tidyOptGetId(opt));
961 			break;
962 	}
963 
964 	/* should not happen */
965 	return NULL;
966 }
967 
php_tidy_create_node(INTERNAL_FUNCTION_PARAMETERS,tidy_base_nodetypes node_type)968 static void php_tidy_create_node(INTERNAL_FUNCTION_PARAMETERS, tidy_base_nodetypes node_type)
969 {
970 	PHPTidyObj *newobj;
971 	TidyNode node;
972 	TIDY_FETCH_OBJECT;
973 
974 	switch (node_type) {
975 		case is_root_node:
976 			node = tidyGetRoot(obj->ptdoc->doc);
977 			break;
978 
979 		case is_html_node:
980 			node = tidyGetHtml(obj->ptdoc->doc);
981 			break;
982 
983 		case is_head_node:
984 			node = tidyGetHead(obj->ptdoc->doc);
985 			break;
986 
987 		case is_body_node:
988 			node = tidyGetBody(obj->ptdoc->doc);
989 			break;
990 
991 		default:
992 			RETURN_NULL();
993 			break;
994 	}
995 
996 	if (!node) {
997 		RETURN_NULL();
998 	}
999 
1000 	tidy_instanciate(tidy_ce_node, return_value TSRMLS_CC);
1001 	newobj = (PHPTidyObj *) zend_object_store_get_object(return_value TSRMLS_CC);
1002 	newobj->type  = is_node;
1003 	newobj->ptdoc = obj->ptdoc;
1004 	newobj->node  = node;
1005 	newobj->ptdoc->ref_count++;
1006 
1007 	tidy_add_default_properties(newobj, is_node TSRMLS_CC);
1008 }
1009 
_php_tidy_apply_config_array(TidyDoc doc,HashTable * ht_options TSRMLS_DC)1010 static int _php_tidy_apply_config_array(TidyDoc doc, HashTable *ht_options TSRMLS_DC)
1011 {
1012 	char *opt_name = NULL;
1013 	zval **opt_val;
1014 	ulong opt_indx;
1015 
1016 	for (zend_hash_internal_pointer_reset(ht_options);
1017 		 zend_hash_get_current_data(ht_options, (void **)&opt_val) == SUCCESS;
1018 		 zend_hash_move_forward(ht_options)) {
1019 
1020 		if(zend_hash_get_current_key(ht_options, &opt_name, &opt_indx, FALSE) == FAILURE) {
1021 			php_error_docref(NULL TSRMLS_CC, E_ERROR, "Could not retrieve key from option array");
1022 			return FAILURE;
1023 		}
1024 
1025 		if(opt_name) {
1026 			_php_tidy_set_tidy_opt(doc, opt_name, *opt_val TSRMLS_CC);
1027 			opt_name = NULL;
1028 		}
1029 
1030 	}
1031 
1032 	return SUCCESS;
1033 }
1034 
php_tidy_parse_string(PHPTidyObj * obj,char * string,int len,char * enc TSRMLS_DC)1035 static int php_tidy_parse_string(PHPTidyObj *obj, char *string, int len, char *enc TSRMLS_DC)
1036 {
1037 	TidyBuffer buf;
1038 
1039 	if(enc) {
1040 		if (tidySetCharEncoding(obj->ptdoc->doc, enc) < 0) {
1041 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not set encoding '%s'", enc);
1042 			return FAILURE;
1043 		}
1044 	}
1045 
1046 	obj->ptdoc->initialized = 1;
1047 
1048 	tidyBufInit(&buf);
1049 	tidyBufAppend(&buf, string, len);
1050 	if (tidyParseBuffer(obj->ptdoc->doc, &buf) < 0) {
1051 		tidyBufFree(&buf);
1052 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", obj->ptdoc->errbuf->bp);
1053 		return FAILURE;
1054 
1055 	}
1056 	tidyBufFree(&buf);
1057 	tidy_doc_update_properties(obj TSRMLS_CC);
1058 
1059 	return SUCCESS;
1060 }
1061 
PHP_MINIT_FUNCTION(tidy)1062 static PHP_MINIT_FUNCTION(tidy)
1063 {
1064 	REGISTER_INI_ENTRIES();
1065 	REGISTER_TIDY_CLASS(tidy, doc,	NULL, 0);
1066 	REGISTER_TIDY_CLASS(tidyNode, node,	NULL, ZEND_ACC_FINAL_CLASS);
1067 
1068 	tidy_object_handlers_doc.cast_object = tidy_doc_cast_handler;
1069 	tidy_object_handlers_node.cast_object = tidy_node_cast_handler;
1070 
1071 	_php_tidy_register_tags(INIT_FUNC_ARGS_PASSTHRU);
1072 	_php_tidy_register_nodetypes(INIT_FUNC_ARGS_PASSTHRU);
1073 
1074 	return SUCCESS;
1075 }
1076 
PHP_RINIT_FUNCTION(tidy)1077 static PHP_RINIT_FUNCTION(tidy)
1078 {
1079 	if (INI_BOOL("tidy.clean_output") == TRUE) {
1080 		if (php_start_ob_buffer_named("ob_tidyhandler", 0, 1 TSRMLS_CC) == FAILURE) {
1081 			zend_error(E_NOTICE, "Failure installing Tidy output buffering.");
1082 		}
1083 	}
1084 
1085 	return SUCCESS;
1086 }
1087 
PHP_MSHUTDOWN_FUNCTION(tidy)1088 static PHP_MSHUTDOWN_FUNCTION(tidy)
1089 {
1090 	UNREGISTER_INI_ENTRIES();
1091 	return SUCCESS;
1092 }
1093 
PHP_MINFO_FUNCTION(tidy)1094 static PHP_MINFO_FUNCTION(tidy)
1095 {
1096 	php_info_print_table_start();
1097 	php_info_print_table_header(2, "Tidy support", "enabled");
1098 	php_info_print_table_row(2, "libTidy Release", (char *)tidyReleaseDate());
1099 	php_info_print_table_row(2, "Extension Version", PHP_TIDY_MODULE_VERSION " ($Id$)");
1100 	php_info_print_table_end();
1101 
1102 	DISPLAY_INI_ENTRIES();
1103 }
1104 
PHP_FUNCTION(ob_tidyhandler)1105 static PHP_FUNCTION(ob_tidyhandler)
1106 {
1107 	char *input;
1108 	int input_len;
1109 	long mode;
1110 	TidyBuffer errbuf;
1111 	TidyDoc doc;
1112 
1113 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &input, &input_len, &mode) == FAILURE) {
1114 		return;
1115 	}
1116 
1117 	doc = tidyCreate();
1118 	tidyBufInit(&errbuf);
1119 
1120 	tidyOptSetBool(doc, TidyForceOutput, yes);
1121 	tidyOptSetBool(doc, TidyMark, no);
1122 
1123 	if (tidySetErrorBuffer(doc, &errbuf) != 0) {
1124 		tidyRelease(doc);
1125 		tidyBufFree(&errbuf);
1126 
1127 		php_error_docref(NULL TSRMLS_CC, E_ERROR, "Could not set Tidy error buffer");
1128 	}
1129 
1130 	TIDY_SET_DEFAULT_CONFIG(doc);
1131 
1132 	if (input_len > 1) {
1133 		TidyBuffer buf;
1134 
1135 		tidyBufInit(&buf);
1136 		tidyBufAppend(&buf, input, input_len);
1137 
1138 		if (tidyParseBuffer(doc, &buf) < 0 || tidyCleanAndRepair(doc) < 0) {
1139 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errbuf.bp);
1140 			RETVAL_NULL();
1141 		} else {
1142 			TidyBuffer output;
1143 			tidyBufInit(&output);
1144 
1145 			tidySaveBuffer(doc, &output);
1146 			RETVAL_STRINGL((char*)output.bp, output.size ? output.size-1 : 0, 1);
1147 
1148 			tidyBufFree(&output);
1149 		}
1150 
1151 		tidyBufFree(&buf);
1152 	} else {
1153 		RETVAL_NULL();
1154 	}
1155 
1156 	tidyRelease(doc);
1157 	tidyBufFree(&errbuf);
1158 }
1159 
1160 /* {{{ proto bool tidy_parse_string(string input [, mixed config_options [, string encoding]])
1161    Parse a document stored in a string */
PHP_FUNCTION(tidy_parse_string)1162 static PHP_FUNCTION(tidy_parse_string)
1163 {
1164 	char *input, *enc = NULL;
1165 	int input_len, enc_len = 0;
1166 	zval **options = NULL;
1167 
1168 	PHPTidyObj *obj;
1169 
1170 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|Zs", &input, &input_len, &options, &enc, &enc_len) == FAILURE) {
1171 		RETURN_FALSE;
1172 	}
1173 
1174 	tidy_instanciate(tidy_ce_doc, return_value TSRMLS_CC);
1175 	obj = (PHPTidyObj *) zend_object_store_get_object(return_value TSRMLS_CC);
1176 
1177 	TIDY_APPLY_CONFIG_ZVAL(obj->ptdoc->doc, options);
1178 
1179 	if(php_tidy_parse_string(obj, input, input_len, enc TSRMLS_CC) == FAILURE) {
1180 		zval_dtor(return_value);
1181 		INIT_ZVAL(*return_value);
1182 		RETURN_FALSE;
1183 	}
1184 
1185 }
1186 /* }}} */
1187 
1188 /* {{{ proto string tidy_get_error_buffer([boolean detailed])
1189    Return warnings and errors which occured parsing the specified document*/
PHP_FUNCTION(tidy_get_error_buffer)1190 static PHP_FUNCTION(tidy_get_error_buffer)
1191 {
1192 	TIDY_FETCH_OBJECT;
1193 
1194 	if (obj->ptdoc->errbuf && obj->ptdoc->errbuf->bp) {
1195 		RETURN_STRINGL((char*)obj->ptdoc->errbuf->bp, obj->ptdoc->errbuf->size-1, 1);
1196 	} else {
1197 		RETURN_FALSE;
1198 	}
1199 }
1200 /* }}} */
1201 
1202 /* {{{ proto string tidy_get_output()
1203    Return a string representing the parsed tidy markup */
PHP_FUNCTION(tidy_get_output)1204 static PHP_FUNCTION(tidy_get_output)
1205 {
1206 	TidyBuffer output;
1207 	TIDY_FETCH_OBJECT;
1208 
1209 	tidyBufInit(&output);
1210 	tidySaveBuffer(obj->ptdoc->doc, &output);
1211 
1212 	RETVAL_STRINGL((char*)output.bp, output.size ? output.size-1 : 0, 1);
1213 
1214 	tidyBufFree(&output);
1215 }
1216 /* }}} */
1217 
1218 /* {{{ proto boolean tidy_parse_file(string file [, mixed config_options [, string encoding [, bool use_include_path]]])
1219    Parse markup in file or URI */
PHP_FUNCTION(tidy_parse_file)1220 static PHP_FUNCTION(tidy_parse_file)
1221 {
1222 	char *inputfile, *enc = NULL;
1223 	int input_len, contents_len, enc_len = 0;
1224 	zend_bool use_include_path = 0;
1225 	char *contents;
1226 	zval **options = NULL;
1227 
1228 	PHPTidyObj *obj;
1229 
1230 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|Zsb", &inputfile, &input_len,
1231 							  &options, &enc, &enc_len, &use_include_path) == FAILURE) {
1232 		RETURN_FALSE;
1233 	}
1234 
1235 	if (strlen(inputfile) != input_len) {
1236 		RETURN_FALSE;
1237 	}
1238 	tidy_instanciate(tidy_ce_doc, return_value TSRMLS_CC);
1239 	obj = (PHPTidyObj *) zend_object_store_get_object(return_value TSRMLS_CC);
1240 
1241 	if (!(contents = php_tidy_file_to_mem(inputfile, use_include_path, &contents_len TSRMLS_CC))) {
1242 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot Load '%s' into memory%s", inputfile, (use_include_path) ? " (Using include path)" : "");
1243 		RETURN_FALSE;
1244 	}
1245 
1246 	TIDY_APPLY_CONFIG_ZVAL(obj->ptdoc->doc, options);
1247 
1248 	if(php_tidy_parse_string(obj, contents, contents_len, enc TSRMLS_CC) == FAILURE) {
1249 		zval_dtor(return_value);
1250 		INIT_ZVAL(*return_value);
1251 		RETVAL_FALSE;
1252 	}
1253 
1254 	efree(contents);
1255 }
1256 /* }}} */
1257 
1258 /* {{{ proto boolean tidy_clean_repair()
1259    Execute configured cleanup and repair operations on parsed markup */
PHP_FUNCTION(tidy_clean_repair)1260 static PHP_FUNCTION(tidy_clean_repair)
1261 {
1262 	TIDY_FETCH_OBJECT;
1263 
1264 	if (tidyCleanAndRepair(obj->ptdoc->doc) >= 0) {
1265 		tidy_doc_update_properties(obj TSRMLS_CC);
1266 		RETURN_TRUE;
1267 	}
1268 
1269 	RETURN_FALSE;
1270 }
1271 /* }}} */
1272 
1273 /* {{{ proto boolean tidy_repair_string(string data [, mixed config_file [, string encoding]])
1274    Repair a string using an optionally provided configuration file */
PHP_FUNCTION(tidy_repair_string)1275 static PHP_FUNCTION(tidy_repair_string)
1276 {
1277 	php_tidy_quick_repair(INTERNAL_FUNCTION_PARAM_PASSTHRU, FALSE);
1278 }
1279 /* }}} */
1280 
1281 /* {{{ proto boolean tidy_repair_file(string filename [, mixed config_file [, string encoding [, bool use_include_path]]])
1282    Repair a file using an optionally provided configuration file */
PHP_FUNCTION(tidy_repair_file)1283 static PHP_FUNCTION(tidy_repair_file)
1284 {
1285 	php_tidy_quick_repair(INTERNAL_FUNCTION_PARAM_PASSTHRU, TRUE);
1286 }
1287 /* }}} */
1288 
1289 /* {{{ proto boolean tidy_diagnose()
1290    Run configured diagnostics on parsed and repaired markup. */
PHP_FUNCTION(tidy_diagnose)1291 static PHP_FUNCTION(tidy_diagnose)
1292 {
1293 	TIDY_FETCH_OBJECT;
1294 
1295 	if (obj->ptdoc->initialized && tidyRunDiagnostics(obj->ptdoc->doc) >= 0) {
1296 		tidy_doc_update_properties(obj TSRMLS_CC);
1297 		RETURN_TRUE;
1298 	}
1299 
1300 	RETURN_FALSE;
1301 }
1302 /* }}} */
1303 
1304 /* {{{ proto string tidy_get_release()
1305    Get release date (version) for Tidy library */
PHP_FUNCTION(tidy_get_release)1306 static PHP_FUNCTION(tidy_get_release)
1307 {
1308 	if (zend_parse_parameters_none() == FAILURE) {
1309 		return;
1310 	}
1311 
1312 	RETURN_STRING((char *)tidyReleaseDate(), 1);
1313 }
1314 /* }}} */
1315 
1316 
1317 #if HAVE_TIDYOPTGETDOC
1318 /* {{{ proto string tidy_get_opt_doc(tidy resource, string optname)
1319    Returns the documentation for the given option name */
PHP_FUNCTION(tidy_get_opt_doc)1320 static PHP_FUNCTION(tidy_get_opt_doc)
1321 {
1322 	PHPTidyObj *obj;
1323 	char *optname, *optval;
1324 	int optname_len;
1325 	TidyOption opt;
1326 
1327 	TIDY_SET_CONTEXT;
1328 
1329 	if (object) {
1330 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &optname, &optname_len) == FAILURE) {
1331 			RETURN_FALSE;
1332 		}
1333 	} else {
1334 		if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, NULL, "Os", &object, tidy_ce_doc, &optname, &optname_len) == FAILURE) {
1335 			RETURN_FALSE;
1336 		}
1337 	}
1338 
1339 	obj = (PHPTidyObj *) zend_object_store_get_object(object TSRMLS_CC);
1340 
1341 	opt = tidyGetOptionByName(obj->ptdoc->doc, optname);
1342 
1343 	if (!opt) {
1344 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown Tidy Configuration Option '%s'", optname);
1345 		RETURN_FALSE;
1346 	}
1347 
1348 	if ( (optval = (char *) tidyOptGetDoc(obj->ptdoc->doc, opt)) ) {
1349 		RETURN_STRING(optval, 1);
1350 	}
1351 
1352 	RETURN_FALSE;
1353 }
1354 /* }}} */
1355 #endif
1356 
1357 
1358 /* {{{ proto array tidy_get_config()
1359    Get current Tidy configuarion */
PHP_FUNCTION(tidy_get_config)1360 static PHP_FUNCTION(tidy_get_config)
1361 {
1362 	TidyIterator itOpt;
1363 	char *opt_name;
1364 	void *opt_value;
1365 	TidyOptionType optt;
1366 
1367 	TIDY_FETCH_OBJECT;
1368 
1369 	itOpt = tidyGetOptionList(obj->ptdoc->doc);
1370 
1371 	array_init(return_value);
1372 
1373 	while (itOpt) {
1374 		TidyOption opt = tidyGetNextOption(obj->ptdoc->doc, &itOpt);
1375 
1376 		opt_name = (char *)tidyOptGetName(opt);
1377 		opt_value = php_tidy_get_opt_val(obj->ptdoc, opt, &optt TSRMLS_CC);
1378 		switch (optt) {
1379 			case TidyString:
1380 				add_assoc_string(return_value, opt_name, (char*)opt_value, 0);
1381 				break;
1382 
1383 			case TidyInteger:
1384 				add_assoc_long(return_value, opt_name, (long)opt_value);
1385 				break;
1386 
1387 			case TidyBoolean:
1388 				add_assoc_bool(return_value, opt_name, (long)opt_value);
1389 				break;
1390 		}
1391 	}
1392 
1393 	return;
1394 }
1395 /* }}} */
1396 
1397 /* {{{ proto int tidy_get_status()
1398    Get status of specfied document. */
PHP_FUNCTION(tidy_get_status)1399 static PHP_FUNCTION(tidy_get_status)
1400 {
1401 	TIDY_FETCH_OBJECT;
1402 
1403 	RETURN_LONG(tidyStatus(obj->ptdoc->doc));
1404 }
1405 /* }}} */
1406 
1407 /* {{{ proto int tidy_get_html_ver()
1408    Get the Detected HTML version for the specified document. */
PHP_FUNCTION(tidy_get_html_ver)1409 static PHP_FUNCTION(tidy_get_html_ver)
1410 {
1411 	TIDY_FETCH_OBJECT;
1412 
1413 	RETURN_LONG(tidyDetectedHtmlVersion(obj->ptdoc->doc));
1414 }
1415 /* }}} */
1416 
1417 /* {{{ proto boolean tidy_is_xhtml()
1418    Indicates if the document is a XHTML document. */
PHP_FUNCTION(tidy_is_xhtml)1419 static PHP_FUNCTION(tidy_is_xhtml)
1420 {
1421 	TIDY_FETCH_OBJECT;
1422 
1423 	RETURN_BOOL(tidyDetectedXhtml(obj->ptdoc->doc));
1424 }
1425 /* }}} */
1426 
1427 /* {{{ proto boolean tidy_is_xml()
1428    Indicates if the document is a generic (non HTML/XHTML) XML document. */
PHP_FUNCTION(tidy_is_xml)1429 static PHP_FUNCTION(tidy_is_xml)
1430 {
1431 	TIDY_FETCH_OBJECT;
1432 
1433 	RETURN_BOOL(tidyDetectedGenericXml(obj->ptdoc->doc));
1434 }
1435 /* }}} */
1436 
1437 /* {{{ proto int tidy_error_count()
1438    Returns the Number of Tidy errors encountered for specified document. */
PHP_FUNCTION(tidy_error_count)1439 static PHP_FUNCTION(tidy_error_count)
1440 {
1441 	TIDY_FETCH_OBJECT;
1442 
1443 	RETURN_LONG(tidyErrorCount(obj->ptdoc->doc));
1444 }
1445 /* }}} */
1446 
1447 /* {{{ proto int tidy_warning_count()
1448    Returns the Number of Tidy warnings encountered for specified document. */
PHP_FUNCTION(tidy_warning_count)1449 static PHP_FUNCTION(tidy_warning_count)
1450 {
1451 	TIDY_FETCH_OBJECT;
1452 
1453 	RETURN_LONG(tidyWarningCount(obj->ptdoc->doc));
1454 }
1455 /* }}} */
1456 
1457 /* {{{ proto int tidy_access_count()
1458    Returns the Number of Tidy accessibility warnings encountered for specified document. */
PHP_FUNCTION(tidy_access_count)1459 static PHP_FUNCTION(tidy_access_count)
1460 {
1461 	TIDY_FETCH_OBJECT;
1462 
1463 	RETURN_LONG(tidyAccessWarningCount(obj->ptdoc->doc));
1464 }
1465 /* }}} */
1466 
1467 /* {{{ proto int tidy_config_count()
1468    Returns the Number of Tidy configuration errors encountered for specified document. */
PHP_FUNCTION(tidy_config_count)1469 static PHP_FUNCTION(tidy_config_count)
1470 {
1471 	TIDY_FETCH_OBJECT;
1472 
1473 	RETURN_LONG(tidyConfigErrorCount(obj->ptdoc->doc));
1474 }
1475 /* }}} */
1476 
1477 /* {{{ proto mixed tidy_getopt(string option)
1478    Returns the value of the specified configuration option for the tidy document. */
PHP_FUNCTION(tidy_getopt)1479 static PHP_FUNCTION(tidy_getopt)
1480 {
1481 	PHPTidyObj *obj;
1482 	char *optname;
1483 	void *optval;
1484 	int optname_len;
1485 	TidyOption opt;
1486 	TidyOptionType optt;
1487 
1488 	TIDY_SET_CONTEXT;
1489 
1490 	if (object) {
1491 		if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &optname, &optname_len) == FAILURE) {
1492 			RETURN_FALSE;
1493 		}
1494 	} else {
1495 		if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, NULL, "Os", &object, tidy_ce_doc, &optname, &optname_len) == FAILURE) {
1496 			RETURN_FALSE;
1497 		}
1498 	}
1499 
1500 	obj = (PHPTidyObj *) zend_object_store_get_object(object TSRMLS_CC);
1501 
1502 	opt = tidyGetOptionByName(obj->ptdoc->doc, optname);
1503 
1504 	if (!opt) {
1505 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown Tidy Configuration Option '%s'", optname);
1506 		RETURN_FALSE;
1507 	}
1508 
1509 	optval = php_tidy_get_opt_val(obj->ptdoc, opt, &optt TSRMLS_CC);
1510 	switch (optt) {
1511 		case TidyString:
1512 			RETURN_STRING((char *)optval, 0);
1513 			break;
1514 
1515 		case TidyInteger:
1516 			RETURN_LONG((long)optval);
1517 			break;
1518 
1519 		case TidyBoolean:
1520 			if (optval) {
1521 				RETURN_TRUE;
1522 			} else {
1523 				RETURN_FALSE;
1524 			}
1525 			break;
1526 
1527 		default:
1528 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to determine type of configuration option");
1529 			break;
1530 	}
1531 
1532 	RETURN_FALSE;
1533 }
1534 /* }}} */
1535 
TIDY_DOC_METHOD(__construct)1536 static TIDY_DOC_METHOD(__construct)
1537 {
1538 	char *inputfile = NULL, *enc = NULL;
1539 	int input_len = 0, enc_len = 0, contents_len = 0;
1540 	zend_bool use_include_path = 0;
1541 	char *contents;
1542 	zval **options = NULL;
1543 
1544 	PHPTidyObj *obj;
1545 	TIDY_SET_CONTEXT;
1546 
1547 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sZsb", &inputfile, &input_len,
1548 							  &options, &enc, &enc_len, &use_include_path) == FAILURE) {
1549 		RETURN_FALSE;
1550 	}
1551 
1552 	obj = (PHPTidyObj *)zend_object_store_get_object(object TSRMLS_CC);
1553 
1554 	if (inputfile) {
1555 		if (strlen(inputfile) != input_len) {
1556 			RETURN_FALSE;
1557 		}
1558 		if (!(contents = php_tidy_file_to_mem(inputfile, use_include_path, &contents_len TSRMLS_CC))) {
1559 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot Load '%s' into memory %s", inputfile, (use_include_path) ? "(Using include path)" : "");
1560 			return;
1561 		}
1562 
1563 		TIDY_APPLY_CONFIG_ZVAL(obj->ptdoc->doc, options);
1564 
1565 		php_tidy_parse_string(obj, contents, contents_len, enc TSRMLS_CC);
1566 
1567 		efree(contents);
1568 	}
1569 }
1570 
TIDY_DOC_METHOD(parseFile)1571 static TIDY_DOC_METHOD(parseFile)
1572 {
1573 	char *inputfile, *enc = NULL;
1574 	int input_len, enc_len = 0, contents_len = 0;
1575 	zend_bool use_include_path = 0;
1576 	char *contents;
1577 	zval **options = NULL;
1578 	PHPTidyObj *obj;
1579 
1580 	TIDY_SET_CONTEXT;
1581 
1582 	obj = (PHPTidyObj *)zend_object_store_get_object(object TSRMLS_CC);
1583 
1584 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|Zsb", &inputfile, &input_len,
1585 							  &options, &enc, &enc_len, &use_include_path) == FAILURE) {
1586 		RETURN_FALSE;
1587 	}
1588 
1589 	if (strlen(inputfile) != input_len) {
1590 		RETURN_FALSE;
1591 	}
1592 	if (!(contents = php_tidy_file_to_mem(inputfile, use_include_path, &contents_len TSRMLS_CC))) {
1593 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot Load '%s' into memory %s", inputfile, (use_include_path) ? "(Using include path)" : "");
1594 		RETURN_FALSE;
1595 	}
1596 
1597 	TIDY_APPLY_CONFIG_ZVAL(obj->ptdoc->doc, options);
1598 
1599 	if(php_tidy_parse_string(obj, contents, contents_len, enc TSRMLS_CC) == FAILURE) {
1600 		RETVAL_FALSE;
1601 	} else {
1602 		RETVAL_TRUE;
1603 	}
1604 
1605 	efree(contents);
1606 }
1607 
TIDY_DOC_METHOD(parseString)1608 static TIDY_DOC_METHOD(parseString)
1609 {
1610 	char *input, *enc = NULL;
1611 	int input_len, enc_len = 0;
1612 	zval **options = NULL;
1613 	PHPTidyObj *obj;
1614 
1615 	TIDY_SET_CONTEXT;
1616 
1617 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|Zs", &input, &input_len, &options, &enc, &enc_len) == FAILURE) {
1618 		RETURN_FALSE;
1619 	}
1620 
1621 	obj = (PHPTidyObj *)zend_object_store_get_object(object TSRMLS_CC);
1622 
1623 	TIDY_APPLY_CONFIG_ZVAL(obj->ptdoc->doc, options);
1624 
1625 	if(php_tidy_parse_string(obj, input, input_len, enc TSRMLS_CC) == SUCCESS) {
1626 		RETURN_TRUE;
1627 	}
1628 
1629 	RETURN_FALSE;
1630 }
1631 
1632 
1633 /* {{{ proto TidyNode tidy_get_root()
1634    Returns a TidyNode Object representing the root of the tidy parse tree */
PHP_FUNCTION(tidy_get_root)1635 static PHP_FUNCTION(tidy_get_root)
1636 {
1637 	php_tidy_create_node(INTERNAL_FUNCTION_PARAM_PASSTHRU, is_root_node);
1638 }
1639 /* }}} */
1640 
1641 /* {{{ proto TidyNode tidy_get_html()
1642    Returns a TidyNode Object starting from the <HTML> tag of the tidy parse tree */
PHP_FUNCTION(tidy_get_html)1643 static PHP_FUNCTION(tidy_get_html)
1644 {
1645 	php_tidy_create_node(INTERNAL_FUNCTION_PARAM_PASSTHRU, is_html_node);
1646 }
1647 /* }}} */
1648 
1649 /* {{{ proto TidyNode tidy_get_head()
1650    Returns a TidyNode Object starting from the <HEAD> tag of the tidy parse tree */
PHP_FUNCTION(tidy_get_head)1651 static PHP_FUNCTION(tidy_get_head)
1652 {
1653 	php_tidy_create_node(INTERNAL_FUNCTION_PARAM_PASSTHRU, is_head_node);
1654 }
1655 /* }}} */
1656 
1657 /* {{{ proto TidyNode tidy_get_body(resource tidy)
1658    Returns a TidyNode Object starting from the <BODY> tag of the tidy parse tree */
PHP_FUNCTION(tidy_get_body)1659 static PHP_FUNCTION(tidy_get_body)
1660 {
1661 	php_tidy_create_node(INTERNAL_FUNCTION_PARAM_PASSTHRU, is_body_node);
1662 }
1663 /* }}} */
1664 
1665 /* {{{ proto boolean tidyNode::hasChildren()
1666    Returns true if this node has children */
TIDY_NODE_METHOD(hasChildren)1667 static TIDY_NODE_METHOD(hasChildren)
1668 {
1669 	TIDY_FETCH_ONLY_OBJECT;
1670 
1671 	if (tidyGetChild(obj->node)) {
1672 		RETURN_TRUE;
1673 	} else {
1674 		RETURN_FALSE;
1675 	}
1676 }
1677 /* }}} */
1678 
1679 /* {{{ proto boolean tidyNode::hasSiblings()
1680    Returns true if this node has siblings */
TIDY_NODE_METHOD(hasSiblings)1681 static TIDY_NODE_METHOD(hasSiblings)
1682 {
1683 	TIDY_FETCH_ONLY_OBJECT;
1684 
1685 	if (obj->node && tidyGetNext(obj->node)) {
1686 		RETURN_TRUE;
1687 	} else {
1688 		RETURN_FALSE;
1689 	}
1690 }
1691 /* }}} */
1692 
1693 /* {{{ proto boolean tidyNode::isComment()
1694    Returns true if this node represents a comment */
TIDY_NODE_METHOD(isComment)1695 static TIDY_NODE_METHOD(isComment)
1696 {
1697 	TIDY_FETCH_ONLY_OBJECT;
1698 
1699 	if (tidyNodeGetType(obj->node) == TidyNode_Comment) {
1700 		RETURN_TRUE;
1701 	} else {
1702 		RETURN_FALSE;
1703 	}
1704 }
1705 /* }}} */
1706 
1707 /* {{{ proto boolean tidyNode::isHtml()
1708    Returns true if this node is part of a HTML document */
TIDY_NODE_METHOD(isHtml)1709 static TIDY_NODE_METHOD(isHtml)
1710 {
1711 	TIDY_FETCH_ONLY_OBJECT;
1712 
1713 	if (tidyNodeGetType(obj->node) & (TidyNode_Start | TidyNode_End | TidyNode_StartEnd)) {
1714 		RETURN_TRUE;
1715 	}
1716 
1717 	RETURN_FALSE;
1718 }
1719 /* }}} */
1720 
1721 /* {{{ proto boolean tidyNode::isText()
1722    Returns true if this node represents text (no markup) */
TIDY_NODE_METHOD(isText)1723 static TIDY_NODE_METHOD(isText)
1724 {
1725 	TIDY_FETCH_ONLY_OBJECT;
1726 
1727 	if (tidyNodeGetType(obj->node) == TidyNode_Text) {
1728 		RETURN_TRUE;
1729 	} else {
1730 		RETURN_FALSE;
1731 	}
1732 }
1733 /* }}} */
1734 
1735 /* {{{ proto boolean tidyNode::isJste()
1736    Returns true if this node is JSTE */
TIDY_NODE_METHOD(isJste)1737 static TIDY_NODE_METHOD(isJste)
1738 {
1739 	TIDY_FETCH_ONLY_OBJECT;
1740 
1741 	if (tidyNodeGetType(obj->node) == TidyNode_Jste) {
1742 		RETURN_TRUE;
1743 	} else {
1744 		RETURN_FALSE;
1745 	}
1746 }
1747 /* }}} */
1748 
1749 /* {{{ proto boolean tidyNode::isAsp()
1750    Returns true if this node is ASP */
TIDY_NODE_METHOD(isAsp)1751 static TIDY_NODE_METHOD(isAsp)
1752 {
1753 	TIDY_FETCH_ONLY_OBJECT;
1754 
1755 	if (tidyNodeGetType(obj->node) == TidyNode_Asp) {
1756 		RETURN_TRUE;
1757 	} else {
1758 		RETURN_FALSE;
1759 	}
1760 }
1761 /* }}} */
1762 
1763 /* {{{ proto boolean tidyNode::isPhp()
1764    Returns true if this node is PHP */
TIDY_NODE_METHOD(isPhp)1765 static TIDY_NODE_METHOD(isPhp)
1766 {
1767 	TIDY_FETCH_ONLY_OBJECT;
1768 
1769 	if (tidyNodeGetType(obj->node) == TidyNode_Php) {
1770 		RETURN_TRUE;
1771 	} else {
1772 		RETURN_FALSE;
1773 	}
1774 }
1775 /* }}} */
1776 
1777 /* {{{ proto tidyNode tidyNode::getParent()
1778    Returns the parent node if available or NULL */
TIDY_NODE_METHOD(getParent)1779 static TIDY_NODE_METHOD(getParent)
1780 {
1781 	TidyNode	parent_node;
1782 	PHPTidyObj *newobj;
1783 	TIDY_FETCH_ONLY_OBJECT;
1784 
1785 	parent_node = tidyGetParent(obj->node);
1786 	if(parent_node) {
1787 		tidy_instanciate(tidy_ce_node, return_value TSRMLS_CC);
1788 		newobj = (PHPTidyObj *) zend_object_store_get_object(return_value TSRMLS_CC);
1789 		newobj->node = parent_node;
1790 		newobj->type = is_node;
1791 		newobj->ptdoc = obj->ptdoc;
1792 		newobj->ptdoc->ref_count++;
1793 		tidy_add_default_properties(newobj, is_node TSRMLS_CC);
1794 	} else {
1795 		ZVAL_NULL(return_value);
1796 	}
1797 }
1798 /* }}} */
1799 
1800 /* {{{ proto void tidyNode::__construct()
1801          __constructor for tidyNode. */
TIDY_NODE_METHOD(__construct)1802 static TIDY_NODE_METHOD(__construct)
1803 {
1804 	php_error_docref(NULL TSRMLS_CC, E_ERROR, "You should not create a tidyNode manually");
1805 }
1806 /* }}} */
1807 
_php_tidy_register_nodetypes(INIT_FUNC_ARGS)1808 static void _php_tidy_register_nodetypes(INIT_FUNC_ARGS)
1809 {
1810 	TIDY_NODE_CONST(ROOT, Root);
1811 	TIDY_NODE_CONST(DOCTYPE, DocType);
1812 	TIDY_NODE_CONST(COMMENT, Comment);
1813 	TIDY_NODE_CONST(PROCINS, ProcIns);
1814 	TIDY_NODE_CONST(TEXT, Text);
1815 	TIDY_NODE_CONST(START, Start);
1816 	TIDY_NODE_CONST(END, End);
1817 	TIDY_NODE_CONST(STARTEND, StartEnd);
1818 	TIDY_NODE_CONST(CDATA, CDATA);
1819 	TIDY_NODE_CONST(SECTION, Section);
1820 	TIDY_NODE_CONST(ASP, Asp);
1821 	TIDY_NODE_CONST(JSTE, Jste);
1822 	TIDY_NODE_CONST(PHP, Php);
1823 	TIDY_NODE_CONST(XMLDECL, XmlDecl);
1824 }
1825 
_php_tidy_register_tags(INIT_FUNC_ARGS)1826 static void _php_tidy_register_tags(INIT_FUNC_ARGS)
1827 {
1828 	TIDY_TAG_CONST(UNKNOWN);
1829 	TIDY_TAG_CONST(A);
1830 	TIDY_TAG_CONST(ABBR);
1831 	TIDY_TAG_CONST(ACRONYM);
1832 	TIDY_TAG_CONST(ADDRESS);
1833 	TIDY_TAG_CONST(ALIGN);
1834 	TIDY_TAG_CONST(APPLET);
1835 	TIDY_TAG_CONST(AREA);
1836 	TIDY_TAG_CONST(B);
1837 	TIDY_TAG_CONST(BASE);
1838 	TIDY_TAG_CONST(BASEFONT);
1839 	TIDY_TAG_CONST(BDO);
1840 	TIDY_TAG_CONST(BGSOUND);
1841 	TIDY_TAG_CONST(BIG);
1842 	TIDY_TAG_CONST(BLINK);
1843 	TIDY_TAG_CONST(BLOCKQUOTE);
1844 	TIDY_TAG_CONST(BODY);
1845 	TIDY_TAG_CONST(BR);
1846 	TIDY_TAG_CONST(BUTTON);
1847 	TIDY_TAG_CONST(CAPTION);
1848 	TIDY_TAG_CONST(CENTER);
1849 	TIDY_TAG_CONST(CITE);
1850 	TIDY_TAG_CONST(CODE);
1851 	TIDY_TAG_CONST(COL);
1852 	TIDY_TAG_CONST(COLGROUP);
1853 	TIDY_TAG_CONST(COMMENT);
1854 	TIDY_TAG_CONST(DD);
1855 	TIDY_TAG_CONST(DEL);
1856 	TIDY_TAG_CONST(DFN);
1857 	TIDY_TAG_CONST(DIR);
1858 	TIDY_TAG_CONST(DIV);
1859 	TIDY_TAG_CONST(DL);
1860 	TIDY_TAG_CONST(DT);
1861 	TIDY_TAG_CONST(EM);
1862 	TIDY_TAG_CONST(EMBED);
1863 	TIDY_TAG_CONST(FIELDSET);
1864 	TIDY_TAG_CONST(FONT);
1865 	TIDY_TAG_CONST(FORM);
1866 	TIDY_TAG_CONST(FRAME);
1867 	TIDY_TAG_CONST(FRAMESET);
1868 	TIDY_TAG_CONST(H1);
1869 	TIDY_TAG_CONST(H2);
1870 	TIDY_TAG_CONST(H3);
1871 	TIDY_TAG_CONST(H4);
1872 	TIDY_TAG_CONST(H5);
1873 	TIDY_TAG_CONST(H6);
1874 	TIDY_TAG_CONST(HEAD);
1875 	TIDY_TAG_CONST(HR);
1876 	TIDY_TAG_CONST(HTML);
1877 	TIDY_TAG_CONST(I);
1878 	TIDY_TAG_CONST(IFRAME);
1879 	TIDY_TAG_CONST(ILAYER);
1880 	TIDY_TAG_CONST(IMG);
1881 	TIDY_TAG_CONST(INPUT);
1882 	TIDY_TAG_CONST(INS);
1883 	TIDY_TAG_CONST(ISINDEX);
1884 	TIDY_TAG_CONST(KBD);
1885 	TIDY_TAG_CONST(KEYGEN);
1886 	TIDY_TAG_CONST(LABEL);
1887 	TIDY_TAG_CONST(LAYER);
1888 	TIDY_TAG_CONST(LEGEND);
1889 	TIDY_TAG_CONST(LI);
1890 	TIDY_TAG_CONST(LINK);
1891 	TIDY_TAG_CONST(LISTING);
1892 	TIDY_TAG_CONST(MAP);
1893 	TIDY_TAG_CONST(MARQUEE);
1894 	TIDY_TAG_CONST(MENU);
1895 	TIDY_TAG_CONST(META);
1896 	TIDY_TAG_CONST(MULTICOL);
1897 	TIDY_TAG_CONST(NOBR);
1898 	TIDY_TAG_CONST(NOEMBED);
1899 	TIDY_TAG_CONST(NOFRAMES);
1900 	TIDY_TAG_CONST(NOLAYER);
1901 	TIDY_TAG_CONST(NOSAVE);
1902 	TIDY_TAG_CONST(NOSCRIPT);
1903 	TIDY_TAG_CONST(OBJECT);
1904 	TIDY_TAG_CONST(OL);
1905 	TIDY_TAG_CONST(OPTGROUP);
1906 	TIDY_TAG_CONST(OPTION);
1907 	TIDY_TAG_CONST(P);
1908 	TIDY_TAG_CONST(PARAM);
1909 	TIDY_TAG_CONST(PLAINTEXT);
1910 	TIDY_TAG_CONST(PRE);
1911 	TIDY_TAG_CONST(Q);
1912 	TIDY_TAG_CONST(RB);
1913 	TIDY_TAG_CONST(RBC);
1914 	TIDY_TAG_CONST(RP);
1915 	TIDY_TAG_CONST(RT);
1916 	TIDY_TAG_CONST(RTC);
1917 	TIDY_TAG_CONST(RUBY);
1918 	TIDY_TAG_CONST(S);
1919 	TIDY_TAG_CONST(SAMP);
1920 	TIDY_TAG_CONST(SCRIPT);
1921 	TIDY_TAG_CONST(SELECT);
1922 	TIDY_TAG_CONST(SERVER);
1923 	TIDY_TAG_CONST(SERVLET);
1924 	TIDY_TAG_CONST(SMALL);
1925 	TIDY_TAG_CONST(SPACER);
1926 	TIDY_TAG_CONST(SPAN);
1927 	TIDY_TAG_CONST(STRIKE);
1928 	TIDY_TAG_CONST(STRONG);
1929 	TIDY_TAG_CONST(STYLE);
1930 	TIDY_TAG_CONST(SUB);
1931 	TIDY_TAG_CONST(SUP);
1932 	TIDY_TAG_CONST(TABLE);
1933 	TIDY_TAG_CONST(TBODY);
1934 	TIDY_TAG_CONST(TD);
1935 	TIDY_TAG_CONST(TEXTAREA);
1936 	TIDY_TAG_CONST(TFOOT);
1937 	TIDY_TAG_CONST(TH);
1938 	TIDY_TAG_CONST(THEAD);
1939 	TIDY_TAG_CONST(TITLE);
1940 	TIDY_TAG_CONST(TR);
1941 	TIDY_TAG_CONST(TT);
1942 	TIDY_TAG_CONST(U);
1943 	TIDY_TAG_CONST(UL);
1944 	TIDY_TAG_CONST(VAR);
1945 	TIDY_TAG_CONST(WBR);
1946 	TIDY_TAG_CONST(XMP);
1947 }
1948 
1949 #endif
1950 
1951 /*
1952  * Local variables:
1953  * tab-width: 4
1954  * c-basic-offset: 4
1955  * End:
1956  * vim600: noet sw=4 ts=4 fdm=marker
1957  * vim<600: noet sw=4 ts=4
1958  */
1959