1 /*
2 * libxml.c: this modules implements the main part of the glue of the
3 * libxml2 library and the Python interpreter. It provides the
4 * entry points where an automatically generated stub is either
5 * unpractical or would not match cleanly the Python model.
6 *
7 * If compiled with MERGED_MODULES, the entry point will be used to
8 * initialize both the libxml2 and the libxslt wrappers
9 *
10 * See Copyright for the status of this software.
11 *
12 * daniel@veillard.com
13 */
14 #define PY_SSIZE_T_CLEAN
15 #include <Python.h>
16 #include <fileobject.h>
17 /* #include "config.h" */
18 #include <libxml/xmlmemory.h>
19 #include <libxml/parser.h>
20 #include <libxml/tree.h>
21 #include <libxml/xpath.h>
22 #include <libxml/xmlerror.h>
23 #include <libxml/xpathInternals.h>
24 #include <libxml/xmlmemory.h>
25 #include <libxml/xmlIO.h>
26 #include <libxml/c14n.h>
27 #include <libxml/xmlreader.h>
28 #include <libxml/xmlsave.h>
29 #include "libxml_wrap.h"
30 #include "libxml2-py.h"
31
32 #if defined(WITH_TRIO)
33 #include "trio.h"
34 #define vsnprintf trio_vsnprintf
35 #endif
36
37 /* #define DEBUG */
38 /* #define DEBUG_SAX */
39 /* #define DEBUG_XPATH */
40 /* #define DEBUG_ERROR */
41 /* #define DEBUG_MEMORY */
42 /* #define DEBUG_FILES */
43 /* #define DEBUG_LOADER */
44
45 #if PY_MAJOR_VERSION >= 3
46 PyObject *PyInit_libxml2mod(void);
47
48 #define PY_IMPORT_STRING_SIZE PyUnicode_FromStringAndSize
49 #define PY_IMPORT_STRING PyUnicode_FromString
50 #else
51 void initlibxml2mod(void);
52 #define PY_IMPORT_STRING_SIZE PyString_FromStringAndSize
53 #define PY_IMPORT_STRING PyString_FromString
54 #endif
55
56
57 /**
58 * TODO:
59 *
60 * macro to flag unimplemented blocks
61 */
62 #define TODO \
63 xmlGenericError(xmlGenericErrorContext, \
64 "Unimplemented block at %s:%d\n", \
65 __FILE__, __LINE__);
66 /*
67 * the following vars are used for XPath extensions, but
68 * are also referenced within the parser cleanup routine.
69 */
70 static int libxml_xpathCallbacksInitialized = 0;
71
72 typedef struct libxml_xpathCallback {
73 xmlXPathContextPtr ctx;
74 xmlChar *name;
75 xmlChar *ns_uri;
76 PyObject *function;
77 } libxml_xpathCallback, *libxml_xpathCallbackPtr;
78 typedef libxml_xpathCallback libxml_xpathCallbackArray[];
79 static int libxml_xpathCallbacksAllocd = 10;
80 static libxml_xpathCallbackArray *libxml_xpathCallbacks = NULL;
81 static int libxml_xpathCallbacksNb = 0;
82
83 /************************************************************************
84 * *
85 * Memory debug interface *
86 * *
87 ************************************************************************/
88
89 #if 0
90 extern void xmlMemFree(void *ptr);
91 extern void *xmlMemMalloc(size_t size);
92 extern void *xmlMemRealloc(void *ptr, size_t size);
93 extern char *xmlMemoryStrdup(const char *str);
94 #endif
95
96 static int libxmlMemoryDebugActivated = 0;
97 static long libxmlMemoryAllocatedBase = 0;
98
99 static int libxmlMemoryDebug = 0;
100 static xmlFreeFunc freeFunc = NULL;
101 static xmlMallocFunc mallocFunc = NULL;
102 static xmlReallocFunc reallocFunc = NULL;
103 static xmlStrdupFunc strdupFunc = NULL;
104
105 static void
106 libxml_xmlErrorInitialize(void); /* forward declare */
107
108 PyObject *
libxml_xmlMemoryUsed(PyObject * self ATTRIBUTE_UNUSED,PyObject * args ATTRIBUTE_UNUSED)109 libxml_xmlMemoryUsed(PyObject * self ATTRIBUTE_UNUSED,
110 PyObject * args ATTRIBUTE_UNUSED)
111 {
112 long ret;
113 PyObject *py_retval;
114
115 ret = xmlMemUsed();
116
117 py_retval = libxml_longWrap(ret);
118 return (py_retval);
119 }
120
121 PyObject *
libxml_xmlDebugMemory(PyObject * self ATTRIBUTE_UNUSED,PyObject * args)122 libxml_xmlDebugMemory(PyObject * self ATTRIBUTE_UNUSED, PyObject * args)
123 {
124 int activate;
125 PyObject *py_retval;
126 long ret;
127
128 if (!PyArg_ParseTuple(args, (char *) "i:xmlDebugMemory", &activate))
129 return (NULL);
130
131 #ifdef DEBUG_MEMORY
132 printf("libxml_xmlDebugMemory(%d) called\n", activate);
133 #endif
134
135 if (activate != 0) {
136 if (libxmlMemoryDebug == 0) {
137 /*
138 * First initialize the library and grab the old memory handlers
139 * and switch the library to memory debugging
140 */
141 xmlMemGet((xmlFreeFunc *) & freeFunc,
142 (xmlMallocFunc *) & mallocFunc,
143 (xmlReallocFunc *) & reallocFunc,
144 (xmlStrdupFunc *) & strdupFunc);
145 if ((freeFunc == xmlMemFree) && (mallocFunc == xmlMemMalloc) &&
146 (reallocFunc == xmlMemRealloc) &&
147 (strdupFunc == xmlMemoryStrdup)) {
148 libxmlMemoryAllocatedBase = xmlMemUsed();
149 } else {
150 /*
151 * cleanup first, because some memory has been
152 * allocated with the non-debug malloc in xmlInitParser
153 * when the python module was imported
154 */
155 xmlCleanupParser();
156 ret = (long) xmlMemSetup(xmlMemFree, xmlMemMalloc,
157 xmlMemRealloc, xmlMemoryStrdup);
158 if (ret < 0)
159 goto error;
160 libxmlMemoryAllocatedBase = xmlMemUsed();
161 /* reinitialize */
162 xmlInitParser();
163 libxml_xmlErrorInitialize();
164 }
165 ret = 0;
166 } else if (libxmlMemoryDebugActivated == 0) {
167 libxmlMemoryAllocatedBase = xmlMemUsed();
168 ret = 0;
169 } else {
170 ret = xmlMemUsed() - libxmlMemoryAllocatedBase;
171 }
172 libxmlMemoryDebug = 1;
173 libxmlMemoryDebugActivated = 1;
174 } else {
175 if (libxmlMemoryDebugActivated == 1)
176 ret = xmlMemUsed() - libxmlMemoryAllocatedBase;
177 else
178 ret = 0;
179 libxmlMemoryDebugActivated = 0;
180 }
181 error:
182 py_retval = libxml_longWrap(ret);
183 return (py_retval);
184 }
185
186 PyObject *
libxml_xmlPythonCleanupParser(PyObject * self ATTRIBUTE_UNUSED,PyObject * args ATTRIBUTE_UNUSED)187 libxml_xmlPythonCleanupParser(PyObject *self ATTRIBUTE_UNUSED,
188 PyObject *args ATTRIBUTE_UNUSED) {
189
190 int ix;
191 long freed = -1;
192
193 if (libxmlMemoryDebug) {
194 freed = xmlMemUsed();
195 }
196
197 xmlCleanupParser();
198 /*
199 * Need to confirm whether we really want to do this (required for
200 * memcheck) in all cases...
201 */
202
203 if (libxml_xpathCallbacks != NULL) { /* if ext funcs declared */
204 for (ix=0; ix<libxml_xpathCallbacksNb; ix++) {
205 if ((*libxml_xpathCallbacks)[ix].name != NULL)
206 xmlFree((*libxml_xpathCallbacks)[ix].name);
207 if ((*libxml_xpathCallbacks)[ix].ns_uri != NULL)
208 xmlFree((*libxml_xpathCallbacks)[ix].ns_uri);
209 }
210 libxml_xpathCallbacksNb = 0;
211 xmlFree(libxml_xpathCallbacks);
212 libxml_xpathCallbacks = NULL;
213 }
214
215 if (libxmlMemoryDebug) {
216 freed -= xmlMemUsed();
217 libxmlMemoryAllocatedBase -= freed;
218 if (libxmlMemoryAllocatedBase < 0)
219 libxmlMemoryAllocatedBase = 0;
220 }
221
222 Py_INCREF(Py_None);
223 return(Py_None);
224 }
225
226 PyObject *
libxml_xmlDumpMemory(ATTRIBUTE_UNUSED PyObject * self,ATTRIBUTE_UNUSED PyObject * args)227 libxml_xmlDumpMemory(ATTRIBUTE_UNUSED PyObject * self,
228 ATTRIBUTE_UNUSED PyObject * args)
229 {
230
231 if (libxmlMemoryDebug != 0)
232 xmlMemoryDump();
233 Py_INCREF(Py_None);
234 return (Py_None);
235 }
236
237 /************************************************************************
238 * *
239 * Handling Python FILE I/O at the C level *
240 * The raw I/O attack directly the File objects, while the *
241 * other routines address the ioWrapper instance instead *
242 * *
243 ************************************************************************/
244
245 /**
246 * xmlPythonFileCloseUnref:
247 * @context: the I/O context
248 *
249 * Close an I/O channel
250 */
251 static int
xmlPythonFileCloseRaw(void * context)252 xmlPythonFileCloseRaw (void * context) {
253 PyObject *file, *ret;
254
255 #ifdef DEBUG_FILES
256 printf("xmlPythonFileCloseUnref\n");
257 #endif
258 file = (PyObject *) context;
259 if (file == NULL) return(-1);
260 ret = PyEval_CallMethod(file, (char *) "close", (char *) "()");
261 if (ret != NULL) {
262 Py_DECREF(ret);
263 }
264 Py_DECREF(file);
265 return(0);
266 }
267
268 /**
269 * xmlPythonFileReadRaw:
270 * @context: the I/O context
271 * @buffer: where to drop data
272 * @len: number of bytes to write
273 *
274 * Read @len bytes to @buffer from the Python file in the I/O channel
275 *
276 * Returns the number of bytes read
277 */
278 static int
xmlPythonFileReadRaw(void * context,char * buffer,int len)279 xmlPythonFileReadRaw (void * context, char * buffer, int len) {
280 PyObject *file;
281 PyObject *ret;
282 int lenread = -1;
283 char *data;
284
285 #ifdef DEBUG_FILES
286 printf("xmlPythonFileReadRaw: %d\n", len);
287 #endif
288 file = (PyObject *) context;
289 if (file == NULL) return(-1);
290 ret = PyEval_CallMethod(file, (char *) "read", (char *) "(i)", len);
291 if (ret == NULL) {
292 printf("xmlPythonFileReadRaw: result is NULL\n");
293 return(-1);
294 } else if (PyBytes_Check(ret)) {
295 lenread = PyBytes_Size(ret);
296 data = PyBytes_AsString(ret);
297 #ifdef PyUnicode_Check
298 } else if (PyUnicode_Check (ret)) {
299 #if PY_VERSION_HEX >= 0x03030000
300 Py_ssize_t size;
301 const char *tmp;
302
303 /* tmp doesn't need to be deallocated */
304 tmp = PyUnicode_AsUTF8AndSize(ret, &size);
305
306 lenread = (int) size;
307 data = (char *) tmp;
308 #else
309 PyObject *b;
310 b = PyUnicode_AsUTF8String(ret);
311 if (b == NULL) {
312 printf("xmlPythonFileReadRaw: failed to convert to UTF-8\n");
313 return(-1);
314 }
315 lenread = PyBytes_Size(b);
316 data = PyBytes_AsString(b);
317 Py_DECREF(b);
318 #endif
319 #endif
320 } else {
321 printf("xmlPythonFileReadRaw: result is not a String\n");
322 Py_DECREF(ret);
323 return(-1);
324 }
325 if (lenread > len)
326 memcpy(buffer, data, len);
327 else
328 memcpy(buffer, data, lenread);
329 Py_DECREF(ret);
330 return(lenread);
331 }
332
333 /**
334 * xmlPythonFileRead:
335 * @context: the I/O context
336 * @buffer: where to drop data
337 * @len: number of bytes to write
338 *
339 * Read @len bytes to @buffer from the I/O channel.
340 *
341 * Returns the number of bytes read
342 */
343 static int
xmlPythonFileRead(void * context,char * buffer,int len)344 xmlPythonFileRead (void * context, char * buffer, int len) {
345 PyObject *file;
346 PyObject *ret;
347 int lenread = -1;
348 char *data;
349
350 #ifdef DEBUG_FILES
351 printf("xmlPythonFileRead: %d\n", len);
352 #endif
353 file = (PyObject *) context;
354 if (file == NULL) return(-1);
355 ret = PyEval_CallMethod(file, (char *) "io_read", (char *) "(i)", len);
356 if (ret == NULL) {
357 printf("xmlPythonFileRead: result is NULL\n");
358 return(-1);
359 } else if (PyBytes_Check(ret)) {
360 lenread = PyBytes_Size(ret);
361 data = PyBytes_AsString(ret);
362 #ifdef PyUnicode_Check
363 } else if (PyUnicode_Check (ret)) {
364 #if PY_VERSION_HEX >= 0x03030000
365 Py_ssize_t size;
366 const char *tmp;
367
368 /* tmp doesn't need to be deallocated */
369 tmp = PyUnicode_AsUTF8AndSize(ret, &size);
370
371 lenread = (int) size;
372 data = (char *) tmp;
373 #else
374 PyObject *b;
375 b = PyUnicode_AsUTF8String(ret);
376 if (b == NULL) {
377 printf("xmlPythonFileRead: failed to convert to UTF-8\n");
378 return(-1);
379 }
380 lenread = PyBytes_Size(b);
381 data = PyBytes_AsString(b);
382 Py_DECREF(b);
383 #endif
384 #endif
385 } else {
386 printf("xmlPythonFileRead: result is not a String\n");
387 Py_DECREF(ret);
388 return(-1);
389 }
390 if (lenread > len)
391 memcpy(buffer, data, len);
392 else
393 memcpy(buffer, data, lenread);
394 Py_DECREF(ret);
395 return(lenread);
396 }
397
398 /**
399 * xmlFileWrite:
400 * @context: the I/O context
401 * @buffer: where to drop data
402 * @len: number of bytes to write
403 *
404 * Write @len bytes from @buffer to the I/O channel.
405 *
406 * Returns the number of bytes written
407 */
408 static int
xmlPythonFileWrite(void * context,const char * buffer,int len)409 xmlPythonFileWrite (void * context, const char * buffer, int len) {
410 PyObject *file;
411 PyObject *string;
412 PyObject *ret = NULL;
413 int written = -1;
414
415 #ifdef DEBUG_FILES
416 printf("xmlPythonFileWrite: %d\n", len);
417 #endif
418 file = (PyObject *) context;
419 if (file == NULL) return(-1);
420 string = PY_IMPORT_STRING_SIZE(buffer, len);
421 if (string == NULL) return(-1);
422 if (PyObject_HasAttrString(file, (char *) "io_write")) {
423 ret = PyEval_CallMethod(file, (char *) "io_write", (char *) "(O)",
424 string);
425 } else if (PyObject_HasAttrString(file, (char *) "write")) {
426 ret = PyEval_CallMethod(file, (char *) "write", (char *) "(O)",
427 string);
428 }
429 Py_DECREF(string);
430 if (ret == NULL) {
431 printf("xmlPythonFileWrite: result is NULL\n");
432 return(-1);
433 } else if (PyLong_Check(ret)) {
434 written = (int) PyLong_AsLong(ret);
435 Py_DECREF(ret);
436 } else if (ret == Py_None) {
437 written = len;
438 Py_DECREF(ret);
439 } else {
440 printf("xmlPythonFileWrite: result is not an Int nor None\n");
441 Py_DECREF(ret);
442 }
443 return(written);
444 }
445
446 /**
447 * xmlPythonFileClose:
448 * @context: the I/O context
449 *
450 * Close an I/O channel
451 */
452 static int
xmlPythonFileClose(void * context)453 xmlPythonFileClose (void * context) {
454 PyObject *file, *ret = NULL;
455
456 #ifdef DEBUG_FILES
457 printf("xmlPythonFileClose\n");
458 #endif
459 file = (PyObject *) context;
460 if (file == NULL) return(-1);
461 if (PyObject_HasAttrString(file, (char *) "io_close")) {
462 ret = PyEval_CallMethod(file, (char *) "io_close", (char *) "()");
463 } else if (PyObject_HasAttrString(file, (char *) "flush")) {
464 ret = PyEval_CallMethod(file, (char *) "flush", (char *) "()");
465 }
466 if (ret != NULL) {
467 Py_DECREF(ret);
468 }
469 return(0);
470 }
471
472 #ifdef LIBXML_OUTPUT_ENABLED
473 /**
474 * xmlOutputBufferCreatePythonFile:
475 * @file: a PyFile_Type
476 * @encoder: the encoding converter or NULL
477 *
478 * Create a buffered output for the progressive saving to a PyFile_Type
479 * buffered C I/O
480 *
481 * Returns the new parser output or NULL
482 */
483 static xmlOutputBufferPtr
xmlOutputBufferCreatePythonFile(PyObject * file,xmlCharEncodingHandlerPtr encoder)484 xmlOutputBufferCreatePythonFile(PyObject *file,
485 xmlCharEncodingHandlerPtr encoder) {
486 xmlOutputBufferPtr ret;
487
488 if (file == NULL) return(NULL);
489
490 ret = xmlAllocOutputBuffer(encoder);
491 if (ret != NULL) {
492 ret->context = file;
493 /* Py_INCREF(file); */
494 ret->writecallback = xmlPythonFileWrite;
495 ret->closecallback = xmlPythonFileClose;
496 }
497
498 return(ret);
499 }
500
501 PyObject *
libxml_xmlCreateOutputBuffer(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)502 libxml_xmlCreateOutputBuffer(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) {
503 PyObject *py_retval;
504 PyObject *file;
505 xmlChar *encoding;
506 xmlCharEncodingHandlerPtr handler = NULL;
507 xmlOutputBufferPtr buffer;
508
509
510 if (!PyArg_ParseTuple(args, (char *)"Oz:xmlOutputBufferCreate",
511 &file, &encoding))
512 return(NULL);
513 if ((encoding != NULL) && (encoding[0] != 0)) {
514 handler = xmlFindCharEncodingHandler((const char *) encoding);
515 }
516 buffer = xmlOutputBufferCreatePythonFile(file, handler);
517 if (buffer == NULL)
518 printf("libxml_xmlCreateOutputBuffer: buffer == NULL\n");
519 py_retval = libxml_xmlOutputBufferPtrWrap(buffer);
520 return(py_retval);
521 }
522
523 /**
524 * libxml_outputBufferGetPythonFile:
525 * @buffer: the I/O buffer
526 *
527 * read the Python I/O from the CObject
528 *
529 * Returns the new parser output or NULL
530 */
531 static PyObject *
libxml_outputBufferGetPythonFile(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)532 libxml_outputBufferGetPythonFile(ATTRIBUTE_UNUSED PyObject *self,
533 PyObject *args) {
534 PyObject *buffer;
535 PyObject *file;
536 xmlOutputBufferPtr obj;
537
538 if (!PyArg_ParseTuple(args, (char *)"O:outputBufferGetPythonFile",
539 &buffer))
540 return(NULL);
541
542 obj = PyoutputBuffer_Get(buffer);
543 if (obj == NULL) {
544 fprintf(stderr,
545 "outputBufferGetPythonFile: obj == NULL\n");
546 Py_INCREF(Py_None);
547 return(Py_None);
548 }
549 if (obj->closecallback != xmlPythonFileClose) {
550 fprintf(stderr,
551 "outputBufferGetPythonFile: not a python file wrapper\n");
552 Py_INCREF(Py_None);
553 return(Py_None);
554 }
555 file = (PyObject *) obj->context;
556 if (file == NULL) {
557 Py_INCREF(Py_None);
558 return(Py_None);
559 }
560 Py_INCREF(file);
561 return(file);
562 }
563
564 static PyObject *
libxml_xmlOutputBufferClose(PyObject * self ATTRIBUTE_UNUSED,PyObject * args)565 libxml_xmlOutputBufferClose(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
566 PyObject *py_retval;
567 int c_retval;
568 xmlOutputBufferPtr out;
569 PyObject *pyobj_out;
570
571 if (!PyArg_ParseTuple(args, (char *)"O:xmlOutputBufferClose", &pyobj_out))
572 return(NULL);
573 out = (xmlOutputBufferPtr) PyoutputBuffer_Get(pyobj_out);
574 /* Buffer may already have been destroyed elsewhere. This is harmless. */
575 if (out == NULL) {
576 Py_INCREF(Py_None);
577 return(Py_None);
578 }
579
580 c_retval = xmlOutputBufferClose(out);
581 py_retval = libxml_intWrap((int) c_retval);
582 return(py_retval);
583 }
584
585 static PyObject *
libxml_xmlOutputBufferFlush(PyObject * self ATTRIBUTE_UNUSED,PyObject * args)586 libxml_xmlOutputBufferFlush(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
587 PyObject *py_retval;
588 int c_retval;
589 xmlOutputBufferPtr out;
590 PyObject *pyobj_out;
591
592 if (!PyArg_ParseTuple(args, (char *)"O:xmlOutputBufferFlush", &pyobj_out))
593 return(NULL);
594 out = (xmlOutputBufferPtr) PyoutputBuffer_Get(pyobj_out);
595
596 c_retval = xmlOutputBufferFlush(out);
597 py_retval = libxml_intWrap((int) c_retval);
598 return(py_retval);
599 }
600
601 static PyObject *
libxml_xmlSaveFileTo(PyObject * self ATTRIBUTE_UNUSED,PyObject * args)602 libxml_xmlSaveFileTo(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
603 PyObject *py_retval;
604 int c_retval;
605 xmlOutputBufferPtr buf;
606 PyObject *pyobj_buf;
607 xmlDocPtr cur;
608 PyObject *pyobj_cur;
609 char * encoding;
610
611 if (!PyArg_ParseTuple(args, (char *)"OOz:xmlSaveFileTo", &pyobj_buf, &pyobj_cur, &encoding))
612 return(NULL);
613 buf = (xmlOutputBufferPtr) PyoutputBuffer_Get(pyobj_buf);
614 cur = (xmlDocPtr) PyxmlNode_Get(pyobj_cur);
615
616 c_retval = xmlSaveFileTo(buf, cur, encoding);
617 /* xmlSaveTo() freed the memory pointed to by buf, so record that in the
618 * Python object. */
619 ((PyoutputBuffer_Object *)(pyobj_buf))->obj = NULL;
620 py_retval = libxml_intWrap((int) c_retval);
621 return(py_retval);
622 }
623
624 static PyObject *
libxml_xmlSaveFormatFileTo(PyObject * self ATTRIBUTE_UNUSED,PyObject * args)625 libxml_xmlSaveFormatFileTo(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
626 PyObject *py_retval;
627 int c_retval;
628 xmlOutputBufferPtr buf;
629 PyObject *pyobj_buf;
630 xmlDocPtr cur;
631 PyObject *pyobj_cur;
632 char * encoding;
633 int format;
634
635 if (!PyArg_ParseTuple(args, (char *)"OOzi:xmlSaveFormatFileTo", &pyobj_buf, &pyobj_cur, &encoding, &format))
636 return(NULL);
637 buf = (xmlOutputBufferPtr) PyoutputBuffer_Get(pyobj_buf);
638 cur = (xmlDocPtr) PyxmlNode_Get(pyobj_cur);
639
640 c_retval = xmlSaveFormatFileTo(buf, cur, encoding, format);
641 /* xmlSaveFormatFileTo() freed the memory pointed to by buf, so record that
642 * in the Python object */
643 ((PyoutputBuffer_Object *)(pyobj_buf))->obj = NULL;
644 py_retval = libxml_intWrap((int) c_retval);
645 return(py_retval);
646 }
647 #endif /* LIBXML_OUTPUT_ENABLED */
648
649
650 /**
651 * xmlParserInputBufferCreatePythonFile:
652 * @file: a PyFile_Type
653 * @encoder: the encoding converter or NULL
654 *
655 * Create a buffered output for the progressive saving to a PyFile_Type
656 * buffered C I/O
657 *
658 * Returns the new parser output or NULL
659 */
660 static xmlParserInputBufferPtr
xmlParserInputBufferCreatePythonFile(PyObject * file,xmlCharEncoding encoding)661 xmlParserInputBufferCreatePythonFile(PyObject *file,
662 xmlCharEncoding encoding) {
663 xmlParserInputBufferPtr ret;
664
665 if (file == NULL) return(NULL);
666
667 ret = xmlAllocParserInputBuffer(encoding);
668 if (ret != NULL) {
669 ret->context = file;
670 /* Py_INCREF(file); */
671 ret->readcallback = xmlPythonFileRead;
672 ret->closecallback = xmlPythonFileClose;
673 }
674
675 return(ret);
676 }
677
678 PyObject *
libxml_xmlCreateInputBuffer(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)679 libxml_xmlCreateInputBuffer(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) {
680 PyObject *py_retval;
681 PyObject *file;
682 xmlChar *encoding;
683 xmlCharEncoding enc = XML_CHAR_ENCODING_NONE;
684 xmlParserInputBufferPtr buffer;
685
686
687 if (!PyArg_ParseTuple(args, (char *)"Oz:xmlParserInputBufferCreate",
688 &file, &encoding))
689 return(NULL);
690 if ((encoding != NULL) && (encoding[0] != 0)) {
691 enc = xmlParseCharEncoding((const char *) encoding);
692 }
693 buffer = xmlParserInputBufferCreatePythonFile(file, enc);
694 if (buffer == NULL)
695 printf("libxml_xmlParserInputBufferCreate: buffer == NULL\n");
696 py_retval = libxml_xmlParserInputBufferPtrWrap(buffer);
697 return(py_retval);
698 }
699
700 /************************************************************************
701 * *
702 * Providing the resolver at the Python level *
703 * *
704 ************************************************************************/
705
706 static xmlExternalEntityLoader defaultExternalEntityLoader = NULL;
707 static PyObject *pythonExternalEntityLoaderObjext;
708
709 static xmlParserInputPtr
pythonExternalEntityLoader(const char * URL,const char * ID,xmlParserCtxtPtr ctxt)710 pythonExternalEntityLoader(const char *URL, const char *ID,
711 xmlParserCtxtPtr ctxt) {
712 xmlParserInputPtr result = NULL;
713 if (pythonExternalEntityLoaderObjext != NULL) {
714 PyObject *ret;
715 PyObject *ctxtobj;
716
717 ctxtobj = libxml_xmlParserCtxtPtrWrap(ctxt);
718 #ifdef DEBUG_LOADER
719 printf("pythonExternalEntityLoader: ready to call\n");
720 #endif
721
722 ret = PyObject_CallFunction(pythonExternalEntityLoaderObjext,
723 (char *) "(ssO)", URL, ID, ctxtobj);
724 Py_XDECREF(ctxtobj);
725 #ifdef DEBUG_LOADER
726 printf("pythonExternalEntityLoader: result ");
727 PyObject_Print(ret, stdout, 0);
728 printf("\n");
729 #endif
730
731 if (ret != NULL) {
732 if (PyObject_HasAttrString(ret, (char *) "read")) {
733 xmlParserInputBufferPtr buf;
734
735 buf = xmlAllocParserInputBuffer(XML_CHAR_ENCODING_NONE);
736 if (buf != NULL) {
737 buf->context = ret;
738 buf->readcallback = xmlPythonFileReadRaw;
739 buf->closecallback = xmlPythonFileCloseRaw;
740 result = xmlNewIOInputStream(ctxt, buf,
741 XML_CHAR_ENCODING_NONE);
742 }
743 #if 0
744 } else {
745 if (URL != NULL)
746 printf("pythonExternalEntityLoader: can't read %s\n",
747 URL);
748 #endif
749 }
750 if (result == NULL) {
751 Py_DECREF(ret);
752 } else if (URL != NULL) {
753 result->filename = (char *) xmlStrdup((const xmlChar *)URL);
754 result->directory = xmlParserGetDirectory((const char *) URL);
755 }
756 }
757 }
758 if ((result == NULL) && (defaultExternalEntityLoader != NULL)) {
759 result = defaultExternalEntityLoader(URL, ID, ctxt);
760 }
761 return(result);
762 }
763
764 PyObject *
libxml_xmlSetEntityLoader(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)765 libxml_xmlSetEntityLoader(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) {
766 PyObject *py_retval;
767 PyObject *loader;
768
769 if (!PyArg_ParseTuple(args, (char *)"O:libxml_xmlSetEntityLoader",
770 &loader))
771 return(NULL);
772
773 if (!PyCallable_Check(loader)) {
774 PyErr_SetString(PyExc_ValueError, "entity loader is not callable");
775 return(NULL);
776 }
777
778 #ifdef DEBUG_LOADER
779 printf("libxml_xmlSetEntityLoader\n");
780 #endif
781 if (defaultExternalEntityLoader == NULL)
782 defaultExternalEntityLoader = xmlGetExternalEntityLoader();
783
784 Py_XDECREF(pythonExternalEntityLoaderObjext);
785 pythonExternalEntityLoaderObjext = loader;
786 Py_XINCREF(pythonExternalEntityLoaderObjext);
787 xmlSetExternalEntityLoader(pythonExternalEntityLoader);
788
789 py_retval = PyLong_FromLong(0);
790 return(py_retval);
791 }
792
793 /************************************************************************
794 * *
795 * Input callback registration *
796 * *
797 ************************************************************************/
798 static PyObject *pythonInputOpenCallbackObject;
799 static int pythonInputCallbackID = -1;
800
801 static int
pythonInputMatchCallback(ATTRIBUTE_UNUSED const char * URI)802 pythonInputMatchCallback(ATTRIBUTE_UNUSED const char *URI)
803 {
804 /* Always return success, real decision whether URI is supported will be
805 * made in open callback. */
806 return 1;
807 }
808
809 static void *
pythonInputOpenCallback(const char * URI)810 pythonInputOpenCallback(const char *URI)
811 {
812 PyObject *ret;
813
814 ret = PyObject_CallFunction(pythonInputOpenCallbackObject,
815 (char *)"s", URI);
816 if (ret == Py_None) {
817 Py_DECREF(Py_None);
818 return NULL;
819 }
820 return ret;
821 }
822
823 PyObject *
libxml_xmlRegisterInputCallback(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)824 libxml_xmlRegisterInputCallback(ATTRIBUTE_UNUSED PyObject *self,
825 PyObject *args) {
826 PyObject *cb;
827
828 if (!PyArg_ParseTuple(args,
829 (const char *)"O:libxml_xmlRegisterInputCallback", &cb))
830 return(NULL);
831
832 if (!PyCallable_Check(cb)) {
833 PyErr_SetString(PyExc_ValueError, "input callback is not callable");
834 return(NULL);
835 }
836
837 /* Python module registers a single callback and manages the list of
838 * all callbacks internally. This is necessitated by xmlInputMatchCallback
839 * API, which does not allow for passing of data objects to discriminate
840 * different Python methods. */
841 if (pythonInputCallbackID == -1) {
842 pythonInputCallbackID = xmlRegisterInputCallbacks(
843 pythonInputMatchCallback, pythonInputOpenCallback,
844 xmlPythonFileReadRaw, xmlPythonFileCloseRaw);
845 if (pythonInputCallbackID == -1)
846 return PyErr_NoMemory();
847 pythonInputOpenCallbackObject = cb;
848 Py_INCREF(pythonInputOpenCallbackObject);
849 }
850
851 Py_INCREF(Py_None);
852 return(Py_None);
853 }
854
855 PyObject *
libxml_xmlUnregisterInputCallback(ATTRIBUTE_UNUSED PyObject * self,ATTRIBUTE_UNUSED PyObject * args)856 libxml_xmlUnregisterInputCallback(ATTRIBUTE_UNUSED PyObject *self,
857 ATTRIBUTE_UNUSED PyObject *args) {
858 int ret;
859
860 ret = xmlPopInputCallbacks();
861 if (pythonInputCallbackID != -1) {
862 /* Assert that the right input callback was popped. libxml's API does not
863 * allow removal by ID, so all that could be done is an assert. */
864 if (pythonInputCallbackID == ret) {
865 pythonInputCallbackID = -1;
866 Py_DECREF(pythonInputOpenCallbackObject);
867 pythonInputOpenCallbackObject = NULL;
868 } else {
869 PyErr_SetString(PyExc_AssertionError, "popped non-python input callback");
870 return(NULL);
871 }
872 } else if (ret == -1) {
873 /* No more callbacks to pop */
874 PyErr_SetString(PyExc_IndexError, "no input callbacks to pop");
875 return(NULL);
876 }
877
878 Py_INCREF(Py_None);
879 return(Py_None);
880 }
881
882 /************************************************************************
883 * *
884 * Handling SAX/xmllib/sgmlop callback interfaces *
885 * *
886 ************************************************************************/
887
888 static void
pythonStartElement(void * user_data,const xmlChar * name,const xmlChar ** attrs)889 pythonStartElement(void *user_data, const xmlChar * name,
890 const xmlChar ** attrs)
891 {
892 int i;
893 PyObject *handler;
894 PyObject *dict;
895 PyObject *attrname;
896 PyObject *attrvalue;
897 PyObject *result = NULL;
898 int type = 0;
899
900 #ifdef DEBUG_SAX
901 printf("pythonStartElement(%s) called\n", name);
902 #endif
903 handler = (PyObject *) user_data;
904 if (PyObject_HasAttrString(handler, (char *) "startElement"))
905 type = 1;
906 else if (PyObject_HasAttrString(handler, (char *) "start"))
907 type = 2;
908 if (type != 0) {
909 /*
910 * the xmllib interface always generates a dictionary,
911 * possibly empty
912 */
913 if ((attrs == NULL) && (type == 1)) {
914 Py_XINCREF(Py_None);
915 dict = Py_None;
916 } else if (attrs == NULL) {
917 dict = PyDict_New();
918 } else {
919 dict = PyDict_New();
920 for (i = 0; attrs[i] != NULL; i++) {
921 attrname = PY_IMPORT_STRING((char *) attrs[i]);
922 i++;
923 if (attrs[i] != NULL) {
924 attrvalue = PY_IMPORT_STRING((char *) attrs[i]);
925 } else {
926 Py_XINCREF(Py_None);
927 attrvalue = Py_None;
928 }
929 PyDict_SetItem(dict, attrname, attrvalue);
930 Py_DECREF(attrname);
931 Py_DECREF(attrvalue);
932 }
933 }
934
935 if (type == 1)
936 result = PyObject_CallMethod(handler, (char *) "startElement",
937 (char *) "sO", name, dict);
938 else if (type == 2)
939 result = PyObject_CallMethod(handler, (char *) "start",
940 (char *) "sO", name, dict);
941 if (PyErr_Occurred())
942 PyErr_Print();
943 Py_XDECREF(dict);
944 Py_XDECREF(result);
945 }
946 }
947
948 static void
pythonStartDocument(void * user_data)949 pythonStartDocument(void *user_data)
950 {
951 PyObject *handler;
952 PyObject *result;
953
954 #ifdef DEBUG_SAX
955 printf("pythonStartDocument() called\n");
956 #endif
957 handler = (PyObject *) user_data;
958 if (PyObject_HasAttrString(handler, (char *) "startDocument")) {
959 result =
960 PyObject_CallMethod(handler, (char *) "startDocument", NULL);
961 if (PyErr_Occurred())
962 PyErr_Print();
963 Py_XDECREF(result);
964 }
965 }
966
967 static void
pythonEndDocument(void * user_data)968 pythonEndDocument(void *user_data)
969 {
970 PyObject *handler;
971 PyObject *result;
972
973 #ifdef DEBUG_SAX
974 printf("pythonEndDocument() called\n");
975 #endif
976 handler = (PyObject *) user_data;
977 if (PyObject_HasAttrString(handler, (char *) "endDocument")) {
978 result =
979 PyObject_CallMethod(handler, (char *) "endDocument", NULL);
980 if (PyErr_Occurred())
981 PyErr_Print();
982 Py_XDECREF(result);
983 }
984 /*
985 * The reference to the handler is released there
986 */
987 Py_XDECREF(handler);
988 }
989
990 static void
pythonEndElement(void * user_data,const xmlChar * name)991 pythonEndElement(void *user_data, const xmlChar * name)
992 {
993 PyObject *handler;
994 PyObject *result;
995
996 #ifdef DEBUG_SAX
997 printf("pythonEndElement(%s) called\n", name);
998 #endif
999 handler = (PyObject *) user_data;
1000 if (PyObject_HasAttrString(handler, (char *) "endElement")) {
1001 result = PyObject_CallMethod(handler, (char *) "endElement",
1002 (char *) "s", name);
1003 if (PyErr_Occurred())
1004 PyErr_Print();
1005 Py_XDECREF(result);
1006 } else if (PyObject_HasAttrString(handler, (char *) "end")) {
1007 result = PyObject_CallMethod(handler, (char *) "end",
1008 (char *) "s", name);
1009 if (PyErr_Occurred())
1010 PyErr_Print();
1011 Py_XDECREF(result);
1012 }
1013 }
1014
1015 static void
pythonReference(void * user_data,const xmlChar * name)1016 pythonReference(void *user_data, const xmlChar * name)
1017 {
1018 PyObject *handler;
1019 PyObject *result;
1020
1021 #ifdef DEBUG_SAX
1022 printf("pythonReference(%s) called\n", name);
1023 #endif
1024 handler = (PyObject *) user_data;
1025 if (PyObject_HasAttrString(handler, (char *) "reference")) {
1026 result = PyObject_CallMethod(handler, (char *) "reference",
1027 (char *) "s", name);
1028 if (PyErr_Occurred())
1029 PyErr_Print();
1030 Py_XDECREF(result);
1031 }
1032 }
1033
1034 static void
pythonCharacters(void * user_data,const xmlChar * ch,int len)1035 pythonCharacters(void *user_data, const xmlChar * ch, int len)
1036 {
1037 PyObject *handler;
1038 PyObject *result = NULL;
1039 int type = 0;
1040
1041 #ifdef DEBUG_SAX
1042 printf("pythonCharacters(%s, %d) called\n", ch, len);
1043 #endif
1044 handler = (PyObject *) user_data;
1045 if (PyObject_HasAttrString(handler, (char *) "characters"))
1046 type = 1;
1047 else if (PyObject_HasAttrString(handler, (char *) "data"))
1048 type = 2;
1049 if (type != 0) {
1050 if (type == 1)
1051 result = PyObject_CallMethod(handler, (char *) "characters",
1052 (char *) "s#", ch, (Py_ssize_t)len);
1053 else if (type == 2)
1054 result = PyObject_CallMethod(handler, (char *) "data",
1055 (char *) "s#", ch, (Py_ssize_t)len);
1056 if (PyErr_Occurred())
1057 PyErr_Print();
1058 Py_XDECREF(result);
1059 }
1060 }
1061
1062 static void
pythonIgnorableWhitespace(void * user_data,const xmlChar * ch,int len)1063 pythonIgnorableWhitespace(void *user_data, const xmlChar * ch, int len)
1064 {
1065 PyObject *handler;
1066 PyObject *result = NULL;
1067 int type = 0;
1068
1069 #ifdef DEBUG_SAX
1070 printf("pythonIgnorableWhitespace(%s, %d) called\n", ch, len);
1071 #endif
1072 handler = (PyObject *) user_data;
1073 if (PyObject_HasAttrString(handler, (char *) "ignorableWhitespace"))
1074 type = 1;
1075 else if (PyObject_HasAttrString(handler, (char *) "data"))
1076 type = 2;
1077 if (type != 0) {
1078 if (type == 1)
1079 result =
1080 PyObject_CallMethod(handler,
1081 (char *) "ignorableWhitespace",
1082 (char *) "s#", ch, (Py_ssize_t)len);
1083 else if (type == 2)
1084 result =
1085 PyObject_CallMethod(handler, (char *) "data",
1086 (char *) "s#", ch, (Py_ssize_t)len);
1087 Py_XDECREF(result);
1088 }
1089 }
1090
1091 static void
pythonProcessingInstruction(void * user_data,const xmlChar * target,const xmlChar * data)1092 pythonProcessingInstruction(void *user_data,
1093 const xmlChar * target, const xmlChar * data)
1094 {
1095 PyObject *handler;
1096 PyObject *result;
1097
1098 #ifdef DEBUG_SAX
1099 printf("pythonProcessingInstruction(%s, %s) called\n", target, data);
1100 #endif
1101 handler = (PyObject *) user_data;
1102 if (PyObject_HasAttrString(handler, (char *) "processingInstruction")) {
1103 result = PyObject_CallMethod(handler, (char *)
1104 "processingInstruction",
1105 (char *) "ss", target, data);
1106 Py_XDECREF(result);
1107 }
1108 }
1109
1110 static void
pythonComment(void * user_data,const xmlChar * value)1111 pythonComment(void *user_data, const xmlChar * value)
1112 {
1113 PyObject *handler;
1114 PyObject *result;
1115
1116 #ifdef DEBUG_SAX
1117 printf("pythonComment(%s) called\n", value);
1118 #endif
1119 handler = (PyObject *) user_data;
1120 if (PyObject_HasAttrString(handler, (char *) "comment")) {
1121 result =
1122 PyObject_CallMethod(handler, (char *) "comment", (char *) "s",
1123 value);
1124 if (PyErr_Occurred())
1125 PyErr_Print();
1126 Py_XDECREF(result);
1127 }
1128 }
1129
1130 static void
pythonWarning(void * user_data,const char * msg,...)1131 pythonWarning(void *user_data, const char *msg, ...)
1132 {
1133 PyObject *handler;
1134 PyObject *result;
1135 va_list args;
1136 char buf[1024];
1137
1138 #ifdef DEBUG_SAX
1139 printf("pythonWarning(%s) called\n", msg);
1140 #endif
1141 handler = (PyObject *) user_data;
1142 if (PyObject_HasAttrString(handler, (char *) "warning")) {
1143 va_start(args, msg);
1144 vsnprintf(buf, 1023, msg, args);
1145 va_end(args);
1146 buf[1023] = 0;
1147 result =
1148 PyObject_CallMethod(handler, (char *) "warning", (char *) "s",
1149 buf);
1150 if (PyErr_Occurred())
1151 PyErr_Print();
1152 Py_XDECREF(result);
1153 }
1154 }
1155
1156 static void
pythonError(void * user_data,const char * msg,...)1157 pythonError(void *user_data, const char *msg, ...)
1158 {
1159 PyObject *handler;
1160 PyObject *result;
1161 va_list args;
1162 char buf[1024];
1163
1164 #ifdef DEBUG_SAX
1165 printf("pythonError(%s) called\n", msg);
1166 #endif
1167 handler = (PyObject *) user_data;
1168 if (PyObject_HasAttrString(handler, (char *) "error")) {
1169 va_start(args, msg);
1170 vsnprintf(buf, 1023, msg, args);
1171 va_end(args);
1172 buf[1023] = 0;
1173 result =
1174 PyObject_CallMethod(handler, (char *) "error", (char *) "s",
1175 buf);
1176 if (PyErr_Occurred())
1177 PyErr_Print();
1178 Py_XDECREF(result);
1179 }
1180 }
1181
1182 static void
pythonFatalError(void * user_data,const char * msg,...)1183 pythonFatalError(void *user_data, const char *msg, ...)
1184 {
1185 PyObject *handler;
1186 PyObject *result;
1187 va_list args;
1188 char buf[1024];
1189
1190 #ifdef DEBUG_SAX
1191 printf("pythonFatalError(%s) called\n", msg);
1192 #endif
1193 handler = (PyObject *) user_data;
1194 if (PyObject_HasAttrString(handler, (char *) "fatalError")) {
1195 va_start(args, msg);
1196 vsnprintf(buf, 1023, msg, args);
1197 va_end(args);
1198 buf[1023] = 0;
1199 result =
1200 PyObject_CallMethod(handler, (char *) "fatalError",
1201 (char *) "s", buf);
1202 if (PyErr_Occurred())
1203 PyErr_Print();
1204 Py_XDECREF(result);
1205 }
1206 }
1207
1208 static void
pythonCdataBlock(void * user_data,const xmlChar * ch,int len)1209 pythonCdataBlock(void *user_data, const xmlChar * ch, int len)
1210 {
1211 PyObject *handler;
1212 PyObject *result = NULL;
1213 int type = 0;
1214
1215 #ifdef DEBUG_SAX
1216 printf("pythonCdataBlock(%s, %d) called\n", ch, len);
1217 #endif
1218 handler = (PyObject *) user_data;
1219 if (PyObject_HasAttrString(handler, (char *) "cdataBlock"))
1220 type = 1;
1221 else if (PyObject_HasAttrString(handler, (char *) "cdata"))
1222 type = 2;
1223 if (type != 0) {
1224 if (type == 1)
1225 result =
1226 PyObject_CallMethod(handler, (char *) "cdataBlock",
1227 (char *) "s#", ch, (Py_ssize_t)len);
1228 else if (type == 2)
1229 result =
1230 PyObject_CallMethod(handler, (char *) "cdata",
1231 (char *) "s#", ch, (Py_ssize_t)len);
1232 if (PyErr_Occurred())
1233 PyErr_Print();
1234 Py_XDECREF(result);
1235 }
1236 }
1237
1238 static void
pythonExternalSubset(void * user_data,const xmlChar * name,const xmlChar * externalID,const xmlChar * systemID)1239 pythonExternalSubset(void *user_data,
1240 const xmlChar * name,
1241 const xmlChar * externalID, const xmlChar * systemID)
1242 {
1243 PyObject *handler;
1244 PyObject *result;
1245
1246 #ifdef DEBUG_SAX
1247 printf("pythonExternalSubset(%s, %s, %s) called\n",
1248 name, externalID, systemID);
1249 #endif
1250 handler = (PyObject *) user_data;
1251 if (PyObject_HasAttrString(handler, (char *) "externalSubset")) {
1252 result =
1253 PyObject_CallMethod(handler, (char *) "externalSubset",
1254 (char *) "sss", name, externalID,
1255 systemID);
1256 Py_XDECREF(result);
1257 }
1258 }
1259
1260 static void
pythonEntityDecl(void * user_data,const xmlChar * name,int type,const xmlChar * publicId,const xmlChar * systemId,xmlChar * content)1261 pythonEntityDecl(void *user_data,
1262 const xmlChar * name,
1263 int type,
1264 const xmlChar * publicId,
1265 const xmlChar * systemId, xmlChar * content)
1266 {
1267 PyObject *handler;
1268 PyObject *result;
1269
1270 handler = (PyObject *) user_data;
1271 if (PyObject_HasAttrString(handler, (char *) "entityDecl")) {
1272 result = PyObject_CallMethod(handler, (char *) "entityDecl",
1273 (char *) "sisss", name, type,
1274 publicId, systemId, content);
1275 if (PyErr_Occurred())
1276 PyErr_Print();
1277 Py_XDECREF(result);
1278 }
1279 }
1280
1281
1282
1283 static void
1284
pythonNotationDecl(void * user_data,const xmlChar * name,const xmlChar * publicId,const xmlChar * systemId)1285 pythonNotationDecl(void *user_data,
1286 const xmlChar * name,
1287 const xmlChar * publicId, const xmlChar * systemId)
1288 {
1289 PyObject *handler;
1290 PyObject *result;
1291
1292 handler = (PyObject *) user_data;
1293 if (PyObject_HasAttrString(handler, (char *) "notationDecl")) {
1294 result = PyObject_CallMethod(handler, (char *) "notationDecl",
1295 (char *) "sss", name, publicId,
1296 systemId);
1297 if (PyErr_Occurred())
1298 PyErr_Print();
1299 Py_XDECREF(result);
1300 }
1301 }
1302
1303 static void
pythonAttributeDecl(void * user_data,const xmlChar * elem,const xmlChar * name,int type,int def,const xmlChar * defaultValue,xmlEnumerationPtr tree)1304 pythonAttributeDecl(void *user_data,
1305 const xmlChar * elem,
1306 const xmlChar * name,
1307 int type,
1308 int def,
1309 const xmlChar * defaultValue, xmlEnumerationPtr tree)
1310 {
1311 PyObject *handler;
1312 PyObject *nameList;
1313 PyObject *newName;
1314 xmlEnumerationPtr node;
1315 PyObject *result;
1316 int count;
1317
1318 handler = (PyObject *) user_data;
1319 if (PyObject_HasAttrString(handler, (char *) "attributeDecl")) {
1320 count = 0;
1321 for (node = tree; node != NULL; node = node->next) {
1322 count++;
1323 }
1324 nameList = PyList_New(count);
1325 count = 0;
1326 for (node = tree; node != NULL; node = node->next) {
1327 newName = PY_IMPORT_STRING((char *) node->name);
1328 PyList_SetItem(nameList, count, newName);
1329 Py_DECREF(newName);
1330 count++;
1331 }
1332 result = PyObject_CallMethod(handler, (char *) "attributeDecl",
1333 (char *) "ssiisO", elem, name, type,
1334 def, defaultValue, nameList);
1335 if (PyErr_Occurred())
1336 PyErr_Print();
1337 Py_XDECREF(nameList);
1338 Py_XDECREF(result);
1339 }
1340 }
1341
1342 static void
pythonElementDecl(void * user_data,const xmlChar * name,int type,ATTRIBUTE_UNUSED xmlElementContentPtr content)1343 pythonElementDecl(void *user_data,
1344 const xmlChar * name,
1345 int type, ATTRIBUTE_UNUSED xmlElementContentPtr content)
1346 {
1347 PyObject *handler;
1348 PyObject *obj;
1349 PyObject *result;
1350
1351 handler = (PyObject *) user_data;
1352 if (PyObject_HasAttrString(handler, (char *) "elementDecl")) {
1353 /* TODO: wrap in an elementContent object */
1354 printf
1355 ("pythonElementDecl: xmlElementContentPtr wrapper missing !\n");
1356 obj = Py_None;
1357 /* Py_XINCREF(Py_None); isn't the reference just borrowed ??? */
1358 result = PyObject_CallMethod(handler, (char *) "elementDecl",
1359 (char *) "siO", name, type, obj);
1360 if (PyErr_Occurred())
1361 PyErr_Print();
1362 Py_XDECREF(result);
1363 }
1364 }
1365
1366 static void
pythonUnparsedEntityDecl(void * user_data,const xmlChar * name,const xmlChar * publicId,const xmlChar * systemId,const xmlChar * notationName)1367 pythonUnparsedEntityDecl(void *user_data,
1368 const xmlChar * name,
1369 const xmlChar * publicId,
1370 const xmlChar * systemId,
1371 const xmlChar * notationName)
1372 {
1373 PyObject *handler;
1374 PyObject *result;
1375
1376 handler = (PyObject *) user_data;
1377 if (PyObject_HasAttrString(handler, (char *) "unparsedEntityDecl")) {
1378 result =
1379 PyObject_CallMethod(handler, (char *) "unparsedEntityDecl",
1380 (char *) "ssss", name, publicId, systemId,
1381 notationName);
1382 if (PyErr_Occurred())
1383 PyErr_Print();
1384 Py_XDECREF(result);
1385 }
1386 }
1387
1388 static void
pythonInternalSubset(void * user_data,const xmlChar * name,const xmlChar * ExternalID,const xmlChar * SystemID)1389 pythonInternalSubset(void *user_data, const xmlChar * name,
1390 const xmlChar * ExternalID, const xmlChar * SystemID)
1391 {
1392 PyObject *handler;
1393 PyObject *result;
1394
1395 #ifdef DEBUG_SAX
1396 printf("pythonInternalSubset(%s, %s, %s) called\n",
1397 name, ExternalID, SystemID);
1398 #endif
1399 handler = (PyObject *) user_data;
1400 if (PyObject_HasAttrString(handler, (char *) "internalSubset")) {
1401 result = PyObject_CallMethod(handler, (char *) "internalSubset",
1402 (char *) "sss", name, ExternalID,
1403 SystemID);
1404 if (PyErr_Occurred())
1405 PyErr_Print();
1406 Py_XDECREF(result);
1407 }
1408 }
1409
1410 static xmlSAXHandler pythonSaxHandler = {
1411 pythonInternalSubset,
1412 NULL, /* TODO pythonIsStandalone, */
1413 NULL, /* TODO pythonHasInternalSubset, */
1414 NULL, /* TODO pythonHasExternalSubset, */
1415 NULL, /* TODO pythonResolveEntity, */
1416 NULL, /* TODO pythonGetEntity, */
1417 pythonEntityDecl,
1418 pythonNotationDecl,
1419 pythonAttributeDecl,
1420 pythonElementDecl,
1421 pythonUnparsedEntityDecl,
1422 NULL, /* OBSOLETED pythonSetDocumentLocator, */
1423 pythonStartDocument,
1424 pythonEndDocument,
1425 pythonStartElement,
1426 pythonEndElement,
1427 pythonReference,
1428 pythonCharacters,
1429 pythonIgnorableWhitespace,
1430 pythonProcessingInstruction,
1431 pythonComment,
1432 pythonWarning,
1433 pythonError,
1434 pythonFatalError,
1435 NULL, /* TODO pythonGetParameterEntity, */
1436 pythonCdataBlock,
1437 pythonExternalSubset,
1438 1,
1439 NULL, /* TODO migrate to SAX2 */
1440 NULL,
1441 NULL,
1442 NULL
1443 };
1444
1445 /************************************************************************
1446 * *
1447 * Handling of specific parser context *
1448 * *
1449 ************************************************************************/
1450
1451 PyObject *
libxml_xmlCreatePushParser(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)1452 libxml_xmlCreatePushParser(ATTRIBUTE_UNUSED PyObject * self,
1453 PyObject * args)
1454 {
1455 const char *chunk;
1456 int size;
1457 const char *URI;
1458 PyObject *pyobj_SAX = NULL;
1459 xmlSAXHandlerPtr SAX = NULL;
1460 xmlParserCtxtPtr ret;
1461 PyObject *pyret;
1462
1463 if (!PyArg_ParseTuple
1464 (args, (char *) "Oziz:xmlCreatePushParser", &pyobj_SAX, &chunk,
1465 &size, &URI))
1466 return (NULL);
1467
1468 #ifdef DEBUG
1469 printf("libxml_xmlCreatePushParser(%p, %s, %d, %s) called\n",
1470 pyobj_SAX, chunk, size, URI);
1471 #endif
1472 if (pyobj_SAX != Py_None) {
1473 SAX = &pythonSaxHandler;
1474 Py_INCREF(pyobj_SAX);
1475 /* The reference is released in pythonEndDocument() */
1476 }
1477 ret = xmlCreatePushParserCtxt(SAX, pyobj_SAX, chunk, size, URI);
1478 pyret = libxml_xmlParserCtxtPtrWrap(ret);
1479 return (pyret);
1480 }
1481
1482 PyObject *
libxml_htmlCreatePushParser(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)1483 libxml_htmlCreatePushParser(ATTRIBUTE_UNUSED PyObject * self,
1484 PyObject * args)
1485 {
1486 #ifdef LIBXML_HTML_ENABLED
1487 const char *chunk;
1488 int size;
1489 const char *URI;
1490 PyObject *pyobj_SAX = NULL;
1491 xmlSAXHandlerPtr SAX = NULL;
1492 xmlParserCtxtPtr ret;
1493 PyObject *pyret;
1494
1495 if (!PyArg_ParseTuple
1496 (args, (char *) "Oziz:htmlCreatePushParser", &pyobj_SAX, &chunk,
1497 &size, &URI))
1498 return (NULL);
1499
1500 #ifdef DEBUG
1501 printf("libxml_htmlCreatePushParser(%p, %s, %d, %s) called\n",
1502 pyobj_SAX, chunk, size, URI);
1503 #endif
1504 if (pyobj_SAX != Py_None) {
1505 SAX = &pythonSaxHandler;
1506 Py_INCREF(pyobj_SAX);
1507 /* The reference is released in pythonEndDocument() */
1508 }
1509 ret = htmlCreatePushParserCtxt(SAX, pyobj_SAX, chunk, size, URI,
1510 XML_CHAR_ENCODING_NONE);
1511 pyret = libxml_xmlParserCtxtPtrWrap(ret);
1512 return (pyret);
1513 #else
1514 Py_INCREF(Py_None);
1515 return (Py_None);
1516 #endif /* LIBXML_HTML_ENABLED */
1517 }
1518
1519 PyObject *
libxml_xmlSAXParseFile(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)1520 libxml_xmlSAXParseFile(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
1521 {
1522 #ifdef LIBXML_SAX1_ENABLED
1523 int recover;
1524 const char *URI;
1525 PyObject *pyobj_SAX = NULL;
1526 xmlSAXHandlerPtr SAX = NULL;
1527
1528 if (!PyArg_ParseTuple(args, (char *) "Osi:xmlSAXParseFile", &pyobj_SAX,
1529 &URI, &recover))
1530 return (NULL);
1531
1532 #ifdef DEBUG
1533 printf("libxml_xmlSAXParseFile(%p, %s, %d) called\n",
1534 pyobj_SAX, URI, recover);
1535 #endif
1536 if (pyobj_SAX == Py_None) {
1537 Py_INCREF(Py_None);
1538 return (Py_None);
1539 }
1540 SAX = &pythonSaxHandler;
1541 Py_INCREF(pyobj_SAX);
1542 /* The reference is released in pythonEndDocument() */
1543 xmlSAXUserParseFile(SAX, pyobj_SAX, URI);
1544 #endif /* LIBXML_SAX1_ENABLED */
1545 Py_INCREF(Py_None);
1546 return (Py_None);
1547 }
1548
1549 PyObject *
libxml_htmlSAXParseFile(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)1550 libxml_htmlSAXParseFile(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
1551 {
1552 #ifdef LIBXML_HTML_ENABLED
1553 const char *URI;
1554 const char *encoding;
1555 PyObject *pyobj_SAX = NULL;
1556 xmlSAXHandlerPtr SAX = NULL;
1557
1558 if (!PyArg_ParseTuple
1559 (args, (char *) "Osz:htmlSAXParseFile", &pyobj_SAX, &URI,
1560 &encoding))
1561 return (NULL);
1562
1563 #ifdef DEBUG
1564 printf("libxml_htmlSAXParseFile(%p, %s, %s) called\n",
1565 pyobj_SAX, URI, encoding);
1566 #endif
1567 if (pyobj_SAX == Py_None) {
1568 Py_INCREF(Py_None);
1569 return (Py_None);
1570 }
1571 SAX = &pythonSaxHandler;
1572 Py_INCREF(pyobj_SAX);
1573 /* The reference is released in pythonEndDocument() */
1574 htmlSAXParseFile(URI, encoding, SAX, pyobj_SAX);
1575 Py_INCREF(Py_None);
1576 return (Py_None);
1577 #else
1578 Py_INCREF(Py_None);
1579 return (Py_None);
1580 #endif /* LIBXML_HTML_ENABLED */
1581 }
1582
1583 /************************************************************************
1584 * *
1585 * Error message callback *
1586 * *
1587 ************************************************************************/
1588
1589 static PyObject *libxml_xmlPythonErrorFuncHandler = NULL;
1590 static PyObject *libxml_xmlPythonErrorFuncCtxt = NULL;
1591
1592 /* helper to build a xmlMalloc'ed string from a format and va_list */
1593 /*
1594 * disabled the loop, the repeated call to vsnprintf without reset of ap
1595 * in case the initial buffer was too small segfaulted on x86_64
1596 * we now directly vsnprintf on a large buffer.
1597 */
1598 static char *
libxml_buildMessage(const char * msg,va_list ap)1599 libxml_buildMessage(const char *msg, va_list ap)
1600 {
1601 int chars;
1602 char *str;
1603
1604 str = (char *) xmlMalloc(1000);
1605 if (str == NULL)
1606 return NULL;
1607
1608 chars = vsnprintf(str, 999, msg, ap);
1609 if (chars >= 998)
1610 str[999] = 0;
1611
1612 return str;
1613 }
1614
1615 static void
libxml_xmlErrorFuncHandler(ATTRIBUTE_UNUSED void * ctx,const char * msg,...)1616 libxml_xmlErrorFuncHandler(ATTRIBUTE_UNUSED void *ctx, const char *msg,
1617 ...)
1618 {
1619 va_list ap;
1620 PyObject *list;
1621 PyObject *message;
1622 PyObject *result;
1623 char str[1000];
1624 unsigned char *ptr = (unsigned char *)str;
1625
1626 #ifdef DEBUG_ERROR
1627 printf("libxml_xmlErrorFuncHandler(%p, %s, ...) called\n", ctx, msg);
1628 #endif
1629
1630
1631 if (libxml_xmlPythonErrorFuncHandler == NULL) {
1632 va_start(ap, msg);
1633 vfprintf(stderr, msg, ap);
1634 va_end(ap);
1635 } else {
1636 va_start(ap, msg);
1637 if (vsnprintf(str, 999, msg, ap) >= 998)
1638 str[999] = 0;
1639 va_end(ap);
1640
1641 #if PY_MAJOR_VERSION >= 3
1642 /* Ensure the error string doesn't start at UTF8 continuation. */
1643 while (*ptr && (*ptr & 0xc0) == 0x80)
1644 ptr++;
1645 #endif
1646
1647 list = PyTuple_New(2);
1648 PyTuple_SetItem(list, 0, libxml_xmlPythonErrorFuncCtxt);
1649 Py_XINCREF(libxml_xmlPythonErrorFuncCtxt);
1650 message = libxml_charPtrConstWrap(ptr);
1651 PyTuple_SetItem(list, 1, message);
1652 result = PyEval_CallObject(libxml_xmlPythonErrorFuncHandler, list);
1653 /* Forget any errors caused in the error handler. */
1654 PyErr_Clear();
1655 Py_XDECREF(list);
1656 Py_XDECREF(result);
1657 }
1658 }
1659
1660 static void
libxml_xmlErrorInitialize(void)1661 libxml_xmlErrorInitialize(void)
1662 {
1663 #ifdef DEBUG_ERROR
1664 printf("libxml_xmlErrorInitialize() called\n");
1665 #endif
1666 xmlSetGenericErrorFunc(NULL, libxml_xmlErrorFuncHandler);
1667 xmlThrDefSetGenericErrorFunc(NULL, libxml_xmlErrorFuncHandler);
1668 }
1669
1670 static PyObject *
libxml_xmlRegisterErrorHandler(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)1671 libxml_xmlRegisterErrorHandler(ATTRIBUTE_UNUSED PyObject * self,
1672 PyObject * args)
1673 {
1674 PyObject *py_retval;
1675 PyObject *pyobj_f;
1676 PyObject *pyobj_ctx;
1677
1678 if (!PyArg_ParseTuple
1679 (args, (char *) "OO:xmlRegisterErrorHandler", &pyobj_f,
1680 &pyobj_ctx))
1681 return (NULL);
1682
1683 #ifdef DEBUG_ERROR
1684 printf("libxml_xmlRegisterErrorHandler(%p, %p) called\n", pyobj_ctx,
1685 pyobj_f);
1686 #endif
1687
1688 if (libxml_xmlPythonErrorFuncHandler != NULL) {
1689 Py_XDECREF(libxml_xmlPythonErrorFuncHandler);
1690 }
1691 if (libxml_xmlPythonErrorFuncCtxt != NULL) {
1692 Py_XDECREF(libxml_xmlPythonErrorFuncCtxt);
1693 }
1694
1695 Py_XINCREF(pyobj_ctx);
1696 Py_XINCREF(pyobj_f);
1697
1698 /* TODO: check f is a function ! */
1699 libxml_xmlPythonErrorFuncHandler = pyobj_f;
1700 libxml_xmlPythonErrorFuncCtxt = pyobj_ctx;
1701
1702 py_retval = libxml_intWrap(1);
1703 return (py_retval);
1704 }
1705
1706
1707 /************************************************************************
1708 * *
1709 * Per parserCtxt error handler *
1710 * *
1711 ************************************************************************/
1712
1713 typedef struct
1714 {
1715 PyObject *f;
1716 PyObject *arg;
1717 } xmlParserCtxtPyCtxt;
1718 typedef xmlParserCtxtPyCtxt *xmlParserCtxtPyCtxtPtr;
1719
1720 static void
libxml_xmlParserCtxtGenericErrorFuncHandler(void * ctx,int severity,char * str)1721 libxml_xmlParserCtxtGenericErrorFuncHandler(void *ctx, int severity, char *str)
1722 {
1723 PyObject *list;
1724 PyObject *result;
1725 xmlParserCtxtPtr ctxt;
1726 xmlParserCtxtPyCtxtPtr pyCtxt;
1727
1728 #ifdef DEBUG_ERROR
1729 printf("libxml_xmlParserCtxtGenericErrorFuncHandler(%p, %s, ...) called\n", ctx, str);
1730 #endif
1731
1732 ctxt = (xmlParserCtxtPtr)ctx;
1733 pyCtxt = (xmlParserCtxtPyCtxtPtr)ctxt->_private;
1734
1735 list = PyTuple_New(4);
1736 PyTuple_SetItem(list, 0, pyCtxt->arg);
1737 Py_XINCREF(pyCtxt->arg);
1738 PyTuple_SetItem(list, 1, libxml_charPtrWrap(str));
1739 PyTuple_SetItem(list, 2, libxml_intWrap(severity));
1740 PyTuple_SetItem(list, 3, Py_None);
1741 Py_INCREF(Py_None);
1742 result = PyEval_CallObject(pyCtxt->f, list);
1743 if (result == NULL)
1744 {
1745 /* TODO: manage for the exception to be propagated... */
1746 PyErr_Print();
1747 }
1748 Py_XDECREF(list);
1749 Py_XDECREF(result);
1750 }
1751
1752 static void
libxml_xmlParserCtxtErrorFuncHandler(void * ctx,const char * msg,...)1753 libxml_xmlParserCtxtErrorFuncHandler(void *ctx, const char *msg, ...)
1754 {
1755 va_list ap;
1756
1757 va_start(ap, msg);
1758 libxml_xmlParserCtxtGenericErrorFuncHandler(ctx,XML_PARSER_SEVERITY_ERROR,libxml_buildMessage(msg,ap));
1759 va_end(ap);
1760 }
1761
1762 static void
libxml_xmlParserCtxtWarningFuncHandler(void * ctx,const char * msg,...)1763 libxml_xmlParserCtxtWarningFuncHandler(void *ctx, const char *msg, ...)
1764 {
1765 va_list ap;
1766
1767 va_start(ap, msg);
1768 libxml_xmlParserCtxtGenericErrorFuncHandler(ctx,XML_PARSER_SEVERITY_WARNING,libxml_buildMessage(msg,ap));
1769 va_end(ap);
1770 }
1771
1772 static void
libxml_xmlParserCtxtValidityErrorFuncHandler(void * ctx,const char * msg,...)1773 libxml_xmlParserCtxtValidityErrorFuncHandler(void *ctx, const char *msg, ...)
1774 {
1775 va_list ap;
1776
1777 va_start(ap, msg);
1778 libxml_xmlParserCtxtGenericErrorFuncHandler(ctx,XML_PARSER_SEVERITY_VALIDITY_ERROR,libxml_buildMessage(msg,ap));
1779 va_end(ap);
1780 }
1781
1782 static void
libxml_xmlParserCtxtValidityWarningFuncHandler(void * ctx,const char * msg,...)1783 libxml_xmlParserCtxtValidityWarningFuncHandler(void *ctx, const char *msg, ...)
1784 {
1785 va_list ap;
1786
1787 va_start(ap, msg);
1788 libxml_xmlParserCtxtGenericErrorFuncHandler(ctx,XML_PARSER_SEVERITY_VALIDITY_WARNING,libxml_buildMessage(msg,ap));
1789 va_end(ap);
1790 }
1791
1792 static PyObject *
libxml_xmlParserCtxtSetErrorHandler(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)1793 libxml_xmlParserCtxtSetErrorHandler(ATTRIBUTE_UNUSED PyObject *self, PyObject *args)
1794 {
1795 PyObject *py_retval;
1796 xmlParserCtxtPtr ctxt;
1797 xmlParserCtxtPyCtxtPtr pyCtxt;
1798 PyObject *pyobj_ctxt;
1799 PyObject *pyobj_f;
1800 PyObject *pyobj_arg;
1801
1802 if (!PyArg_ParseTuple(args, (char *)"OOO:xmlParserCtxtSetErrorHandler",
1803 &pyobj_ctxt, &pyobj_f, &pyobj_arg))
1804 return(NULL);
1805 ctxt = (xmlParserCtxtPtr) PyparserCtxt_Get(pyobj_ctxt);
1806 if (ctxt->_private == NULL) {
1807 pyCtxt = xmlMalloc(sizeof(xmlParserCtxtPyCtxt));
1808 if (pyCtxt == NULL) {
1809 py_retval = libxml_intWrap(-1);
1810 return(py_retval);
1811 }
1812 memset(pyCtxt,0,sizeof(xmlParserCtxtPyCtxt));
1813 ctxt->_private = pyCtxt;
1814 }
1815 else {
1816 pyCtxt = (xmlParserCtxtPyCtxtPtr)ctxt->_private;
1817 }
1818 /* TODO: check f is a function ! */
1819 Py_XDECREF(pyCtxt->f);
1820 Py_XINCREF(pyobj_f);
1821 pyCtxt->f = pyobj_f;
1822 Py_XDECREF(pyCtxt->arg);
1823 Py_XINCREF(pyobj_arg);
1824 pyCtxt->arg = pyobj_arg;
1825
1826 if (pyobj_f != Py_None) {
1827 ctxt->sax->error = libxml_xmlParserCtxtErrorFuncHandler;
1828 ctxt->sax->warning = libxml_xmlParserCtxtWarningFuncHandler;
1829 ctxt->vctxt.error = libxml_xmlParserCtxtValidityErrorFuncHandler;
1830 ctxt->vctxt.warning = libxml_xmlParserCtxtValidityWarningFuncHandler;
1831 }
1832 else {
1833 ctxt->sax->error = xmlParserError;
1834 ctxt->vctxt.error = xmlParserValidityError;
1835 ctxt->sax->warning = xmlParserWarning;
1836 ctxt->vctxt.warning = xmlParserValidityWarning;
1837 }
1838
1839 py_retval = libxml_intWrap(1);
1840 return(py_retval);
1841 }
1842
1843 static PyObject *
libxml_xmlParserCtxtGetErrorHandler(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)1844 libxml_xmlParserCtxtGetErrorHandler(ATTRIBUTE_UNUSED PyObject *self, PyObject *args)
1845 {
1846 PyObject *py_retval;
1847 xmlParserCtxtPtr ctxt;
1848 xmlParserCtxtPyCtxtPtr pyCtxt;
1849 PyObject *pyobj_ctxt;
1850
1851 if (!PyArg_ParseTuple(args, (char *)"O:xmlParserCtxtGetErrorHandler",
1852 &pyobj_ctxt))
1853 return(NULL);
1854 ctxt = (xmlParserCtxtPtr) PyparserCtxt_Get(pyobj_ctxt);
1855 py_retval = PyTuple_New(2);
1856 if (ctxt->_private != NULL) {
1857 pyCtxt = (xmlParserCtxtPyCtxtPtr)ctxt->_private;
1858
1859 PyTuple_SetItem(py_retval, 0, pyCtxt->f);
1860 Py_XINCREF(pyCtxt->f);
1861 PyTuple_SetItem(py_retval, 1, pyCtxt->arg);
1862 Py_XINCREF(pyCtxt->arg);
1863 }
1864 else {
1865 /* no python error handler registered */
1866 PyTuple_SetItem(py_retval, 0, Py_None);
1867 Py_XINCREF(Py_None);
1868 PyTuple_SetItem(py_retval, 1, Py_None);
1869 Py_XINCREF(Py_None);
1870 }
1871 return(py_retval);
1872 }
1873
1874 static PyObject *
libxml_xmlFreeParserCtxt(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)1875 libxml_xmlFreeParserCtxt(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) {
1876 xmlParserCtxtPtr ctxt;
1877 PyObject *pyobj_ctxt;
1878 xmlParserCtxtPyCtxtPtr pyCtxt;
1879
1880 if (!PyArg_ParseTuple(args, (char *)"O:xmlFreeParserCtxt", &pyobj_ctxt))
1881 return(NULL);
1882 ctxt = (xmlParserCtxtPtr) PyparserCtxt_Get(pyobj_ctxt);
1883
1884 if (ctxt != NULL) {
1885 pyCtxt = (xmlParserCtxtPyCtxtPtr)((xmlParserCtxtPtr)ctxt)->_private;
1886 if (pyCtxt) {
1887 Py_XDECREF(pyCtxt->f);
1888 Py_XDECREF(pyCtxt->arg);
1889 xmlFree(pyCtxt);
1890 }
1891 xmlFreeParserCtxt(ctxt);
1892 }
1893
1894 Py_INCREF(Py_None);
1895 return(Py_None);
1896 }
1897
1898 /***
1899 * xmlValidCtxt stuff
1900 */
1901
1902 typedef struct
1903 {
1904 PyObject *warn;
1905 PyObject *error;
1906 PyObject *arg;
1907 } xmlValidCtxtPyCtxt;
1908 typedef xmlValidCtxtPyCtxt *xmlValidCtxtPyCtxtPtr;
1909
1910 static void
libxml_xmlValidCtxtGenericErrorFuncHandler(void * ctx,ATTRIBUTE_UNUSED int severity,char * str)1911 libxml_xmlValidCtxtGenericErrorFuncHandler(void *ctx, ATTRIBUTE_UNUSED int severity, char *str)
1912 {
1913 PyObject *list;
1914 PyObject *result;
1915 xmlValidCtxtPyCtxtPtr pyCtxt;
1916
1917 #ifdef DEBUG_ERROR
1918 printf("libxml_xmlValidCtxtGenericErrorFuncHandler(%p, %d, %s, ...) called\n", ctx, severity, str);
1919 #endif
1920
1921 pyCtxt = (xmlValidCtxtPyCtxtPtr)ctx;
1922
1923 list = PyTuple_New(2);
1924 PyTuple_SetItem(list, 0, libxml_charPtrWrap(str));
1925 PyTuple_SetItem(list, 1, pyCtxt->arg);
1926 Py_XINCREF(pyCtxt->arg);
1927 result = PyEval_CallObject(pyCtxt->error, list);
1928 if (result == NULL)
1929 {
1930 /* TODO: manage for the exception to be propagated... */
1931 PyErr_Print();
1932 }
1933 Py_XDECREF(list);
1934 Py_XDECREF(result);
1935 }
1936
1937 static void
libxml_xmlValidCtxtGenericWarningFuncHandler(void * ctx,ATTRIBUTE_UNUSED int severity,char * str)1938 libxml_xmlValidCtxtGenericWarningFuncHandler(void *ctx, ATTRIBUTE_UNUSED int severity, char *str)
1939 {
1940 PyObject *list;
1941 PyObject *result;
1942 xmlValidCtxtPyCtxtPtr pyCtxt;
1943
1944 #ifdef DEBUG_ERROR
1945 printf("libxml_xmlValidCtxtGenericWarningFuncHandler(%p, %d, %s, ...) called\n", ctx, severity, str);
1946 #endif
1947
1948 pyCtxt = (xmlValidCtxtPyCtxtPtr)ctx;
1949
1950 list = PyTuple_New(2);
1951 PyTuple_SetItem(list, 0, libxml_charPtrWrap(str));
1952 PyTuple_SetItem(list, 1, pyCtxt->arg);
1953 Py_XINCREF(pyCtxt->arg);
1954 result = PyEval_CallObject(pyCtxt->warn, list);
1955 if (result == NULL)
1956 {
1957 /* TODO: manage for the exception to be propagated... */
1958 PyErr_Print();
1959 }
1960 Py_XDECREF(list);
1961 Py_XDECREF(result);
1962 }
1963
1964 static void
libxml_xmlValidCtxtErrorFuncHandler(void * ctx,const char * msg,...)1965 libxml_xmlValidCtxtErrorFuncHandler(void *ctx, const char *msg, ...)
1966 {
1967 va_list ap;
1968
1969 va_start(ap, msg);
1970 libxml_xmlValidCtxtGenericErrorFuncHandler(ctx,XML_PARSER_SEVERITY_VALIDITY_ERROR,libxml_buildMessage(msg,ap));
1971 va_end(ap);
1972 }
1973
1974 static void
libxml_xmlValidCtxtWarningFuncHandler(void * ctx,const char * msg,...)1975 libxml_xmlValidCtxtWarningFuncHandler(void *ctx, const char *msg, ...)
1976 {
1977 va_list ap;
1978
1979 va_start(ap, msg);
1980 libxml_xmlValidCtxtGenericWarningFuncHandler(ctx,XML_PARSER_SEVERITY_VALIDITY_WARNING,libxml_buildMessage(msg,ap));
1981 va_end(ap);
1982 }
1983
1984 static PyObject *
libxml_xmlSetValidErrors(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)1985 libxml_xmlSetValidErrors(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
1986 {
1987 PyObject *py_retval;
1988 PyObject *pyobj_error;
1989 PyObject *pyobj_warn;
1990 PyObject *pyobj_ctx;
1991 PyObject *pyobj_arg = Py_None;
1992 xmlValidCtxtPtr ctxt;
1993 xmlValidCtxtPyCtxtPtr pyCtxt;
1994
1995 if (!PyArg_ParseTuple
1996 (args, (char *) "OOO|O:xmlSetValidErrors", &pyobj_ctx, &pyobj_error, &pyobj_warn, &pyobj_arg))
1997 return (NULL);
1998
1999 #ifdef DEBUG_ERROR
2000 printf("libxml_xmlSetValidErrors(%p, %p, %p) called\n", pyobj_ctx, pyobj_error, pyobj_warn);
2001 #endif
2002
2003 ctxt = PyValidCtxt_Get(pyobj_ctx);
2004 pyCtxt = xmlMalloc(sizeof(xmlValidCtxtPyCtxt));
2005 if (pyCtxt == NULL) {
2006 py_retval = libxml_intWrap(-1);
2007 return(py_retval);
2008 }
2009 memset(pyCtxt, 0, sizeof(xmlValidCtxtPyCtxt));
2010
2011
2012 /* TODO: check warn and error is a function ! */
2013 Py_XDECREF(pyCtxt->error);
2014 Py_XINCREF(pyobj_error);
2015 pyCtxt->error = pyobj_error;
2016
2017 Py_XDECREF(pyCtxt->warn);
2018 Py_XINCREF(pyobj_warn);
2019 pyCtxt->warn = pyobj_warn;
2020
2021 Py_XDECREF(pyCtxt->arg);
2022 Py_XINCREF(pyobj_arg);
2023 pyCtxt->arg = pyobj_arg;
2024
2025 ctxt->error = libxml_xmlValidCtxtErrorFuncHandler;
2026 ctxt->warning = libxml_xmlValidCtxtWarningFuncHandler;
2027 ctxt->userData = pyCtxt;
2028
2029 py_retval = libxml_intWrap(1);
2030 return (py_retval);
2031 }
2032
2033
2034 static PyObject *
libxml_xmlFreeValidCtxt(PyObject * self ATTRIBUTE_UNUSED,PyObject * args)2035 libxml_xmlFreeValidCtxt(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
2036 xmlValidCtxtPtr cur;
2037 xmlValidCtxtPyCtxtPtr pyCtxt;
2038 PyObject *pyobj_cur;
2039
2040 if (!PyArg_ParseTuple(args, (char *)"O:xmlFreeValidCtxt", &pyobj_cur))
2041 return(NULL);
2042 cur = (xmlValidCtxtPtr) PyValidCtxt_Get(pyobj_cur);
2043
2044 pyCtxt = (xmlValidCtxtPyCtxtPtr)(cur->userData);
2045 if (pyCtxt != NULL)
2046 {
2047 Py_XDECREF(pyCtxt->error);
2048 Py_XDECREF(pyCtxt->warn);
2049 Py_XDECREF(pyCtxt->arg);
2050 xmlFree(pyCtxt);
2051 }
2052
2053 xmlFreeValidCtxt(cur);
2054 Py_INCREF(Py_None);
2055 return(Py_None);
2056 }
2057
2058 #ifdef LIBXML_READER_ENABLED
2059 /************************************************************************
2060 * *
2061 * Per xmlTextReader error handler *
2062 * *
2063 ************************************************************************/
2064
2065 typedef struct
2066 {
2067 PyObject *f;
2068 PyObject *arg;
2069 } xmlTextReaderPyCtxt;
2070 typedef xmlTextReaderPyCtxt *xmlTextReaderPyCtxtPtr;
2071
2072 static void
libxml_xmlTextReaderErrorCallback(void * arg,const char * msg,int severity,xmlTextReaderLocatorPtr locator)2073 libxml_xmlTextReaderErrorCallback(void *arg,
2074 const char *msg,
2075 int severity,
2076 xmlTextReaderLocatorPtr locator)
2077 {
2078 xmlTextReaderPyCtxt *pyCtxt = (xmlTextReaderPyCtxt *)arg;
2079 PyObject *list;
2080 PyObject *result;
2081
2082 list = PyTuple_New(4);
2083 PyTuple_SetItem(list, 0, pyCtxt->arg);
2084 Py_XINCREF(pyCtxt->arg);
2085 PyTuple_SetItem(list, 1, libxml_charPtrConstWrap(msg));
2086 PyTuple_SetItem(list, 2, libxml_intWrap(severity));
2087 PyTuple_SetItem(list, 3, libxml_xmlTextReaderLocatorPtrWrap(locator));
2088 result = PyEval_CallObject(pyCtxt->f, list);
2089 if (result == NULL)
2090 {
2091 /* TODO: manage for the exception to be propagated... */
2092 PyErr_Print();
2093 }
2094 Py_XDECREF(list);
2095 Py_XDECREF(result);
2096 }
2097
2098 static PyObject *
libxml_xmlTextReaderSetErrorHandler(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)2099 libxml_xmlTextReaderSetErrorHandler(ATTRIBUTE_UNUSED PyObject *self, PyObject *args)
2100 {
2101 xmlTextReaderPtr reader;
2102 xmlTextReaderPyCtxtPtr pyCtxt;
2103 xmlTextReaderErrorFunc f;
2104 void *arg;
2105 PyObject *pyobj_reader;
2106 PyObject *pyobj_f;
2107 PyObject *pyobj_arg;
2108 PyObject *py_retval;
2109
2110 if (!PyArg_ParseTuple(args, (char *)"OOO:xmlTextReaderSetErrorHandler", &pyobj_reader, &pyobj_f, &pyobj_arg))
2111 return(NULL);
2112 reader = (xmlTextReaderPtr) PyxmlTextReader_Get(pyobj_reader);
2113 /* clear previous error handler */
2114 xmlTextReaderGetErrorHandler(reader,&f,&arg);
2115 if (arg != NULL) {
2116 if (f == (xmlTextReaderErrorFunc) libxml_xmlTextReaderErrorCallback) {
2117 /* ok, it's our error handler! */
2118 pyCtxt = (xmlTextReaderPyCtxtPtr)arg;
2119 Py_XDECREF(pyCtxt->f);
2120 Py_XDECREF(pyCtxt->arg);
2121 xmlFree(pyCtxt);
2122 }
2123 else {
2124 /*
2125 * there already an arg, and it's not ours,
2126 * there is definitely something wrong going on here...
2127 * we don't know how to free it, so we bail out...
2128 */
2129 py_retval = libxml_intWrap(-1);
2130 return(py_retval);
2131 }
2132 }
2133 xmlTextReaderSetErrorHandler(reader,NULL,NULL);
2134 /* set new error handler */
2135 if (pyobj_f != Py_None)
2136 {
2137 pyCtxt = (xmlTextReaderPyCtxtPtr)xmlMalloc(sizeof(xmlTextReaderPyCtxt));
2138 if (pyCtxt == NULL) {
2139 py_retval = libxml_intWrap(-1);
2140 return(py_retval);
2141 }
2142 Py_XINCREF(pyobj_f);
2143 pyCtxt->f = pyobj_f;
2144 Py_XINCREF(pyobj_arg);
2145 pyCtxt->arg = pyobj_arg;
2146 xmlTextReaderSetErrorHandler(reader,
2147 (xmlTextReaderErrorFunc) libxml_xmlTextReaderErrorCallback,
2148 pyCtxt);
2149 }
2150
2151 py_retval = libxml_intWrap(1);
2152 return(py_retval);
2153 }
2154
2155 static PyObject *
libxml_xmlTextReaderGetErrorHandler(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)2156 libxml_xmlTextReaderGetErrorHandler(ATTRIBUTE_UNUSED PyObject *self, PyObject *args)
2157 {
2158 xmlTextReaderPtr reader;
2159 xmlTextReaderPyCtxtPtr pyCtxt;
2160 xmlTextReaderErrorFunc f;
2161 void *arg;
2162 PyObject *pyobj_reader;
2163 PyObject *py_retval;
2164
2165 if (!PyArg_ParseTuple(args, (char *)"O:xmlTextReaderSetErrorHandler", &pyobj_reader))
2166 return(NULL);
2167 reader = (xmlTextReaderPtr) PyxmlTextReader_Get(pyobj_reader);
2168 xmlTextReaderGetErrorHandler(reader,&f,&arg);
2169 py_retval = PyTuple_New(2);
2170 if (f == (xmlTextReaderErrorFunc)libxml_xmlTextReaderErrorCallback) {
2171 /* ok, it's our error handler! */
2172 pyCtxt = (xmlTextReaderPyCtxtPtr)arg;
2173 PyTuple_SetItem(py_retval, 0, pyCtxt->f);
2174 Py_XINCREF(pyCtxt->f);
2175 PyTuple_SetItem(py_retval, 1, pyCtxt->arg);
2176 Py_XINCREF(pyCtxt->arg);
2177 }
2178 else
2179 {
2180 /* f is null or it's not our error handler */
2181 PyTuple_SetItem(py_retval, 0, Py_None);
2182 Py_XINCREF(Py_None);
2183 PyTuple_SetItem(py_retval, 1, Py_None);
2184 Py_XINCREF(Py_None);
2185 }
2186 return(py_retval);
2187 }
2188
2189 static PyObject *
libxml_xmlFreeTextReader(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)2190 libxml_xmlFreeTextReader(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) {
2191 xmlTextReaderPtr reader;
2192 PyObject *pyobj_reader;
2193 xmlTextReaderPyCtxtPtr pyCtxt;
2194 xmlTextReaderErrorFunc f;
2195 void *arg;
2196
2197 if (!PyArg_ParseTuple(args, (char *)"O:xmlFreeTextReader", &pyobj_reader))
2198 return(NULL);
2199 if (!PyCapsule_CheckExact(pyobj_reader)) {
2200 Py_INCREF(Py_None);
2201 return(Py_None);
2202 }
2203 reader = (xmlTextReaderPtr) PyxmlTextReader_Get(pyobj_reader);
2204 if (reader == NULL) {
2205 Py_INCREF(Py_None);
2206 return(Py_None);
2207 }
2208
2209 xmlTextReaderGetErrorHandler(reader,&f,&arg);
2210 if (arg != NULL) {
2211 if (f == (xmlTextReaderErrorFunc) libxml_xmlTextReaderErrorCallback) {
2212 /* ok, it's our error handler! */
2213 pyCtxt = (xmlTextReaderPyCtxtPtr)arg;
2214 Py_XDECREF(pyCtxt->f);
2215 Py_XDECREF(pyCtxt->arg);
2216 xmlFree(pyCtxt);
2217 }
2218 /*
2219 * else, something wrong happened, because the error handler is
2220 * not owned by the python bindings...
2221 */
2222 }
2223
2224 xmlFreeTextReader(reader);
2225 Py_INCREF(Py_None);
2226 return(Py_None);
2227 }
2228 #endif
2229
2230 /************************************************************************
2231 * *
2232 * XPath extensions *
2233 * *
2234 ************************************************************************/
2235
2236 static void
libxml_xmlXPathFuncCallback(xmlXPathParserContextPtr ctxt,int nargs)2237 libxml_xmlXPathFuncCallback(xmlXPathParserContextPtr ctxt, int nargs)
2238 {
2239 PyObject *list, *cur, *result;
2240 xmlXPathObjectPtr obj;
2241 xmlXPathContextPtr rctxt;
2242 PyObject *current_function = NULL;
2243 const xmlChar *name;
2244 const xmlChar *ns_uri;
2245 int i;
2246
2247 if (ctxt == NULL)
2248 return;
2249 rctxt = ctxt->context;
2250 if (rctxt == NULL)
2251 return;
2252 name = rctxt->function;
2253 ns_uri = rctxt->functionURI;
2254 #ifdef DEBUG_XPATH
2255 printf("libxml_xmlXPathFuncCallback called name %s URI %s\n", name,
2256 ns_uri);
2257 #endif
2258
2259 /*
2260 * Find the function, it should be there it was there at lookup
2261 */
2262 for (i = 0; i < libxml_xpathCallbacksNb; i++) {
2263 if ( /* TODO (ctxt == libxml_xpathCallbacks[i].ctx) && */
2264 (xmlStrEqual(name, (*libxml_xpathCallbacks)[i].name)) &&
2265 (xmlStrEqual(ns_uri, (*libxml_xpathCallbacks)[i].ns_uri))) {
2266 current_function = (*libxml_xpathCallbacks)[i].function;
2267 }
2268 }
2269 if (current_function == NULL) {
2270 printf
2271 ("libxml_xmlXPathFuncCallback: internal error %s not found !\n",
2272 name);
2273 return;
2274 }
2275
2276 list = PyTuple_New(nargs + 1);
2277 PyTuple_SetItem(list, 0, libxml_xmlXPathParserContextPtrWrap(ctxt));
2278 for (i = nargs - 1; i >= 0; i--) {
2279 obj = valuePop(ctxt);
2280 cur = libxml_xmlXPathObjectPtrWrap(obj);
2281 PyTuple_SetItem(list, i + 1, cur);
2282 }
2283 result = PyEval_CallObject(current_function, list);
2284 Py_DECREF(list);
2285
2286 obj = libxml_xmlXPathObjectPtrConvert(result);
2287 valuePush(ctxt, obj);
2288 }
2289
2290 static xmlXPathFunction
libxml_xmlXPathFuncLookupFunc(void * ctxt,const xmlChar * name,const xmlChar * ns_uri)2291 libxml_xmlXPathFuncLookupFunc(void *ctxt, const xmlChar * name,
2292 const xmlChar * ns_uri)
2293 {
2294 int i;
2295
2296 #ifdef DEBUG_XPATH
2297 printf("libxml_xmlXPathFuncLookupFunc(%p, %s, %s) called\n",
2298 ctxt, name, ns_uri);
2299 #endif
2300 /*
2301 * This is called once only. The address is then stored in the
2302 * XPath expression evaluation, the proper object to call can
2303 * then still be found using the execution context function
2304 * and functionURI fields.
2305 */
2306 for (i = 0; i < libxml_xpathCallbacksNb; i++) {
2307 if ((ctxt == (*libxml_xpathCallbacks)[i].ctx) &&
2308 (xmlStrEqual(name, (*libxml_xpathCallbacks)[i].name)) &&
2309 (xmlStrEqual(ns_uri, (*libxml_xpathCallbacks)[i].ns_uri))) {
2310 return (libxml_xmlXPathFuncCallback);
2311 }
2312 }
2313 return (NULL);
2314 }
2315
2316 static void
libxml_xpathCallbacksInitialize(void)2317 libxml_xpathCallbacksInitialize(void)
2318 {
2319 int i;
2320
2321 if (libxml_xpathCallbacksInitialized != 0)
2322 return;
2323
2324 #ifdef DEBUG_XPATH
2325 printf("libxml_xpathCallbacksInitialized called\n");
2326 #endif
2327 libxml_xpathCallbacks = (libxml_xpathCallbackArray*)xmlMalloc(
2328 libxml_xpathCallbacksAllocd*sizeof(libxml_xpathCallback));
2329
2330 for (i = 0; i < libxml_xpathCallbacksAllocd; i++) {
2331 (*libxml_xpathCallbacks)[i].ctx = NULL;
2332 (*libxml_xpathCallbacks)[i].name = NULL;
2333 (*libxml_xpathCallbacks)[i].ns_uri = NULL;
2334 (*libxml_xpathCallbacks)[i].function = NULL;
2335 }
2336 libxml_xpathCallbacksInitialized = 1;
2337 }
2338
2339 PyObject *
libxml_xmlRegisterXPathFunction(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)2340 libxml_xmlRegisterXPathFunction(ATTRIBUTE_UNUSED PyObject * self,
2341 PyObject * args)
2342 {
2343 PyObject *py_retval;
2344 int c_retval = 0;
2345 xmlChar *name;
2346 xmlChar *ns_uri;
2347 xmlXPathContextPtr ctx;
2348 PyObject *pyobj_ctx;
2349 PyObject *pyobj_f;
2350 int i;
2351
2352 if (!PyArg_ParseTuple
2353 (args, (char *) "OszO:registerXPathFunction", &pyobj_ctx, &name,
2354 &ns_uri, &pyobj_f))
2355 return (NULL);
2356
2357 ctx = (xmlXPathContextPtr) PyxmlXPathContext_Get(pyobj_ctx);
2358 if (libxml_xpathCallbacksInitialized == 0)
2359 libxml_xpathCallbacksInitialize();
2360 xmlXPathRegisterFuncLookup(ctx, libxml_xmlXPathFuncLookupFunc, ctx);
2361
2362 if ((pyobj_ctx == NULL) || (name == NULL) || (pyobj_f == NULL)) {
2363 py_retval = libxml_intWrap(-1);
2364 return (py_retval);
2365 }
2366 #ifdef DEBUG_XPATH
2367 printf("libxml_registerXPathFunction(%p, %s, %s) called\n",
2368 ctx, name, ns_uri);
2369 #endif
2370 for (i = 0; i < libxml_xpathCallbacksNb; i++) {
2371 if ((ctx == (*libxml_xpathCallbacks)[i].ctx) &&
2372 (xmlStrEqual(name, (*libxml_xpathCallbacks)[i].name)) &&
2373 (xmlStrEqual(ns_uri, (*libxml_xpathCallbacks)[i].ns_uri))) {
2374 Py_XINCREF(pyobj_f);
2375 Py_XDECREF((*libxml_xpathCallbacks)[i].function);
2376 (*libxml_xpathCallbacks)[i].function = pyobj_f;
2377 c_retval = 1;
2378 goto done;
2379 }
2380 }
2381 if (libxml_xpathCallbacksNb >= libxml_xpathCallbacksAllocd) {
2382 libxml_xpathCallbacksAllocd+=10;
2383 libxml_xpathCallbacks = (libxml_xpathCallbackArray*)xmlRealloc(
2384 libxml_xpathCallbacks,
2385 libxml_xpathCallbacksAllocd*sizeof(libxml_xpathCallback));
2386 }
2387 i = libxml_xpathCallbacksNb++;
2388 Py_XINCREF(pyobj_f);
2389 (*libxml_xpathCallbacks)[i].ctx = ctx;
2390 (*libxml_xpathCallbacks)[i].name = xmlStrdup(name);
2391 (*libxml_xpathCallbacks)[i].ns_uri = xmlStrdup(ns_uri);
2392 (*libxml_xpathCallbacks)[i].function = pyobj_f;
2393 c_retval = 1;
2394
2395 done:
2396 py_retval = libxml_intWrap((int) c_retval);
2397 return (py_retval);
2398 }
2399
2400 PyObject *
libxml_xmlXPathRegisterVariable(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)2401 libxml_xmlXPathRegisterVariable(ATTRIBUTE_UNUSED PyObject * self,
2402 PyObject * args)
2403 {
2404 PyObject *py_retval;
2405 int c_retval = 0;
2406 xmlChar *name;
2407 xmlChar *ns_uri;
2408 xmlXPathContextPtr ctx;
2409 xmlXPathObjectPtr val;
2410 PyObject *pyobj_ctx;
2411 PyObject *pyobj_value;
2412
2413 if (!PyArg_ParseTuple
2414 (args, (char *) "OszO:xpathRegisterVariable", &pyobj_ctx, &name,
2415 &ns_uri, &pyobj_value))
2416 return (NULL);
2417
2418 ctx = (xmlXPathContextPtr) PyxmlXPathContext_Get(pyobj_ctx);
2419 val = libxml_xmlXPathObjectPtrConvert(pyobj_value);
2420
2421 c_retval = xmlXPathRegisterVariableNS(ctx, name, ns_uri, val);
2422 py_retval = libxml_intWrap(c_retval);
2423 return (py_retval);
2424 }
2425
2426 /************************************************************************
2427 * *
2428 * Global properties access *
2429 * *
2430 ************************************************************************/
2431 static PyObject *
libxml_name(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)2432 libxml_name(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2433 {
2434 PyObject *resultobj, *obj;
2435 xmlNodePtr cur;
2436 const xmlChar *res;
2437
2438 if (!PyArg_ParseTuple(args, (char *) "O:name", &obj))
2439 return NULL;
2440 cur = PyxmlNode_Get(obj);
2441
2442 #ifdef DEBUG
2443 printf("libxml_name: cur = %p type %d\n", cur, cur->type);
2444 #endif
2445
2446 switch (cur->type) {
2447 case XML_DOCUMENT_NODE:
2448 #ifdef LIBXML_DOCB_ENABLED
2449 case XML_DOCB_DOCUMENT_NODE:
2450 #endif
2451 case XML_HTML_DOCUMENT_NODE:{
2452 xmlDocPtr doc = (xmlDocPtr) cur;
2453
2454 res = doc->URL;
2455 break;
2456 }
2457 case XML_ATTRIBUTE_NODE:{
2458 xmlAttrPtr attr = (xmlAttrPtr) cur;
2459
2460 res = attr->name;
2461 break;
2462 }
2463 case XML_NAMESPACE_DECL:{
2464 xmlNsPtr ns = (xmlNsPtr) cur;
2465
2466 res = ns->prefix;
2467 break;
2468 }
2469 default:
2470 res = cur->name;
2471 break;
2472 }
2473 resultobj = libxml_constxmlCharPtrWrap(res);
2474
2475 return resultobj;
2476 }
2477
2478 static PyObject *
libxml_doc(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)2479 libxml_doc(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2480 {
2481 PyObject *resultobj, *obj;
2482 xmlNodePtr cur;
2483 xmlDocPtr res;
2484
2485 if (!PyArg_ParseTuple(args, (char *) "O:doc", &obj))
2486 return NULL;
2487 cur = PyxmlNode_Get(obj);
2488
2489 #ifdef DEBUG
2490 printf("libxml_doc: cur = %p\n", cur);
2491 #endif
2492
2493 switch (cur->type) {
2494 case XML_DOCUMENT_NODE:
2495 #ifdef LIBXML_DOCB_ENABLED
2496 case XML_DOCB_DOCUMENT_NODE:
2497 #endif
2498 case XML_HTML_DOCUMENT_NODE:
2499 res = NULL;
2500 break;
2501 case XML_ATTRIBUTE_NODE:{
2502 xmlAttrPtr attr = (xmlAttrPtr) cur;
2503
2504 res = attr->doc;
2505 break;
2506 }
2507 case XML_NAMESPACE_DECL:
2508 res = NULL;
2509 break;
2510 default:
2511 res = cur->doc;
2512 break;
2513 }
2514 resultobj = libxml_xmlDocPtrWrap(res);
2515 return resultobj;
2516 }
2517
2518 static PyObject *
libxml_properties(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)2519 libxml_properties(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2520 {
2521 PyObject *resultobj, *obj;
2522 xmlNodePtr cur;
2523 xmlAttrPtr res;
2524
2525 if (!PyArg_ParseTuple(args, (char *) "O:properties", &obj))
2526 return NULL;
2527 cur = PyxmlNode_Get(obj);
2528 if ((cur != NULL) && (cur->type == XML_ELEMENT_NODE))
2529 res = cur->properties;
2530 else
2531 res = NULL;
2532 resultobj = libxml_xmlAttrPtrWrap(res);
2533 return resultobj;
2534 }
2535
2536 static PyObject *
libxml_next(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)2537 libxml_next(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2538 {
2539 PyObject *resultobj, *obj;
2540 xmlNodePtr cur;
2541 xmlNodePtr res;
2542
2543 if (!PyArg_ParseTuple(args, (char *) "O:next", &obj))
2544 return NULL;
2545 cur = PyxmlNode_Get(obj);
2546
2547 #ifdef DEBUG
2548 printf("libxml_next: cur = %p\n", cur);
2549 #endif
2550
2551 switch (cur->type) {
2552 case XML_DOCUMENT_NODE:
2553 #ifdef LIBXML_DOCB_ENABLED
2554 case XML_DOCB_DOCUMENT_NODE:
2555 #endif
2556 case XML_HTML_DOCUMENT_NODE:
2557 res = NULL;
2558 break;
2559 case XML_ATTRIBUTE_NODE:{
2560 xmlAttrPtr attr = (xmlAttrPtr) cur;
2561
2562 res = (xmlNodePtr) attr->next;
2563 break;
2564 }
2565 case XML_NAMESPACE_DECL:{
2566 xmlNsPtr ns = (xmlNsPtr) cur;
2567
2568 res = (xmlNodePtr) ns->next;
2569 break;
2570 }
2571 default:
2572 res = cur->next;
2573 break;
2574
2575 }
2576 resultobj = libxml_xmlNodePtrWrap(res);
2577 return resultobj;
2578 }
2579
2580 static PyObject *
libxml_prev(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)2581 libxml_prev(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2582 {
2583 PyObject *resultobj, *obj;
2584 xmlNodePtr cur;
2585 xmlNodePtr res;
2586
2587 if (!PyArg_ParseTuple(args, (char *) "O:prev", &obj))
2588 return NULL;
2589 cur = PyxmlNode_Get(obj);
2590
2591 #ifdef DEBUG
2592 printf("libxml_prev: cur = %p\n", cur);
2593 #endif
2594
2595 switch (cur->type) {
2596 case XML_DOCUMENT_NODE:
2597 #ifdef LIBXML_DOCB_ENABLED
2598 case XML_DOCB_DOCUMENT_NODE:
2599 #endif
2600 case XML_HTML_DOCUMENT_NODE:
2601 res = NULL;
2602 break;
2603 case XML_ATTRIBUTE_NODE:{
2604 xmlAttrPtr attr = (xmlAttrPtr) cur;
2605
2606 res = (xmlNodePtr) attr->prev;
2607 }
2608 break;
2609 case XML_NAMESPACE_DECL:
2610 res = NULL;
2611 break;
2612 default:
2613 res = cur->prev;
2614 break;
2615 }
2616 resultobj = libxml_xmlNodePtrWrap(res);
2617 return resultobj;
2618 }
2619
2620 static PyObject *
libxml_children(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)2621 libxml_children(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2622 {
2623 PyObject *resultobj, *obj;
2624 xmlNodePtr cur;
2625 xmlNodePtr res;
2626
2627 if (!PyArg_ParseTuple(args, (char *) "O:children", &obj))
2628 return NULL;
2629 cur = PyxmlNode_Get(obj);
2630
2631 #ifdef DEBUG
2632 printf("libxml_children: cur = %p\n", cur);
2633 #endif
2634
2635 switch (cur->type) {
2636 case XML_ELEMENT_NODE:
2637 case XML_ENTITY_REF_NODE:
2638 case XML_ENTITY_NODE:
2639 case XML_PI_NODE:
2640 case XML_COMMENT_NODE:
2641 case XML_DOCUMENT_NODE:
2642 #ifdef LIBXML_DOCB_ENABLED
2643 case XML_DOCB_DOCUMENT_NODE:
2644 #endif
2645 case XML_HTML_DOCUMENT_NODE:
2646 case XML_DTD_NODE:
2647 res = cur->children;
2648 break;
2649 case XML_ATTRIBUTE_NODE:{
2650 xmlAttrPtr attr = (xmlAttrPtr) cur;
2651
2652 res = attr->children;
2653 break;
2654 }
2655 default:
2656 res = NULL;
2657 break;
2658 }
2659 resultobj = libxml_xmlNodePtrWrap(res);
2660 return resultobj;
2661 }
2662
2663 static PyObject *
libxml_last(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)2664 libxml_last(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2665 {
2666 PyObject *resultobj, *obj;
2667 xmlNodePtr cur;
2668 xmlNodePtr res;
2669
2670 if (!PyArg_ParseTuple(args, (char *) "O:last", &obj))
2671 return NULL;
2672 cur = PyxmlNode_Get(obj);
2673
2674 #ifdef DEBUG
2675 printf("libxml_last: cur = %p\n", cur);
2676 #endif
2677
2678 switch (cur->type) {
2679 case XML_ELEMENT_NODE:
2680 case XML_ENTITY_REF_NODE:
2681 case XML_ENTITY_NODE:
2682 case XML_PI_NODE:
2683 case XML_COMMENT_NODE:
2684 case XML_DOCUMENT_NODE:
2685 #ifdef LIBXML_DOCB_ENABLED
2686 case XML_DOCB_DOCUMENT_NODE:
2687 #endif
2688 case XML_HTML_DOCUMENT_NODE:
2689 case XML_DTD_NODE:
2690 res = cur->last;
2691 break;
2692 case XML_ATTRIBUTE_NODE:{
2693 xmlAttrPtr attr = (xmlAttrPtr) cur;
2694
2695 res = attr->last;
2696 break;
2697 }
2698 default:
2699 res = NULL;
2700 break;
2701 }
2702 resultobj = libxml_xmlNodePtrWrap(res);
2703 return resultobj;
2704 }
2705
2706 static PyObject *
libxml_parent(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)2707 libxml_parent(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2708 {
2709 PyObject *resultobj, *obj;
2710 xmlNodePtr cur;
2711 xmlNodePtr res;
2712
2713 if (!PyArg_ParseTuple(args, (char *) "O:parent", &obj))
2714 return NULL;
2715 cur = PyxmlNode_Get(obj);
2716
2717 #ifdef DEBUG
2718 printf("libxml_parent: cur = %p\n", cur);
2719 #endif
2720
2721 switch (cur->type) {
2722 case XML_DOCUMENT_NODE:
2723 case XML_HTML_DOCUMENT_NODE:
2724 #ifdef LIBXML_DOCB_ENABLED
2725 case XML_DOCB_DOCUMENT_NODE:
2726 #endif
2727 res = NULL;
2728 break;
2729 case XML_ATTRIBUTE_NODE:{
2730 xmlAttrPtr attr = (xmlAttrPtr) cur;
2731
2732 res = attr->parent;
2733 }
2734 break;
2735 case XML_ENTITY_DECL:
2736 case XML_NAMESPACE_DECL:
2737 case XML_XINCLUDE_START:
2738 case XML_XINCLUDE_END:
2739 res = NULL;
2740 break;
2741 default:
2742 res = cur->parent;
2743 break;
2744 }
2745 resultobj = libxml_xmlNodePtrWrap(res);
2746 return resultobj;
2747 }
2748
2749 static PyObject *
libxml_type(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)2750 libxml_type(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2751 {
2752 PyObject *resultobj, *obj;
2753 xmlNodePtr cur;
2754 const xmlChar *res = NULL;
2755
2756 if (!PyArg_ParseTuple(args, (char *) "O:last", &obj))
2757 return NULL;
2758 cur = PyxmlNode_Get(obj);
2759 if (cur == NULL) {
2760 Py_INCREF(Py_None);
2761 return (Py_None);
2762 }
2763
2764 #ifdef DEBUG
2765 printf("libxml_type: cur = %p\n", cur);
2766 #endif
2767
2768 switch (cur->type) {
2769 case XML_ELEMENT_NODE:
2770 res = (const xmlChar *) "element";
2771 break;
2772 case XML_ATTRIBUTE_NODE:
2773 res = (const xmlChar *) "attribute";
2774 break;
2775 case XML_TEXT_NODE:
2776 res = (const xmlChar *) "text";
2777 break;
2778 case XML_CDATA_SECTION_NODE:
2779 res = (const xmlChar *) "cdata";
2780 break;
2781 case XML_ENTITY_REF_NODE:
2782 res = (const xmlChar *) "entity_ref";
2783 break;
2784 case XML_ENTITY_NODE:
2785 res = (const xmlChar *) "entity";
2786 break;
2787 case XML_PI_NODE:
2788 res = (const xmlChar *) "pi";
2789 break;
2790 case XML_COMMENT_NODE:
2791 res = (const xmlChar *) "comment";
2792 break;
2793 case XML_DOCUMENT_NODE:
2794 res = (const xmlChar *) "document_xml";
2795 break;
2796 case XML_DOCUMENT_TYPE_NODE:
2797 res = (const xmlChar *) "doctype";
2798 break;
2799 case XML_DOCUMENT_FRAG_NODE:
2800 res = (const xmlChar *) "fragment";
2801 break;
2802 case XML_NOTATION_NODE:
2803 res = (const xmlChar *) "notation";
2804 break;
2805 case XML_HTML_DOCUMENT_NODE:
2806 res = (const xmlChar *) "document_html";
2807 break;
2808 case XML_DTD_NODE:
2809 res = (const xmlChar *) "dtd";
2810 break;
2811 case XML_ELEMENT_DECL:
2812 res = (const xmlChar *) "elem_decl";
2813 break;
2814 case XML_ATTRIBUTE_DECL:
2815 res = (const xmlChar *) "attribute_decl";
2816 break;
2817 case XML_ENTITY_DECL:
2818 res = (const xmlChar *) "entity_decl";
2819 break;
2820 case XML_NAMESPACE_DECL:
2821 res = (const xmlChar *) "namespace";
2822 break;
2823 case XML_XINCLUDE_START:
2824 res = (const xmlChar *) "xinclude_start";
2825 break;
2826 case XML_XINCLUDE_END:
2827 res = (const xmlChar *) "xinclude_end";
2828 break;
2829 #ifdef LIBXML_DOCB_ENABLED
2830 case XML_DOCB_DOCUMENT_NODE:
2831 res = (const xmlChar *) "document_docbook";
2832 break;
2833 #endif
2834 }
2835 #ifdef DEBUG
2836 printf("libxml_type: cur = %p: %s\n", cur, res);
2837 #endif
2838
2839 resultobj = libxml_constxmlCharPtrWrap(res);
2840 return resultobj;
2841 }
2842
2843 /************************************************************************
2844 * *
2845 * Specific accessor functions *
2846 * *
2847 ************************************************************************/
2848 PyObject *
libxml_xmlNodeGetNsDefs(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)2849 libxml_xmlNodeGetNsDefs(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2850 {
2851 PyObject *py_retval;
2852 xmlNsPtr c_retval;
2853 xmlNodePtr node;
2854 PyObject *pyobj_node;
2855
2856 if (!PyArg_ParseTuple
2857 (args, (char *) "O:xmlNodeGetNsDefs", &pyobj_node))
2858 return (NULL);
2859 node = (xmlNodePtr) PyxmlNode_Get(pyobj_node);
2860
2861 if ((node == NULL) || (node->type != XML_ELEMENT_NODE)) {
2862 Py_INCREF(Py_None);
2863 return (Py_None);
2864 }
2865 c_retval = node->nsDef;
2866 py_retval = libxml_xmlNsPtrWrap((xmlNsPtr) c_retval);
2867 return (py_retval);
2868 }
2869
2870 PyObject *
libxml_xmlNodeRemoveNsDef(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)2871 libxml_xmlNodeRemoveNsDef(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2872 {
2873 PyObject *py_retval;
2874 xmlNsPtr ns, prev;
2875 xmlNodePtr node;
2876 PyObject *pyobj_node;
2877 xmlChar *href;
2878 xmlNsPtr c_retval;
2879
2880 if (!PyArg_ParseTuple
2881 (args, (char *) "Oz:xmlNodeRemoveNsDef", &pyobj_node, &href))
2882 return (NULL);
2883 node = (xmlNodePtr) PyxmlNode_Get(pyobj_node);
2884 ns = NULL;
2885
2886 if ((node == NULL) || (node->type != XML_ELEMENT_NODE)) {
2887 Py_INCREF(Py_None);
2888 return (Py_None);
2889 }
2890
2891 if (href == NULL) {
2892 ns = node->nsDef;
2893 node->nsDef = NULL;
2894 c_retval = 0;
2895 }
2896 else {
2897 prev = NULL;
2898 ns = node->nsDef;
2899 while (ns != NULL) {
2900 if (xmlStrEqual(ns->href, href)) {
2901 if (prev != NULL)
2902 prev->next = ns->next;
2903 else
2904 node->nsDef = ns->next;
2905 ns->next = NULL;
2906 c_retval = 0;
2907 break;
2908 }
2909 prev = ns;
2910 ns = ns->next;
2911 }
2912 }
2913
2914 c_retval = ns;
2915 py_retval = libxml_xmlNsPtrWrap((xmlNsPtr) c_retval);
2916 return (py_retval);
2917 }
2918
2919 PyObject *
libxml_xmlNodeGetNs(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)2920 libxml_xmlNodeGetNs(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2921 {
2922 PyObject *py_retval;
2923 xmlNsPtr c_retval;
2924 xmlNodePtr node;
2925 PyObject *pyobj_node;
2926
2927 if (!PyArg_ParseTuple(args, (char *) "O:xmlNodeGetNs", &pyobj_node))
2928 return (NULL);
2929 node = (xmlNodePtr) PyxmlNode_Get(pyobj_node);
2930
2931 if ((node == NULL) ||
2932 ((node->type != XML_ELEMENT_NODE) &&
2933 (node->type != XML_ATTRIBUTE_NODE))) {
2934 Py_INCREF(Py_None);
2935 return (Py_None);
2936 }
2937 c_retval = node->ns;
2938 py_retval = libxml_xmlNsPtrWrap((xmlNsPtr) c_retval);
2939 return (py_retval);
2940 }
2941
2942 #ifdef LIBXML_OUTPUT_ENABLED
2943 /************************************************************************
2944 * *
2945 * Serialization front-end *
2946 * *
2947 ************************************************************************/
2948
2949 static PyObject *
libxml_serializeNode(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)2950 libxml_serializeNode(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
2951 {
2952 PyObject *py_retval = NULL;
2953 xmlChar *c_retval;
2954 PyObject *pyobj_node;
2955 xmlNodePtr node;
2956 xmlDocPtr doc;
2957 const char *encoding;
2958 int format;
2959 xmlSaveCtxtPtr ctxt;
2960 xmlBufferPtr buf;
2961 int options = 0;
2962
2963 if (!PyArg_ParseTuple(args, (char *) "Ozi:serializeNode", &pyobj_node,
2964 &encoding, &format))
2965 return (NULL);
2966 node = (xmlNodePtr) PyxmlNode_Get(pyobj_node);
2967
2968 if (node == NULL) {
2969 Py_INCREF(Py_None);
2970 return (Py_None);
2971 }
2972 if (node->type == XML_DOCUMENT_NODE) {
2973 doc = (xmlDocPtr) node;
2974 node = NULL;
2975 #ifdef LIBXML_HTML_ENABLED
2976 } else if (node->type == XML_HTML_DOCUMENT_NODE) {
2977 doc = (xmlDocPtr) node;
2978 node = NULL;
2979 #endif
2980 } else {
2981 if (node->type == XML_NAMESPACE_DECL)
2982 doc = NULL;
2983 else
2984 doc = node->doc;
2985 if ((doc == NULL) || (doc->type == XML_DOCUMENT_NODE)) {
2986 #ifdef LIBXML_HTML_ENABLED
2987 } else if (doc->type == XML_HTML_DOCUMENT_NODE) {
2988 #endif /* LIBXML_HTML_ENABLED */
2989 } else {
2990 Py_INCREF(Py_None);
2991 return (Py_None);
2992 }
2993 }
2994
2995
2996 buf = xmlBufferCreate();
2997 if (buf == NULL) {
2998 Py_INCREF(Py_None);
2999 return (Py_None);
3000 }
3001 if (format) options |= XML_SAVE_FORMAT;
3002 ctxt = xmlSaveToBuffer(buf, encoding, options);
3003 if (ctxt == NULL) {
3004 xmlBufferFree(buf);
3005 Py_INCREF(Py_None);
3006 return (Py_None);
3007 }
3008 if (node == NULL)
3009 xmlSaveDoc(ctxt, doc);
3010 else
3011 xmlSaveTree(ctxt, node);
3012 xmlSaveClose(ctxt);
3013
3014 c_retval = buf->content;
3015 buf->content = NULL;
3016
3017 xmlBufferFree(buf);
3018 py_retval = libxml_charPtrWrap((char *) c_retval);
3019
3020 return (py_retval);
3021 }
3022
3023 static PyObject *
libxml_saveNodeTo(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)3024 libxml_saveNodeTo(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
3025 {
3026 PyObject *py_file = NULL;
3027 FILE *output;
3028 PyObject *pyobj_node;
3029 xmlNodePtr node;
3030 xmlDocPtr doc;
3031 const char *encoding;
3032 int format;
3033 int len;
3034 xmlOutputBufferPtr buf;
3035 xmlCharEncodingHandlerPtr handler = NULL;
3036
3037 if (!PyArg_ParseTuple(args, (char *) "OOzi:serializeNode", &pyobj_node,
3038 &py_file, &encoding, &format))
3039 return (NULL);
3040 node = (xmlNodePtr) PyxmlNode_Get(pyobj_node);
3041 if (node == NULL) {
3042 return (PyLong_FromLong((long) -1));
3043 }
3044 output = PyFile_Get(py_file);
3045 if (output == NULL) {
3046 return (PyLong_FromLong((long) -1));
3047 }
3048
3049 if (node->type == XML_DOCUMENT_NODE) {
3050 doc = (xmlDocPtr) node;
3051 } else if (node->type == XML_HTML_DOCUMENT_NODE) {
3052 doc = (xmlDocPtr) node;
3053 } else {
3054 doc = node->doc;
3055 }
3056 #ifdef LIBXML_HTML_ENABLED
3057 if (doc->type == XML_HTML_DOCUMENT_NODE) {
3058 if (encoding == NULL)
3059 encoding = (const char *) htmlGetMetaEncoding(doc);
3060 }
3061 #endif /* LIBXML_HTML_ENABLED */
3062 if (encoding != NULL) {
3063 handler = xmlFindCharEncodingHandler(encoding);
3064 if (handler == NULL) {
3065 return (PyLong_FromLong((long) -1));
3066 }
3067 }
3068 if (doc->type == XML_HTML_DOCUMENT_NODE) {
3069 if (handler == NULL)
3070 handler = xmlFindCharEncodingHandler("HTML");
3071 if (handler == NULL)
3072 handler = xmlFindCharEncodingHandler("ascii");
3073 }
3074
3075 buf = xmlOutputBufferCreateFile(output, handler);
3076 if (node->type == XML_DOCUMENT_NODE) {
3077 len = xmlSaveFormatFileTo(buf, doc, encoding, format);
3078 #ifdef LIBXML_HTML_ENABLED
3079 } else if (node->type == XML_HTML_DOCUMENT_NODE) {
3080 htmlDocContentDumpFormatOutput(buf, doc, encoding, format);
3081 len = xmlOutputBufferClose(buf);
3082 } else if (doc->type == XML_HTML_DOCUMENT_NODE) {
3083 htmlNodeDumpFormatOutput(buf, doc, node, encoding, format);
3084 len = xmlOutputBufferClose(buf);
3085 #endif /* LIBXML_HTML_ENABLED */
3086 } else {
3087 xmlNodeDumpOutput(buf, doc, node, 0, format, encoding);
3088 len = xmlOutputBufferClose(buf);
3089 }
3090 PyFile_Release(output);
3091 return (PyLong_FromLong((long) len));
3092 }
3093 #endif /* LIBXML_OUTPUT_ENABLED */
3094
3095 /************************************************************************
3096 * *
3097 * Extra stuff *
3098 * *
3099 ************************************************************************/
3100 PyObject *
libxml_xmlNewNode(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)3101 libxml_xmlNewNode(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
3102 {
3103 PyObject *py_retval;
3104 xmlChar *name;
3105 xmlNodePtr node;
3106
3107 if (!PyArg_ParseTuple(args, (char *) "s:xmlNewNode", &name))
3108 return (NULL);
3109 node = (xmlNodePtr) xmlNewNode(NULL, name);
3110 #ifdef DEBUG
3111 printf("NewNode: %s : %p\n", name, (void *) node);
3112 #endif
3113
3114 if (node == NULL) {
3115 Py_INCREF(Py_None);
3116 return (Py_None);
3117 }
3118 py_retval = libxml_xmlNodePtrWrap(node);
3119 return (py_retval);
3120 }
3121
3122
3123 /************************************************************************
3124 * *
3125 * Local Catalog stuff *
3126 * *
3127 ************************************************************************/
3128 static PyObject *
libxml_addLocalCatalog(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)3129 libxml_addLocalCatalog(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
3130 {
3131 xmlChar *URL;
3132 xmlParserCtxtPtr ctxt;
3133 PyObject *pyobj_ctxt;
3134
3135 if (!PyArg_ParseTuple(args, (char *)"Os:addLocalCatalog", &pyobj_ctxt, &URL))
3136 return(NULL);
3137
3138 ctxt = (xmlParserCtxtPtr) PyparserCtxt_Get(pyobj_ctxt);
3139
3140 if (URL != NULL) {
3141 ctxt->catalogs = xmlCatalogAddLocal(ctxt->catalogs, URL);
3142 }
3143
3144 #ifdef DEBUG
3145 printf("LocalCatalog: %s\n", URL);
3146 #endif
3147
3148 Py_INCREF(Py_None);
3149 return (Py_None);
3150 }
3151
3152 #ifdef LIBXML_SCHEMAS_ENABLED
3153
3154 /************************************************************************
3155 * *
3156 * RelaxNG error handler registration *
3157 * *
3158 ************************************************************************/
3159
3160 typedef struct
3161 {
3162 PyObject *warn;
3163 PyObject *error;
3164 PyObject *arg;
3165 } xmlRelaxNGValidCtxtPyCtxt;
3166 typedef xmlRelaxNGValidCtxtPyCtxt *xmlRelaxNGValidCtxtPyCtxtPtr;
3167
3168 static void
libxml_xmlRelaxNGValidityGenericErrorFuncHandler(void * ctx,char * str)3169 libxml_xmlRelaxNGValidityGenericErrorFuncHandler(void *ctx, char *str)
3170 {
3171 PyObject *list;
3172 PyObject *result;
3173 xmlRelaxNGValidCtxtPyCtxtPtr pyCtxt;
3174
3175 #ifdef DEBUG_ERROR
3176 printf("libxml_xmlRelaxNGValidityGenericErrorFuncHandler(%p, %s, ...) called\n", ctx, str);
3177 #endif
3178
3179 pyCtxt = (xmlRelaxNGValidCtxtPyCtxtPtr)ctx;
3180
3181 list = PyTuple_New(2);
3182 PyTuple_SetItem(list, 0, libxml_charPtrWrap(str));
3183 PyTuple_SetItem(list, 1, pyCtxt->arg);
3184 Py_XINCREF(pyCtxt->arg);
3185 result = PyEval_CallObject(pyCtxt->error, list);
3186 if (result == NULL)
3187 {
3188 /* TODO: manage for the exception to be propagated... */
3189 PyErr_Print();
3190 }
3191 Py_XDECREF(list);
3192 Py_XDECREF(result);
3193 }
3194
3195 static void
libxml_xmlRelaxNGValidityGenericWarningFuncHandler(void * ctx,char * str)3196 libxml_xmlRelaxNGValidityGenericWarningFuncHandler(void *ctx, char *str)
3197 {
3198 PyObject *list;
3199 PyObject *result;
3200 xmlRelaxNGValidCtxtPyCtxtPtr pyCtxt;
3201
3202 #ifdef DEBUG_ERROR
3203 printf("libxml_xmlRelaxNGValidityGenericWarningFuncHandler(%p, %s, ...) called\n", ctx, str);
3204 #endif
3205
3206 pyCtxt = (xmlRelaxNGValidCtxtPyCtxtPtr)ctx;
3207
3208 list = PyTuple_New(2);
3209 PyTuple_SetItem(list, 0, libxml_charPtrWrap(str));
3210 PyTuple_SetItem(list, 1, pyCtxt->arg);
3211 Py_XINCREF(pyCtxt->arg);
3212 result = PyEval_CallObject(pyCtxt->warn, list);
3213 if (result == NULL)
3214 {
3215 /* TODO: manage for the exception to be propagated... */
3216 PyErr_Print();
3217 }
3218 Py_XDECREF(list);
3219 Py_XDECREF(result);
3220 }
3221
3222 static void
libxml_xmlRelaxNGValidityErrorFunc(void * ctx,const char * msg,...)3223 libxml_xmlRelaxNGValidityErrorFunc(void *ctx, const char *msg, ...)
3224 {
3225 va_list ap;
3226
3227 va_start(ap, msg);
3228 libxml_xmlRelaxNGValidityGenericErrorFuncHandler(ctx, libxml_buildMessage(msg, ap));
3229 va_end(ap);
3230 }
3231
3232 static void
libxml_xmlRelaxNGValidityWarningFunc(void * ctx,const char * msg,...)3233 libxml_xmlRelaxNGValidityWarningFunc(void *ctx, const char *msg, ...)
3234 {
3235 va_list ap;
3236
3237 va_start(ap, msg);
3238 libxml_xmlRelaxNGValidityGenericWarningFuncHandler(ctx, libxml_buildMessage(msg, ap));
3239 va_end(ap);
3240 }
3241
3242 static PyObject *
libxml_xmlRelaxNGSetValidErrors(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)3243 libxml_xmlRelaxNGSetValidErrors(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
3244 {
3245 PyObject *py_retval;
3246 PyObject *pyobj_error;
3247 PyObject *pyobj_warn;
3248 PyObject *pyobj_ctx;
3249 PyObject *pyobj_arg = Py_None;
3250 xmlRelaxNGValidCtxtPtr ctxt;
3251 xmlRelaxNGValidCtxtPyCtxtPtr pyCtxt;
3252
3253 if (!PyArg_ParseTuple
3254 (args, (char *) "OOO|O:xmlRelaxNGSetValidErrors", &pyobj_ctx, &pyobj_error, &pyobj_warn, &pyobj_arg))
3255 return (NULL);
3256
3257 #ifdef DEBUG_ERROR
3258 printf("libxml_xmlRelaxNGSetValidErrors(%p, %p, %p) called\n", pyobj_ctx, pyobj_error, pyobj_warn);
3259 #endif
3260
3261 ctxt = PyrelaxNgValidCtxt_Get(pyobj_ctx);
3262 if (xmlRelaxNGGetValidErrors(ctxt, NULL, NULL, (void **) &pyCtxt) == -1)
3263 {
3264 py_retval = libxml_intWrap(-1);
3265 return(py_retval);
3266 }
3267
3268 if (pyCtxt == NULL)
3269 {
3270 /* first time to set the error handlers */
3271 pyCtxt = xmlMalloc(sizeof(xmlRelaxNGValidCtxtPyCtxt));
3272 if (pyCtxt == NULL) {
3273 py_retval = libxml_intWrap(-1);
3274 return(py_retval);
3275 }
3276 memset(pyCtxt, 0, sizeof(xmlRelaxNGValidCtxtPyCtxt));
3277 }
3278
3279 /* TODO: check warn and error is a function ! */
3280 Py_XDECREF(pyCtxt->error);
3281 Py_XINCREF(pyobj_error);
3282 pyCtxt->error = pyobj_error;
3283
3284 Py_XDECREF(pyCtxt->warn);
3285 Py_XINCREF(pyobj_warn);
3286 pyCtxt->warn = pyobj_warn;
3287
3288 Py_XDECREF(pyCtxt->arg);
3289 Py_XINCREF(pyobj_arg);
3290 pyCtxt->arg = pyobj_arg;
3291
3292 xmlRelaxNGSetValidErrors(ctxt, &libxml_xmlRelaxNGValidityErrorFunc, &libxml_xmlRelaxNGValidityWarningFunc, pyCtxt);
3293
3294 py_retval = libxml_intWrap(1);
3295 return (py_retval);
3296 }
3297
3298 static PyObject *
libxml_xmlRelaxNGFreeValidCtxt(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)3299 libxml_xmlRelaxNGFreeValidCtxt(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) {
3300 xmlRelaxNGValidCtxtPtr ctxt;
3301 xmlRelaxNGValidCtxtPyCtxtPtr pyCtxt;
3302 PyObject *pyobj_ctxt;
3303
3304 if (!PyArg_ParseTuple(args, (char *)"O:xmlRelaxNGFreeValidCtxt", &pyobj_ctxt))
3305 return(NULL);
3306 ctxt = (xmlRelaxNGValidCtxtPtr) PyrelaxNgValidCtxt_Get(pyobj_ctxt);
3307
3308 if (xmlRelaxNGGetValidErrors(ctxt, NULL, NULL, (void **) &pyCtxt) == 0)
3309 {
3310 if (pyCtxt != NULL)
3311 {
3312 Py_XDECREF(pyCtxt->error);
3313 Py_XDECREF(pyCtxt->warn);
3314 Py_XDECREF(pyCtxt->arg);
3315 xmlFree(pyCtxt);
3316 }
3317 }
3318
3319 xmlRelaxNGFreeValidCtxt(ctxt);
3320 Py_INCREF(Py_None);
3321 return(Py_None);
3322 }
3323
3324 typedef struct
3325 {
3326 PyObject *warn;
3327 PyObject *error;
3328 PyObject *arg;
3329 } xmlSchemaValidCtxtPyCtxt;
3330 typedef xmlSchemaValidCtxtPyCtxt *xmlSchemaValidCtxtPyCtxtPtr;
3331
3332 static void
libxml_xmlSchemaValidityGenericErrorFuncHandler(void * ctx,char * str)3333 libxml_xmlSchemaValidityGenericErrorFuncHandler(void *ctx, char *str)
3334 {
3335 PyObject *list;
3336 PyObject *result;
3337 xmlSchemaValidCtxtPyCtxtPtr pyCtxt;
3338
3339 #ifdef DEBUG_ERROR
3340 printf("libxml_xmlSchemaValidityGenericErrorFuncHandler(%p, %s, ...) called\n", ctx, str);
3341 #endif
3342
3343 pyCtxt = (xmlSchemaValidCtxtPyCtxtPtr) ctx;
3344
3345 list = PyTuple_New(2);
3346 PyTuple_SetItem(list, 0, libxml_charPtrWrap(str));
3347 PyTuple_SetItem(list, 1, pyCtxt->arg);
3348 Py_XINCREF(pyCtxt->arg);
3349 result = PyEval_CallObject(pyCtxt->error, list);
3350 if (result == NULL)
3351 {
3352 /* TODO: manage for the exception to be propagated... */
3353 PyErr_Print();
3354 }
3355 Py_XDECREF(list);
3356 Py_XDECREF(result);
3357 }
3358
3359 static void
libxml_xmlSchemaValidityGenericWarningFuncHandler(void * ctx,char * str)3360 libxml_xmlSchemaValidityGenericWarningFuncHandler(void *ctx, char *str)
3361 {
3362 PyObject *list;
3363 PyObject *result;
3364 xmlSchemaValidCtxtPyCtxtPtr pyCtxt;
3365
3366 #ifdef DEBUG_ERROR
3367 printf("libxml_xmlSchemaValidityGenericWarningFuncHandler(%p, %s, ...) called\n", ctx, str);
3368 #endif
3369
3370 pyCtxt = (xmlSchemaValidCtxtPyCtxtPtr) ctx;
3371
3372 list = PyTuple_New(2);
3373 PyTuple_SetItem(list, 0, libxml_charPtrWrap(str));
3374 PyTuple_SetItem(list, 1, pyCtxt->arg);
3375 Py_XINCREF(pyCtxt->arg);
3376 result = PyEval_CallObject(pyCtxt->warn, list);
3377 if (result == NULL)
3378 {
3379 /* TODO: manage for the exception to be propagated... */
3380 PyErr_Print();
3381 }
3382 Py_XDECREF(list);
3383 Py_XDECREF(result);
3384 }
3385
3386 static void
libxml_xmlSchemaValidityErrorFunc(void * ctx,const char * msg,...)3387 libxml_xmlSchemaValidityErrorFunc(void *ctx, const char *msg, ...)
3388 {
3389 va_list ap;
3390
3391 va_start(ap, msg);
3392 libxml_xmlSchemaValidityGenericErrorFuncHandler(ctx, libxml_buildMessage(msg, ap));
3393 va_end(ap);
3394 }
3395
3396 static void
libxml_xmlSchemaValidityWarningFunc(void * ctx,const char * msg,...)3397 libxml_xmlSchemaValidityWarningFunc(void *ctx, const char *msg, ...)
3398 {
3399 va_list ap;
3400
3401 va_start(ap, msg);
3402 libxml_xmlSchemaValidityGenericWarningFuncHandler(ctx, libxml_buildMessage(msg, ap));
3403 va_end(ap);
3404 }
3405
3406 PyObject *
libxml_xmlSchemaSetValidErrors(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)3407 libxml_xmlSchemaSetValidErrors(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
3408 {
3409 PyObject *py_retval;
3410 PyObject *pyobj_error;
3411 PyObject *pyobj_warn;
3412 PyObject *pyobj_ctx;
3413 PyObject *pyobj_arg = Py_None;
3414 xmlSchemaValidCtxtPtr ctxt;
3415 xmlSchemaValidCtxtPyCtxtPtr pyCtxt;
3416
3417 if (!PyArg_ParseTuple
3418 (args, (char *) "OOO|O:xmlSchemaSetValidErrors", &pyobj_ctx, &pyobj_error, &pyobj_warn, &pyobj_arg))
3419 return (NULL);
3420
3421 #ifdef DEBUG_ERROR
3422 printf("libxml_xmlSchemaSetValidErrors(%p, %p, %p) called\n", pyobj_ctx, pyobj_error, pyobj_warn);
3423 #endif
3424
3425 ctxt = PySchemaValidCtxt_Get(pyobj_ctx);
3426 if (xmlSchemaGetValidErrors(ctxt, NULL, NULL, (void **) &pyCtxt) == -1)
3427 {
3428 py_retval = libxml_intWrap(-1);
3429 return(py_retval);
3430 }
3431
3432 if (pyCtxt == NULL)
3433 {
3434 /* first time to set the error handlers */
3435 pyCtxt = xmlMalloc(sizeof(xmlSchemaValidCtxtPyCtxt));
3436 if (pyCtxt == NULL) {
3437 py_retval = libxml_intWrap(-1);
3438 return(py_retval);
3439 }
3440 memset(pyCtxt, 0, sizeof(xmlSchemaValidCtxtPyCtxt));
3441 }
3442
3443 /* TODO: check warn and error is a function ! */
3444 Py_XDECREF(pyCtxt->error);
3445 Py_XINCREF(pyobj_error);
3446 pyCtxt->error = pyobj_error;
3447
3448 Py_XDECREF(pyCtxt->warn);
3449 Py_XINCREF(pyobj_warn);
3450 pyCtxt->warn = pyobj_warn;
3451
3452 Py_XDECREF(pyCtxt->arg);
3453 Py_XINCREF(pyobj_arg);
3454 pyCtxt->arg = pyobj_arg;
3455
3456 xmlSchemaSetValidErrors(ctxt, &libxml_xmlSchemaValidityErrorFunc, &libxml_xmlSchemaValidityWarningFunc, pyCtxt);
3457
3458 py_retval = libxml_intWrap(1);
3459 return(py_retval);
3460 }
3461
3462 static PyObject *
libxml_xmlSchemaFreeValidCtxt(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)3463 libxml_xmlSchemaFreeValidCtxt(ATTRIBUTE_UNUSED PyObject * self, PyObject * args)
3464 {
3465 xmlSchemaValidCtxtPtr ctxt;
3466 xmlSchemaValidCtxtPyCtxtPtr pyCtxt;
3467 PyObject *pyobj_ctxt;
3468
3469 if (!PyArg_ParseTuple(args, (char *)"O:xmlSchemaFreeValidCtxt", &pyobj_ctxt))
3470 return(NULL);
3471 ctxt = (xmlSchemaValidCtxtPtr) PySchemaValidCtxt_Get(pyobj_ctxt);
3472
3473 if (xmlSchemaGetValidErrors(ctxt, NULL, NULL, (void **) &pyCtxt) == 0)
3474 {
3475 if (pyCtxt != NULL)
3476 {
3477 Py_XDECREF(pyCtxt->error);
3478 Py_XDECREF(pyCtxt->warn);
3479 Py_XDECREF(pyCtxt->arg);
3480 xmlFree(pyCtxt);
3481 }
3482 }
3483
3484 xmlSchemaFreeValidCtxt(ctxt);
3485 Py_INCREF(Py_None);
3486 return(Py_None);
3487 }
3488
3489 #endif
3490
3491 #ifdef LIBXML_C14N_ENABLED
3492 #ifdef LIBXML_OUTPUT_ENABLED
3493
3494 /************************************************************************
3495 * *
3496 * XML Canonicalization c14n *
3497 * *
3498 ************************************************************************/
3499
3500 static int
PyxmlNodeSet_Convert(PyObject * py_nodeset,xmlNodeSetPtr * result)3501 PyxmlNodeSet_Convert(PyObject *py_nodeset, xmlNodeSetPtr *result)
3502 {
3503 xmlNodeSetPtr nodeSet;
3504 int is_tuple = 0;
3505
3506 if (PyTuple_Check(py_nodeset))
3507 is_tuple = 1;
3508 else if (PyList_Check(py_nodeset))
3509 is_tuple = 0;
3510 else if (py_nodeset == Py_None) {
3511 *result = NULL;
3512 return 0;
3513 }
3514 else {
3515 PyErr_SetString(PyExc_TypeError,
3516 "must be a tuple or list of nodes.");
3517 return -1;
3518 }
3519
3520 nodeSet = (xmlNodeSetPtr) xmlMalloc(sizeof(xmlNodeSet));
3521 if (nodeSet == NULL) {
3522 PyErr_SetString(PyExc_MemoryError, "");
3523 return -1;
3524 }
3525
3526 nodeSet->nodeNr = 0;
3527 nodeSet->nodeMax = (is_tuple
3528 ? PyTuple_GET_SIZE(py_nodeset)
3529 : PyList_GET_SIZE(py_nodeset));
3530 nodeSet->nodeTab
3531 = (xmlNodePtr *) xmlMalloc (nodeSet->nodeMax
3532 * sizeof(xmlNodePtr));
3533 if (nodeSet->nodeTab == NULL) {
3534 xmlFree(nodeSet);
3535 PyErr_SetString(PyExc_MemoryError, "");
3536 return -1;
3537 }
3538 memset(nodeSet->nodeTab, 0 ,
3539 nodeSet->nodeMax * sizeof(xmlNodePtr));
3540
3541 {
3542 int idx;
3543 for (idx=0; idx < nodeSet->nodeMax; ++idx) {
3544 xmlNodePtr pynode =
3545 PyxmlNode_Get (is_tuple
3546 ? PyTuple_GET_ITEM(py_nodeset, idx)
3547 : PyList_GET_ITEM(py_nodeset, idx));
3548 if (pynode)
3549 nodeSet->nodeTab[nodeSet->nodeNr++] = pynode;
3550 }
3551 }
3552 *result = nodeSet;
3553 return 0;
3554 }
3555
3556 static int
PystringSet_Convert(PyObject * py_strings,xmlChar *** result)3557 PystringSet_Convert(PyObject *py_strings, xmlChar *** result)
3558 {
3559 /* NOTE: the array should be freed, but the strings are shared
3560 with the python strings and so must not be freed. */
3561
3562 xmlChar ** strings;
3563 int is_tuple = 0;
3564 int count;
3565 int init_index = 0;
3566
3567 if (PyTuple_Check(py_strings))
3568 is_tuple = 1;
3569 else if (PyList_Check(py_strings))
3570 is_tuple = 0;
3571 else if (py_strings == Py_None) {
3572 *result = NULL;
3573 return 0;
3574 }
3575 else {
3576 PyErr_SetString(PyExc_TypeError,
3577 "must be a tuple or list of strings.");
3578 return -1;
3579 }
3580
3581 count = (is_tuple
3582 ? PyTuple_GET_SIZE(py_strings)
3583 : PyList_GET_SIZE(py_strings));
3584
3585 strings = (xmlChar **) xmlMalloc(sizeof(xmlChar *) * count);
3586
3587 if (strings == NULL) {
3588 PyErr_SetString(PyExc_MemoryError, "");
3589 return -1;
3590 }
3591
3592 memset(strings, 0 , sizeof(xmlChar *) * count);
3593
3594 {
3595 int idx;
3596 for (idx=0; idx < count; ++idx) {
3597 char* s = PyBytes_AsString
3598 (is_tuple
3599 ? PyTuple_GET_ITEM(py_strings, idx)
3600 : PyList_GET_ITEM(py_strings, idx));
3601 if (s)
3602 strings[init_index++] = (xmlChar *)s;
3603 else {
3604 xmlFree(strings);
3605 PyErr_SetString(PyExc_TypeError,
3606 "must be a tuple or list of strings.");
3607 return -1;
3608 }
3609 }
3610 }
3611
3612 *result = strings;
3613 return 0;
3614 }
3615
3616 static PyObject *
libxml_C14NDocDumpMemory(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)3617 libxml_C14NDocDumpMemory(ATTRIBUTE_UNUSED PyObject * self,
3618 PyObject * args)
3619 {
3620 PyObject *py_retval = NULL;
3621
3622 PyObject *pyobj_doc;
3623 PyObject *pyobj_nodes;
3624 int exclusive;
3625 PyObject *pyobj_prefixes;
3626 int with_comments;
3627
3628 xmlDocPtr doc;
3629 xmlNodeSetPtr nodes;
3630 xmlChar **prefixes = NULL;
3631 xmlChar *doc_txt;
3632
3633 int result;
3634
3635 if (!PyArg_ParseTuple(args, (char *) "OOiOi:C14NDocDumpMemory",
3636 &pyobj_doc,
3637 &pyobj_nodes,
3638 &exclusive,
3639 &pyobj_prefixes,
3640 &with_comments))
3641 return (NULL);
3642
3643 doc = (xmlDocPtr) PyxmlNode_Get(pyobj_doc);
3644 if (!doc) {
3645 PyErr_SetString(PyExc_TypeError, "bad document.");
3646 return NULL;
3647 }
3648
3649 result = PyxmlNodeSet_Convert(pyobj_nodes, &nodes);
3650 if (result < 0) return NULL;
3651
3652 if (exclusive) {
3653 result = PystringSet_Convert(pyobj_prefixes, &prefixes);
3654 if (result < 0) {
3655 if (nodes) {
3656 xmlFree(nodes->nodeTab);
3657 xmlFree(nodes);
3658 }
3659 return NULL;
3660 }
3661 }
3662
3663 result = xmlC14NDocDumpMemory(doc,
3664 nodes,
3665 exclusive,
3666 prefixes,
3667 with_comments,
3668 &doc_txt);
3669
3670 if (nodes) {
3671 xmlFree(nodes->nodeTab);
3672 xmlFree(nodes);
3673 }
3674 if (prefixes) {
3675 xmlChar ** idx = prefixes;
3676 while (*idx) xmlFree(*(idx++));
3677 xmlFree(prefixes);
3678 }
3679
3680 if (result < 0) {
3681 PyErr_SetString(PyExc_Exception,
3682 "libxml2 xmlC14NDocDumpMemory failure.");
3683 return NULL;
3684 }
3685 else {
3686 py_retval = PY_IMPORT_STRING_SIZE((const char *) doc_txt,
3687 result);
3688 xmlFree(doc_txt);
3689 return py_retval;
3690 }
3691 }
3692
3693 static PyObject *
libxml_C14NDocSaveTo(ATTRIBUTE_UNUSED PyObject * self,PyObject * args)3694 libxml_C14NDocSaveTo(ATTRIBUTE_UNUSED PyObject * self,
3695 PyObject * args)
3696 {
3697 PyObject *pyobj_doc;
3698 PyObject *py_file;
3699 PyObject *pyobj_nodes;
3700 int exclusive;
3701 PyObject *pyobj_prefixes;
3702 int with_comments;
3703
3704 xmlDocPtr doc;
3705 xmlNodeSetPtr nodes;
3706 xmlChar **prefixes = NULL;
3707 FILE * output;
3708 xmlOutputBufferPtr buf;
3709
3710 int result;
3711 int len;
3712
3713 if (!PyArg_ParseTuple(args, (char *) "OOiOiO:C14NDocSaveTo",
3714 &pyobj_doc,
3715 &pyobj_nodes,
3716 &exclusive,
3717 &pyobj_prefixes,
3718 &with_comments,
3719 &py_file))
3720 return (NULL);
3721
3722 doc = (xmlDocPtr) PyxmlNode_Get(pyobj_doc);
3723 if (!doc) {
3724 PyErr_SetString(PyExc_TypeError, "bad document.");
3725 return NULL;
3726 }
3727
3728 output = PyFile_Get(py_file);
3729 if (output == NULL) {
3730 PyErr_SetString(PyExc_TypeError, "bad file.");
3731 return NULL;
3732 }
3733 buf = xmlOutputBufferCreateFile(output, NULL);
3734
3735 result = PyxmlNodeSet_Convert(pyobj_nodes, &nodes);
3736 if (result < 0) return NULL;
3737
3738 if (exclusive) {
3739 result = PystringSet_Convert(pyobj_prefixes, &prefixes);
3740 if (result < 0) {
3741 if (nodes) {
3742 xmlFree(nodes->nodeTab);
3743 xmlFree(nodes);
3744 }
3745 return NULL;
3746 }
3747 }
3748
3749 result = xmlC14NDocSaveTo(doc,
3750 nodes,
3751 exclusive,
3752 prefixes,
3753 with_comments,
3754 buf);
3755
3756 if (nodes) {
3757 xmlFree(nodes->nodeTab);
3758 xmlFree(nodes);
3759 }
3760 if (prefixes) {
3761 xmlChar ** idx = prefixes;
3762 while (*idx) xmlFree(*(idx++));
3763 xmlFree(prefixes);
3764 }
3765
3766 PyFile_Release(output);
3767 len = xmlOutputBufferClose(buf);
3768
3769 if (result < 0) {
3770 PyErr_SetString(PyExc_Exception,
3771 "libxml2 xmlC14NDocSaveTo failure.");
3772 return NULL;
3773 }
3774 else
3775 return PyLong_FromLong((long) len);
3776 }
3777
3778 #endif
3779 #endif
3780
3781 static PyObject *
libxml_getObjDesc(PyObject * self ATTRIBUTE_UNUSED,PyObject * args)3782 libxml_getObjDesc(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
3783
3784 PyObject *obj;
3785 char *str;
3786
3787 if (!PyArg_ParseTuple(args, (char *)"O:getObjDesc", &obj))
3788 return NULL;
3789 str = PyCapsule_GetPointer(obj, PyCapsule_GetName(obj));
3790 return Py_BuildValue((char *)"s", str);
3791 }
3792
3793 static PyObject *
libxml_compareNodesEqual(PyObject * self ATTRIBUTE_UNUSED,PyObject * args)3794 libxml_compareNodesEqual(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
3795
3796 PyObject *py_node1, *py_node2;
3797 xmlNodePtr node1, node2;
3798
3799 if (!PyArg_ParseTuple(args, (char *)"OO:compareNodesEqual",
3800 &py_node1, &py_node2))
3801 return NULL;
3802 /* To compare two node objects, we compare their pointer addresses */
3803 node1 = PyxmlNode_Get(py_node1);
3804 node2 = PyxmlNode_Get(py_node2);
3805 if ( node1 == node2 )
3806 return Py_BuildValue((char *)"i", 1);
3807 else
3808 return Py_BuildValue((char *)"i", 0);
3809
3810 }
3811
3812 static PyObject *
libxml_nodeHash(PyObject * self ATTRIBUTE_UNUSED,PyObject * args)3813 libxml_nodeHash(PyObject *self ATTRIBUTE_UNUSED, PyObject *args) {
3814
3815 PyObject *py_node1;
3816 xmlNodePtr node1;
3817
3818 if (!PyArg_ParseTuple(args, (char *)"O:nodeHash", &py_node1))
3819 return NULL;
3820 /* For simplicity, we use the node pointer address as a hash value */
3821 node1 = PyxmlNode_Get(py_node1);
3822
3823 return PyLong_FromVoidPtr(node1);
3824
3825 }
3826
3827 /************************************************************************
3828 * *
3829 * The registration stuff *
3830 * *
3831 ************************************************************************/
3832 static PyMethodDef libxmlMethods[] = {
3833 #include "libxml2-export.c"
3834 {(char *) "name", libxml_name, METH_VARARGS, NULL},
3835 {(char *) "children", libxml_children, METH_VARARGS, NULL},
3836 {(char *) "properties", libxml_properties, METH_VARARGS, NULL},
3837 {(char *) "last", libxml_last, METH_VARARGS, NULL},
3838 {(char *) "prev", libxml_prev, METH_VARARGS, NULL},
3839 {(char *) "next", libxml_next, METH_VARARGS, NULL},
3840 {(char *) "parent", libxml_parent, METH_VARARGS, NULL},
3841 {(char *) "type", libxml_type, METH_VARARGS, NULL},
3842 {(char *) "doc", libxml_doc, METH_VARARGS, NULL},
3843 {(char *) "xmlNewNode", libxml_xmlNewNode, METH_VARARGS, NULL},
3844 {(char *) "xmlNodeRemoveNsDef", libxml_xmlNodeRemoveNsDef, METH_VARARGS, NULL},
3845 {(char *)"xmlSetValidErrors", libxml_xmlSetValidErrors, METH_VARARGS, NULL},
3846 {(char *)"xmlFreeValidCtxt", libxml_xmlFreeValidCtxt, METH_VARARGS, NULL},
3847 #ifdef LIBXML_OUTPUT_ENABLED
3848 {(char *) "serializeNode", libxml_serializeNode, METH_VARARGS, NULL},
3849 {(char *) "saveNodeTo", libxml_saveNodeTo, METH_VARARGS, NULL},
3850 {(char *) "outputBufferCreate", libxml_xmlCreateOutputBuffer, METH_VARARGS, NULL},
3851 {(char *) "outputBufferGetPythonFile", libxml_outputBufferGetPythonFile, METH_VARARGS, NULL},
3852 {(char *) "xmlOutputBufferClose", libxml_xmlOutputBufferClose, METH_VARARGS, NULL},
3853 { (char *)"xmlOutputBufferFlush", libxml_xmlOutputBufferFlush, METH_VARARGS, NULL },
3854 { (char *)"xmlSaveFileTo", libxml_xmlSaveFileTo, METH_VARARGS, NULL },
3855 { (char *)"xmlSaveFormatFileTo", libxml_xmlSaveFormatFileTo, METH_VARARGS, NULL },
3856 #endif /* LIBXML_OUTPUT_ENABLED */
3857 {(char *) "inputBufferCreate", libxml_xmlCreateInputBuffer, METH_VARARGS, NULL},
3858 {(char *) "setEntityLoader", libxml_xmlSetEntityLoader, METH_VARARGS, NULL},
3859 {(char *)"xmlRegisterErrorHandler", libxml_xmlRegisterErrorHandler, METH_VARARGS, NULL },
3860 {(char *)"xmlParserCtxtSetErrorHandler", libxml_xmlParserCtxtSetErrorHandler, METH_VARARGS, NULL },
3861 {(char *)"xmlParserCtxtGetErrorHandler", libxml_xmlParserCtxtGetErrorHandler, METH_VARARGS, NULL },
3862 {(char *)"xmlFreeParserCtxt", libxml_xmlFreeParserCtxt, METH_VARARGS, NULL },
3863 #ifdef LIBXML_READER_ENABLED
3864 {(char *)"xmlTextReaderSetErrorHandler", libxml_xmlTextReaderSetErrorHandler, METH_VARARGS, NULL },
3865 {(char *)"xmlTextReaderGetErrorHandler", libxml_xmlTextReaderGetErrorHandler, METH_VARARGS, NULL },
3866 {(char *)"xmlFreeTextReader", libxml_xmlFreeTextReader, METH_VARARGS, NULL },
3867 #endif
3868 {(char *)"addLocalCatalog", libxml_addLocalCatalog, METH_VARARGS, NULL },
3869 #ifdef LIBXML_SCHEMAS_ENABLED
3870 {(char *)"xmlRelaxNGSetValidErrors", libxml_xmlRelaxNGSetValidErrors, METH_VARARGS, NULL},
3871 {(char *)"xmlRelaxNGFreeValidCtxt", libxml_xmlRelaxNGFreeValidCtxt, METH_VARARGS, NULL},
3872 {(char *)"xmlSchemaSetValidErrors", libxml_xmlSchemaSetValidErrors, METH_VARARGS, NULL},
3873 {(char *)"xmlSchemaFreeValidCtxt", libxml_xmlSchemaFreeValidCtxt, METH_VARARGS, NULL},
3874 #endif
3875 #ifdef LIBXML_C14N_ENABLED
3876 #ifdef LIBXML_OUTPUT_ENABLED
3877 {(char *)"xmlC14NDocDumpMemory", libxml_C14NDocDumpMemory, METH_VARARGS, NULL},
3878 {(char *)"xmlC14NDocSaveTo", libxml_C14NDocSaveTo, METH_VARARGS, NULL},
3879 #endif
3880 #endif
3881 {(char *) "getObjDesc", libxml_getObjDesc, METH_VARARGS, NULL},
3882 {(char *) "compareNodesEqual", libxml_compareNodesEqual, METH_VARARGS, NULL},
3883 {(char *) "nodeHash", libxml_nodeHash, METH_VARARGS, NULL},
3884 {(char *) "xmlRegisterInputCallback", libxml_xmlRegisterInputCallback, METH_VARARGS, NULL},
3885 {(char *) "xmlUnregisterInputCallback", libxml_xmlUnregisterInputCallback, METH_VARARGS, NULL},
3886 {NULL, NULL, 0, NULL}
3887 };
3888
3889 #if PY_MAJOR_VERSION >= 3
3890 #define INITERROR return NULL
3891
3892 static struct PyModuleDef moduledef = {
3893 PyModuleDef_HEAD_INIT,
3894 "libxml2mod",
3895 NULL,
3896 -1,
3897 libxmlMethods,
3898 NULL,
3899 NULL,
3900 NULL,
3901 NULL
3902 };
3903
3904 #else
3905 #define INITERROR return
3906
3907 #ifdef MERGED_MODULES
3908 extern void initlibxsltmod(void);
3909 #endif
3910
3911 #endif
3912
3913 #if PY_MAJOR_VERSION >= 3
PyInit_libxml2mod(void)3914 PyObject *PyInit_libxml2mod(void)
3915 #else
3916 void initlibxml2mod(void)
3917 #endif
3918 {
3919 PyObject *module;
3920
3921 #if PY_MAJOR_VERSION >= 3
3922 module = PyModule_Create(&moduledef);
3923 #else
3924 /* initialize the python extension module */
3925 module = Py_InitModule((char *) "libxml2mod", libxmlMethods);
3926 #endif
3927 if (module == NULL)
3928 INITERROR;
3929
3930 /* initialize libxml2 */
3931 xmlInitParser();
3932 /* TODO this probably need to be revamped for Python3 */
3933 libxml_xmlErrorInitialize();
3934
3935 #if PY_MAJOR_VERSION < 3
3936 #ifdef MERGED_MODULES
3937 initlibxsltmod();
3938 #endif
3939 #endif
3940
3941 #if PY_MAJOR_VERSION >= 3
3942 return module;
3943 #endif
3944 }
3945