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