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