1 /*
2 +----------------------------------------------------------------------+
3 | Copyright (c) The PHP Group |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | http://www.php.net/license/3_01.txt. |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Author: Rob Richards <rrichards@php.net> |
14 | Pierre-A. Joye <pajoye@php.net> |
15 +----------------------------------------------------------------------+
16 */
17
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21
22
23 #include "php.h"
24 #include "php_ini.h"
25 #include "ext/standard/info.h"
26 #include "php_xmlwriter.h"
27 #include "php_xmlwriter_arginfo.h"
28 #include "ext/standard/php_string.h"
29
30 static zend_class_entry *xmlwriter_class_entry_ce;
31
32 typedef int (*xmlwriter_read_one_char_t)(xmlTextWriterPtr writer, const xmlChar *content);
33 typedef int (*xmlwriter_read_int_t)(xmlTextWriterPtr writer);
34
35 /* {{{ XMLWRITER_FROM_OBJECT */
36 #define XMLWRITER_FROM_OBJECT(ptr, object) \
37 { \
38 ze_xmlwriter_object *obj = Z_XMLWRITER_P(object); \
39 ptr = obj->ptr; \
40 if (!ptr) { \
41 zend_throw_error(NULL, "Invalid or uninitialized XMLWriter object"); \
42 RETURN_THROWS(); \
43 } \
44 }
45 /* }}} */
46
47 static zend_object_handlers xmlwriter_object_handlers;
48
49 /* {{{{ xmlwriter_object_dtor */
xmlwriter_object_dtor(zend_object * object)50 static void xmlwriter_object_dtor(zend_object *object)
51 {
52 ze_xmlwriter_object *intern = php_xmlwriter_fetch_object(object);
53
54 /* freeing the resource here may leak, but otherwise we may use it after it has been freed */
55 if (intern->ptr) {
56 xmlFreeTextWriter(intern->ptr);
57 intern->ptr = NULL;
58 }
59 if (intern->output) {
60 xmlBufferFree(intern->output);
61 intern->output = NULL;
62 }
63 zend_objects_destroy_object(object);
64 }
65 /* }}} */
66
67 /* {{{ xmlwriter_object_free_storage */
xmlwriter_object_free_storage(zend_object * object)68 static void xmlwriter_object_free_storage(zend_object *object)
69 {
70 ze_xmlwriter_object *intern = php_xmlwriter_fetch_object(object);
71
72 zend_object_std_dtor(&intern->std);
73 }
74 /* }}} */
75
76
77 /* {{{ xmlwriter_object_new */
xmlwriter_object_new(zend_class_entry * class_type)78 static zend_object *xmlwriter_object_new(zend_class_entry *class_type)
79 {
80 ze_xmlwriter_object *intern;
81
82 intern = zend_object_alloc(sizeof(ze_xmlwriter_object), class_type);
83 zend_object_std_init(&intern->std, class_type);
84 object_properties_init(&intern->std, class_type);
85 intern->std.handlers = &xmlwriter_object_handlers;
86
87 return &intern->std;
88 }
89 /* }}} */
90
91 #define XMLW_NAME_CHK(__arg_no, __subject) \
92 if (xmlValidateName((xmlChar *) name, 0) != 0) { \
93 zend_argument_value_error(__arg_no, "must be a valid %s, \"%s\" given", __subject, name); \
94 RETURN_THROWS(); \
95 } \
96
97 /* {{{ function prototypes */
98 static PHP_MINIT_FUNCTION(xmlwriter);
99 static PHP_MSHUTDOWN_FUNCTION(xmlwriter);
100 static PHP_MINFO_FUNCTION(xmlwriter);
101 /* }}} */
102
103 /* _xmlwriter_get_valid_file_path should be made a
104 common function in libxml extension as code is common to a few xml extensions */
105 /* {{{ _xmlwriter_get_valid_file_path */
_xmlwriter_get_valid_file_path(char * source,char * resolved_path,int resolved_path_len)106 static char *_xmlwriter_get_valid_file_path(char *source, char *resolved_path, int resolved_path_len ) {
107 xmlURI *uri;
108 xmlChar *escsource;
109 char *file_dest;
110 int isFileUri = 0;
111
112 uri = xmlCreateURI();
113 escsource = xmlURIEscapeStr((xmlChar *)source, (xmlChar *) ":");
114 xmlParseURIReference(uri, (char *)escsource);
115 xmlFree(escsource);
116
117 if (uri->scheme != NULL) {
118 /* absolute file uris - libxml only supports localhost or empty host */
119 if (strncasecmp(source, "file:///", 8) == 0) {
120 if (source[sizeof("file:///") - 1] == '\0') {
121 xmlFreeURI(uri);
122 return NULL;
123 }
124 isFileUri = 1;
125 #ifdef PHP_WIN32
126 source += 8;
127 #else
128 source += 7;
129 #endif
130 } else if (strncasecmp(source, "file://localhost/",17) == 0) {
131 if (source[sizeof("file://localhost/") - 1] == '\0') {
132 xmlFreeURI(uri);
133 return NULL;
134 }
135
136 isFileUri = 1;
137 #ifdef PHP_WIN32
138 source += 17;
139 #else
140 source += 16;
141 #endif
142 }
143 }
144
145 if ((uri->scheme == NULL || isFileUri)) {
146 char file_dirname[MAXPATHLEN];
147 size_t dir_len;
148
149 if (!VCWD_REALPATH(source, resolved_path) && !expand_filepath(source, resolved_path)) {
150 xmlFreeURI(uri);
151 return NULL;
152 }
153
154 memcpy(file_dirname, source, strlen(source));
155 dir_len = php_dirname(file_dirname, strlen(source));
156
157 if (dir_len > 0) {
158 zend_stat_t buf;
159 if (php_sys_stat(file_dirname, &buf) != 0) {
160 xmlFreeURI(uri);
161 return NULL;
162 }
163 }
164
165 file_dest = resolved_path;
166 } else {
167 file_dest = source;
168 }
169
170 xmlFreeURI(uri);
171
172 return file_dest;
173 }
174 /* }}} */
175
176 /* {{{ xmlwriter_module_entry */
177 zend_module_entry xmlwriter_module_entry = {
178 STANDARD_MODULE_HEADER,
179 "xmlwriter",
180 ext_functions,
181 PHP_MINIT(xmlwriter),
182 PHP_MSHUTDOWN(xmlwriter),
183 NULL,
184 NULL,
185 PHP_MINFO(xmlwriter),
186 PHP_XMLWRITER_VERSION,
187 STANDARD_MODULE_PROPERTIES
188 };
189 /* }}} */
190
191 #ifdef COMPILE_DL_XMLWRITER
ZEND_GET_MODULE(xmlwriter)192 ZEND_GET_MODULE(xmlwriter)
193 #endif
194
195 /* {{{ xmlwriter_objects_clone
196 static void xmlwriter_objects_clone(void *object, void **object_clone)
197 {
198 TODO
199 }
200 }}} */
201
202 static void php_xmlwriter_string_arg(INTERNAL_FUNCTION_PARAMETERS, xmlwriter_read_one_char_t internal_function, char *subject_name)
203 {
204 xmlTextWriterPtr ptr;
205 char *name;
206 size_t name_len;
207 int retval;
208 zval *self;
209
210 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &self, xmlwriter_class_entry_ce, &name, &name_len) == FAILURE) {
211 RETURN_THROWS();
212 }
213 XMLWRITER_FROM_OBJECT(ptr, self);
214
215 if (subject_name != NULL) {
216 XMLW_NAME_CHK(2, subject_name);
217 }
218
219 if (ptr) {
220 retval = internal_function(ptr, (xmlChar *) name);
221 if (retval != -1) {
222 RETURN_TRUE;
223 }
224 }
225
226 RETURN_FALSE;
227 }
228
php_xmlwriter_end(INTERNAL_FUNCTION_PARAMETERS,xmlwriter_read_int_t internal_function)229 static void php_xmlwriter_end(INTERNAL_FUNCTION_PARAMETERS, xmlwriter_read_int_t internal_function)
230 {
231 xmlTextWriterPtr ptr;
232 int retval;
233 zval *self;
234
235 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &self, xmlwriter_class_entry_ce) == FAILURE) {
236 RETURN_THROWS();
237 }
238 XMLWRITER_FROM_OBJECT(ptr, self);
239
240 if (ptr) {
241 retval = internal_function(ptr);
242 if (retval != -1) {
243 RETURN_TRUE;
244 }
245 }
246
247 RETURN_FALSE;
248 }
249
250 /* {{{ Toggle indentation on/off - returns FALSE on error */
PHP_FUNCTION(xmlwriter_set_indent)251 PHP_FUNCTION(xmlwriter_set_indent)
252 {
253 xmlTextWriterPtr ptr;
254 int retval;
255 zend_bool indent;
256 zval *self;
257
258 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ob", &self, xmlwriter_class_entry_ce, &indent) == FAILURE) {
259 RETURN_THROWS();
260 }
261 XMLWRITER_FROM_OBJECT(ptr, self);
262
263 if (ptr) {
264 retval = xmlTextWriterSetIndent(ptr, indent);
265 if (retval == 0) {
266 RETURN_TRUE;
267 }
268 }
269
270 RETURN_FALSE;
271 }
272 /* }}} */
273
274 /* {{{ Set string used for indenting - returns FALSE on error */
PHP_FUNCTION(xmlwriter_set_indent_string)275 PHP_FUNCTION(xmlwriter_set_indent_string)
276 {
277 php_xmlwriter_string_arg(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextWriterSetIndentString, NULL);
278 }
279 /* }}} */
280
281 /* {{{ Create start attribute - returns FALSE on error */
PHP_FUNCTION(xmlwriter_start_attribute)282 PHP_FUNCTION(xmlwriter_start_attribute)
283 {
284 php_xmlwriter_string_arg(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextWriterStartAttribute, "attribute name");
285 }
286 /* }}} */
287
288 /* {{{ End attribute - returns FALSE on error */
PHP_FUNCTION(xmlwriter_end_attribute)289 PHP_FUNCTION(xmlwriter_end_attribute)
290 {
291 php_xmlwriter_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextWriterEndAttribute);
292 }
293 /* }}} */
294
295 /* {{{ Create start namespaced attribute - returns FALSE on error */
PHP_FUNCTION(xmlwriter_start_attribute_ns)296 PHP_FUNCTION(xmlwriter_start_attribute_ns)
297 {
298 xmlTextWriterPtr ptr;
299 char *name, *prefix, *uri;
300 size_t name_len, prefix_len, uri_len;
301 int retval;
302 zval *self;
303
304 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os!ss!", &self, xmlwriter_class_entry_ce,
305 &prefix, &prefix_len, &name, &name_len, &uri, &uri_len) == FAILURE) {
306 RETURN_THROWS();
307 }
308 XMLWRITER_FROM_OBJECT(ptr, self);
309
310 XMLW_NAME_CHK(3, "attribute name");
311
312 if (ptr) {
313 retval = xmlTextWriterStartAttributeNS(ptr, (xmlChar *)prefix, (xmlChar *)name, (xmlChar *)uri);
314 if (retval != -1) {
315 RETURN_TRUE;
316 }
317 }
318
319 RETURN_FALSE;
320 }
321 /* }}} */
322
323 /* {{{ Write full attribute - returns FALSE on error */
PHP_FUNCTION(xmlwriter_write_attribute)324 PHP_FUNCTION(xmlwriter_write_attribute)
325 {
326 xmlTextWriterPtr ptr;
327 char *name, *content;
328 size_t name_len, content_len;
329 int retval;
330 zval *self;
331
332 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Oss", &self, xmlwriter_class_entry_ce,
333 &name, &name_len, &content, &content_len) == FAILURE) {
334 RETURN_THROWS();
335 }
336 XMLWRITER_FROM_OBJECT(ptr, self);
337
338 XMLW_NAME_CHK(2, "attribute name");
339
340 if (ptr) {
341 retval = xmlTextWriterWriteAttribute(ptr, (xmlChar *)name, (xmlChar *)content);
342 if (retval != -1) {
343 RETURN_TRUE;
344 }
345 }
346
347 RETURN_FALSE;
348 }
349 /* }}} */
350
351 /* {{{ Write full namespaced attribute - returns FALSE on error */
PHP_FUNCTION(xmlwriter_write_attribute_ns)352 PHP_FUNCTION(xmlwriter_write_attribute_ns)
353 {
354 xmlTextWriterPtr ptr;
355 char *name, *prefix, *uri, *content;
356 size_t name_len, prefix_len, uri_len, content_len;
357 int retval;
358 zval *self;
359
360 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os!ss!s", &self, xmlwriter_class_entry_ce,
361 &prefix, &prefix_len, &name, &name_len, &uri, &uri_len, &content, &content_len) == FAILURE) {
362 RETURN_THROWS();
363 }
364 XMLWRITER_FROM_OBJECT(ptr, self);
365
366 XMLW_NAME_CHK(3, "attribute name");
367
368 if (ptr) {
369 retval = xmlTextWriterWriteAttributeNS(ptr, (xmlChar *)prefix, (xmlChar *)name, (xmlChar *)uri, (xmlChar *)content);
370 if (retval != -1) {
371 RETURN_TRUE;
372 }
373 }
374
375 RETURN_FALSE;
376 }
377 /* }}} */
378
379 /* {{{ Create start element tag - returns FALSE on error */
PHP_FUNCTION(xmlwriter_start_element)380 PHP_FUNCTION(xmlwriter_start_element)
381 {
382 php_xmlwriter_string_arg(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextWriterStartElement, "element name");
383 }
384 /* }}} */
385
386 /* {{{ Create start namespaced element tag - returns FALSE on error */
PHP_FUNCTION(xmlwriter_start_element_ns)387 PHP_FUNCTION(xmlwriter_start_element_ns)
388 {
389 xmlTextWriterPtr ptr;
390 char *name, *prefix, *uri;
391 size_t name_len, prefix_len, uri_len;
392 int retval;
393 zval *self;
394
395 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os!ss!", &self, xmlwriter_class_entry_ce,
396 &prefix, &prefix_len, &name, &name_len, &uri, &uri_len) == FAILURE) {
397 RETURN_THROWS();
398 }
399 XMLWRITER_FROM_OBJECT(ptr, self);
400
401 XMLW_NAME_CHK(3, "element name");
402
403 if (ptr) {
404 retval = xmlTextWriterStartElementNS(ptr, (xmlChar *)prefix, (xmlChar *)name, (xmlChar *)uri);
405 if (retval != -1) {
406 RETURN_TRUE;
407 }
408
409 }
410
411 RETURN_FALSE;
412 }
413 /* }}} */
414
415 /* {{{ End current element - returns FALSE on error */
PHP_FUNCTION(xmlwriter_end_element)416 PHP_FUNCTION(xmlwriter_end_element)
417 {
418 php_xmlwriter_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextWriterEndElement);
419 }
420 /* }}} */
421
422 /* {{{ End current element - returns FALSE on error */
PHP_FUNCTION(xmlwriter_full_end_element)423 PHP_FUNCTION(xmlwriter_full_end_element)
424 {
425 php_xmlwriter_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextWriterFullEndElement);
426 }
427 /* }}} */
428
429 /* {{{ Write full element tag - returns FALSE on error */
PHP_FUNCTION(xmlwriter_write_element)430 PHP_FUNCTION(xmlwriter_write_element)
431 {
432 xmlTextWriterPtr ptr;
433 char *name, *content = NULL;
434 size_t name_len, content_len;
435 int retval;
436 zval *self;
437
438 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os|s!", &self, xmlwriter_class_entry_ce,
439 &name, &name_len, &content, &content_len) == FAILURE) {
440 RETURN_THROWS();
441 }
442 XMLWRITER_FROM_OBJECT(ptr, self);
443
444 XMLW_NAME_CHK(2, "element name");
445
446 if (ptr) {
447 if (!content) {
448 retval = xmlTextWriterStartElement(ptr, (xmlChar *)name);
449 if (retval == -1) {
450 RETURN_FALSE;
451 }
452 xmlTextWriterEndElement(ptr);
453 if (retval == -1) {
454 RETURN_FALSE;
455 }
456 } else {
457 retval = xmlTextWriterWriteElement(ptr, (xmlChar *)name, (xmlChar *)content);
458 }
459 if (retval != -1) {
460 RETURN_TRUE;
461 }
462 }
463
464 RETURN_FALSE;
465 }
466 /* }}} */
467
468 /* {{{ Write full namesapced element tag - returns FALSE on error */
PHP_FUNCTION(xmlwriter_write_element_ns)469 PHP_FUNCTION(xmlwriter_write_element_ns)
470 {
471 xmlTextWriterPtr ptr;
472 char *name, *prefix, *uri, *content = NULL;
473 size_t name_len, prefix_len, uri_len, content_len;
474 int retval;
475 zval *self;
476
477 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os!ss!|s!", &self, xmlwriter_class_entry_ce,
478 &prefix, &prefix_len, &name, &name_len, &uri, &uri_len, &content, &content_len) == FAILURE) {
479 RETURN_THROWS();
480 }
481 XMLWRITER_FROM_OBJECT(ptr, self);
482
483 XMLW_NAME_CHK(3, "element name");
484
485 if (ptr) {
486 if (!content) {
487 retval = xmlTextWriterStartElementNS(ptr,(xmlChar *)prefix, (xmlChar *)name, (xmlChar *)uri);
488 if (retval == -1) {
489 RETURN_FALSE;
490 }
491 retval = xmlTextWriterEndElement(ptr);
492 if (retval == -1) {
493 RETURN_FALSE;
494 }
495 } else {
496 retval = xmlTextWriterWriteElementNS(ptr, (xmlChar *)prefix, (xmlChar *)name, (xmlChar *)uri, (xmlChar *)content);
497 }
498 if (retval != -1) {
499 RETURN_TRUE;
500 }
501 }
502
503 RETURN_FALSE;
504 }
505 /* }}} */
506
507 /* {{{ Create start PI tag - returns FALSE on error */
PHP_FUNCTION(xmlwriter_start_pi)508 PHP_FUNCTION(xmlwriter_start_pi)
509 {
510 php_xmlwriter_string_arg(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextWriterStartPI, "PI target");
511 }
512 /* }}} */
513
514 /* {{{ End current PI - returns FALSE on error */
PHP_FUNCTION(xmlwriter_end_pi)515 PHP_FUNCTION(xmlwriter_end_pi)
516 {
517 php_xmlwriter_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextWriterEndPI);
518 }
519 /* }}} */
520
521 /* {{{ Write full PI tag - returns FALSE on error */
PHP_FUNCTION(xmlwriter_write_pi)522 PHP_FUNCTION(xmlwriter_write_pi)
523 {
524 xmlTextWriterPtr ptr;
525 char *name, *content;
526 size_t name_len, content_len;
527 int retval;
528 zval *self;
529
530 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Oss", &self, xmlwriter_class_entry_ce,
531 &name, &name_len, &content, &content_len) == FAILURE) {
532 RETURN_THROWS();
533 }
534 XMLWRITER_FROM_OBJECT(ptr, self);
535
536 XMLW_NAME_CHK(2, "PI target");
537
538 if (ptr) {
539 retval = xmlTextWriterWritePI(ptr, (xmlChar *)name, (xmlChar *)content);
540 if (retval != -1) {
541 RETURN_TRUE;
542 }
543 }
544
545 RETURN_FALSE;
546 }
547 /* }}} */
548
549 /* {{{ Create start CDATA tag - returns FALSE on error */
PHP_FUNCTION(xmlwriter_start_cdata)550 PHP_FUNCTION(xmlwriter_start_cdata)
551 {
552 xmlTextWriterPtr ptr;
553 int retval;
554 zval *self;
555
556 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &self, xmlwriter_class_entry_ce) == FAILURE) {
557 RETURN_THROWS();
558 }
559 XMLWRITER_FROM_OBJECT(ptr, self);
560
561 if (ptr) {
562 retval = xmlTextWriterStartCDATA(ptr);
563 if (retval != -1) {
564 RETURN_TRUE;
565 }
566 }
567
568 RETURN_FALSE;
569 }
570 /* }}} */
571
572 /* {{{ End current CDATA - returns FALSE on error */
PHP_FUNCTION(xmlwriter_end_cdata)573 PHP_FUNCTION(xmlwriter_end_cdata)
574 {
575 php_xmlwriter_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextWriterEndCDATA);
576 }
577 /* }}} */
578
579 /* {{{ Write full CDATA tag - returns FALSE on error */
PHP_FUNCTION(xmlwriter_write_cdata)580 PHP_FUNCTION(xmlwriter_write_cdata)
581 {
582 php_xmlwriter_string_arg(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextWriterWriteCDATA, NULL);
583 }
584 /* }}} */
585
586 /* {{{ Write text - returns FALSE on error */
PHP_FUNCTION(xmlwriter_write_raw)587 PHP_FUNCTION(xmlwriter_write_raw)
588 {
589 php_xmlwriter_string_arg(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextWriterWriteRaw, NULL);
590 }
591 /* }}} */
592
593 /* {{{ Write text - returns FALSE on error */
PHP_FUNCTION(xmlwriter_text)594 PHP_FUNCTION(xmlwriter_text)
595 {
596 php_xmlwriter_string_arg(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextWriterWriteString, NULL);
597 }
598 /* }}} */
599
600 /* {{{ Create start comment - returns FALSE on error */
PHP_FUNCTION(xmlwriter_start_comment)601 PHP_FUNCTION(xmlwriter_start_comment)
602 {
603 xmlTextWriterPtr ptr;
604 int retval;
605 zval *self;
606
607 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &self, xmlwriter_class_entry_ce) == FAILURE) {
608 RETURN_THROWS();
609 }
610 XMLWRITER_FROM_OBJECT(ptr, self);
611
612 if (ptr) {
613 retval = xmlTextWriterStartComment(ptr);
614 if (retval != -1) {
615 RETURN_TRUE;
616 }
617 }
618
619 RETURN_FALSE;
620 }
621 /* }}} */
622
623 /* {{{ Create end comment - returns FALSE on error */
PHP_FUNCTION(xmlwriter_end_comment)624 PHP_FUNCTION(xmlwriter_end_comment)
625 {
626 php_xmlwriter_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextWriterEndComment);
627 }
628 /* }}} */
629
630 /* {{{ Write full comment tag - returns FALSE on error */
PHP_FUNCTION(xmlwriter_write_comment)631 PHP_FUNCTION(xmlwriter_write_comment)
632 {
633 php_xmlwriter_string_arg(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextWriterWriteComment, NULL);
634 }
635 /* }}} */
636
637 /* {{{ Create document tag - returns FALSE on error */
PHP_FUNCTION(xmlwriter_start_document)638 PHP_FUNCTION(xmlwriter_start_document)
639 {
640 xmlTextWriterPtr ptr;
641 char *version = NULL, *enc = NULL, *alone = NULL;
642 size_t version_len, enc_len, alone_len;
643 int retval;
644 zval *self;
645
646 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|s!s!s!", &self, xmlwriter_class_entry_ce, &version, &version_len, &enc, &enc_len, &alone, &alone_len) == FAILURE) {
647 RETURN_THROWS();
648 }
649 XMLWRITER_FROM_OBJECT(ptr, self);
650
651 if (ptr) {
652 retval = xmlTextWriterStartDocument(ptr, version, enc, alone);
653 if (retval != -1) {
654 RETURN_TRUE;
655 }
656 }
657
658 RETURN_FALSE;
659 }
660 /* }}} */
661
662 /* {{{ End current document - returns FALSE on error */
PHP_FUNCTION(xmlwriter_end_document)663 PHP_FUNCTION(xmlwriter_end_document)
664 {
665 php_xmlwriter_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextWriterEndDocument);
666 }
667 /* }}} */
668
669 /* {{{ Create start DTD tag - returns FALSE on error */
PHP_FUNCTION(xmlwriter_start_dtd)670 PHP_FUNCTION(xmlwriter_start_dtd)
671 {
672 xmlTextWriterPtr ptr;
673 char *name, *pubid = NULL, *sysid = NULL;
674 size_t name_len, pubid_len, sysid_len;
675 int retval;
676 zval *self;
677
678 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os|s!s!", &self, xmlwriter_class_entry_ce, &name, &name_len, &pubid, &pubid_len, &sysid, &sysid_len) == FAILURE) {
679 RETURN_THROWS();
680 }
681 XMLWRITER_FROM_OBJECT(ptr, self);
682
683 if (ptr) {
684 retval = xmlTextWriterStartDTD(ptr, (xmlChar *)name, (xmlChar *)pubid, (xmlChar *)sysid);
685 if (retval != -1) {
686 RETURN_TRUE;
687 }
688 }
689
690 RETURN_FALSE;
691 }
692 /* }}} */
693
694 /* {{{ End current DTD - returns FALSE on error */
PHP_FUNCTION(xmlwriter_end_dtd)695 PHP_FUNCTION(xmlwriter_end_dtd)
696 {
697 php_xmlwriter_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextWriterEndDTD);
698 }
699 /* }}} */
700
701 /* {{{ Write full DTD tag - returns FALSE on error */
PHP_FUNCTION(xmlwriter_write_dtd)702 PHP_FUNCTION(xmlwriter_write_dtd)
703 {
704 xmlTextWriterPtr ptr;
705 char *name, *pubid = NULL, *sysid = NULL, *subset = NULL;
706 size_t name_len, pubid_len, sysid_len, subset_len;
707 int retval;
708 zval *self;
709
710 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os|s!s!s!", &self, xmlwriter_class_entry_ce, &name, &name_len, &pubid, &pubid_len, &sysid, &sysid_len, &subset, &subset_len) == FAILURE) {
711 RETURN_THROWS();
712 }
713 XMLWRITER_FROM_OBJECT(ptr, self);
714
715 if (ptr) {
716 retval = xmlTextWriterWriteDTD(ptr, (xmlChar *)name, (xmlChar *)pubid, (xmlChar *)sysid, (xmlChar *)subset);
717 if (retval != -1) {
718 RETURN_TRUE;
719 }
720 }
721
722 RETURN_FALSE;
723 }
724 /* }}} */
725
726 /* {{{ Create start DTD element - returns FALSE on error */
PHP_FUNCTION(xmlwriter_start_dtd_element)727 PHP_FUNCTION(xmlwriter_start_dtd_element)
728 {
729 php_xmlwriter_string_arg(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextWriterStartDTDElement, "element name");
730 }
731 /* }}} */
732
733 /* {{{ End current DTD element - returns FALSE on error */
PHP_FUNCTION(xmlwriter_end_dtd_element)734 PHP_FUNCTION(xmlwriter_end_dtd_element)
735 {
736 php_xmlwriter_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextWriterEndDTDElement);
737 }
738 /* }}} */
739
740 /* {{{ Write full DTD element tag - returns FALSE on error */
PHP_FUNCTION(xmlwriter_write_dtd_element)741 PHP_FUNCTION(xmlwriter_write_dtd_element)
742 {
743 xmlTextWriterPtr ptr;
744 char *name, *content;
745 size_t name_len, content_len;
746 int retval;
747 zval *self;
748
749 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Oss", &self, xmlwriter_class_entry_ce,
750 &name, &name_len, &content, &content_len) == FAILURE) {
751 RETURN_THROWS();
752 }
753 XMLWRITER_FROM_OBJECT(ptr, self);
754
755 XMLW_NAME_CHK(2, "element name");
756
757 if (ptr) {
758 retval = xmlTextWriterWriteDTDElement(ptr, (xmlChar *)name, (xmlChar *)content);
759 if (retval != -1) {
760 RETURN_TRUE;
761 }
762 }
763
764 RETURN_FALSE;
765 }
766 /* }}} */
767
768 /* {{{ Create start DTD AttList - returns FALSE on error */
PHP_FUNCTION(xmlwriter_start_dtd_attlist)769 PHP_FUNCTION(xmlwriter_start_dtd_attlist)
770 {
771 php_xmlwriter_string_arg(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextWriterStartDTDAttlist, "element name");
772 }
773 /* }}} */
774
775 /* {{{ End current DTD AttList - returns FALSE on error */
PHP_FUNCTION(xmlwriter_end_dtd_attlist)776 PHP_FUNCTION(xmlwriter_end_dtd_attlist)
777 {
778 php_xmlwriter_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextWriterEndDTDAttlist);
779 }
780 /* }}} */
781
782 /* {{{ Write full DTD AttList tag - returns FALSE on error */
PHP_FUNCTION(xmlwriter_write_dtd_attlist)783 PHP_FUNCTION(xmlwriter_write_dtd_attlist)
784 {
785 xmlTextWriterPtr ptr;
786 char *name, *content;
787 size_t name_len, content_len;
788 int retval;
789 zval *self;
790
791 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Oss", &self, xmlwriter_class_entry_ce,
792 &name, &name_len, &content, &content_len) == FAILURE) {
793 RETURN_THROWS();
794 }
795 XMLWRITER_FROM_OBJECT(ptr, self);
796
797 XMLW_NAME_CHK(2, "element name");
798
799 if (ptr) {
800 retval = xmlTextWriterWriteDTDAttlist(ptr, (xmlChar *)name, (xmlChar *)content);
801 if (retval != -1) {
802 RETURN_TRUE;
803 }
804 }
805
806 RETURN_FALSE;
807 }
808 /* }}} */
809
810 /* {{{ Create start DTD Entity - returns FALSE on error */
PHP_FUNCTION(xmlwriter_start_dtd_entity)811 PHP_FUNCTION(xmlwriter_start_dtd_entity)
812 {
813 xmlTextWriterPtr ptr;
814 char *name;
815 size_t name_len;
816 int retval;
817 zend_bool isparm;
818 zval *self;
819
820 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Osb", &self, xmlwriter_class_entry_ce, &name, &name_len, &isparm) == FAILURE) {
821 RETURN_THROWS();
822 }
823 XMLWRITER_FROM_OBJECT(ptr, self);
824
825 XMLW_NAME_CHK(2, "attribute name");
826
827 if (ptr) {
828 retval = xmlTextWriterStartDTDEntity(ptr, isparm, (xmlChar *)name);
829 if (retval != -1) {
830 RETURN_TRUE;
831 }
832 }
833
834 RETURN_FALSE;
835 }
836 /* }}} */
837
838 /* {{{ End current DTD Entity - returns FALSE on error */
PHP_FUNCTION(xmlwriter_end_dtd_entity)839 PHP_FUNCTION(xmlwriter_end_dtd_entity)
840 {
841 php_xmlwriter_end(INTERNAL_FUNCTION_PARAM_PASSTHRU, xmlTextWriterEndDTDEntity);
842 }
843 /* }}} */
844
845 /* {{{ Write full DTD Entity tag - returns FALSE on error */
PHP_FUNCTION(xmlwriter_write_dtd_entity)846 PHP_FUNCTION(xmlwriter_write_dtd_entity)
847 {
848 xmlTextWriterPtr ptr;
849 char *name, *content;
850 size_t name_len, content_len;
851 int retval;
852 /* Optional parameters */
853 char *pubid = NULL, *sysid = NULL, *ndataid = NULL;
854 zend_bool pe = 0;
855 size_t pubid_len, sysid_len, ndataid_len;
856 zval *self;
857
858 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Oss|bs!s!s!", &self, xmlwriter_class_entry_ce,
859 &name, &name_len, &content, &content_len, &pe, &pubid, &pubid_len,
860 &sysid, &sysid_len, &ndataid, &ndataid_len) == FAILURE) {
861 RETURN_THROWS();
862 }
863 XMLWRITER_FROM_OBJECT(ptr, self);
864
865 XMLW_NAME_CHK(2, "element name");
866
867 if (ptr) {
868 retval = xmlTextWriterWriteDTDEntity(ptr, pe, (xmlChar *)name, (xmlChar *)pubid, (xmlChar *)sysid, (xmlChar *)ndataid, (xmlChar *)content);
869 if (retval != -1) {
870 RETURN_TRUE;
871 }
872 }
873
874 RETURN_FALSE;
875 }
876 /* }}} */
877
878 /* {{{ Create new xmlwriter using source uri for output */
PHP_FUNCTION(xmlwriter_open_uri)879 PHP_FUNCTION(xmlwriter_open_uri)
880 {
881 char *valid_file = NULL;
882 xmlTextWriterPtr ptr;
883 char *source;
884 char resolved_path[MAXPATHLEN + 1];
885 size_t source_len;
886 zval *self = getThis();
887 ze_xmlwriter_object *ze_obj = NULL;
888
889 if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &source, &source_len) == FAILURE) {
890 RETURN_THROWS();
891 }
892
893 if (self) {
894 /* We do not use XMLWRITER_FROM_OBJECT, xmlwriter init function here */
895 ze_obj = Z_XMLWRITER_P(self);
896 }
897
898 if (source_len == 0) {
899 zend_argument_value_error(1, "cannot be empty");
900 RETURN_THROWS();
901 }
902
903 valid_file = _xmlwriter_get_valid_file_path(source, resolved_path, MAXPATHLEN);
904 if (!valid_file) {
905 php_error_docref(NULL, E_WARNING, "Unable to resolve file path");
906 RETURN_FALSE;
907 }
908
909 ptr = xmlNewTextWriterFilename(valid_file, 0);
910
911 if (!ptr) {
912 RETURN_FALSE;
913 }
914
915 if (self) {
916 if (ze_obj->ptr) {
917 xmlFreeTextWriter(ze_obj->ptr);
918 }
919 if (ze_obj->output) {
920 xmlBufferFree(ze_obj->output);
921 }
922 ze_obj->ptr = ptr;
923 ze_obj->output = NULL;
924 RETURN_TRUE;
925 } else {
926 ze_obj = php_xmlwriter_fetch_object(xmlwriter_object_new(xmlwriter_class_entry_ce));
927 ze_obj->ptr = ptr;
928 ze_obj->output = NULL;
929 RETURN_OBJ(&ze_obj->std);
930 }
931 }
932 /* }}} */
933
934 /* {{{ Create new xmlwriter using memory for string output */
PHP_FUNCTION(xmlwriter_open_memory)935 PHP_FUNCTION(xmlwriter_open_memory)
936 {
937 xmlTextWriterPtr ptr;
938 xmlBufferPtr buffer;
939 zval *self = getThis();
940 ze_xmlwriter_object *ze_obj = NULL;
941
942 if (zend_parse_parameters_none() == FAILURE) {
943 RETURN_THROWS();
944 }
945
946 if (self) {
947 /* We do not use XMLWRITER_FROM_OBJECT, xmlwriter init function here */
948 ze_obj = Z_XMLWRITER_P(self);
949 }
950
951 buffer = xmlBufferCreate();
952
953 if (buffer == NULL) {
954 php_error_docref(NULL, E_WARNING, "Unable to create output buffer");
955 RETURN_FALSE;
956 }
957
958 ptr = xmlNewTextWriterMemory(buffer, 0);
959 if (! ptr) {
960 xmlBufferFree(buffer);
961 RETURN_FALSE;
962 }
963
964 if (self) {
965 if (ze_obj->ptr) {
966 xmlFreeTextWriter(ze_obj->ptr);
967 }
968 if (ze_obj->output) {
969 xmlBufferFree(ze_obj->output);
970 }
971 ze_obj->ptr = ptr;
972 ze_obj->output = buffer;
973 RETURN_TRUE;
974 } else {
975 ze_obj = php_xmlwriter_fetch_object(xmlwriter_object_new(xmlwriter_class_entry_ce));
976 ze_obj->ptr = ptr;
977 ze_obj->output = buffer;
978 RETURN_OBJ(&ze_obj->std);
979 }
980
981 }
982 /* }}} */
983
984 /* {{{ php_xmlwriter_flush */
php_xmlwriter_flush(INTERNAL_FUNCTION_PARAMETERS,int force_string)985 static void php_xmlwriter_flush(INTERNAL_FUNCTION_PARAMETERS, int force_string) {
986 xmlTextWriterPtr ptr;
987 xmlBufferPtr buffer;
988 zend_bool empty = 1;
989 int output_bytes;
990 zval *self;
991
992 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|b", &self, xmlwriter_class_entry_ce, &empty) == FAILURE) {
993 RETURN_THROWS();
994 }
995 XMLWRITER_FROM_OBJECT(ptr, self);
996
997 if (ptr) {
998 buffer = Z_XMLWRITER_P(self)->output;
999 if (force_string == 1 && buffer == NULL) {
1000 RETURN_EMPTY_STRING();
1001 }
1002 output_bytes = xmlTextWriterFlush(ptr);
1003 if (buffer) {
1004 RETVAL_STRING((char *) buffer->content);
1005 if (empty) {
1006 xmlBufferEmpty(buffer);
1007 }
1008 } else {
1009 RETVAL_LONG(output_bytes);
1010 }
1011 return;
1012 }
1013
1014 RETURN_EMPTY_STRING();
1015 }
1016 /* }}} */
1017
1018 /* {{{ Output current buffer as string */
PHP_FUNCTION(xmlwriter_output_memory)1019 PHP_FUNCTION(xmlwriter_output_memory)
1020 {
1021 php_xmlwriter_flush(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
1022 }
1023 /* }}} */
1024
1025 /* {{{ Output current buffer */
PHP_FUNCTION(xmlwriter_flush)1026 PHP_FUNCTION(xmlwriter_flush)
1027 {
1028 php_xmlwriter_flush(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
1029 }
1030 /* }}} */
1031
1032 /* {{{ PHP_MINIT_FUNCTION */
PHP_MINIT_FUNCTION(xmlwriter)1033 static PHP_MINIT_FUNCTION(xmlwriter)
1034 {
1035 zend_class_entry ce;
1036
1037 memcpy(&xmlwriter_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
1038 xmlwriter_object_handlers.offset = XtOffsetOf(ze_xmlwriter_object, std);
1039 xmlwriter_object_handlers.dtor_obj = xmlwriter_object_dtor;
1040 xmlwriter_object_handlers.free_obj = xmlwriter_object_free_storage;
1041 xmlwriter_object_handlers.clone_obj = NULL;
1042 INIT_CLASS_ENTRY(ce, "XMLWriter", class_XMLWriter_methods);
1043 ce.create_object = xmlwriter_object_new;
1044 xmlwriter_class_entry_ce = zend_register_internal_class(&ce);
1045
1046 return SUCCESS;
1047 }
1048 /* }}} */
1049
1050 /* {{{ PHP_MSHUTDOWN_FUNCTION */
PHP_MSHUTDOWN_FUNCTION(xmlwriter)1051 static PHP_MSHUTDOWN_FUNCTION(xmlwriter)
1052 {
1053 return SUCCESS;
1054 }
1055 /* }}} */
1056
1057 /* {{{ PHP_MINFO_FUNCTION */
PHP_MINFO_FUNCTION(xmlwriter)1058 static PHP_MINFO_FUNCTION(xmlwriter)
1059 {
1060 php_info_print_table_start();
1061 {
1062 php_info_print_table_row(2, "XMLWriter", "enabled");
1063 }
1064 php_info_print_table_end();
1065 }
1066 /* }}} */
1067