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