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