/* Taken from libxml2, xmlSAXParseMemoryWithData */ xmlDocPtr mxslt_doc_xml_load_entity(mxslt_doc_t * document, char * localfile) { xmlParserCtxtPtr ctx; xmlParserInputPtr input; xmlDocPtr retval; xmlChar * filename; mxslt_doc_debug_print(document, MXSLT_DBG_LIBXML | MXSLT_DBG_DEBUG | MXSLT_DBG_VERBOSE0, "load_entity/xmlCreateMemoryParserCtxt -- replacing entities: %08x\n", xmlSubstituteEntitiesDefaultValue); /* SNIPPET: This is a good mix&shake of * xmlCreateMemoryParserCtxt, xmlCreateFileParserCtxt */ ctx=xmlNewParserCtxt(); if(ctx == NULL) return NULL; #if LIBXML_VERSION >= 20600 xmlCtxtUseOptions(ctx, MXSLT_XSLT_OPTIONS); #endif /* Remember which document we are parsing * in this context */ /* ctx->_private=document; */ filename=xmlCanonicPath((xmlChar *)localfile); if(filename == NULL) { xmlFreeParserCtxt(ctx); return NULL; } input=xmlLoadExternalEntity((char *)filename, NULL, ctx); xmlFree(filename); if(input == NULL) { xmlFreeParserCtxt(ctx); return NULL; } inputPush(ctx, input); if(ctx->directory == NULL) ctx->directory=xmlParserGetDirectory(localfile); /* END SNIPPET */ /* MXSLT_DUMP_CTX(ctx); */ /* Parse document */ xmlParseDocument(ctx); if(ctx->wellFormed) retval=ctx->myDoc; else { retval=NULL; xmlFreeDoc(ctx->myDoc); ctx->myDoc=NULL; } xmlFreeParserCtxt(ctx); return retval; }
bool HHVM_METHOD(XMLReader, XML, const String& source, const Variant& encoding /*= null_variant*/, int64_t options /*= 0*/) { auto* data = Native::data<XMLReader>(this_); const String& str_encoding = encoding.isNull() ? null_string : encoding.toString(); xmlParserInputBufferPtr inputbfr = xmlParserInputBufferCreateMem( source.c_str(), source.size(), XML_CHAR_ENCODING_NONE); if (inputbfr != nullptr) { char *uri = nullptr; String directory = g_context->getCwd(); if (!directory.empty()) { if (directory[directory.size() - 1] != '/') { directory += "/"; } uri = (char *) xmlCanonicPath((const xmlChar *) directory.c_str()); } xmlTextReaderPtr reader = xmlNewTextReader(inputbfr, uri); if (reader != nullptr) { int ret = 0; #if LIBXML_VERSION >= 20628 ret = xmlTextReaderSetup(reader, nullptr, uri, str_encoding.data(), options); #endif if (ret == 0) { data->m_ptr = reader; data->m_input = inputbfr; if (uri) { xmlFree(uri); } return true; } } if (uri) { xmlFree(uri); } } if (inputbfr) { xmlFreeParserInputBuffer(inputbfr); } raise_warning("Unable to load source data"); return false; }
bool c_XMLReader::t_xml(const String& source, const String& encoding /*= null_string*/, int64_t options /*= 0*/) { xmlParserInputBufferPtr inputbfr = xmlParserInputBufferCreateMem(source.c_str(), source.size(), XML_CHAR_ENCODING_NONE); if (inputbfr != NULL) { char *uri = NULL; String directory = g_context->getCwd(); if (!directory.empty()) { if (directory[directory.size() - 1] != '/') { directory += "/"; } uri = (char *) xmlCanonicPath((const xmlChar *) directory.c_str()); } xmlTextReaderPtr reader = xmlNewTextReader(inputbfr, uri); if (reader != NULL) { int ret = 0; #if LIBXML_VERSION >= 20628 ret = xmlTextReaderSetup(reader, NULL, uri, encoding.data(), options); #endif if (ret == 0) { m_ptr = reader; m_input = inputbfr; if (uri) { xmlFree(uri); } return true; } } if (uri) { xmlFree(uri); } } if (inputbfr) { xmlFreeParserInputBuffer(inputbfr); } raise_warning("Unable to load source data"); return false; }
bool c_XMLReader::t_xml(CStrRef source, CStrRef encoding /*= null_string*/, int64 options /*= 0*/) { INSTANCE_METHOD_INJECTION_BUILTIN(XMLReader, XMLReader::xml); xmlParserInputBufferPtr inputbfr = xmlParserInputBufferCreateMem(source.c_str(), source.size(), XML_CHAR_ENCODING_NONE); if (inputbfr != NULL) { char *uri = NULL; String directory = g_context->getCwd(); if (!directory.empty()) { if (directory[directory.size() - 1] != '/') { directory += '/'; } uri = (char *) xmlCanonicPath((const xmlChar *) directory.c_str()); } xmlTextReaderPtr reader = xmlNewTextReader(inputbfr, uri); if (reader != NULL) { int ret = xmlTextReaderSetup(reader, NULL, uri, encoding.data(), options); if (ret == 0) { m_ptr = reader; m_input = inputbfr; if (uri) { xmlFree(uri); } return true; } } if (uri) { xmlFree(uri); } } if (inputbfr) { xmlFreeParserInputBuffer(inputbfr); } raise_warning("Unable to load source data"); return false; }
/* {{{ proto boolean XMLReader::XML(string source [, string encoding [, int options]]) Sets the string that the XMLReader will parse. */ PHP_METHOD(xmlreader, XML) { zval *id; size_t source_len = 0, encoding_len = 0; zend_long options = 0; xmlreader_object *intern = NULL; char *source, *uri = NULL, *encoding = NULL; int resolved_path_len, ret = 0; char *directory=NULL, resolved_path[MAXPATHLEN]; xmlParserInputBufferPtr inputbfr; xmlTextReaderPtr reader; if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|s!l", &source, &source_len, &encoding, &encoding_len, &options) == FAILURE) { return; } id = getThis(); if (id != NULL && ! instanceof_function(Z_OBJCE_P(id), xmlreader_class_entry)) { id = NULL; } if (id != NULL) { intern = Z_XMLREADER_P(id); xmlreader_free_resources(intern); } if (!source_len) { php_error_docref(NULL, E_WARNING, "Empty string supplied as input"); RETURN_FALSE; } inputbfr = xmlParserInputBufferCreateMem(source, source_len, XML_CHAR_ENCODING_NONE); if (inputbfr != NULL) { /* Get the URI of the current script so that we can set the base directory in libxml */ #if HAVE_GETCWD directory = VCWD_GETCWD(resolved_path, MAXPATHLEN); #elif HAVE_GETWD directory = VCWD_GETWD(resolved_path); #endif if (directory) { resolved_path_len = strlen(resolved_path); if (resolved_path[resolved_path_len - 1] != DEFAULT_SLASH) { resolved_path[resolved_path_len] = DEFAULT_SLASH; resolved_path[++resolved_path_len] = '\0'; } uri = (char *) xmlCanonicPath((const xmlChar *) resolved_path); } reader = xmlNewTextReader(inputbfr, uri); if (reader != NULL) { #if LIBXML_VERSION >= 20628 ret = xmlTextReaderSetup(reader, NULL, uri, encoding, options); #endif if (ret == 0) { if (id == NULL) { object_init_ex(return_value, xmlreader_class_entry); intern = Z_XMLREADER_P(return_value); } else { RETVAL_TRUE; } intern->input = inputbfr; intern->ptr = reader; if (uri) { xmlFree(uri); } return; } } } if (uri) { xmlFree(uri); } if (inputbfr) { xmlFreeParserInputBuffer(inputbfr); } php_error_docref(NULL, E_WARNING, "Unable to load source data"); RETURN_FALSE; }
/* Taken from libxml2, xmlSAXParseMemoryWithData */ xmlDocPtr mxslt_doc_xml_parse(mxslt_doc_t * document, xmlParserInputBufferPtr buf, char * localfile) { xmlParserCtxtPtr ctx; xmlParserInputPtr input; xmlDocPtr retval; mxslt_doc_debug_print(document, MXSLT_DBG_LIBXML | MXSLT_DBG_DEBUG | MXSLT_DBG_VERBOSE0, "xml_parse/xmlCreateMemoryParserCtxt -- replacing entities: %08x\n", xmlSubstituteEntitiesDefaultValue); if(buf == NULL) return NULL; /* SNIPPET: This is a good mix&shake of * xmlCreateMemoryParserCtxt, xmlCreateFileParserCtxt */ ctx=xmlNewParserCtxt(); if(ctx == NULL) { xmlFreeParserInputBuffer(buf); return NULL; } #if LIBXML_VERSION >= 20600 xmlCtxtUseOptions(ctx, MXSLT_XSLT_OPTIONS); #endif /* Default are no longer changed... since 2.6.0 they * are completely ignored, leading to broken modxslt :|| */ if(ctx->sax) { ctx->sax->resolveEntity=mxslt_sax_resolve_entity; ctx->sax->processingInstruction=mxslt_sax_processing_instruction; } /* Remember which document we are parsing * in this context */ /* ctx->_private=document; */ input=xmlNewInputStream(ctx); if(input == NULL) { xmlFreeParserInputBuffer(buf); xmlFreeParserCtxt(ctx); return NULL; } input->filename=(char *)xmlCanonicPath((xmlChar *)localfile); if(input->filename == NULL) { xmlFreeParserCtxt(ctx); xmlFreeParserInputBuffer(buf); xmlFreeInputStream(input); return NULL; } input->buf=buf; #if LIBXML_VERSION < 20900 input->base=input->buf->buffer->content; input->cur=input->buf->buffer->content; input->end=&input->buf->buffer->content[input->buf->buffer->use]; #else /* With libxml2 2.9.0, the buffer struct can only be accessed through * methods. */ input->base=xmlBufContent(input->buf->buffer); input->cur=xmlBufContent(input->buf->buffer); input->end=xmlBufEnd(input->buf->buffer); #endif inputPush(ctx, input); if(ctx->directory == NULL) ctx->directory=xmlParserGetDirectory(localfile); /* END SNIPPET */ if(mxslt_doc_debug_level(document, MXSLT_DBG_LIBXML | MXSLT_DBG_DEBUG | MXSLT_DBG_VERBOSE2)) mxslt_doc_dump_ctx(ctx, document); /* Parse document */ xmlParseDocument(ctx); if(ctx->wellFormed) retval=ctx->myDoc; else { retval=NULL; xmlFreeDoc(ctx->myDoc); ctx->myDoc=NULL; } xmlFreeParserCtxt(ctx); /* xmlFreeParserInputBuffer(buf); */ return retval; }
/* This function replaces processingInstruction */ void mxslt_sax_processing_instruction(void * ctx, const xmlChar * target, const xmlChar * data) { xmlParserCtxtPtr ctxt=(xmlParserCtxtPtr)ctx; mxslt_doc_t * document=(mxslt_get_state()->document); mxslt_pi_style_t * style_pi; mxslt_pi_param_t * param_pi; mxslt_pi_base_t * base_pi; char * type = NULL, * tmp; xmlNodePtr pi; int status; /* WARNING: don't change this array! Look below! */ static const mxslt_attr_search_t xml_stylesheet[] = { { (xmlChar *)"href", mxslt_sizeof_str("href") }, { (xmlChar *)"media", mxslt_sizeof_str("media") }, { (xmlChar *)"type", mxslt_sizeof_str("type") } }; /* WARNING: don't change this array! Look below! */ static const mxslt_attr_search_t mxslt_param[] = { { (xmlChar *)"name", mxslt_sizeof_str("name") }, { (xmlChar *)"value", mxslt_sizeof_str("value") } }; /* WARNING: don't change this array! Look below! */ static const mxslt_attr_search_t mxslt_base[] = { { (xmlChar *)"value", mxslt_sizeof_str("value") } }; /* This array _must_ have the same number of elements * as the array xml_stylesheet */ char * xml_stylesheet_values[] = { NULL, NULL, NULL }; enum xml_stylesheet_types { t_href=0, t_media, t_type }; /* This array _must_ have the same number of elements * as the array mxslt_param */ char * mxslt_param_values[] = { NULL, NULL }; enum mxslt_param_types { t_name=0, t_select }; /* This array _must_ have the same number of elements * as the array mxslt_base */ char * mxslt_base_values[] = { NULL }; enum mxslt_base_types { t_value=0 }; mxslt_doc_debug_print(document, MXSLT_DBG_LIBXML, "processing instruction \"%s\", attributes |%s|\n", target, data); /* Ignore pi when we're parsing the stylesheet */ if(document->flags & MXSLT_STYLE) return; /* Create a new pi node */ pi=xmlNewPI(target, data); if(!pi) return; /* Check if target is a known pi */ switch(target[0]) { case 'x': if(!xmlStrEqual(target+1, (xmlChar *)"xml-stylesheet"+1)) break; /* Get href, type and media from attribute list */ status=mxslt_get_static_attr((char *)data, xml_stylesheet, xml_stylesheet_values, mxslt_sizeof_array(xml_stylesheet)); if(status != MXSLT_OK) { if(xml_stylesheet_values[0]) xfree(xml_stylesheet_values[0]); if(xml_stylesheet_values[1]) xfree(xml_stylesheet_values[1]); if(xml_stylesheet_values[2]) xfree(xml_stylesheet_values[2]); goto error; } if(xml_stylesheet_values[t_type] && xml_stylesheet_values[t_href]) { /* Decode type */ type=(char *)xmlStringDecodeEntities(ctxt, (xmlChar *)xml_stylesheet_values[t_type], XML_SUBSTITUTE_REF|XML_SUBSTITUTE_PEREF, 0, 0, 0); /* Skip blanks before type */ for(tmp=type; MXSLT_IS_BLANK(*tmp); tmp++) ; /* compare type string */ if(!strncmp(tmp, "text/xml", mxslt_sizeof_str("text/xml")) || !strncmp(tmp, "text/xsl", mxslt_sizeof_str("text/xsl"))) { /* trailing spaces are allowed */ for(tmp+=mxslt_sizeof_str("text/x?l"); MXSLT_IS_BLANK(*tmp); tmp++) ; /* Check there's nothing else beside them */ if(*tmp != '\0') { xmlFree(type); break; } /* Type is ok, add parameter to processing * instruction */ style_pi=(mxslt_pi_style_t *)xmalloc(sizeof(mxslt_pi_style_t)); style_pi->type=MXSLT_PI_STDST; style_pi->ctype=type; style_pi->href=(char *)xmlStringDecodeEntities(ctxt, (xmlChar *)xml_stylesheet_values[t_href], XML_SUBSTITUTE_REF|XML_SUBSTITUTE_PEREF, 0, 0, 0); if(xml_stylesheet_values[t_media]) style_pi->media=(char *)xmlStringDecodeEntities(ctxt, (xmlChar *)xml_stylesheet_values[t_media], XML_SUBSTITUTE_REF|XML_SUBSTITUTE_PEREF, 0, 0, 0); else style_pi->media=NULL; /* tie up xmlNode and style_pi */ XML_LINK_PI(document, pi, style_pi); } else { mxslt_error(document, "warning - <xml-stylesheet type=\"... unknown: '%s'!\n", type); xmlFree(type); } } else { if(!xml_stylesheet_values[t_href]) mxslt_error(document, "warning - <xml-stylesheet href=\"... is missing, skipping PI!\n"); if(!xml_stylesheet_values[t_type]) mxslt_error(document, "warning - <xml-stylesheet type=\"... is missing, skipping PI!\n"); } if(xml_stylesheet_values[t_media]) xfree(xml_stylesheet_values[t_media]); if(xml_stylesheet_values[t_href]) xfree(xml_stylesheet_values[t_href]); if(xml_stylesheet_values[t_type]) xfree(xml_stylesheet_values[t_type]); break; case 'm': if(target[1] != 'o' || target[2] != 'd' || target[3] != 'x' || target[4] != 's' || target[5] != 'l' || target[6] != 't' || target[7] != '-') break; switch(target[8]) { case 'b': if(!xmlStrEqual(target+8, (xmlChar *)"modxslt-base"+8)) { mxslt_error(document, "warning - unknown modxslt PI: %s in %s\n", target, document->localfile); break; } /* Read modxslt-base */ status=mxslt_get_static_attr((char *)data, mxslt_base, mxslt_base_values, mxslt_sizeof_array(mxslt_base)); if(status != MXSLT_OK) { if(mxslt_base_values[0]) xfree(mxslt_base_values[0]); goto error; } /* Verify we got the base */ if(!mxslt_base_values[0]) { mxslt_error(document, "warning - <modxslt-base ... base=\" is missing, skipping PI\n", target, document->localfile); break; } /* Remember the pi we found */ base_pi=(mxslt_pi_base_t *)(xmalloc(sizeof(mxslt_pi_base_t))); base_pi->type=MXSLT_PI_UBASE; base_pi->file=(char *)xmlCanonicPath((xmlChar *)mxslt_base_values[0]); base_pi->directory=xmlParserGetDirectory(mxslt_base_values[0]); xfree(mxslt_base_values[0]); /* Switch base in the current context */ if(ctxt->input->filename) xmlFree((char *)ctxt->input->filename); if(ctxt->directory) xmlFree(ctxt->directory); /* Remember those information */ ctxt->input->filename=(char *)xmlStrdup((xmlChar *)base_pi->file); ctxt->directory=(char *)xmlStrdup((xmlChar *)base_pi->directory); /* tie up xmlNode and style_pi */ XML_LINK_PI(document, pi, base_pi); break; case 'p': if(!xmlStrEqual(target+8, (xmlChar *)"modxslt-param"+8)) { mxslt_error(document, "warning - unknown modxslt PI: %s in %s\n", target, document->localfile); break; } status=mxslt_get_static_attr((char *)data, mxslt_param, mxslt_param_values, mxslt_sizeof_array(mxslt_param)); if(status != MXSLT_OK) { if(mxslt_param_values[0]) xfree(mxslt_param_values[0]); if(mxslt_param_values[1]) xfree(mxslt_param_values[1]); goto error; } if(mxslt_param_values[t_name]) { /* Allocate and create pi */ param_pi=(mxslt_pi_param_t *)xmalloc(sizeof(mxslt_pi_param_t)); param_pi->type=MXSLT_PI_PARAM; param_pi->param=(char *)xmlStringDecodeEntities(ctxt, (xmlChar *)mxslt_param_values[t_name], XML_SUBSTITUTE_REF|XML_SUBSTITUTE_PEREF, 0, 0, 0); param_pi->value=(char *)xmlStringDecodeEntities(ctxt, (xmlChar *)mxslt_param_values[t_select], XML_SUBSTITUTE_REF|XML_SUBSTITUTE_PEREF, 0, 0, 0); /* Link pi to list of pis */ XML_LINK_PI(document, pi, param_pi); } else { mxslt_error(document, "warning - modxslt-param specified without ``name'' attribute in `%s'\n", document->localfile); } /* Free memory up */ if(mxslt_param_values[t_select]) xfree(mxslt_param_values[t_select]); if(mxslt_param_values[t_name]) xfree(mxslt_param_values[t_name]); break; case 's': if(!xmlStrEqual(target+8, (xmlChar *)"modxslt-stylesheet"+8)) { mxslt_error(document, "warning - unknown modxslt PI: %s in %s\n", target, document->localfile); break; } status=mxslt_get_static_attr((char *)data, xml_stylesheet, xml_stylesheet_values, mxslt_sizeof_array(xml_stylesheet)); if(status != MXSLT_OK) { if(xml_stylesheet_values[0]) xfree(xml_stylesheet_values[0]); if(xml_stylesheet_values[1]) xfree(xml_stylesheet_values[1]); if(xml_stylesheet_values[2]) xfree(xml_stylesheet_values[2]); goto error; } if(xml_stylesheet_values[t_type]) { /* Decode type */ type=(char *)xmlStringDecodeEntities(ctxt, (xmlChar *)xml_stylesheet_values[t_type], XML_SUBSTITUTE_REF|XML_SUBSTITUTE_PEREF, 0, 0, 0); /* Skip blanks before type */ for(tmp=type; MXSLT_IS_BLANK(*tmp); tmp++) ; /* compare type string */ if(!strncmp(tmp, "text/xml", mxslt_sizeof_str("text/xml")) || !strncmp(tmp, "text/xsl", mxslt_sizeof_str("text/xsl"))) { /* trailing spaces are allowed */ for(tmp+=mxslt_sizeof_str("text/x?l"); MXSLT_IS_BLANK(*tmp); tmp++) ; /* Check there's nothing else beside them */ if(*tmp != '\0') { mxslt_error(document, "warning - <modxslt-stylesheet type=\"... trailing junk: '%s'!\n", type); xmlFree(type); break; } /* Type is ok, add parameter to processing * instruction */ style_pi=(mxslt_pi_style_t *)xmalloc(sizeof(mxslt_pi_style_t)); style_pi->type=MXSLT_PI_MODST; style_pi->ctype=type; if(xml_stylesheet_values[t_href]) style_pi->href=(char *)xmlStringDecodeEntities(ctxt, (xmlChar *)xml_stylesheet_values[t_href], XML_SUBSTITUTE_REF|XML_SUBSTITUTE_PEREF, 0, 0, 0); else style_pi->href=NULL; if(xml_stylesheet_values[t_media]) style_pi->media=(char *)xmlStringDecodeEntities(ctxt, (xmlChar *)xml_stylesheet_values[t_media], XML_SUBSTITUTE_REF|XML_SUBSTITUTE_PEREF, 0, 0, 0); else style_pi->media=NULL; /* Link to nodes chain */ XML_LINK_PI(document, pi, style_pi); } else { mxslt_error(document, "warning - <modxslt-stylesheet type=\"... unknown: '%s'!\n", type); xmlFree(type); } } if(xml_stylesheet_values[t_media]) xfree(xml_stylesheet_values[t_media]); if(xml_stylesheet_values[t_href]) xfree(xml_stylesheet_values[t_href]); if(xml_stylesheet_values[t_type]) xfree(xml_stylesheet_values[t_type]); break; default: mxslt_error(document, "warning - unknown modxslt PI: %s in %s\n", target, document->localfile); break; } break; } /* Taken from `processingInstruction' */ switch(ctxt->inSubset) { case 1: xmlAddChild((xmlNodePtr)ctxt->myDoc->intSubset, pi); return; case 2: xmlAddChild((xmlNodePtr)ctxt->myDoc->extSubset, pi); return; } if(!ctxt->myDoc->children || !ctxt->node) { xmlAddChild((xmlNodePtr)ctxt->myDoc, pi); return; } if(ctxt->node->type == XML_ELEMENT_NODE) xmlAddChild(ctxt->node, pi); else xmlAddSibling(ctxt->node, pi); return; error: mxslt_error(document, "warning - weird data while processing PI: %s in %s\n", target, document->localfile); xmlFreeNode(pi); return; }