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

Reply via email to