/******************************************************************** * FUNCTION consume_node * * Internal consume XML node function * see agt_xml_consume_node for details. * * EXTRA INPUTS: * eoferr == TRUE if an End of File error should be generated * == FALSE if not * nserr == TRUE if bad namespace should be checked * == FALSE if not * clean == TRUE is a string should be cleaned before returned * == FALSE if a string node should be returned as-is * * RETURNS: * status of the operation * Try to fail on fatal errors only *********************************************************************/ static status_t consume_node (ses_cb_t *scb, boolean advance, xml_node_t *node, ncx_layer_t layer, xml_msg_hdr_t *msghdr, boolean eoferr, boolean nserr, boolean clean) { int ret, nodetyp; const xmlChar *badns; xmlChar *valstr, *namestr; uint32 len; status_t res, res2; boolean done; /* init local vars */ done = FALSE; res = NO_ERR; res2 = NO_ERR; badns = NULL; /* loop past any unused xmlTextReader node types */ while (!done) { /* check if a new node should be read */ if (advance) { /* advance the node pointer */ ret = xmlTextReaderRead(scb->reader); if (ret != 1) { /* do not treat this as an internal error */ res = ERR_XML_READER_EOF; if (msghdr && eoferr) { /* generate an operation-failed error */ agt_record_error(scb, msghdr, layer, res, NULL, NCX_NT_NONE, NULL, NCX_NT_NONE, NULL); } return res; } } /* get the node depth to match the end node correctly */ node->depth = xmlTextReaderDepth(scb->reader); if (node->depth == -1) { /* this never actaully happens */ SET_ERROR(ERR_XML_READER_INTERNAL); node->depth = 0; } /* get the internal nodetype, check it and convert it */ nodetyp = xmlTextReaderNodeType(scb->reader); switch (nodetyp) { case XML_ELEMENT_NODE: /* classify element as empty or start */ if (xmlTextReaderIsEmptyElement(scb->reader)) { node->nodetyp = XML_NT_EMPTY; } else { node->nodetyp = XML_NT_START; } done = TRUE; break; case XML_ELEMENT_DECL: node->nodetyp = XML_NT_END; done = TRUE; break; case XML_TEXT_NODE: /* case XML_DTD_NODE: */ node->nodetyp = XML_NT_STRING; done = TRUE; break; default: /* unused node type -- keep trying */ if (LOGDEBUG3) { log_debug3("\nxml_consume_node: skip unused node (%s)", xml_get_node_name(nodetyp)); } advance = TRUE; } } /* finish the node, depending on its type */ switch (node->nodetyp) { case XML_NT_START: case XML_NT_END: case XML_NT_EMPTY: /* get the element QName */ namestr = xml_strdup(xmlTextReaderConstName(scb->reader)); if (!namestr) { res = ERR_INTERNAL_MEM; } else { node->qname = namestr; /* check for namespace prefix in the name * only error returned is unknown-namespace */ len = 0; res = xml_check_ns(scb->reader, namestr, &node->nsid, &len, &badns); if (!nserr && res != NO_ERR) { node->nsid = xmlns_inv_id(); len = 0; res = NO_ERR; } /* set the element name to the char after the prefix, if any */ node->elname = (const xmlChar *)(namestr+len); /* get all the attributes, except for XML_NT_END */ if (res == NO_ERR && node->nodetyp != XML_NT_END) { res2 = get_all_attrs(scb, node, &node->attrs, layer, msghdr, nserr); } /* Set the node module */ if (res == NO_ERR) { if (node->nsid) { node->module = xmlns_get_module(node->nsid); } else { /* no entry, use the default module (ncx) */ node->module = NCX_DEF_MODULE; } } } break; case XML_NT_STRING: /* get the text value -- this is a malloced string */ node->simval = NULL; valstr = xmlTextReaderValue(scb->reader); if (valstr) { if (clean) { node->simfree = xml_copy_clean_string(valstr); } else { node->simfree = xml_strdup(valstr); } if (node->simfree) { node->simlen = xml_strlen(node->simfree); node->simval = (const xmlChar *)node->simfree; } /* see if this is a QName string; if so save the NSID */ xml_check_qname_content(scb->reader, node); xmlFree(valstr); } if (!node->simval) { /* prevent a NULL ptr reference */ node->simval = EMPTY_STRING; node->simlen = 0; node->simfree = NULL; } break; default: break; } if ((res != NO_ERR) && msghdr) { if (badns) { /* generate an operation-failed error */ agt_record_error(scb, msghdr, layer, res, node, NCX_NT_STRING, badns, NCX_NT_NONE, NULL); } else { agt_record_error(scb, msghdr, layer, res, node, NCX_NT_NONE, NULL, NCX_NT_NONE, NULL); } } if (LOGDEBUG4) { log_debug4("\nxml_consume_node: return (%d)", (res==NO_ERR) ? res2 : res); if (scb->state != SES_ST_INIT) { xml_dump_node(node); } } /* return general error first, then attribute error * It doesn't really matter since the caller will * assume all error reports have been queued upon return */ return (res==NO_ERR) ? res2 : res; } /* consume_node */
/******************************************************************** * FUNCTION parse_parm * * Parse, and fill one val_value_t struct during * processing of a parmset * * Error messages are printed by this function!! * Do not duplicate error messages upon error return * * * INPUTS: * tkc == token chain * val == container val to fill in * keepvals == TRUE to save existing parms in 'ps', as needed * FALSE to overwrite old parms in 'ps', as needed * * RETURNS: * status of the operation *********************************************************************/ static status_t parse_parm (tk_chain_t *tkc, val_value_t *val, boolean keepvals) { obj_template_t *obj; const xmlChar *modname; val_value_t *curparm, *newparm; status_t res; ncx_iqual_t iqual; boolean match, usewarning, isdefault; /* get the next token, which must be a TSTRING * representing the parameter name */ if (TK_CUR_TYP(tkc) != TK_TT_TSTRING) { res = ERR_NCX_WRONG_TKTYPE; ncx_conf_exp_err(tkc, res, "parameter name"); return res; } curparm = NULL; usewarning = ncx_warning_enabled(ERR_NCX_CONF_PARM_EXISTS); /* check if this TSTRING is a parameter in this parmset * make sure to always check for prefix:identifier * This is automatically processed in tk.c */ if (TK_CUR_MOD(tkc)) { modname = xmlns_get_module (xmlns_find_ns_by_prefix(TK_CUR_MOD(tkc))); if (modname) { curparm = val_find_child(val, modname, TK_CUR_VAL(tkc)); } } else { curparm = val_find_child(val, val_get_mod_name(val), TK_CUR_VAL(tkc)); } if (curparm) { obj = curparm->obj; } else { obj = obj_find_child(val->obj, TK_CUR_MOD(tkc), TK_CUR_VAL(tkc)); } if (!obj) { res = ERR_NCX_UNKNOWN_PARM; if (TK_CUR_MOD(tkc)) { log_error("\nError: parameter '%s:%s' not found", TK_CUR_MOD(tkc), TK_CUR_VAL(tkc)); } else { log_error("\nError: parameter '%s' not found", TK_CUR_VAL(tkc)); } ncx_conf_exp_err(tkc, res, "parameter name"); return res; } /* got a valid parameter name, now create a new parm * even if it may not be kept. There are corner-cases * that require the new value be parsed before knowing * if a parm value is a duplicate or not */ newparm = val_new_value(); if (!newparm) { res = ERR_INTERNAL_MEM; ncx_print_errormsg(tkc, NULL, res); return res; } val_init_from_template(newparm, obj); /* parse the parameter value */ res = parse_val(tkc, obj, newparm); if (res != NO_ERR) { val_free_value(newparm); return res; } /* check if a potential current value exists, or just * add the newparm to the parmset */ if (curparm) { isdefault = val_set_by_default(curparm); iqual = obj_get_iqualval(obj); if (iqual == NCX_IQUAL_ONE || iqual == NCX_IQUAL_OPT) { /* only one allowed, check really a match */ match = TRUE; if (val_has_index(curparm) && !val_index_match(newparm, curparm)) { match = FALSE; } if (!match) { val_add_child(newparm, val); } else if (isdefault) { dlq_remove(curparm); val_free_value(curparm); val_add_child(newparm, val); } else if (keepvals) { if (usewarning) { /* keep current value and toss new value */ log_warn("\nWarning: Parameter '%s' already exists. " "Not using new value\n", curparm->name); if (LOGDEBUG2) { val_dump_value(newparm, NCX_DEF_INDENT); log_debug2("\n"); } } val_free_value(newparm); } else { if (usewarning) { /* replace current value and warn old value tossed */ log_warn("\nconf: Parameter '%s' already exists. " "Overwriting with new value\n", curparm->name); if (LOGDEBUG2) { val_dump_value(newparm, NCX_DEF_INDENT); log_debug2("\n"); } } dlq_remove(curparm); val_free_value(curparm); val_add_child(newparm, val); } } else { /* mutliple instances allowed */ val_add_child(newparm, val); } } else { val_add_child(newparm, val); } return NO_ERR; } /* parse_parm */