shane Sun Oct 5 16:45:28 2003 EDT
Added files:
/php-src/ext/dom/examples relaxNG.php relaxNG.rng relaxNG.xml
relaxNG2.rng relaxNG3.rng shipping.php
shipping.xml shipping.xsd
Modified files:
/php-src/ext/dom document.c dom_fe.h element.c
Log:
Add schema and relaxNG validation support
domdocument->schemaValidate(string filename)
domdocument->schemaValidateSource(string xml)
domdocument->relaxNGValidate(string filename)
domdocument->relaxNGValidateSource(string xml)
also fix domelement->setAttributeNS
Index: php-src/ext/dom/document.c
diff -u php-src/ext/dom/document.c:1.28 php-src/ext/dom/document.c:1.29
--- php-src/ext/dom/document.c:1.28 Sun Oct 5 07:52:22 2003
+++ php-src/ext/dom/document.c Sun Oct 5 16:45:26 2003
@@ -17,7 +17,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: document.c,v 1.28 2003/10/05 11:52:22 rrichards Exp $ */
+/* $Id: document.c,v 1.29 2003/10/05 20:45:26 shane Exp $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -27,6 +27,10 @@
#if HAVE_LIBXML && HAVE_DOM
#include "php_dom.h"
#include <libxml/SAX.h>
+#ifdef LIBXML_SCHEMAS_ENABLED
+#include <libxml/relaxng.h>
+#include <libxml/xmlschemas.h>
+#endif
typedef struct _idsIterator idsIterator;
struct _idsIterator {
@@ -83,6 +87,12 @@
PHP_FALIAS(saveHTML, dom_document_save_html, NULL)
PHP_FALIAS(saveHTMLFile, dom_document_save_html_file, NULL)
#endif /* defined(LIBXML_HTML_ENABLED) */
+#if defined(LIBXML_SCHEMAS_ENABLED)
+ PHP_FALIAS(schemaValidate, dom_document_schema_validate_file, NULL)
+ PHP_FALIAS(schemaValidateSource, dom_document_schema_validate_xml, NULL)
+ PHP_FALIAS(relaxNGValidate, dom_document_relaxNG_validate_file, NULL)
+ PHP_FALIAS(relaxNGValidateSource, dom_document_relaxNG_validate_xml, NULL)
+#endif
{NULL, NULL, NULL}
};
@@ -1204,6 +1214,56 @@
}
/* }}} end dom_document_document */
+char *_dom_get_valid_file_path(char *source, char *resolved_path, int
resolved_path_len TSRMLS_DC) {
+ xmlURI *uri;
+ xmlChar *escsource;
+ char *file_dest;
+ int isFileUri = 0;
+
+ uri = xmlCreateURI();
+ escsource = xmlURIEscapeStr(source, ":");
+ xmlParseURIReference(uri, escsource);
+ xmlFree(escsource);
+
+ if (uri->scheme != NULL) {
+ /* absolute file uris - libxml only supports localhost or empty host */
+ if (strncasecmp(source, "file:///",8) == 0) {
+ isFileUri = 1;
+#ifdef PHP_WIN32
+ source += 8;
+#else
+ source += 7;
+#endif
+ } else if (strncasecmp(source, "file://localhost/",17) == 0) {
+ isFileUri = 1;
+#ifdef PHP_WIN32
+ source += 17;
+#else
+ source += 16;
+#endif
+ }
+ }
+
+ file_dest = source;
+
+ if ((uri->scheme == NULL || isFileUri)) {
+ /* XXX possible buffer overflow if VCWD_REALPATH does not know size of
resolved_path */
+ if (! VCWD_REALPATH(source, resolved_path)) {
+ expand_filepath(source, resolved_path TSRMLS_CC);
+ }
+ file_dest = resolved_path;
+ }
+
+ xmlFreeURI(uri);
+
+ if ((PG(safe_mode) && (!php_checkuid(file_dest, NULL,
CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(file_dest TSRMLS_CC)) {
+ return NULL;
+ } else {
+ return file_dest;
+ }
+}
+
+
/* {{{ */
static xmlDocPtr dom_document_parser(zval *id, int mode, char *source TSRMLS_DC) {
xmlDocPtr ret;
@@ -1235,50 +1295,8 @@
keep_blanks = xmlKeepBlanksDefault(keep_blanks);
if (mode == DOM_LOAD_FILE) {
-
- xmlURI *uri;
- xmlChar *escsource;
- char *file_dest;
- int isFileUri = 0;
-
- uri = xmlCreateURI();
- escsource = xmlURIEscapeStr(source, ":");
- xmlParseURIReference(uri, escsource);
- xmlFree(escsource);
-
- if (uri->scheme != NULL) {
- /* absolute file uris - libxml only supports localhost or
empty host */
- if (strncasecmp(source, "file:///",8) == 0) {
- isFileUri = 1;
-#ifdef PHP_WIN32
- source += 8;
-#else
- source += 7;
-#endif
- } else if (strncasecmp(source, "file://localhost/",17) == 0) {
- isFileUri = 1;
-#ifdef PHP_WIN32
- source += 17;
-#else
- source += 16;
-#endif
- }
- }
-
- file_dest = source;
-
- if ((uri->scheme == NULL || isFileUri)) {
- if (! VCWD_REALPATH(source, resolved_path)) {
- expand_filepath(source, resolved_path TSRMLS_CC);
- }
- file_dest = resolved_path;
- }
-
- xmlFreeURI(uri);
-
- if ((PG(safe_mode) && (!php_checkuid(file_dest, NULL,
CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(file_dest TSRMLS_CC)) {
- ctxt = NULL;
- } else {
+ char *file_dest = _dom_get_valid_file_path(source, resolved_path,
MAXPATHLEN TSRMLS_CC);
+ if (file_dest) {
ctxt = xmlCreateFileParserCtxt(file_dest);
}
} else {
@@ -1293,11 +1311,11 @@
/* If loading from memory, we need to set the base directory for the document
*/
if (mode != DOM_LOAD_FILE) {
- #if HAVE_GETCWD
- directory = VCWD_GETCWD(resolved_path, MAXPATHLEN);
- #elif HAVE_GETWD
- directory = VCWD_GETWD(resolved_path);
- #endif
+#if HAVE_GETCWD
+ directory = VCWD_GETCWD(resolved_path, MAXPATHLEN);
+#elif HAVE_GETWD
+ directory = VCWD_GETWD(resolved_path);
+#endif
if (directory) {
if(ctxt->directory != NULL) {
xmlFree((char *) ctxt->directory);
@@ -1531,6 +1549,173 @@
}
/* }}} end dom_document_validate */
+#if defined(LIBXML_SCHEMAS_ENABLED)
+static void
+_dom_document_schema_validate(INTERNAL_FUNCTION_PARAMETERS, int type)
+{
+ zval *id;
+ xmlDoc *docp;
+ dom_object *intern;
+ char *source = NULL, *valid_file = NULL, *directory = NULL;
+ int source_len = 0;
+ xmlSchemaParserCtxtPtr parser;
+ xmlSchemaPtr sptr;
+ xmlSchemaValidCtxtPtr vptr;
+ int is_valid;
+ char resolved_path[MAXPATHLEN + 1];
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &source,
&source_len) == FAILURE) {
+ return;
+ }
+
+ DOM_GET_THIS_OBJ(docp, id, xmlDocPtr, intern);
+
+ switch (type) {
+ case DOM_LOAD_FILE:
+ valid_file = _dom_get_valid_file_path(source, resolved_path,
MAXPATHLEN TSRMLS_CC);
+ if (!valid_file) {
+ php_error(E_WARNING, "Invalid Schema file source");
+ RETURN_FALSE;
+ }
+ parser = xmlSchemaNewParserCtxt(valid_file);
+ break;
+ case DOM_LOAD_STRING:
+ parser = xmlSchemaNewMemParserCtxt(source, source_len);
+ /* If loading from memory, we need to set the base directory for the
document
+ but it is not apparent how to do that for schema's */
+ break;
+ }
+
+ xmlSchemaSetParserErrors(parser,
+ (xmlSchemaValidityErrorFunc) php_dom_validate_error,
+ (xmlSchemaValidityWarningFunc) php_dom_validate_error,
+ parser);
+ sptr = xmlSchemaParse(parser);
+ xmlSchemaFreeParserCtxt(parser);
+ if (!sptr) {
+ php_error(E_WARNING, "Invalid Schema");
+ RETURN_FALSE;
+ }
+
+ docp = (xmlDocPtr) dom_object_get_node(intern);
+
+ vptr = xmlSchemaNewValidCtxt(sptr);
+ if (!vptr) {
+ xmlSchemaFree(sptr);
+ php_error(E_ERROR, "Invalid Schema Validation Context");
+ RETURN_FALSE;
+ }
+
+ xmlSchemaSetValidErrors(vptr, php_dom_validate_error, php_dom_validate_error,
vptr);
+ is_valid = xmlSchemaValidateDoc(vptr, docp);
+ xmlSchemaFree(sptr);
+ xmlSchemaFreeValidCtxt(vptr);
+
+ if (is_valid == 0) {
+ RETURN_TRUE;
+ } else {
+ RETURN_FALSE;
+ }
+}
+
+/* {{{ proto boolean domnode _dom_document_schema_validate(string filename); */
+PHP_FUNCTION(dom_document_schema_validate_file)
+{
+ _dom_document_schema_validate(INTERNAL_FUNCTION_PARAM_PASSTHRU, DOM_LOAD_FILE);
+}
+/* }}} end _dom_document_schema_validate */
+
+/* {{{ proto boolean domnode _dom_document_schema_validate(string source); */
+PHP_FUNCTION(dom_document_schema_validate_xml)
+{
+ _dom_document_schema_validate(INTERNAL_FUNCTION_PARAM_PASSTHRU,
DOM_LOAD_STRING);
+}
+/* }}} end _dom_document_schema_validate */
+
+
+static void
+_dom_document_relaxNG_validate(INTERNAL_FUNCTION_PARAMETERS, int type)
+{
+ zval *id;
+ xmlDoc *docp;
+ dom_object *intern;
+ char *source = NULL, *valid_file = NULL, *directory = NULL;
+ int source_len = 0;
+ xmlRelaxNGParserCtxtPtr parser;
+ xmlRelaxNGPtr sptr;
+ xmlRelaxNGValidCtxtPtr vptr;
+ int is_valid;
+ char resolved_path[MAXPATHLEN + 1];
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &source,
&source_len) == FAILURE) {
+ return;
+ }
+
+ DOM_GET_THIS_OBJ(docp, id, xmlDocPtr, intern);
+
+ switch (type) {
+ case DOM_LOAD_FILE:
+ valid_file = _dom_get_valid_file_path(source, resolved_path,
MAXPATHLEN TSRMLS_CC);
+ if (!valid_file) {
+ php_error(E_WARNING, "Invalid RelaxNG file source");
+ RETURN_FALSE;
+ }
+ parser = xmlRelaxNGNewParserCtxt(valid_file);
+ break;
+ case DOM_LOAD_STRING:
+ parser = xmlRelaxNGNewMemParserCtxt(source, source_len);
+ /* If loading from memory, we need to set the base directory for the
document
+ but it is not apparent how to do that for schema's */
+ break;
+ }
+
+ xmlRelaxNGSetParserErrors(parser,
+ (xmlRelaxNGValidityErrorFunc) php_dom_validate_error,
+ (xmlRelaxNGValidityWarningFunc) php_dom_validate_error,
+ parser);
+ sptr = xmlRelaxNGParse(parser);
+ xmlRelaxNGFreeParserCtxt(parser);
+ if (!sptr) {
+ php_error(E_WARNING, "Invalid RelaxNG");
+ RETURN_FALSE;
+ }
+
+ docp = (xmlDocPtr) dom_object_get_node(intern);
+
+ vptr = xmlRelaxNGNewValidCtxt(sptr);
+ if (!vptr) {
+ xmlRelaxNGFree(sptr);
+ php_error(E_ERROR, "Invalid RelaxNG Validation Context");
+ RETURN_FALSE;
+ }
+
+ xmlRelaxNGSetValidErrors(vptr, php_dom_validate_error, php_dom_validate_error,
vptr);
+ is_valid = xmlRelaxNGValidateDoc(vptr, docp);
+ xmlRelaxNGFree(sptr);
+ xmlRelaxNGFreeValidCtxt(vptr);
+
+ if (is_valid == 0) {
+ RETURN_TRUE;
+ } else {
+ RETURN_FALSE;
+ }
+}
+
+/* {{{ proto boolean domnode dom_document_relaxNG_validate_file(string filename); */
+PHP_FUNCTION(dom_document_relaxNG_validate_file)
+{
+ _dom_document_relaxNG_validate(INTERNAL_FUNCTION_PARAM_PASSTHRU,
DOM_LOAD_FILE);
+}
+/* }}} end dom_document_relaxNG_validate_file */
+
+/* {{{ proto boolean domnode dom_document_relaxNG_validate_xml(string source); */
+PHP_FUNCTION(dom_document_relaxNG_validate_xml)
+{
+ _dom_document_relaxNG_validate(INTERNAL_FUNCTION_PARAM_PASSTHRU,
DOM_LOAD_STRING);
+}
+/* }}} end dom_document_relaxNG_validate_xml */
+
+#endif
#if defined(LIBXML_HTML_ENABLED)
Index: php-src/ext/dom/dom_fe.h
diff -u php-src/ext/dom/dom_fe.h:1.5 php-src/ext/dom/dom_fe.h:1.6
--- php-src/ext/dom/dom_fe.h:1.5 Mon Sep 8 14:28:35 2003
+++ php-src/ext/dom/dom_fe.h Sun Oct 5 16:45:26 2003
@@ -17,7 +17,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: dom_fe.h,v 1.5 2003/09/08 18:28:35 rrichards Exp $ */
+/* $Id: dom_fe.h,v 1.6 2003/10/05 20:45:26 shane Exp $ */
#ifndef DOM_FE_H
#define DOM_FE_H
@@ -133,6 +133,13 @@
PHP_FUNCTION(dom_document_save_html);
PHP_FUNCTION(dom_document_save_html_file);
#endif /* defined(LIBXML_HTML_ENABLED) */
+
+#if defined(LIBXML_SCHEMAS_ENABLED)
+PHP_FUNCTION(dom_document_schema_validate_file);
+PHP_FUNCTION(dom_document_schema_validate_xml);
+PHP_FUNCTION(dom_document_relaxNG_validate_file);
+PHP_FUNCTION(dom_document_relaxNG_validate_xml);
+#endif
/* domnode methods */
PHP_FUNCTION(dom_node_insert_before);
Index: php-src/ext/dom/element.c
diff -u php-src/ext/dom/element.c:1.14 php-src/ext/dom/element.c:1.15
--- php-src/ext/dom/element.c:1.14 Sun Oct 5 07:52:22 2003
+++ php-src/ext/dom/element.c Sun Oct 5 16:45:26 2003
@@ -17,7 +17,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: element.c,v 1.14 2003/10/05 11:52:22 rrichards Exp $ */
+/* $Id: element.c,v 1.15 2003/10/05 20:45:26 shane Exp $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -497,15 +497,16 @@
zval *id, *rv = NULL;
xmlNodePtr elemp, nodep = NULL;
xmlNsPtr nsptr;
- int ret, uri_len = 0, name_len = 0;
- char *uri, *name;
+ xmlAttr *attr;
+ int ret, uri_len = 0, name_len = 0, value_len = 0;
+ char *uri, *name, *value;
char *localname = NULL, *prefix = NULL;
dom_object *intern;
int errorcode = 0, stricterror;
DOM_GET_THIS_OBJ(elemp, id, xmlNodePtr, intern);
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &uri, &uri_len,
&name, &name_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss", &uri, &uri_len,
&name, &name_len, &value, &value_len) == FAILURE) {
return;
}
@@ -537,6 +538,12 @@
if (errorcode == 0) {
nodep = (xmlNodePtr) xmlSetNsProp(elemp, nsptr, localname,
NULL);
+ }
+
+ attr = xmlSetProp(nodep, localname, value);
+ if (!attr) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "No such attribute
'%s'", localname);
+ RETURN_FALSE;
}
}
Index: php-src/ext/dom/examples/relaxNG.php
+++ php-src/ext/dom/examples/relaxNG.php
<?php
$dom = new domDocument;
$dom->load('relaxNG.xml');
if (!$dom->relaxNGValidate('relaxNG.rng')) {
print "Document is not valid";
} else {
print "Document is valid";
}
?>
Index: php-src/ext/dom/examples/relaxNG.rng
+++ php-src/ext/dom/examples/relaxNG.rng
<?xml version="1.0" encoding="iso-8859-1"?>
<grammar xmlns="http://relaxng.org/ns/structure/1.0"
datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
<include href="relaxNG2.rng">
<define name="TEI.prose"><ref name="INCLUDE"/></define>
</include>
</grammar>
Index: php-src/ext/dom/examples/relaxNG.xml
+++ php-src/ext/dom/examples/relaxNG.xml
<TEI.2>hello</TEI.2>
Index: php-src/ext/dom/examples/relaxNG2.rng
+++ php-src/ext/dom/examples/relaxNG2.rng
<?xml version="1.0" encoding="utf-8"?>
<grammar xmlns="http://relaxng.org/ns/structure/1.0"
xmlns:t="http://www.thaiopensource.com/ns/annotations"
xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0"
datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
<start>
<ref name="TEI.2"/>
</start>
<define name="IGNORE">
<notAllowed/>
</define>
<define name="INCLUDE">
<empty/>
</define>
<include href="relaxNG3.rng"/>
<define name="TEI.2">
<element name="TEI.2">
<text/>
</element>
</define>
</grammar>
Index: php-src/ext/dom/examples/relaxNG3.rng
+++ php-src/ext/dom/examples/relaxNG3.rng
<?xml version="1.0" encoding="utf-8"?>
<grammar xmlns="http://relaxng.org/ns/structure/1.0"
xmlns:t="http://www.thaiopensource.com/ns/annotations"
xmlns:a="http://relaxng.org/ns/compatibility/annotations/1.0"
datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
<define name="TEI.prose" combine="interleave">
<ref name="IGNORE"/>
</define>
</grammar>
Index: php-src/ext/dom/examples/shipping.php
+++ php-src/ext/dom/examples/shipping.php
<?php
$dom = new domDocument;
$dom->load('shipping.xml');
if (!$dom->schemaValidate('shipping.xsd')) {
print "Document is not valid";
} else {
print "Document is valid";
}
?>
Index: php-src/ext/dom/examples/shipping.xml
+++ php-src/ext/dom/examples/shipping.xml
<?xml version="1.0"?>
<shipOrder>
<shipTo>
<name>Tove Svendson</name>
<street>Ragnhildvei 2</street>
<address>4000 Stavanger</address>
<country>Norway</country>
</shipTo>
<items>
<item>
<title>Empire Burlesque</title>
<quantity>1</quantity>
<price>10.90</price>
</item>
<item>
<title>Hide your heart</title>
<quantity>1</quantity>
<price>9.90</price>
</item>
</items>
</shipOrder>
Index: php-src/ext/dom/examples/shipping.xsd
+++ php-src/ext/dom/examples/shipping.xsd
<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="shipOrder" type="order"/>
<xsd:complexType name="order">
<xsd:all>
<xsd:element name="shipTo" type="shipAddress"/>
<xsd:element name="items" type="cdItems"/>
</xsd:all>
</xsd:complexType>
<xsd:complexType name="shipAddress">
<xsd:all>
<xsd:element name="name" type="xsd:string"/>
<xsd:element name="street" type="xsd:string"/>
<xsd:element name="address" type="xsd:string"/>
<xsd:element name="country" type="xsd:string"/>
</xsd:all>
</xsd:complexType>
<xsd:complexType name="cdItems">
<xsd:sequence>
<xsd:element name="item" type="cdItem" maxOccurs="unbounded"
minOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="cdItem">
<xsd:all>
<xsd:element name="title" type="xsd:string"/>
<xsd:element name="quantity" type="xsd:positiveInteger"/>
<xsd:element name="price" type="xsd:decimal"/>
</xsd:all>
</xsd:complexType>
</xsd:schema>
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php