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