xmlDocPtr XSLStyleSheet::locateStylesheetSubResource(xmlDocPtr parentDoc, const xmlChar* uri) { bool matchedParent = (parentDoc == document()); for (unsigned i = 0; i < m_children.size(); ++i) { XSLImportRule* import = m_children.at(i).get(); XSLStyleSheet* child = import->styleSheet(); if (!child) continue; if (matchedParent) { if (child->processed()) continue; // libxslt has been given this sheet already. // Check the URI of the child stylesheet against the doc URI. // In order to ensure that libxml canonicalized both URLs, we get the original href // string from the import rule and canonicalize it using libxml before comparing it // with the URI argument. CString importHref = import->href().utf8(); xmlChar* base = xmlNodeGetBase(parentDoc, (xmlNodePtr)parentDoc); xmlChar* childURI = xmlBuildURI((const xmlChar*)importHref.data(), base); bool equalURIs = xmlStrEqual(uri, childURI); xmlFree(base); xmlFree(childURI); if (equalURIs) { child->markAsProcessed(); return child->document(); } continue; } xmlDocPtr result = import->styleSheet()->locateStylesheetSubResource(parentDoc, uri); if (result) return result; } return 0; }
/** * xmlSchematronLoadInclude: * @ctxt: a schema validation context * @cur: the include element * * Load the include document, Push the current pointer * * Returns the updated node pointer */ static xmlNodePtr xmlSchematronLoadInclude(xmlSchematronParserCtxtPtr ctxt, xmlNodePtr cur) { xmlNodePtr ret = NULL; xmlDocPtr doc = NULL; xmlChar *href = NULL; xmlChar *base = NULL; xmlChar *URI = NULL; if ((ctxt == NULL) || (cur == NULL)) return(NULL); href = xmlGetNoNsProp(cur, BAD_CAST "href"); if (href == NULL) { xmlSchematronPErr(ctxt, cur, XML_SCHEMAP_NOROOT, "Include has no href attribute", NULL, NULL); return(cur->next); } /* do the URI base composition, load and find the root */ base = xmlNodeGetBase(cur->doc, cur); URI = xmlBuildURI(href, base); doc = xmlReadFile((const char *) URI, NULL, SCHEMATRON_PARSE_OPTIONS); if (doc == NULL) { xmlSchematronPErr(ctxt, cur, XML_SCHEMAP_FAILED_LOAD, "could not load include '%s'.\n", URI, NULL); goto done; } ret = xmlDocGetRootElement(doc); if (ret == NULL) { xmlSchematronPErr(ctxt, cur, XML_SCHEMAP_FAILED_LOAD, "could not find root from include '%s'.\n", URI, NULL); goto done; } /* Success, push the include for rollback on exit */ xmlSchematronPushInclude(ctxt, doc, cur); done: if (ret == NULL) { if (doc != NULL) xmlFreeDoc(doc); } if (href == NULL) xmlFree(href); if (base == NULL) xmlFree(base); if (URI == NULL) xmlFree(URI); return(ret); }
std::string utils::absolute_url(const std::string& url, const std::string& link) { xmlChar * newurl = xmlBuildURI((const xmlChar *)link.c_str(), (const xmlChar *)url.c_str()); std::string retval; if (newurl) { retval = (const char *)newurl; xmlFree(newurl); } else { retval = link; } return retval; }
static void handleURI(const char *str) { int ret; xmlURIPtr uri; xmlChar *res = NULL, *parsed = NULL; uri = xmlCreateURI(); if (base == NULL) { ret = xmlParseURIReference(uri, str); if (ret != 0) printf("%s : error %d\n", str, ret); else { if (debug) { if (uri->scheme) printf("scheme: %s\n", uri->scheme); if (uri->opaque) printf("opaque: %s\n", uri->opaque); if (uri->authority) printf("authority: %s\n", uri->authority); if (uri->server) printf("server: %s\n", uri->server); if (uri->user) printf("user: %s\n", uri->user); if (uri->port != 0) printf("port: %d\n", uri->port); if (uri->path) printf("path: %s\n", uri->path); if (uri->query) printf("query: %s\n", uri->query); if (uri->fragment) printf("fragment: %s\n", uri->fragment); if (uri->query_raw) printf("query_raw: %s\n", uri->query_raw); if (uri->cleanup != 0) printf("cleanup\n"); } xmlNormalizeURIPath(uri->path); if (escape != 0) { parsed = xmlSaveUri(uri); res = xmlURIEscape(parsed); printf("%s\n", (char *) res); } else { xmlPrintURI(stdout, uri); printf("\n"); } } } else { res = xmlBuildURI((xmlChar *)str, (xmlChar *) base); if (res != NULL) { printf("%s\n", (char *) res); } else printf("::ERROR::\n"); } if (res != NULL) xmlFree(res); if (parsed != NULL) xmlFree(parsed); xmlFreeURI(uri); }
/** * fo_image_new_from_uri: * @uri: URI of image. * @base: Base URI for resolving relative URI @uri values. * * Creates a new #FoImage from the resource at @uri. * * If @uri is a relative URI, it is resolved relative to @base. * * Return value: the newly created #FoImage or #NULL. **/ FoImage * fo_image_new_from_uri (const gchar *uri, const gchar *base) { FoImage *fo_image; gchar *resolved_uri; fo_image = FO_IMAGE (g_object_new (fo_image_get_type (), NULL)); resolved_uri = (gchar *) xmlBuildURI ((const xmlChar *) uri, (const xmlChar *) base); fo_image_set_uri (fo_image, resolved_uri); xmlFree ((xmlChar *) resolved_uri); return fo_image_get_pixbuf (fo_image) != NULL ? fo_image : NULL; }
/* HREF finder implemented in libxml2 but could be any HTML parser */ size_t follow_links(CURLM *multi_handle, memory *mem, char *url) { int opts = HTML_PARSE_NOBLANKS | HTML_PARSE_NOERROR | \ HTML_PARSE_NOWARNING | HTML_PARSE_NONET; htmlDocPtr doc = htmlReadMemory(mem->buf, mem->size, url, NULL, opts); if(!doc) return 0; xmlChar *xpath = (xmlChar*) "//a/@href"; xmlXPathContextPtr context = xmlXPathNewContext(doc); xmlXPathObjectPtr result = xmlXPathEvalExpression(xpath, context); xmlXPathFreeContext(context); if(!result) return 0; xmlNodeSetPtr nodeset = result->nodesetval; if(xmlXPathNodeSetIsEmpty(nodeset)) { xmlXPathFreeObject(result); return 0; } size_t count = 0; for(int i = 0; i < nodeset->nodeNr; i++) { double r = rand(); int x = r * nodeset->nodeNr / RAND_MAX; const xmlNode *node = nodeset->nodeTab[x]->xmlChildrenNode; xmlChar *href = xmlNodeListGetString(doc, node, 1); if(follow_relative_links) { xmlChar *orig = href; href = xmlBuildURI(href, (xmlChar *) url); xmlFree(orig); } char *link = (char *) href; if(!link || strlen(link) < 20) continue; if(!strncmp(link, "http://", 7) || !strncmp(link, "https://", 8)) { curl_multi_add_handle(multi_handle, make_handle(link)); if(count++ == max_link_per_page) break; } xmlFree(link); } xmlXPathFreeObject(result); return count; }
/* This function replaces resolveEntity * Is this still needed? */ xmlParserInputPtr mxslt_sax_resolve_entity(void * ctx, const xmlChar * publicId, const xmlChar * systemId) { xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx; mxslt_doc_t * document=(mxslt_get_state()->document); xmlParserInputPtr ret; xmlChar *URI; const char *base = NULL; char * id; /* If standalone, do not read any * external DTD */ if(ctxt->standalone == 1) return NULL; if(ctxt->input) base=ctxt->input->filename; if(!base) base=ctxt->directory; /* In resolve entity */ id=mxslt_yy_str_parse(document, (char *)systemId, strlen((char *)systemId)); mxslt_doc_debug_print(document, MXSLT_DBG_LIBXML, "%s needs entity publicId: %s, systemId: %s\n", base, mxslt_debug_string(publicId), mxslt_debug_string(systemId)); mxslt_doc_debug_print(document, MXSLT_DBG_LIBXML | MXSLT_DBG_DEBUG, "base: %s, filename: %s, directory: %s\n", base, mxslt_debug_string(ctxt->input->filename), mxslt_debug_string(ctxt->directory)); if(mxslt_doc_debug_level(document, MXSLT_DBG_LIBXML | MXSLT_DBG_DEBUG | MXSLT_DBG_VERBOSE1)) mxslt_doc_dump_ctx(ctxt, document); URI=xmlBuildURI((xmlChar *)id, (const xmlChar *)base); mxslt_doc_debug_print(document, MXSLT_DBG_LIBXML | MXSLT_DBG_VERBOSE0, "loading entity: %s, publicid: %s\n", mxslt_debug_string(URI), mxslt_debug_string(publicId)); ret = xmlLoadExternalEntity((const char *) URI, (const char *) publicId, ctxt); if(URI != NULL) xmlFree(URI); xfree(id); return(ret); }
/* to correctly escape and expand URLs */ xmlChar * common_build_url (const gchar *url, const gchar *baseURL) { xmlChar *escapedURL, *absURL, *escapedBaseURL; escapedURL = common_uri_escape (url); if (baseURL) { escapedBaseURL = common_uri_escape (baseURL); absURL = xmlBuildURI (escapedURL, escapedBaseURL); if (absURL) xmlFree (escapedURL); else absURL = escapedURL; xmlFree (escapedBaseURL); } else { absURL = escapedURL; } return absURL; }
xmlDocPtr parseDoc(std::string document, std::string baseUri, bool resolveXIncludes) { xmlDocPtr doc = xmlReadMemory(document.c_str(), document.size(), baseUri.c_str(), NULL, 0); if (doc == nullptr) { THROW_EXC("failed to parse xml queries"); } if (resolveXIncludes) { int ret = xmlXIncludeProcess(doc); if (ret < 0) { THROW_EXC("xinclude failed"); } } string schemaUrl; xmlNodePtr tmp = doc->children; while (tmp) { if (tmp->type == XML_ELEMENT_NODE) { xmlAttributePtr attr = ((xmlElementPtr)tmp)->attributes; while (attr) { if (string((char*)attr->name) == "noNamespaceSchemaLocation" && string("http://www.w3.org/2001/XMLSchema-instance") == (char*)((xmlNodePtr)attr)->ns->href ) { schemaUrl = (char*)attr->children->content; } attr = (xmlAttribute*)attr->next; } } tmp = tmp->next; } LOG_INFO("using schema '" << schemaUrl << "' for validating"); char *absUri = (char*)xmlBuildURI((xmlChar*)schemaUrl.c_str(),(xmlChar*)baseUri.c_str()); if (!schemaUrl.empty()) { validateDoc(doc,baseUri, string(absUri)); } return doc; }
/** * xsltDocumentFunction: * @ctxt: the XPath Parser context * @nargs: the number of arguments * * Implement the document() XSLT function * node-set document(object, node-set?) */ void xsltDocumentFunction(xmlXPathParserContextPtr ctxt, int nargs) { xmlXPathObjectPtr obj, obj2 = NULL; xmlChar *base = NULL, *URI; if ((nargs < 1) || (nargs > 2)) { xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, "document() : invalid number of args %d\n", nargs); ctxt->error = XPATH_INVALID_ARITY; return; } if (ctxt->value == NULL) { xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, "document() : invalid arg value\n"); ctxt->error = XPATH_INVALID_TYPE; return; } if (nargs == 2) { if (ctxt->value->type != XPATH_NODESET) { xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, "document() : invalid arg expecting a nodeset\n"); ctxt->error = XPATH_INVALID_TYPE; return; } obj2 = valuePop(ctxt); } if (ctxt->value->type == XPATH_NODESET) { int i; xmlXPathObjectPtr newobj, ret; obj = valuePop(ctxt); ret = xmlXPathNewNodeSet(NULL); if ((obj != NULL) && obj->nodesetval) { for (i = 0; i < obj->nodesetval->nodeNr; i++) { valuePush(ctxt, xmlXPathNewNodeSet(obj->nodesetval->nodeTab[i])); xmlXPathStringFunction(ctxt, 1); if (nargs == 2) { valuePush(ctxt, xmlXPathObjectCopy(obj2)); } else { valuePush(ctxt, xmlXPathNewNodeSet(obj->nodesetval-> nodeTab[i])); } xsltDocumentFunction(ctxt, 2); newobj = valuePop(ctxt); ret->nodesetval = xmlXPathNodeSetMerge(ret->nodesetval, newobj->nodesetval); xmlXPathFreeObject(newobj); } } if (obj != NULL) xmlXPathFreeObject(obj); if (obj2 != NULL) xmlXPathFreeObject(obj2); valuePush(ctxt, ret); return; } /* * Make sure it's converted to a string */ xmlXPathStringFunction(ctxt, 1); if (ctxt->value->type != XPATH_STRING) { xsltTransformError(xsltXPathGetTransformContext(ctxt), NULL, NULL, "document() : invalid arg expecting a string\n"); ctxt->error = XPATH_INVALID_TYPE; if (obj2 != NULL) xmlXPathFreeObject(obj2); return; } obj = valuePop(ctxt); if (obj->stringval == NULL) { valuePush(ctxt, xmlXPathNewNodeSet(NULL)); } else { xsltTransformContextPtr tctxt; tctxt = xsltXPathGetTransformContext(ctxt); if ((obj2 != NULL) && (obj2->nodesetval != NULL) && (obj2->nodesetval->nodeNr > 0) && IS_XSLT_REAL_NODE(obj2->nodesetval->nodeTab[0])) { xmlNodePtr target; target = obj2->nodesetval->nodeTab[0]; if ((target->type == XML_ATTRIBUTE_NODE) || (target->type == XML_PI_NODE)) { target = ((xmlAttrPtr) target)->parent; } base = xmlNodeGetBase(target->doc, target); } else { if ((tctxt != NULL) && (tctxt->inst != NULL)) { base = xmlNodeGetBase(tctxt->inst->doc, tctxt->inst); } else if ((tctxt != NULL) && (tctxt->style != NULL) && (tctxt->style->doc != NULL)) { base = xmlNodeGetBase(tctxt->style->doc, (xmlNodePtr) tctxt->style->doc); } } URI = xmlBuildURI(obj->stringval, base); if (base != NULL) xmlFree(base); if (URI == NULL) { if ((tctxt != NULL) && (tctxt->style != NULL) && (tctxt->style->doc != NULL) && (xmlStrEqual(URI, tctxt->style->doc->URL))) { /* This selects the stylesheet's doc itself. */ valuePush(ctxt, xmlXPathNewNodeSet((xmlNodePtr) tctxt->style->doc)); } else { valuePush(ctxt, xmlXPathNewNodeSet(NULL)); } } else { xsltDocumentFunctionLoadDocument( ctxt, URI ); xmlFree(URI); } } xmlXPathFreeObject(obj); if (obj2 != NULL) xmlXPathFreeObject(obj2); }
/** * xmlXIncludeLoadNode: * @ctxt: an XInclude context * @nr: the node number * * Find and load the infoset replacement for the given node. * * Returns 0 if substitution succeeded, -1 if some processing failed */ static int xmlXIncludeLoadNode(xmlXIncludeCtxtPtr ctxt, int nr) { xmlNodePtr cur; xmlChar *href; xmlChar *parse; xmlChar *base; xmlChar *URI; int xml = 1; /* default Issue 64 */ if (ctxt == NULL) return(-1); if ((nr < 0) || (nr >= ctxt->incNr)) return(-1); cur = ctxt->incTab[nr]; if (cur == NULL) return(-1); #ifdef DEBUG_XINCLUDE xmlDebugDumpNode(stdout, cur, 0); #endif /* * read the attributes */ href = xmlGetNsProp(cur, XINCLUDE_NS, XINCLUDE_HREF); if (href == NULL) { href = xmlGetProp(cur, XINCLUDE_HREF); if (href == NULL) { xmlGenericError(xmlGenericErrorContext, "XInclude: no href\n"); return(-1); } } parse = xmlGetNsProp(cur, XINCLUDE_NS, XINCLUDE_PARSE); if (parse == NULL) { parse = xmlGetProp(cur, XINCLUDE_PARSE); } if (parse != NULL) { if (xmlStrEqual(parse, XINCLUDE_PARSE_XML)) xml = 1; else if (xmlStrEqual(parse, XINCLUDE_PARSE_TEXT)) xml = 0; else { xmlGenericError(xmlGenericErrorContext, "XInclude: invalid value %s for %s\n", parse, XINCLUDE_PARSE); if (href != NULL) xmlFree(href); if (parse != NULL) xmlFree(parse); return(-1); } } /* * compute the URI */ base = xmlNodeGetBase(ctxt->doc, cur); if (base == NULL) { URI = xmlBuildURI(href, ctxt->doc->URL); } else { URI = xmlBuildURI(href, base); } if (URI == NULL) { xmlChar *escbase; xmlChar *eschref; /* * Some escaping may be needed */ escbase = xmlURIEscape(base); eschref = xmlURIEscape(href); URI = xmlBuildURI(eschref, escbase); if (escbase != NULL) xmlFree(escbase); if (eschref != NULL) xmlFree(eschref); } if (URI == NULL) { xmlGenericError(xmlGenericErrorContext, "XInclude: failed build URL\n"); if (parse != NULL) xmlFree(parse); if (href != NULL) xmlFree(href); if (base != NULL) xmlFree(base); return(-1); } #ifdef DEBUG_XINCLUDE xmlGenericError(xmlGenericErrorContext, "parse: %s\n", xml ? "xml": "text"); xmlGenericError(xmlGenericErrorContext, "URI: %s\n", URI); #endif /* * Cleanup */ if (xml) { xmlXIncludeLoadDoc(ctxt, URI, nr); /* xmlXIncludeGetFragment(ctxt, cur, URI); */ } else { xmlXIncludeLoadTxt(ctxt, URI, nr); } /* * Cleanup */ if (URI != NULL) xmlFree(URI); if (parse != NULL) xmlFree(parse); if (href != NULL) xmlFree(href); if (base != NULL) xmlFree(base); return(0); }
/* Custom xslt loader */ static xmlDocPtr custom_loader(const xmlChar *URI, xmlDictPtr dict, int options, void *ctxt, xsltLoadType type) { xmlDocPtr ret; xmlChar *rel_path, *fn, *final_URI = NULL; char *path_URI = NULL; xsltStylesheet *c; ice_config_t *config; switch (type) { /* In case an include is loaded */ case XSLT_LOAD_STYLESHEET: /* URI is an escaped URI, make an unescaped version */ path_URI = util_url_unescape((const char*)URI); /* Error if we can't unescape */ if (path_URI == NULL) return NULL; /* Not look in admindir if the include file exists */ if (access(path_URI, F_OK) == 0) { free(path_URI); break; } free(path_URI); c = (xsltStylesheet *) ctxt; /* Check if we actually have context/path */ if (ctxt == NULL || c->doc->URL == NULL) break; /* Construct the right path */ rel_path = xmlBuildRelativeURI(URI, c->doc->URL); if (rel_path != NULL && admin_path != NULL) { fn = xmlBuildURI(rel_path, admin_path); final_URI = fn; xmlFree(rel_path); } /* Fail if there was an error constructing the path */ if (final_URI == NULL) { if (rel_path) xmlFree(rel_path); return NULL; } break; /* In case a top stylesheet is loaded */ case XSLT_LOAD_START: config = config_get_config(); /* Admin path is cached, so that we don't need to get it from * the config every time we load a xsl include. * Whenever a new top stylesheet is loaded, we check here * if the path in the config has changed and adjust it, if needed. */ if (admin_path != NULL && strcmp(config->adminroot_dir, (char *)admin_path) != 0) { xmlFree(admin_path); admin_path = NULL; } /* Do we need to load the admin path? */ if (!admin_path) { size_t len = strlen(config->adminroot_dir); admin_path = xmlMalloc(len+2); if (!admin_path) return NULL; /* Copy over admin path and add a tailing slash. */ xmlStrPrintf(admin_path, len+2, XMLSTR("%s/"), XMLSTR(config->adminroot_dir)); } config_release_config(); break; /* Avoid warnings about other events we don't care for */ default: break; } /* Get the actual xmlDoc */ if (final_URI) { ret = xslt_loader(final_URI, dict, options, ctxt, type); xmlFree(final_URI); } else { ret = xslt_loader(URI, dict, options, ctxt, type); } return ret; }
char * read_scheda(char *baseUrl, xmlChar *url, char *epgdb_root) { static char buf[2048]; int i; FILE *fd; char cachefile[strlen(epgdb_root) + strlen((char*)url) + 2]; htmlDocPtr docScheda = NULL; xmlXPathContextPtr contextScheda = NULL; xmlXPathObjectPtr par = NULL; xmlChar *urlScheda = NULL; /* build cache filename */ buf[0]='\0'; strcpy(cachefile, epgdb_root); cachefile[strlen(epgdb_root)] = '/'; for (i=0; i<strlen((char*)url); i++) if (url[i] == '/' || url[i] == '\\' || url[i] == '?' || url[i] == '&' || url[i] == '=') cachefile[i+strlen(epgdb_root)+1] = '_'; else cachefile[i+strlen(epgdb_root)+1] = url[i]; cachefile[i+strlen(epgdb_root)+1] = '\0'; /* try to read from cache */ fd = fopen(cachefile, "r"); if (fd) { fread(buf, 2048, 1, fd); fclose(fd); return buf; } /* ok... no cache... download it! */ urlScheda = xmlBuildURI(url, (xmlChar *)baseUrl); if (urlScheda != NULL ) { docScheda = htmlReadFile((char *)urlScheda, NULL, HTML_PARSE_RECOVER|HTML_PARSE_NOERROR|HTML_PARSE_NOWARNING); if (docScheda != NULL ) { contextScheda = xmlXPathNewContext(docScheda); if (contextScheda != NULL) { // Prende il primo paragrafo sotto la div con id="box" par = xmlXPathEvalExpression((const xmlChar *)"//div[@id='box']/p[1]", contextScheda); if (par != NULL && !xmlXPathNodeSetIsEmpty(par->nodesetval)) { append_scheda(buf, par->nodesetval->nodeTab[0]->children, 0, 2048); xmlXPathFreeObject(par); } xmlXPathFreeContext(contextScheda); } xmlFreeDoc(docScheda); } xmlFree(urlScheda); } /* save the cache */ if (strlen(buf) > 0) { fd = fopen(cachefile, "w"); if (fd) { fwrite(buf, strlen(buf)+1, 1, fd); fclose(fd); } } return buf; }
int xsltParseStylesheetImport(xsltStylesheetPtr style, xmlNodePtr cur) { int ret = -1; xmlDocPtr import = NULL; xmlChar *base = NULL; xmlChar *uriRef = NULL; xmlChar *URI = NULL; xsltStylesheetPtr res; xsltSecurityPrefsPtr sec; if ((cur == NULL) || (style == NULL)) return (ret); uriRef = xmlGetNsProp(cur, (const xmlChar *)"href", NULL); if (uriRef == NULL) { xsltTransformError(NULL, style, cur, "xsl:import : missing href attribute\n"); goto error; } base = xmlNodeGetBase(style->doc, cur); URI = xmlBuildURI(uriRef, base); if (URI == NULL) { xsltTransformError(NULL, style, cur, "xsl:import : invalid URI reference %s\n", uriRef); goto error; } res = style; while (res != NULL) { if (res->doc == NULL) break; if (xmlStrEqual(res->doc->URL, URI)) { xsltTransformError(NULL, style, cur, "xsl:import : recursion detected on imported URL %s\n", URI); goto error; } res = res->parent; } sec = xsltGetDefaultSecurityPrefs(); if (sec != NULL) { int secres; secres = xsltCheckRead(sec, NULL, URI); if (secres == 0) { xsltTransformError(NULL, NULL, NULL, "xsl:import: read rights for %s denied\n", URI); goto error; } } import = xsltDocDefaultLoader(URI, style->dict, XSLT_PARSE_OPTIONS, (void *) style, XSLT_LOAD_STYLESHEET); if (import == NULL) { xsltTransformError(NULL, style, cur, "xsl:import : unable to load %s\n", URI); goto error; } res = xsltParseStylesheetImportedDoc(import, style); if (res != NULL) { res->next = style->imports; style->imports = res; if (style->parent == NULL) { xsltFixImportedCompSteps(style, res); } ret = 0; } else { xmlFreeDoc(import); } error: if (uriRef != NULL) xmlFree(uriRef); if (base != NULL) xmlFree(base); if (URI != NULL) xmlFree(URI); return (ret); }
int xsltParseStylesheetInclude(xsltStylesheetPtr style, xmlNodePtr cur) { int ret = -1; xmlDocPtr oldDoc; xmlChar *base = NULL; xmlChar *uriRef = NULL; xmlChar *URI = NULL; xsltStylesheetPtr result; xsltDocumentPtr include; xsltDocumentPtr docptr; int oldNopreproc; if ((cur == NULL) || (style == NULL)) return (ret); uriRef = xmlGetNsProp(cur, (const xmlChar *)"href", NULL); if (uriRef == NULL) { xsltTransformError(NULL, style, cur, "xsl:include : missing href attribute\n"); goto error; } base = xmlNodeGetBase(style->doc, cur); URI = xmlBuildURI(uriRef, base); if (URI == NULL) { xsltTransformError(NULL, style, cur, "xsl:include : invalid URI reference %s\n", uriRef); goto error; } docptr = style->includes; while (docptr != NULL) { if (xmlStrEqual(docptr->doc->URL, URI)) { xsltTransformError(NULL, style, cur, "xsl:include : recursion detected on included URL %s\n", URI); goto error; } docptr = docptr->includes; } include = xsltLoadStyleDocument(style, URI); if (include == NULL) { xsltTransformError(NULL, style, cur, "xsl:include : unable to load %s\n", URI); goto error; } #ifdef XSLT_REFACTORED if (IS_XSLT_ELEM_FAST(cur) && (cur->psvi != NULL)) { ((xsltStyleItemIncludePtr) cur->psvi)->include = include; } else { xsltTransformError(NULL, style, cur, "Internal error: (xsltParseStylesheetInclude) " "The xsl:include element was not compiled.\n", URI); style->errors++; } #endif oldDoc = style->doc; style->doc = include->doc; include->includes = style->includes; style->includes = include; oldNopreproc = style->nopreproc; style->nopreproc = include->preproc; result = xsltParseStylesheetProcess(style, include->doc); style->nopreproc = oldNopreproc; include->preproc = 1; style->includes = include->includes; style->doc = oldDoc; if (result == NULL) { ret = -1; goto error; } ret = 0; error: if (uriRef != NULL) xmlFree(uriRef); if (base != NULL) xmlFree(base); if (URI != NULL) xmlFree(URI); return (ret); }
/** * xsltDocumentFunction: * @ctxt: the XPath Parser context * @nargs: the number of arguments * * Implement the document() XSLT function * node-set document(object, node-set?) */ void xsltDocumentFunction(xmlXPathParserContextPtr ctxt, int nargs){ xsltDocumentPtr doc; xmlXPathObjectPtr obj, obj2 = NULL; xmlChar *base = NULL, *URI; if ((nargs < 1) || (nargs > 2)) { xsltPrintErrorContext(xsltXPathGetTransformContext(ctxt), NULL, NULL); xsltGenericError(xsltGenericErrorContext, "document() : invalid number of args %d\n", nargs); ctxt->error = XPATH_INVALID_ARITY; return; } if (ctxt->value == NULL) { xsltPrintErrorContext(xsltXPathGetTransformContext(ctxt), NULL, NULL); xsltGenericError(xsltGenericErrorContext, "document() : invalid arg value\n"); ctxt->error = XPATH_INVALID_TYPE; return; } if (nargs == 2) { if (ctxt->value->type != XPATH_NODESET) { xsltPrintErrorContext(xsltXPathGetTransformContext(ctxt), NULL, NULL); xsltGenericError(xsltGenericErrorContext, "document() : invalid arg expecting a nodeset\n"); ctxt->error = XPATH_INVALID_TYPE; return; } obj2 = valuePop(ctxt); } if (ctxt->value->type == XPATH_NODESET) { int i; xmlXPathObjectPtr newobj, ret; obj = valuePop(ctxt); ret = xmlXPathNewNodeSet(NULL); if (obj->nodesetval) { for (i = 0; i < obj->nodesetval->nodeNr; i++) { valuePush(ctxt, xmlXPathNewNodeSet(obj->nodesetval->nodeTab[i])); xmlXPathStringFunction(ctxt, 1); if (nargs == 2) { valuePush(ctxt, xmlXPathObjectCopy(obj2)); } else { valuePush(ctxt, xmlXPathNewNodeSet(obj->nodesetval->nodeTab[i])); } xsltDocumentFunction(ctxt, 2); newobj = valuePop(ctxt); ret->nodesetval = xmlXPathNodeSetMerge(ret->nodesetval, newobj->nodesetval); xmlXPathFreeObject(newobj); } } xmlXPathFreeObject(obj); if (obj2 != NULL) xmlXPathFreeObject(obj2); valuePush(ctxt, ret); return; } /* * Make sure it's converted to a string */ xmlXPathStringFunction(ctxt, 1); if (ctxt->value->type != XPATH_STRING) { xsltPrintErrorContext(xsltXPathGetTransformContext(ctxt), NULL, NULL); xsltGenericError(xsltGenericErrorContext, "document() : invalid arg expecting a string\n"); ctxt->error = XPATH_INVALID_TYPE; if (obj2 != NULL) xmlXPathFreeObject(obj2); return; } obj = valuePop(ctxt); if (obj->stringval == NULL) { valuePush(ctxt, xmlXPathNewNodeSet(NULL)); } else { if ((obj2 != NULL) && (obj2->nodesetval != NULL) && (obj2->nodesetval->nodeNr > 0) && IS_XSLT_REAL_NODE(obj2->nodesetval->nodeTab[0])) { xmlNodePtr target; target = obj2->nodesetval->nodeTab[0]; if (target->type == XML_ATTRIBUTE_NODE) { target = ((xmlAttrPtr) target)->parent; } base = xmlNodeGetBase(target->doc, target); } else { xsltTransformContextPtr tctxt; tctxt = xsltXPathGetTransformContext(ctxt); if ((tctxt != NULL) && (tctxt->inst != NULL)) { base = xmlNodeGetBase(tctxt->inst->doc, tctxt->inst); } else if ((tctxt != NULL) && (tctxt->style != NULL) && (tctxt->style->doc != NULL)) { base = xmlNodeGetBase(tctxt->style->doc, (xmlNodePtr) tctxt->style->doc); } } URI = xmlBuildURI(obj->stringval, base); if (base != NULL) xmlFree(base); if (URI == NULL) { valuePush(ctxt, xmlXPathNewNodeSet(NULL)); } else { xsltTransformContextPtr tctxt; tctxt = xsltXPathGetTransformContext(ctxt); if (tctxt == NULL) { xsltPrintErrorContext(xsltXPathGetTransformContext(ctxt), NULL, NULL); xsltGenericError(xsltGenericErrorContext, "document() : internal error tctxt == NULL\n"); valuePush(ctxt, xmlXPathNewNodeSet(NULL)); } else { if (xmlStrEqual(tctxt->style->doc->URL, URI)) { valuePush(ctxt, xmlXPathNewNodeSet((xmlNodePtr)tctxt->style->doc)); } else { doc = xsltLoadDocument(tctxt, URI); if (doc == NULL) valuePush(ctxt, xmlXPathNewNodeSet(NULL)); else { /* TODO: use XPointer of HTML location for fragment ID */ /* pbm #xxx can lead to location sets, not nodesets :-) */ valuePush(ctxt, xmlXPathNewNodeSet((xmlNodePtr) doc->doc)); } } } xmlFree(URI); } } xmlXPathFreeObject(obj); if (obj2 != NULL) xmlXPathFreeObject(obj2); }