static char *parse_text_element(xmlTextReaderPtr reader, char *name) { char *string = NULL; __attribute__nonnull__(reader); __attribute__nonnull__(name); // parse string element attributes here (like xml:lang) while (xmlTextReaderNextNode(reader)) { if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_END_ELEMENT && !xmlStrcmp(xmlTextReaderConstLocalName(reader), BAD_CAST name)) { return string; } switch (xmlTextReaderNodeType(reader)) { case XML_READER_TYPE_TEXT: string = (char *)xmlTextReaderValue(reader); break; default: oscap_seterr(OSCAP_EFAMILY_OSCAP, "Unknown XML element in platform"); break; } } return string; }
struct cpe_platform *cpe_platform_parse(xmlTextReaderPtr reader) { struct cpe_platform *ret; __attribute__nonnull__(reader); // allocate platform structure here ret = cpe_platform_new(); if (ret == NULL) return NULL; // parse platform attributes here ret->id = (char *)xmlTextReaderGetAttribute(reader, ATTR_ID_STR); if (ret->id == NULL) { cpe_platform_free(ret); return NULL; // if there is no "id" in platform element, return NULL } // skip from <platform> node to next one xmlTextReaderNextNode(reader); // while we have element that is not "platform", it is inside this element, otherwise it's ended // element </platform> and we should end. If there is no one from "if" statement cases, we are parsing // attribute or text ,.. and we can continue to next node. while (xmlStrcmp(xmlTextReaderConstLocalName(reader), TAG_PLATFORM_STR) != 0) { if (!xmlStrcmp(xmlTextReaderConstLocalName(reader), ATTR_TITLE_STR) && xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) { oscap_list_add(ret->titles, oscap_text_new_parse(OSCAP_TEXT_TRAITS_PLAIN, reader)); } else if (!xmlStrcmp(xmlTextReaderConstLocalName(reader), TAG_REMARK_STR) && xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) { ret->remark = parse_text_element(reader, (char *)TAG_REMARK_STR); // TODO: 0-n remarks ! } else if (!xmlStrcmp(xmlTextReaderConstLocalName(reader), TAG_LOGICAL_TEST_STR) && xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) { /* Maybe we shall not allocate this in constructor? */ cpe_testexpr_free(ret->expr); ret->expr = cpe_testexpr_parse(reader); } else if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) oscap_seterr(OSCAP_EFAMILY_OSCAP, "Unknown XML element in platform"); // get the next node xmlTextReaderNextNode(reader); } return ret; }
static struct cpe_ext_deprecation *cpe_ext_deprecation_parse(xmlTextReaderPtr reader) { __attribute__nonnull__(reader); if (xmlStrcmp(xmlTextReaderConstLocalName(reader), BAD_CAST TAG_CPE_EXT_DEPRECATION_STR) != 0 || xmlTextReaderNodeType(reader) != 1) { oscap_seterr(OSCAP_EFAMILY_OSCAP, "Found '%s' node when expecting: '%s'!", xmlTextReaderConstLocalName(reader), TAG_CPE_EXT_DEPRECATION_STR); } const xmlChar* nsuri = xmlTextReaderConstNamespaceUri(reader); if (nsuri && xmlStrcmp(nsuri, BAD_CAST XMLNS_CPE2D3_EXTENSION) != 0) { oscap_seterr(OSCAP_EFAMILY_OSCAP, "Found '%s' namespace when expecting: '%s'!", nsuri, XMLNS_CPE2D3_EXTENSION); return NULL; } struct cpe_ext_deprecation *deprecation = cpe_ext_deprecation_new(); deprecation->date = (char *) xmlTextReaderGetAttribute(reader, BAD_CAST ATTR_DATE_STR); if (xmlTextReaderIsEmptyElement(reader) == 0) { // the element contains child nodes xmlTextReaderNextNode(reader); while (xmlStrcmp(xmlTextReaderConstLocalName(reader), BAD_CAST TAG_CPE_EXT_DEPRECATION_STR) != 0) { if (xmlTextReaderNodeType(reader) != XML_READER_TYPE_ELEMENT) { xmlTextReaderNextNode(reader); continue; } if (xmlStrcmp(xmlTextReaderConstLocalName(reader), BAD_CAST TAG_CPE_EXT_DEPRECATEDBY_STR) == 0) { struct cpe_ext_deprecatedby *deprecatedby = cpe_ext_deprecatedby_parse(reader); if (deprecatedby == NULL) { cpe_ext_deprecation_free(deprecation); return NULL; } oscap_list_add(deprecation->deprecatedbys, deprecatedby); } else { oscap_seterr(OSCAP_EFAMILY_OSCAP, "Unexpected element within deprecation element: '%s'", xmlTextReaderConstLocalName(reader)); cpe_ext_deprecation_free(deprecation); return NULL; } xmlTextReaderNextNode(reader); } } return deprecation; }
struct cpe_lang_model *cpe_lang_model_import_source(struct oscap_source *source) { xmlTextReaderPtr reader = oscap_source_get_xmlTextReader(source); struct cpe_lang_model *ret = NULL; if (reader != NULL) { xmlTextReaderNextNode(reader); ret = cpe_lang_model_parse(reader); if (ret != NULL) { cpe_lang_model_set_origin_file(ret, oscap_source_readable_origin(source)); } } xmlFreeTextReader(reader); return ret; }
struct cpe_testexpr *cpe_testexpr_parse(xmlTextReaderPtr reader) { xmlChar *temp = NULL; size_t elem_cnt = 0; struct cpe_testexpr *ret = NULL; __attribute__nonnull__(reader); // allocation ret = cpe_testexpr_new(); if (ret == NULL) return NULL; // it's fact-ref only, fill the structure and return it if (!xmlStrcmp(xmlTextReaderConstLocalName(reader), TAG_FACT_REF_STR) && xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) { ret->oper = CPE_LANG_OPER_MATCH; temp = xmlTextReaderGetAttribute(reader, ATTR_NAME_STR); ret->meta.cpe = cpe_name_new((char *)temp); xmlFree(temp); return ret; // it's check-fact-ref only, fill the structure and return it } else if (!xmlStrcmp(xmlTextReaderConstLocalName(reader), TAG_CHECK_FACT_REF_STR) && xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) { ret->oper = CPE_LANG_OPER_CHECK; ret->meta.check.system = (char*)xmlTextReaderGetAttribute(reader, ATTR_SYSTEM_STR); ret->meta.check.href = (char*)xmlTextReaderGetAttribute(reader, ATTR_HREF_STR); ret->meta.check.id = (char*)xmlTextReaderGetAttribute(reader, ATTR_ID_REF_STR); return ret; } else if (!xmlStrcmp(xmlTextReaderConstLocalName(reader), TAG_LOGICAL_TEST_STR) && xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) { // it's logical-test, fill the structure and go to next node temp = xmlTextReaderGetAttribute(reader, ATTR_OPERATOR_STR); if (xmlStrcasecmp(temp, VAL_AND_STR) == 0) ret->oper = CPE_LANG_OPER_AND; else if (xmlStrcasecmp(temp, VAL_OR_STR) == 0) ret->oper = CPE_LANG_OPER_OR; else { // unknown operator problem xmlFree(temp); oscap_free(ret); return NULL; } xmlFree(temp); ret->meta.expr = oscap_list_new(); // initialise a list of subexpressions temp = xmlTextReaderGetAttribute(reader, ATTR_NEGATE_STR); if (temp && xmlStrcasecmp(temp, VAL_TRUE_STR) == 0) ret->oper |= CPE_LANG_OPER_NOT; xmlFree(temp); } else if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) oscap_seterr(OSCAP_EFAMILY_OSCAP, "Unknown XML element in test expression"); // go to next node // skip to next node xmlTextReaderNextNode(reader); int depth = xmlTextReaderDepth(reader); //printf("[%d] logical-test\n", depth); // while it's not 'logical-test' or it's not ended element .. //while (!xmlStrcmp(xmlTextReaderConstLocalName(reader), TAG_FACT_REF_STR) || // !xmlStrcmp(xmlTextReaderConstLocalName(reader), TAG_LOGICAL_TEST_STR)) { while (xmlTextReaderDepth(reader) >= depth) { //printf("[%d:%d] logical-test::%s\n", depth, xmlTextReaderDepth(reader), xmlTextReaderConstLocalName(reader)); if (xmlTextReaderNodeType(reader) != XML_READER_TYPE_ELEMENT) { xmlTextReaderNextNode(reader); continue; } elem_cnt++; // We assume that the expression is a logical one (meaning that it // can have subexpressions). // TODO: Enforce that assumption and don't rely on just validation. // .. and the next node is logical-test element, we need recursive call if (!xmlStrcmp(xmlTextReaderConstLocalName(reader), TAG_LOGICAL_TEST_STR) && xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) { // ret->meta.expr[elem_cnt - 1] = *(cpe_testexpr_parse(reader)); oscap_list_add(ret->meta.expr, cpe_testexpr_parse(reader)); if (xmlTextReaderDepth(reader) < depth) { return ret; } else if (xmlTextReaderDepth(reader) == depth) continue; } else if (!xmlStrcmp(xmlTextReaderConstLocalName(reader), TAG_FACT_REF_STR) && xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) { // fill the structure struct cpe_testexpr *subexpr = cpe_testexpr_new(); subexpr->oper = CPE_LANG_OPER_MATCH; temp = xmlTextReaderGetAttribute(reader, ATTR_NAME_STR); subexpr->meta.cpe = cpe_name_new((char *)temp); //printf("FACT-REF: %s\n", temp); xmlFree(temp); oscap_list_add(ret->meta.expr, subexpr); } else if (!xmlStrcmp(xmlTextReaderConstLocalName(reader), TAG_CHECK_FACT_REF_STR) && xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) { struct cpe_testexpr *subexpr = cpe_testexpr_new(); subexpr->oper = CPE_LANG_OPER_CHECK; subexpr->meta.check.system = (char*)xmlTextReaderGetAttribute(reader, ATTR_SYSTEM_STR); subexpr->meta.check.href = (char*)xmlTextReaderGetAttribute(reader, ATTR_HREF_STR); subexpr->meta.check.id = (char*)xmlTextReaderGetAttribute(reader, ATTR_ID_REF_STR); oscap_list_add(ret->meta.expr, subexpr); } else if (xmlTextReaderNodeType(reader) == XML_READER_TYPE_ELEMENT) { oscap_seterr(OSCAP_EFAMILY_OSCAP, "Unknown XML element in test expression"); } xmlTextReaderNextNode(reader); } //ret->meta.expr[elem_cnt].oper = CPE_LANG_OPER_HALT; return ret; }