static int ds_sds_compose_add_component_dependencies(xmlDocPtr doc, xmlNodePtr datastream, struct oscap_source *component_source, xmlNodePtr catalog, int component_type) { xmlDocPtr component_doc = oscap_source_get_xmlDoc(component_source); if (component_doc == NULL) { return -1; } xmlXPathContextPtr xpathCtx = xmlXPathNewContext(component_doc); if (xpathCtx == NULL) { oscap_seterr(OSCAP_EFAMILY_XML, "Error: unable to create new XPath context."); return -1; } xmlXPathObjectPtr xpathObj = xmlXPathEvalExpression( // we want robustness and support for future versions, this expression // retrieves check-content-refs from any namespace BAD_CAST _get_dep_xpath_for_type(component_type), xpathCtx); if (xpathObj == NULL) { oscap_seterr(OSCAP_EFAMILY_XML, "Error: Unable to evalute XPath expression."); xmlXPathFreeContext(xpathCtx); return -1; } xmlNsPtr cat_ns = xmlSearchNsByHref(doc, datastream, BAD_CAST cat_ns_uri); xmlNodeSetPtr nodeset = xpathObj->nodesetval; if (nodeset != NULL) { struct oscap_htable *exported = oscap_htable_new(); char* filepath_cpy = oscap_strdup(oscap_source_readable_origin(component_source)); const char* dir = dirname(filepath_cpy); for (int i = 0; i < nodeset->nodeNr; i++) { xmlNodePtr node = nodeset->nodeTab[i]; if (node->type != XML_ELEMENT_NODE) continue; if (xmlHasProp(node, BAD_CAST "href")) { char* href = (char*)xmlGetProp(node, BAD_CAST "href"); if (oscap_htable_get(exported, href) != NULL) { // This path has been already exported. Do not export duplicate. xmlFree(href); continue; } oscap_htable_add(exported, href, ""); if (oscap_acquire_url_is_supported(href)) { /* If the referenced component is remote one, do not include * it within the DataStream. Such component shall only be * downloaded once the scan is run. */ xmlFree(href); continue; } char* real_path = (strcmp(dir, "") == 0 || strcmp(dir, ".") == 0) ? oscap_strdup(href) : oscap_sprintf("%s/%s", dir, href); char* mangled_path = ds_sds_mangle_filepath(real_path); char* cref_id = oscap_sprintf("scap_org.open-scap_cref_%s", mangled_path); int counter = 0; while (ds_sds_find_component_ref(datastream, cref_id) != NULL) { // While the given component ID already exists in the document. oscap_free(cref_id); cref_id = oscap_sprintf("scap_org.open-scap_cref_%s%03d", mangled_path, counter++); } oscap_free(mangled_path); char* uri = oscap_sprintf("#%s", cref_id); // we don't want duplicated uri elements in the catalog if (ds_sds_compose_catalog_has_uri(doc, catalog, uri) == 0) { oscap_free(uri); oscap_free(cref_id); oscap_free(real_path); xmlFree(href); continue; } int ret = ds_sds_compose_add_component_with_ref(doc, datastream, real_path, cref_id); if (ret == 0) { xmlNodePtr catalog_uri = xmlNewNode(cat_ns, BAD_CAST "uri"); xmlSetProp(catalog_uri, BAD_CAST "name", BAD_CAST href); xmlSetProp(catalog_uri, BAD_CAST "uri", BAD_CAST uri); xmlAddChild(catalog, catalog_uri); } oscap_free(cref_id); oscap_free(uri); oscap_free(real_path); xmlFree(href); if (ret < 0) { // oscap_seterr has already been called oscap_htable_free0(exported); return -1; } } } oscap_htable_free0(exported); oscap_free(filepath_cpy); } xmlXPathFreeObject(xpathObj); xmlXPathFreeContext(xpathCtx); return 0; }
static int ds_sds_dump_component_by_href(struct ds_sds_session *session, char* xlink_href, char *target_filename_dirname, const char* relative_filepath, char* cref_id, char **component_id) { if (!xlink_href || strlen(xlink_href) < 2) { oscap_seterr(OSCAP_EFAMILY_XML, "No or invalid xlink:href attribute on given component-ref."); return -1; } if (xlink_href[0] == '#') { *component_id = xlink_href + 1; return ds_sds_dump_local_component(*component_id, session, target_filename_dirname, relative_filepath); } else if (oscap_str_startswith(xlink_href, "file:")){ char* sep = strchr(xlink_href, '#'); const char *filename = xlink_href + strlen("file:"); if (sep == NULL) { *component_id = NULL; } else { *sep = '\0'; *component_id = sep + 1; } return ds_sds_dump_file_component(filename, *component_id, session, target_filename_dirname, relative_filepath); } else if (oscap_acquire_url_is_supported(xlink_href)){ char *sep = strchr(xlink_href, '#'); char* url = xlink_href; if (sep == NULL) { *component_id = NULL; } else { *sep = '\0'; *component_id = sep + 1; } if (!ds_sds_session_fetch_remote_resources(session)) { static bool fetch_remote_resources_suggested = false; if (!fetch_remote_resources_suggested) { fetch_remote_resources_suggested = true; ds_sds_session_remote_resources_progress(session)(true, "WARNING: Datastream component '%s' points out to the remote '%s'. " "Use '--fetch-remote-resources' option to download it.\n", cref_id, url); } ds_sds_session_remote_resources_progress(session)(true, "WARNING: Skipping '%s' file which is referenced from datastream\n", url); return -2; } return ds_dsd_dump_remote_component(url, *component_id, session, target_filename_dirname, relative_filepath); } else { oscap_seterr(OSCAP_EFAMILY_XML, "Unsupported type of xlink:href attribute on given component-ref - '%s'.", xlink_href); return -1; } return 0; }