diff --git a/ChangeLog b/ChangeLog index 5651796a..e721f4e7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,8 +1,16 @@ +Wed Nov 10 12:55:18 CET 2004 Daniel Veillard + + * python/generator.py python/libxml.c python/libxml2class.txt + python/libxml_wrap.h python/types.c: Applied patch from Brent + Hendricks adding support for late DTD validation. + * python/tests/Makefile.am python/tests/dtdvalid.py + python/tests/test.dtd: integrated the provided regression test + Tue nov 9 19:24:31 CET 2004 Dodji Seketeli * configure.in: detect when struct sockaddr_storage - has the __ss_family member instead of ss_family and - behave accordingly. We know can use ipv6 on aix. + has the __ss_family member instead of ss_family and + behave accordingly. We now can use ipv6 on aix. Tue Nov 9 17:15:46 CET 2004 Daniel Veillard diff --git a/config.h.in b/config.h.in index 8a652870..590e0cec 100644 --- a/config.h.in +++ b/config.h.in @@ -25,6 +25,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_ARPA_NAMESER_H +/* Whether struct sockaddr::__ss_family exists */ +#undef HAVE_BROKEN_SS_FAMILY + /* Define to 1 if you have the `class' function. */ #undef HAVE_CLASS @@ -279,5 +282,8 @@ /* Win32 Std C name mangling work-around */ #undef snprintf +/* ss_family is not defined here, use __ss_family instead */ +#undef ss_family + /* Win32 Std C name mangling work-around */ #undef vsnprintf diff --git a/python/generator.py b/python/generator.py index 04b3832f..60320652 100755 --- a/python/generator.py +++ b/python/generator.py @@ -270,6 +270,7 @@ py_types = { 'xmlParserCtxt *': ('O', "parserCtxt", "xmlParserCtxtPtr", "xmlParserCtxtPtr"), 'htmlParserCtxtPtr': ('O', "parserCtxt", "xmlParserCtxtPtr", "xmlParserCtxtPtr"), 'htmlParserCtxt *': ('O', "parserCtxt", "xmlParserCtxtPtr", "xmlParserCtxtPtr"), + 'xmlValidCtxtPtr': ('O', "ValidCtxt", "xmlValidCtxtPtr", "xmlValidCtxtPtr"), 'xmlCatalogPtr': ('O', "catalog", "xmlCatalogPtr", "xmlCatalogPtr"), 'FILE *': ('O', "File", "FILEPtr", "FILE *"), 'xmlURIPtr': ('O', "URI", "xmlURIPtr", "xmlURIPtr"), @@ -345,6 +346,14 @@ def skip_function(name): return 1 if name == "xmlErrMemory": return 1 + + if name == "xmlValidBuildContentModel": + return 1 + if name == "xmlValidateElementDecl": + return 1 + if name == "xmlValidateAttributeDecl": + return 1 + return 0 def print_function_wrapper(name, output, export, include): @@ -668,6 +677,7 @@ classes_type = { "xmlParserCtxt *": ("._o", "parserCtxt(_obj=%s)", "parserCtxt"), "htmlParserCtxtPtr": ("._o", "parserCtxt(_obj=%s)", "parserCtxt"), "htmlParserCtxt *": ("._o", "parserCtxt(_obj=%s)", "parserCtxt"), + "xmlValidCtxtPtr": ("._o", "ValidCtxt(_obj=%s)", "ValidCtxt"), "xmlCatalogPtr": ("._o", "catalog(_obj=%s)", "catalog"), "xmlURIPtr": ("._o", "URI(_obj=%s)", "URI"), "xmlErrorPtr": ("._o", "Error(_obj=%s)", "Error"), @@ -718,6 +728,7 @@ classes_destructors = { "Schema": "xmlSchemaFree", "SchemaParserCtxt": "xmlSchemaFreeParserCtxt", "SchemaValidCtxt": "xmlSchemaFreeValidCtxt", + "ValidCtxt": "xmlFreeValidCtxt", } functions_noexcept = { diff --git a/python/libxml.c b/python/libxml.c index 9d33c771..ae1a0f4a 100644 --- a/python/libxml.c +++ b/python/libxml.c @@ -1554,7 +1554,7 @@ libxml_xmlParserCtxtGenericErrorFuncHandler(void *ctx, int severity, char *str) xmlParserCtxtPyCtxtPtr pyCtxt; #ifdef DEBUG_ERROR - printf("libxml_xmlParserCtxtGenericErrorFuncHandler(%p, %s, ...) called\n", ctx, msg); + printf("libxml_xmlParserCtxtGenericErrorFuncHandler(%p, %s, ...) called\n", ctx, str); #endif ctxt = (xmlParserCtxtPtr)ctx; @@ -1723,6 +1723,141 @@ libxml_xmlFreeParserCtxt(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) { return(Py_None); } +/*** + * xmlValidCtxt stuff + */ + +typedef struct +{ + PyObject *warn; + PyObject *error; + PyObject *arg; +} xmlValidCtxtPyCtxt; +typedef xmlValidCtxtPyCtxt *xmlValidCtxtPyCtxtPtr; + +static void +libxml_xmlValidCtxtGenericErrorFuncHandler(void *ctx, int severity, char *str) +{ + PyObject *list; + PyObject *result; + xmlValidCtxtPyCtxtPtr pyCtxt; + +#ifdef DEBUG_ERROR + printf("libxml_xmlValidCtxtGenericErrorFuncHandler(%p, %d, %s, ...) called\n", ctx, severity, str); +#endif + + pyCtxt = (xmlValidCtxtPyCtxtPtr)ctx; + + list = PyTuple_New(2); + PyTuple_SetItem(list, 0, libxml_charPtrWrap(str)); + PyTuple_SetItem(list, 1, pyCtxt->arg); + Py_XINCREF(pyCtxt->arg); + result = PyEval_CallObject(pyCtxt->error, list); + if (result == NULL) + { + /* TODO: manage for the exception to be propagated... */ + PyErr_Print(); + } + Py_XDECREF(list); + Py_XDECREF(result); +} + +static void +libxml_xmlValidCtxtGenericWarningFuncHandler(void *ctx, int severity, char *str) +{ + PyObject *list; + PyObject *result; + xmlValidCtxtPyCtxtPtr pyCtxt; + +#ifdef DEBUG_ERROR + printf("libxml_xmlValidCtxtGenericWarningFuncHandler(%p, %d, %s, ...) called\n", ctx, severity, str); +#endif + + pyCtxt = (xmlValidCtxtPyCtxtPtr)ctx; + + list = PyTuple_New(2); + PyTuple_SetItem(list, 0, libxml_charPtrWrap(str)); + PyTuple_SetItem(list, 1, pyCtxt->arg); + Py_XINCREF(pyCtxt->arg); + result = PyEval_CallObject(pyCtxt->warn, list); + if (result == NULL) + { + /* TODO: manage for the exception to be propagated... */ + PyErr_Print(); + } + Py_XDECREF(list); + Py_XDECREF(result); +} + +static void +libxml_xmlValidCtxtErrorFuncHandler(void *ctx, const char *msg, ...) +{ + va_list ap; + + va_start(ap, msg); + libxml_xmlValidCtxtGenericErrorFuncHandler(ctx,XML_PARSER_SEVERITY_VALIDITY_ERROR,libxml_buildMessage(msg,ap)); + va_end(ap); +} + +static void +libxml_xmlValidCtxtWarningFuncHandler(void *ctx, const char *msg, ...) +{ + va_list ap; + + va_start(ap, msg); + libxml_xmlValidCtxtGenericWarningFuncHandler(ctx,XML_PARSER_SEVERITY_VALIDITY_WARNING,libxml_buildMessage(msg,ap)); + va_end(ap); +} + +static PyObject * +libxml_xmlSetValidErrors(ATTRIBUTE_UNUSED PyObject * self, PyObject * args) +{ + PyObject *py_retval; + PyObject *pyobj_error; + PyObject *pyobj_warn; + PyObject *pyobj_ctx; + PyObject *pyobj_arg = Py_None; + xmlValidCtxtPtr ctxt; + xmlValidCtxtPyCtxtPtr pyCtxt; + + if (!PyArg_ParseTuple + (args, (char *) "OOO|O:xmlSetValidErrors", &pyobj_ctx, &pyobj_error, &pyobj_warn, &pyobj_arg)) + return (NULL); + +#ifdef DEBUG_ERROR + printf("libxml_xmlSetValidErrors(%p, %p, %p) called\n", pyobj_ctx, pyobj_error, pyobj_warn); +#endif + + ctxt = PyValidCtxt_Get(pyobj_ctx); + pyCtxt = xmlMalloc(sizeof(xmlValidCtxtPyCtxt)); + if (pyCtxt == NULL) { + py_retval = libxml_intWrap(-1); + return(py_retval); + } + memset(pyCtxt, 0, sizeof(xmlValidCtxtPyCtxt)); + + + /* TODO: check warn and error is a function ! */ + Py_XDECREF(pyCtxt->error); + Py_XINCREF(pyobj_error); + pyCtxt->error = pyobj_error; + + Py_XDECREF(pyCtxt->warn); + Py_XINCREF(pyobj_warn); + pyCtxt->warn = pyobj_warn; + + Py_XDECREF(pyCtxt->arg); + Py_XINCREF(pyobj_arg); + pyCtxt->arg = pyobj_arg; + + ctxt->error = libxml_xmlValidCtxtErrorFuncHandler; + ctxt->warning = libxml_xmlValidCtxtWarningFuncHandler; + ctxt->userData = pyCtxt; + + py_retval = libxml_intWrap(1); + return (py_retval); +} + /************************************************************************ * * * Per xmlTextReader error handler * @@ -3482,6 +3617,7 @@ static PyMethodDef libxmlMethods[] = { {(char *) "type", libxml_type, METH_VARARGS, NULL}, {(char *) "doc", libxml_doc, METH_VARARGS, NULL}, {(char *) "xmlNewNode", libxml_xmlNewNode, METH_VARARGS, NULL}, + {(char *)"xmlSetValidErrors", libxml_xmlSetValidErrors, METH_VARARGS, NULL}, #ifdef LIBXML_OUTPUT_ENABLED {(char *) "serializeNode", libxml_serializeNode, METH_VARARGS, NULL}, {(char *) "saveNodeTo", libxml_saveNodeTo, METH_VARARGS, NULL}, diff --git a/python/libxml2class.txt b/python/libxml2class.txt index 972074ce..3d61714e 100644 --- a/python/libxml2class.txt +++ b/python/libxml2class.txt @@ -187,6 +187,7 @@ normalizeURIPath() parseURI() # functions from module valid +newValidCtxt() validateNameValue() validateNamesValue() validateNmtokenValue() @@ -632,7 +633,20 @@ Class xmlDoc(xmlNode) isRef() removeID() removeRef() + validCtxtNormalizeAttributeValue() validNormalizeAttributeValue() + validateDocument() + validateDocumentFinal() + validateDtd() + validateDtdFinal() + validateElement() + validateNotationUse() + validateOneAttribute() + validateOneElement() + validateOneNamespace() + validatePopElement() + validatePushElement() + validateRoot() # functions from module xinclude xincludeProcess() @@ -687,18 +701,23 @@ Class xpathContext() Class xmlAttribute(xmlNode) -Class catalog() +Class ValidCtxt() - # functions from module catalog - add() - catalogIsEmpty() - convertSGMLCatalog() - dump() - remove() - resolve() - resolvePublic() - resolveSystem() - resolveURI() + # functions from module valid + validCtxtNormalizeAttributeValue() + validateDocument() + validateDocumentFinal() + validateDtd() + validateDtdFinal() + validateElement() + validateNotationUse() + validateOneAttribute() + validateOneElement() + validateOneNamespace() + validatePopElement() + validatePushCData() + validatePushElement() + validateRoot() Class xmlElement(xmlNode) @@ -786,6 +805,18 @@ Class xmlReg() regexpExec() regexpIsDeterminist() regexpPrint() +Class catalog() + + # functions from module catalog + add() + catalogIsEmpty() + convertSGMLCatalog() + dump() + remove() + resolve() + resolvePublic() + resolveSystem() + resolveURI() Class xmlEntity(xmlNode) diff --git a/python/libxml_wrap.h b/python/libxml_wrap.h index e8210753..2758e993 100644 --- a/python/libxml_wrap.h +++ b/python/libxml_wrap.h @@ -73,6 +73,14 @@ typedef struct { xmlParserCtxtPtr obj; } PyparserCtxt_Object; +#define PyValidCtxt_Get(v) (((v) == Py_None) ? NULL : \ + (((PyValidCtxt_Object *)(v))->obj)) + +typedef struct { + PyObject_HEAD + xmlValidCtxtPtr obj; +} PyValidCtxt_Object; + #define Pycatalog_Get(v) (((v) == Py_None) ? NULL : \ (((Pycatalog_Object *)(v))->obj)) @@ -213,6 +221,7 @@ PyObject * libxml_xmlXPathContextPtrWrap(xmlXPathContextPtr ctxt); PyObject * libxml_xmlParserCtxtPtrWrap(xmlParserCtxtPtr ctxt); PyObject * libxml_xmlXPathParserContextPtrWrap(xmlXPathParserContextPtr ctxt); PyObject * libxml_xmlXPathObjectPtrWrap(xmlXPathObjectPtr obj); +PyObject * libxml_xmlValidCtxtPtrWrap(xmlValidCtxtPtr valid); PyObject * libxml_xmlCatalogPtrWrap(xmlCatalogPtr obj); PyObject * libxml_xmlURIPtrWrap(xmlURIPtr uri); PyObject * libxml_xmlOutputBufferPtrWrap(xmlOutputBufferPtr buffer); diff --git a/python/tests/Makefile.am b/python/tests/Makefile.am index 722e0ec6..1ae9b6ca 100644 --- a/python/tests/Makefile.am +++ b/python/tests/Makefile.am @@ -36,12 +36,14 @@ PYTESTS= \ thread2.py \ sync.py \ tstLastError.py \ - indexes.py + indexes.py \ + dtdvalid.py XMLS= \ tst.xml \ valid.xml \ - invalid.xml + invalid.xml \ + test.dtd EXTRA_DIST = $(PYTESTS) $(XMLS) diff --git a/python/tests/dtdvalid.py b/python/tests/dtdvalid.py new file mode 100755 index 00000000..2011f2c6 --- /dev/null +++ b/python/tests/dtdvalid.py @@ -0,0 +1,32 @@ +#!/usr/bin/python -u +import libxml2 +import sys + +# Memory debug specific +libxml2.debugMemory(1) + +dtd="""""" +instance=""" +""" + +dtd = libxml2.parseDTD(None, 'test.dtd') +ctxt = libxml2.newValidCtxt() +doc = libxml2.parseDoc(instance) +ret = doc.validateDtd(ctxt, dtd) +if ret != 1: + print "error doing DTD validation" + sys.exit(1) + +doc.freeDoc() +dtd.freeDtd() +del dtd +del ctxt + +# Memory debug specific +libxml2.cleanupParser() +if libxml2.debugMemory(1) == 0: + print "OK" +else: + print "Memory leak %d bytes" % (libxml2.debugMemory(1)) + libxml2.dumpMemory() + diff --git a/python/tests/test.dtd b/python/tests/test.dtd new file mode 100644 index 00000000..b61b4380 --- /dev/null +++ b/python/tests/test.dtd @@ -0,0 +1 @@ + diff --git a/python/types.c b/python/types.c index fa91a65a..329d2706 100644 --- a/python/types.c +++ b/python/types.c @@ -477,6 +477,26 @@ libxml_xmlXPathObjectPtrConvert(PyObject * obj) return (ret); } +PyObject * +libxml_xmlValidCtxtPtrWrap(xmlValidCtxtPtr valid) +{ + PyObject *ret; + +#ifdef DEBUG + printf("libxml_xmlValidCtxtPtrWrap: valid = %p\n", valid); +#endif + if (valid == NULL) { + Py_INCREF(Py_None); + return (Py_None); + } + + ret = + PyCObject_FromVoidPtrAndDesc((void *) valid, + (char *) "xmlValidCtxtPtr", NULL); + + return (ret); +} + PyObject * libxml_xmlCatalogPtrWrap(xmlCatalogPtr catal) {