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