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