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