diff options
Diffstat (limited to 'ext/domxml/php_domxml.c')
-rw-r--r-- | ext/domxml/php_domxml.c | 297 |
1 files changed, 267 insertions, 30 deletions
diff --git a/ext/domxml/php_domxml.c b/ext/domxml/php_domxml.c index 6b7b11d7c9..30bf0ef895 100644 --- a/ext/domxml/php_domxml.c +++ b/ext/domxml/php_domxml.c @@ -150,6 +150,7 @@ static int le_domxmlpip; static int le_domxmlcommentp; static int le_domxmlnotationp; static int le_domxmlparserp; + /*static int le_domxmlentityp;*/ static int le_domxmlentityrefp; /*static int le_domxmlnsp;*/ @@ -158,6 +159,10 @@ static int le_domxmlentityrefp; #if HAVE_DOMXSLT static int le_domxsltstylesheetp; #endif +static void domxml_error(void *ctx, const char *msg, ...); +static void domxml_error_ext(void *ctx, const char *msg, ...); +static void domxml_error_validate(void *ctx, const char *msg, ...); +static xmlDocPtr php_dom_xmlSAXParse(xmlSAXHandlerPtr sax, const char *buffer, int size, int recovery, void *data); #if defined(LIBXML_XPATH_ENABLED) static int le_xpathctxp; @@ -193,9 +198,9 @@ static int node_children(zval **children, xmlNode *nodep TSRMLS_DC); static zend_function_entry domxml_functions[] = { PHP_FE(domxml_version, NULL) - PHP_FE(xmldoc, NULL) + PHP_FE(xmldoc, third_arg_force_ref) PHP_FALIAS(domxml_open_mem, xmldoc, NULL) - PHP_FE(xmldocfile, NULL) + PHP_FE(xmldocfile, third_arg_force_ref) PHP_FALIAS(domxml_open_file, xmldocfile, NULL) #if defined(LIBXML_HTML_ENABLED) PHP_FE(html_doc, NULL) @@ -262,7 +267,7 @@ static zend_function_entry domxml_functions[] = { PHP_FALIAS(set_content, domxml_node_set_content, NULL) PHP_FALIAS(new_xmldoc, domxml_new_xmldoc, NULL) PHP_FALIAS(domxml_dumpmem, domxml_dump_mem, NULL) - + PHP_FE(domxml_doc_validate, second_arg_force_ref) {NULL, NULL, NULL} }; @@ -303,6 +308,8 @@ static function_entry php_domxmldoc_class_functions[] = { PHP_FALIAS(xpath_new_context, xpath_new_context, NULL) PHP_FALIAS(xptr_new_context, xptr_new_context, NULL) #endif + PHP_FALIAS(validate, domxml_doc_validate, first_arg_force_ref) + {NULL, NULL, NULL} }; @@ -498,8 +505,7 @@ static void dom_object_set_data(void *obj, zval *wrapper) static zval *dom_object_get_data(void *obj) { -/* - char tmp[20]; +/* char tmp[20]; sprintf(tmp, "%08X", obj); fprintf(stderr, "Trying getting %s from object ...", tmp); if(((xmlNodePtr) obj)->_private) @@ -1271,7 +1277,6 @@ PHPAPI zval *php_domobject_new(xmlNodePtr obj, int *found, zval *wrapper_in TSR return (wrapper); } - static void domxml_error(void *ctx, const char *msg, ...) { char buf[1024]; @@ -1282,6 +1287,145 @@ static void domxml_error(void *ctx, const char *msg, ...) php_error(E_WARNING, buf); } +static void domxml_error_ext(void *ctx, const char *msg, ...) +{ + xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; + xmlParserInputPtr input = NULL; + char buf[1024]; + va_list ap; + + va_start(ap, msg); + vsnprintf(buf, 1024, msg, ap); + va_end(ap); + + if (ctxt != NULL && ctxt->_private != NULL) { + zval *errormessages; + MAKE_STD_ZVAL(errormessages); + + if(array_init(errormessages) != SUCCESS) { + // do error handling here + } + add_assoc_string(errormessages,"errormessage",buf,1); + input = ctxt->input; + add_assoc_string(errormessages,"nodename",ctxt->name,1); + if (input != NULL) { + add_assoc_long(errormessages,"line",input->line); + add_assoc_long(errormessages,"col",input->col); + if (input->filename != NULL) { + add_assoc_string(errormessages,"directory",(char *) input->directory,1); + add_assoc_string(errormessages,"file",(char *) input->filename,1); + } + } + add_next_index_zval(ctxt->_private,errormessages); + } + php_error(E_WARNING, buf); + +} + +static void domxml_error_validate(void *ctx, const char *msg, ...) +{ + domxml_ErrorCtxt *ctxt ; + char buf[1024]; + + va_list ap; + + va_start(ap, msg); + vsnprintf(buf, 1024, msg, ap); + va_end(ap); + ctxt = (domxml_ErrorCtxt*) ctx; + + if (ctxt != NULL && ctxt->errors != NULL) { + zval *errormessages; + MAKE_STD_ZVAL(errormessages); + if(array_init(errormessages) != SUCCESS) { + // do error handling here + } + if (ctxt->parser != NULL) { + add_assoc_string(errormessages,"nodename",ctxt->parser->name,1); + + if (ctxt->parser->input != NULL) { + add_assoc_long(errormessages,"line",ctxt->parser->input->line); + add_assoc_long(errormessages,"col",ctxt->parser->input->col); + if (ctxt->parser->input->filename != NULL) { + add_assoc_string(errormessages,"directory",(char *) ctxt->parser->input->directory,1); + add_assoc_string(errormessages,"file",(char *) ctxt->parser->input->filename,1); + } + } + } + + if (ctxt->valid->node != NULL) + { +// php_error(E_WARNING,"nodename %s",(char *) ctxt->valid->name); + +// node = *ctxt->node; + } + add_assoc_string(errormessages,"errormessage",buf,1); + add_next_index_zval(ctxt->errors,errormessages); + } + + php_error(E_WARNING, buf); + +} + +xmlDocPtr php_dom_xmlSAXParse(xmlSAXHandlerPtr sax, const char *buffer, int size, int recovery, void *data) { + + xmlDocPtr ret; + xmlParserCtxtPtr ctxt; + domxml_ErrorCtxt errorCtxt; + char *directory = NULL; + + xmlInitParser(); + /*if size == -1, we assume, it's a filename not a inmemory xml doc*/ + if (size == -1) { + ctxt = (xmlParserCtxt *) xmlCreateFileParserCtxt( buffer); + } else { + ctxt = (xmlParserCtxt *) xmlCreateMemoryParserCtxt((xmlChar *) buffer, size); + } + if (ctxt == NULL) { + return(NULL); + } + if (sax != NULL) { + if (ctxt->sax != NULL) + xmlFree(ctxt->sax); + ctxt->sax = sax; + } + if (data!=NULL) { + ctxt->_private=data; + } + + /* store directory name */ + if (size == -1) { + if ((ctxt->directory == NULL) && (directory == NULL)) + directory = xmlParserGetDirectory(buffer); + if ((ctxt->directory == NULL) && (directory != NULL)) + ctxt->directory = (char *) xmlStrdup((xmlChar *) directory); + } + errorCtxt.valid = &ctxt->vctxt; + errorCtxt.errors = data; + errorCtxt.parser = ctxt; + + ctxt->sax->error = domxml_error_ext; + ctxt->sax->warning = domxml_error_ext; + ctxt->vctxt.userData= (void *) &errorCtxt; + ctxt->vctxt.error = (xmlValidityErrorFunc) domxml_error_validate; + ctxt->vctxt.warning = (xmlValidityWarningFunc) domxml_error_validate; + + xmlParseDocument(ctxt); + + if ((ctxt->wellFormed) || recovery) { + ret = ctxt->myDoc; + } else { + ret = NULL; + xmlFreeDoc(ctxt->myDoc); + ctxt->myDoc = NULL; + } + if (sax != NULL) + ctxt->sax = NULL; + + xmlFreeParserCtxt(ctxt); + + return(ret); +} PHP_RINIT_FUNCTION(domxml) { @@ -3383,25 +3527,29 @@ PHP_FUNCTION(domxml_doc_ids) } /* }}} */ -/* {{{ proto object xmldoc(string xmldoc[, int mode]) +/* {{{ proto object xmldoc(string xmldoc[, int mode[, array error]]) Creates DOM object of XML document */ PHP_FUNCTION(xmldoc) { zval *rv = NULL; xmlDoc *docp; - int ret; + int ret; char *buffer; int buffer_len; int mode = 0, prevSubstValue; int oldvalue = xmlDoValidityCheckingDefaultValue; -/* xmlDtdPtr dtd; */ + zval *errors ; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &buffer, &buffer_len, &mode) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz", &buffer, &buffer_len, &mode, &errors) == FAILURE) { return; } /* Either of the following line force validation */ /* xmlLoadExtDtdDefaultValue = XML_DETECT_IDS; */ /* xmlDoValidityCheckingDefaultValue = 1; */ + if (ZEND_NUM_ARGS() == 3 ) { + zval_dtor(errors); + array_init(errors); + } if(mode & DOMXML_LOAD_SUBSTITUTE_ENTITIES) prevSubstValue = xmlSubstituteEntitiesDefault (1); @@ -3414,15 +3562,27 @@ PHP_FUNCTION(xmldoc) switch (mode & (DOMXML_LOAD_PARSING | DOMXML_LOAD_VALIDATING | DOMXML_LOAD_RECOVERING)) { case DOMXML_LOAD_PARSING: xmlDoValidityCheckingDefaultValue = 0; - docp = xmlParseDoc(buffer); + if (ZEND_NUM_ARGS() == 3) { + docp = php_dom_xmlSAXParse( NULL, (char *) buffer, buffer_len, 0 , errors); + } else { + docp = xmlParseDoc(buffer); + } break; case DOMXML_LOAD_VALIDATING: xmlDoValidityCheckingDefaultValue = 1; - docp = xmlParseDoc(buffer); + if (ZEND_NUM_ARGS() == 3) { + docp = php_dom_xmlSAXParse(NULL, (char *) buffer, buffer_len, 0, errors); + } else { + docp = xmlParseDoc(buffer); + } break; case DOMXML_LOAD_RECOVERING: xmlDoValidityCheckingDefaultValue = 0; - docp = xmlRecoverDoc(buffer); + if (ZEND_NUM_ARGS() == 3) { + docp = php_dom_xmlSAXParse(NULL, (char *) buffer, buffer_len, 1, errors); + } else { + docp = xmlRecoverDoc(buffer); + } break; } xmlSubstituteEntitiesDefault (prevSubstValue); @@ -3445,7 +3605,7 @@ PHP_FUNCTION(xmldoc) } /* }}} */ -/* {{{ proto object xmldocfile(string filename) +/* {{{ proto object xmldocfile(string filename[, int mode[, array error]) Creates DOM object of XML document in file */ PHP_FUNCTION(xmldocfile) { @@ -3453,31 +3613,67 @@ PHP_FUNCTION(xmldocfile) xmlDoc *docp; int ret, file_len; char *file; + int mode = 0, prevSubstValue; + int oldvalue = xmlDoValidityCheckingDefaultValue; + zval *errors = NULL; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &file, &file_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz", &file, &file_len, &mode, &errors) == FAILURE) { return; } + + if (ZEND_NUM_ARGS() == 3 ) { + zval_dtor(errors); + array_init(errors); + } + + if(mode & DOMXML_LOAD_SUBSTITUTE_ENTITIES) + prevSubstValue = xmlSubstituteEntitiesDefault (1); + else + prevSubstValue = xmlSubstituteEntitiesDefault (0); + + if(mode & DOMXML_LOAD_COMPLETE_ATTRS) + xmlLoadExtDtdDefaultValue |= XML_COMPLETE_ATTRS; + + switch (mode & (DOMXML_LOAD_PARSING | DOMXML_LOAD_VALIDATING | DOMXML_LOAD_RECOVERING)) { + case DOMXML_LOAD_PARSING: + xmlDoValidityCheckingDefaultValue = 0; + if (ZEND_NUM_ARGS() == 3) { + docp = php_dom_xmlSAXParse( NULL, (char *) file, -1 , 0 , errors); + } else { + docp = xmlParseFile(file); + } + break; + case DOMXML_LOAD_VALIDATING: + xmlDoValidityCheckingDefaultValue = 1; + if (ZEND_NUM_ARGS() == 3) { + docp = php_dom_xmlSAXParse(NULL, (char *) file, -1, 0, errors); + } else { + docp = xmlParseFile(file); + } + break; + case DOMXML_LOAD_RECOVERING: + xmlDoValidityCheckingDefaultValue = 0; + if (ZEND_NUM_ARGS() == 3) { + docp = php_dom_xmlSAXParse(NULL, (char*) file, -1, 1, errors); + } else { + docp = xmlRecoverFile(file); + } + break; + } + xmlSubstituteEntitiesDefault (prevSubstValue); + xmlDoValidityCheckingDefaultValue = oldvalue; - docp = xmlParseFile(file); if (!docp) { RETURN_FALSE; } - DOMXML_RET_OBJ(rv, (xmlNodePtr) docp, &ret); -/* add_property_resource(return_value, "doc", ret); - if (docp->name) - add_property_stringl(return_value, "name", (char *) docp->name, strlen(docp->name), 1); - if (docp->URL) - add_property_stringl(return_value, "url", (char *) docp->URL, strlen(docp->URL), 1); - add_property_stringl(return_value, "version", (char *) docp->version, strlen(docp->version), 1); - if (docp->encoding) - add_property_stringl(return_value, "encoding", (char *) docp->encoding, strlen(docp->encoding), 1); - add_property_long(return_value, "standalone", docp->standalone); - add_property_long(return_value, "type", Z_TYPE_P(docp)); - add_property_long(return_value, "compression", docp->compression); - add_property_long(return_value, "charset", docp->charset); - zend_list_addref(ret);*/ + if(DOMXML_IS_TYPE(getThis(), domxmldoc_class_entry)) { + DOMXML_DOMOBJ_NEW(getThis(), (xmlNodePtr) docp, &ret); + } else { + DOMXML_RET_OBJ(rv, (xmlNodePtr) docp, &ret); + } + } /* }}} */ @@ -3650,6 +3846,47 @@ PHP_FUNCTION(domxml_doc_set_root) } /* }}} */ +/* {{{ proto bool domxml_doc_validate(array &error) + Validates a DomDocument according to his DTD*/ +PHP_FUNCTION(domxml_doc_validate) +{ + zval *id; + xmlValidCtxt cvp; + xmlDoc *docp; + domxml_ErrorCtxt errorCtxt; + zval *errors ; + int oldvalue = xmlDoValidityCheckingDefaultValue; + + DOMXML_PARAM_ONE(docp, id, le_domxmldocp,"|z",&errors); + errorCtxt.valid = &cvp; + + if (ZEND_NUM_ARGS() == 1) { + zval_dtor(errors); + array_init(errors); + errorCtxt.errors = errors; + } else { + errorCtxt.errors = NULL; + } + + errorCtxt.parser = NULL; + xmlDoValidityCheckingDefaultValue = 1; + cvp.userData = (void *) &errorCtxt; + cvp.error = (xmlValidityErrorFunc) domxml_error_validate; + cvp.warning = (xmlValidityWarningFunc) domxml_error_validate; + if (docp->intSubset == NULL) { + php_error(E_NOTICE, "%s(): No DTD given in XML-Document", get_active_function_name(TSRMLS_C)); + } + + if (xmlValidateDocument(&cvp, docp)) { + RETVAL_TRUE; + } else { + RETVAL_FALSE; + } + xmlDoValidityCheckingDefaultValue = oldvalue; + +} +/* }}} */ + /* {{{ proto object domxml_new_xmldoc(string version) Creates new xmldoc */ PHP_FUNCTION(domxml_new_xmldoc) |