static xml_node_t * __ni_ifup_generate_match(ni_ifworker_t *w) { xml_node_t *match, *op; unsigned int i; if (!(match = xml_node_new(NI_NANNY_IFPOLICY_MATCH, NULL))) return NULL; if (w->children.count) { op = xml_node_new(NI_NANNY_IFPOLICY_MATCH_COND_OR, match); if (!__ni_ifup_generate_match_dev(op, w)) { xml_node_free(match); return NULL; } for (i = 0; i < w->children.count; i++) { ni_ifworker_t *child = w->children.data[i]; if (!__ni_ifup_generate_match_dev(op, child)) { xml_node_free(match); return NULL; } } } else { if (!__ni_ifup_generate_match_dev(match, w)) { xml_node_free(match); return NULL; } } return match; }
xml_node_t * xml_node_scan(FILE *fp, const char *location) { xml_reader_t reader; xml_node_t *root = xml_node_new(NULL, NULL); if (xml_reader_init_file(&reader, fp, location) < 0) return NULL; if (reader.shared_location) root->location = xml_location_new(reader.shared_location, reader.lineCount); /* Note! We do not deal with properly formatted XML documents here. * Specifically, we do not expect them to have a document header. */ if (!xml_process_element_nested(&reader, root, 0)) { xml_node_free(root); return NULL; } if (xml_reader_destroy(&reader) < 0) { xml_node_free(root); return NULL; } return root; }
/* * Use some locking here... */ int ni_dhcp6_load_duid(ni_opaque_t *duid, const char *filename) { char path[PATH_MAX]; const char *name = CONFIG_DHCP6_DUID_NODE; xml_node_t *xml = NULL; xml_node_t *node; FILE *fp; int rv; if (!filename) { snprintf(path, sizeof(path), "%s/%s", ni_config_storedir(), CONFIG_DHCP6_DUID_FILE); filename = path; } else { name = "duid"; } if ((fp = fopen(filename, "r")) == NULL) { if (errno != ENOENT) ni_error("unable to open %s for reading: %m", filename); return -1; } xml = xml_node_scan(fp, NULL); fclose(fp); if (xml == NULL) { ni_error("%s: unable to parse xml file", filename); return -1; } if (xml->name == NULL) node = xml->children; else node = xml; if (!node || !ni_string_eq(node->name, name)) { ni_error("%s: does not contain %s", filename, name); xml_node_free(xml); return -1; } rv = 0; if (!node->cdata || !ni_duid_parse_hex(duid, node->cdata)) { ni_error("%s: unable to parse %s xml file", filename, name); rv = -1; } xml_node_free(xml); return rv; }
static int __ni_dhcp6_lease_ia_type_to_xml(const ni_dhcp6_ia_t *ia_list, unsigned ia_type, xml_node_t *node) { const ni_dhcp6_ia_t *ia; xml_node_t *ia_node; const char *ia_name = ni_dhcp6_option_name(ia_type); unsigned int count = 0; int ret; for (ia = ia_list; ia; ia = ia->next) { if (ia->type != ia_type) continue; ia_node = xml_node_new(ia_name, NULL); if ((ret = __ni_dhcp6_lease_ia_data_to_xml(ia, ia_node) == 0)) { xml_node_add_child(node, ia_node); count++; } else { xml_node_free(ia_node); if (ret < 0) return ret; } } return count == 0 ? 1 : 0; }
/* * Free an XML node */ void xml_node_free(xml_node_t *node) { xml_node_t *child; if (!node) return; ni_assert(node->refcount); if (--(node->refcount) != 0) return; while ((child = node->children) != NULL) { node->children = child->next; xml_node_free(child); } if (node->location) xml_location_free(node->location); ni_var_array_destroy(&node->attrs); free(node->cdata); free(node->name); free(node); }
void xml_document_free(xml_document_t *doc) { xml_node_free(doc->root); ni_string_free(&doc->dtd); free(doc); }
static int ni_addrconf_lease_static_data_to_xml(const ni_addrconf_lease_t *lease, xml_node_t *node) { static const struct group_map { const char *name; int (*func)(const ni_addrconf_lease_t *lease, xml_node_t *node); } *g, group_map[] = { { NI_ADDRCONF_LEASE_XML_ADDRS_DATA_NODE, ni_addrconf_lease_addrs_data_to_xml }, { NI_ADDRCONF_LEASE_XML_ROUTES_DATA_NODE, ni_addrconf_lease_routes_data_to_xml }, { NI_ADDRCONF_LEASE_XML_DNS_DATA_NODE, ni_addrconf_lease_dns_data_to_xml }, { NULL, NULL } }; xml_node_t *data; if (!ni_string_empty(lease->hostname)) xml_node_new_element("hostname", node, lease->hostname); for (g = group_map; g && g->name && g->func; ++g) { data = xml_node_new(g->name, NULL); if (g->func(lease, data) == 0) { xml_node_add_child(node, data); } else { xml_node_free(data); } } return 0; }
static inline void __xml_node_list_drop(xml_node_t **pos) { xml_node_t *np; if ((np = __xml_node_list_remove(pos)) != NULL) xml_node_free(np); }
void xml_document_set_root(xml_document_t *doc, xml_node_t *root) { if (doc->root != root) { xml_node_free(doc->root); doc->root = root; } }
void ni_managed_device_set_policy(ni_managed_device_t *mdev, ni_managed_policy_t *mpolicy, xml_node_t *config) { if (!xml_node_is_empty(mdev->selected_config)) xml_node_free(mdev->selected_config); mdev->selected_config = config; mdev->selected_policy = mpolicy; mdev->selected_policy_seq = mpolicy? mpolicy->seqno : 0; }
static int __ni_dhcp6_lease_ia_data_to_xml(const ni_dhcp6_ia_t *ia, xml_node_t *node) { const char *ia_address = ni_dhcp6_option_name(NI_DHCP6_OPTION_IA_ADDRESS); const char *ia_prefix = ni_dhcp6_option_name(NI_DHCP6_OPTION_IA_PREFIX); const ni_dhcp6_ia_addr_t *iadr; xml_node_t *iadr_node; unsigned int count = 0; char buf[32] = { '\0' }; int ret; switch (ia->type) { case NI_DHCP6_OPTION_IA_TA: xml_node_new_element_uint("interface-id", node, ia->iaid); snprintf(buf, sizeof(buf), "%"PRId64, (int64_t)ia->acquired.tv_sec); xml_node_new_element("acquired", node, buf); break; case NI_DHCP6_OPTION_IA_NA: case NI_DHCP6_OPTION_IA_PD: xml_node_new_element_uint("interface-id", node, ia->iaid); snprintf(buf, sizeof(buf), "%"PRId64, (int64_t)ia->acquired.tv_sec); xml_node_new_element("acquired", node, buf); xml_node_new_element_uint("renewal-time", node, ia->renewal_time); xml_node_new_element_uint("rebind-time", node, ia->rebind_time); break; default: return -1; } for (iadr = ia->addrs; iadr; iadr = iadr->next) { switch (ia->type) { case NI_DHCP6_OPTION_IA_NA: case NI_DHCP6_OPTION_IA_TA: iadr_node = xml_node_new(ia_address, NULL); break; case NI_DHCP6_OPTION_IA_PD: iadr_node = xml_node_new(ia_prefix, NULL); break; default: return -1; } ret = __ni_dhcp6_lease_ia_addr_to_xml(iadr, ia->type, iadr_node); if (ret) { xml_node_free(iadr_node); if (ret < 0) return -1; } else { count++; xml_node_add_child(node, iadr_node); } } __ni_dhcp6_lease_status_to_xml(&ia->status, node); return count == 0 ? 1 : 0; }
void xml_node_array_destroy(xml_node_array_t *array) { unsigned int i; for (i = 0; i < array->count; ++i) xml_node_free(array->data[i]); if (array->data) free(array->data); memset(array, 0, sizeof(*array)); }
int main(int argc, char *argv[]) { XMLROOT *root = NULL; XMLNODE *node = NULL; struct cstring *xml_string=NULL; CLOG_INFO *log = NULL; printf("cXML test program\n"); log = clog_open("test.log", clog_getlevel("TRACE"),NULL,0); root = xml_root_new(log); if(0==xml_fread(log, root, argv[1])) { fprintf(stderr, "Something was wrong with the XML File, please check the log!\n"); xml_root_free(log, root); exit(1); } xml_string = xml_node_tostring(log, root->data); if(NULL!=xml_string) { fprintf(stderr, "%s\n", xml_string->string); cstring_free(&xml_string); } xml_root_free(log, root); { // test xml creation functionality.. XMLNODE* tmpx = NULL; XMLNODE* tmpy = NULL; node = xml_node_create(log, NULL, "tickets_container", 17); xml_node_addattribute(log, node, "bob", "3"); tmpx = xml_node_create(log, node, "ticket", 6); tmpy = xml_node_create(log, tmpx, "id", 2); xml_node_adddata(log, tmpy, "3", 1); xml_string = xml_node_tostring(log, node); if(0!=xml_string->length) { fprintf(stderr, "%s\n", xml_string->string); cstring_free(&xml_string); } xml_node_free(log, node); } clog_close(log); return EXIT_SUCCESS; }
int ni_dhcp6_lease_data_to_xml(const ni_addrconf_lease_t *lease, xml_node_t *node, const char *ifname) { static const struct group_map { const char *name; int (*func)(const ni_addrconf_lease_t *, xml_node_t *, const char *); } *g, group_map[] = { { NI_ADDRCONF_LEASE_XML_DNS_DATA_NODE, ni_addrconf_lease_dns_data_to_xml }, { NI_ADDRCONF_LEASE_XML_NTP_DATA_NODE, ni_addrconf_lease_ntp_data_to_xml }, { NI_ADDRCONF_LEASE_XML_SIP_DATA_NODE, ni_addrconf_lease_sip_data_to_xml }, { NI_ADDRCONF_LEASE_XML_PTZ_DATA_NODE, ni_addrconf_lease_ptz_data_to_xml }, { NI_ADDRCONF_LEASE_XML_OPTS_DATA_NODE, ni_addrconf_lease_opts_data_to_xml }, { NULL, NULL } }; xml_node_t *data; if (!node || !lease) return -1; if (lease->family != AF_INET6 || lease->type != NI_ADDRCONF_DHCP) return -1; if (__ni_dhcp6_lease_head_to_xml(lease, node) != 0) return -1; if (__ni_dhcp6_lease_ia_type_to_xml(lease->dhcp6.ia_list, NI_DHCP6_OPTION_IA_NA, node) < 0) return -1; if (__ni_dhcp6_lease_ia_type_to_xml(lease->dhcp6.ia_list, NI_DHCP6_OPTION_IA_TA, node) < 0) return -1; if (__ni_dhcp6_lease_ia_type_to_xml(lease->dhcp6.ia_list, NI_DHCP6_OPTION_IA_PD, node) < 0) return -1; if (__ni_dhcp6_lease_boot_to_xml(lease, node) < 0) return -1; for (g = group_map; g && g->name && g->func; ++g) { data = xml_node_new(g->name, NULL); if (g->func(lease, data, ifname) == 0) { xml_node_add_child(node, data); } else { xml_node_free(data); } } return 0; }
int ni_dhcp6_save_duid(const ni_opaque_t *duid, const char *filename) { char path[PATH_MAX]; const char *name = CONFIG_DHCP6_DUID_NODE; ni_opaque_t temp = NI_OPAQUE_INIT; xml_node_t *node; FILE *fp; int rv = -1; if (!duid || !duid->len) { ni_error("BUG: Refusing to save empty duid"); return -1; } if(ni_dhcp6_load_duid(&temp, filename) == 0) return 1; if (!filename) { snprintf(path, sizeof(path), "%s/%s", ni_config_storedir(), CONFIG_DHCP6_DUID_FILE); filename = path; } else { name = "duid"; } if ((node = xml_node_new(name, NULL)) == NULL) { ni_error("Unable to create %s xml node: %m", name); return -1; } ni_duid_format_hex(&node->cdata, duid); if ((fp = fopen(filename, "w")) == NULL) { ni_error("%s: unable to open file for writing: %m", filename); } else if ((rv = xml_node_print(node, fp)) < 0) { ni_error("%s: unable to write %s xml representation", filename, name); } xml_node_free(node); fclose(fp); if(rv < 0) unlink(filename); return rv; }
static void ni_dhcp4_tester_protocol_event(enum ni_dhcp4_event ev, const ni_dhcp4_device_t *dev, ni_addrconf_lease_t *lease) { ni_debug_dhcp("%s(ev=%u, dev=%s[%u], config-uuid=%s)", __func__, ev, dev->ifname, dev->link.ifindex, dev->config ? ni_uuid_print(&dev->config->uuid) : "<none>"); switch (ev) { case NI_DHCP4_EVENT_ACQUIRED: if (lease && lease->state == NI_ADDRCONF_STATE_GRANTED) { FILE *fp = stdout; if (dhcp4_tester_opts.output != NULL) { fp = fopen(dhcp4_tester_opts.output, "w"); if (!fp) { ni_error("Cannot open %s for output", dhcp4_tester_opts.output); dhcp4_tester_status = NI_WICKED_RC_ERROR; return; } } if (dhcp4_tester_opts.outfmt == NI_DHCP4_TESTER_OUT_LEASE_XML) { xml_node_t *xml = NULL; if (ni_addrconf_lease_to_xml(lease, &xml, dev->ifname) != 0) { if (dhcp4_tester_opts.output) fclose(fp); dhcp4_tester_status = NI_WICKED_RC_ERROR; return; } xml_node_print(xml, fp); xml_node_free(xml); } else { ni_leaseinfo_dump(fp, lease, dev->ifname, NULL); } fflush(fp); if (dhcp4_tester_opts.output) fclose(fp); dhcp4_tester_status = NI_WICKED_RC_SUCCESS; } break; default: break; } }
static int __ni_addrconf_lease_static_to_xml(const ni_addrconf_lease_t *lease, xml_node_t *node) { xml_node_t *data; int ret = 1; if (!lease || !node) return -1; if (!(data = ni_addrconf_lease_xml_new_type_node(lease, NULL))) return -1; if ((ret = ni_addrconf_lease_static_data_to_xml(lease, data)) == 0) xml_node_add_child(node, data); else xml_node_free(data); return ret; }
int ni_dhcp6_lease_to_xml(const ni_addrconf_lease_t *lease, xml_node_t *node, const char *ifname) { xml_node_t *data; int ret; if (!lease || !node) return -1; if (!(data = ni_addrconf_lease_xml_new_type_node(lease, NULL))) return -1; if ((ret = ni_dhcp6_lease_data_to_xml(lease, data, ifname)) == 0) xml_node_add_child(node, data); else xml_node_free(data); return ret; }
void xml_node_delete_callbacked(xml_node_t *node, void (*callback)(void *)) { xml_node_t *child, *child_next; if (node->client_data && callback) callback(node->client_data); xml_node_unlink(node); /* Delete children. */ for (child = node->children; child; child = child_next) { child_next = child->next; child->parent = NULL; xml_node_delete_callbacked(child, callback); } /* Free memory taken by node. */ xml_node_free(node); }
ni_bool_t ni_iaid_map_del_iaid(ni_iaid_map_t *map, unsigned int iaid) { xml_node_t *root, *node = NULL; unsigned int curr; if (!(root = ni_iaid_map_root_node(map))) return FALSE; while ((node = ni_iaid_map_next_node(root, node))) { if (!ni_iaid_map_node_to_iaid(node, &curr) || iaid != curr) continue; xml_node_detach(node); xml_node_free(node); return TRUE; } return FALSE; }
int ni_addrconf_lease_routes_data_to_xml(const ni_addrconf_lease_t *lease, xml_node_t *node) { ni_route_table_t *tab; ni_route_nexthop_t *nh; xml_node_t *route, *hop; ni_route_t *rp; unsigned int count = 0; unsigned int i; /* A very limitted view */ for (tab = lease->routes; tab; tab = tab->next) { if (tab->tid != 254) /* RT_TABLE_MAIN for now */ continue; for (i = 0; i < tab->routes.count; ++i) { if (!(rp = tab->routes.data[i])) continue; route = xml_node_new("route", NULL); if (ni_sockaddr_is_specified(&rp->destination)) { xml_node_new_element("destination", route, ni_sockaddr_prefix_print(&rp->destination, rp->prefixlen)); } for (nh = &rp->nh; nh; nh = nh->next) { if (!ni_sockaddr_is_specified(&nh->gateway)) continue; hop = xml_node_new("nexthop", route); xml_node_new_element("gateway", hop, ni_sockaddr_print(&nh->gateway)); } if (route->children) { xml_node_add_child(node, route); count++; } else { xml_node_free(route); } } } return count ? 0 : 1; }
int ni_addrconf_lease_to_xml(const ni_addrconf_lease_t *lease, xml_node_t **result) { xml_node_t *node; int ret = -1; if (!lease || !result) { errno = EINVAL; return -1; } *result = NULL; /* initialize... */ node = xml_node_new(NI_ADDRCONF_LEASE_XML_NODE, NULL); switch (lease->type) { case NI_ADDRCONF_STATIC: case NI_ADDRCONF_AUTOCONF: case NI_ADDRCONF_INTRINSIC: if ((ret = __ni_addrconf_lease_info_to_xml(lease, node)) != 0) break; if ((ret = __ni_addrconf_lease_static_to_xml(lease, node)) != 0) break; break; case NI_ADDRCONF_DHCP: if ((ret = __ni_addrconf_lease_info_to_xml(lease, node)) != 0) break; if ((ret = __ni_addrconf_lease_dhcp_to_xml(lease, node)) != 0) break; break; default: ; /* fall through error */ } if (ret == 0) { *result = node; } else { xml_node_free(node); } return ret; }
static xml_node_t * __ni_ifup_generate_match_type_dev(ni_netdev_t *dev) { const char *type; xml_node_t *ret; if (!dev || dev->link.type == NI_IFTYPE_UNKNOWN) return NULL; if (!(type = ni_linktype_type_to_name(dev->link.type))) return NULL; if (!(ret = xml_node_new(NI_NANNY_IFPOLICY_MATCH_COND_AND, NULL))) return NULL; if (!xml_node_new_element(NI_NANNY_IFPOLICY_MATCH_DEV, ret, dev->name) || !xml_node_new_element(NI_NANNY_IFPOLICY_MATCH_LINK_TYPE, ret, type)) { xml_node_free(ret); return NULL; } return ret; }
ni_bool_t ni_iaid_map_del_name(ni_iaid_map_t *map, const char *name) { xml_node_t *root, *node = NULL; const char *attr; if (ni_string_empty(name)) return FALSE; if (!(root = ni_iaid_map_root_node(map))) return FALSE; while ((node = ni_iaid_map_next_node(root, node))) { attr = xml_node_get_attr(node, NI_CONFIG_DEFAULT_IAID_DEVICE); if (!ni_string_eq(name, attr)) continue; xml_node_detach(node); xml_node_free(node); return TRUE; } return FALSE; }
/* * Provide all possible descriptions of a device. */ xml_node_t * ni_objectmodel_get_names(const ni_dbus_object_t *object) { xml_node_t *result; unsigned int i; ni_bool_t ok = FALSE; result = xml_node_new(NULL, NULL); for (i = 0; i < ni_objectmodel_ns_count; ++i) { ni_objectmodel_ns_t *ns; ns = ni_objectmodel_ns_list[i]; if (ns->describe && ns->describe(ns, object, result)) ok = TRUE; } if (!ok) { xml_node_free(result); result = NULL; } return result; }
/** * @brief Return the contact/abuse page with a marked error indicator for the user in the event of a user submission error. * @param branch a null-terminated string containing the source of the error: "Abuse" or "Contact" * @param xpath a null-terminated string containing the xpath of the element in the returned page that should be colored red. * @param id a null-terminated string containing the id of the error text <span> element to be added to the document. * @param message a null-terminated string containing the actual error message text to be displayed to the user. * @return NULL on failure, or a pointer to the processed contact page with error message on success. */ http_page_t * contact_business_add_error(chr_t *branch, uchr_t *xpath, uchr_t *id, uchr_t *message) { http_page_t *page = NULL; xmlNodePtr node, error; xmlXPathObjectPtr xpath_obj; // We are here either for the contact or abuse page. if (!st_cmp_cs_eq(NULLER(branch), PLACER("Abuse", 5)) && !((page = http_page_get("contact/abuse")))) { return NULL; } else if (!page && !(page = http_page_get("contact/contact"))) { return NULL; } if ((xpath_obj = xml_xpath_eval(xpath, page->xpath_ctx)) && xpath_obj->nodesetval && xpath_obj->nodesetval->nodeNr && xpath_obj->nodesetval->nodeTab[0]) { node = (xmlNodePtr)xpath_obj->nodesetval->nodeTab[0]; // Make the field red. xml_node_set_property(node, (uchr_t *)"class", (uchr_t *)"red"); // Add the error message. if ((error = xml_node_new((uchr_t *)"span"))) { xml_node_set_property(error, (uchr_t *)"id", id); xml_node_set_content(error, message); if (!(xml_node_add_sibling(node, error))) { xml_node_free(error); } } } return page; }
static ni_bool_t ni_ifup_hire_nanny(ni_ifworker_t *w) { xml_node_t *ifcfg = NULL, *policy = NULL; ni_netdev_t *dev; unsigned int i; ni_bool_t rv = FALSE; char *pname; if (!w) return rv; ni_debug_application("%s: hiring nanny", w->name); /* Create a config duplicate for a policy */ ifcfg = xml_node_clone(w->config.node, NULL); if (!ifcfg) goto error; pname = ni_ifpolicy_name_from_ifname(w->name); ni_debug_application("%s: converting config into policy '%s'", w->name, pname); policy = ni_convert_cfg_into_policy_node(ifcfg, __ni_ifup_generate_match(w), pname, w->config.origin); ni_string_free(&pname); if (!policy) { policy = ifcfg; /* Free cloned config*/ goto error; } #if 0 /* Do we need this? */ /* Add link type to match node*/ if (dev) { ni_debug_application("%s: adding link type (%s) to match", w->name, ni_linktype_type_to_name(dev->link.type)); ni_ifpolicy_match_add_link_type(policy, dev->link.type); } ni_debug_application("%s: adding minimum device state (%s) to match", w->name, ni_ifworker_state_name(w->fsm.state)); /* Add minimum device state to match node */ if (!ni_ifpolicy_match_add_min_state(policy, w->fsm.state)) goto error; #endif dev = w->device; if (dev) { ni_debug_application("%s: enabling device for nanny", w->name); if (!ni_nanny_call_device_enable(w->name)) goto error; } ni_debug_application("%s: adding policy %s to nanny", w->name, xml_node_get_attr(policy, NI_NANNY_IFPOLICY_NAME)); if (ni_nanny_addpolicy_node(policy, w->config.origin) <= 0) { ni_nanny_call_device_disable(w->name); goto error; } ni_debug_application("%s: nanny hired!", w->name); ni_ifworker_success(w); /* Append policies for all children in case they contain some special options */ for (i = 0; i < w->children.count; i++) { ni_ifworker_t *child = w->children.data[i]; if (!ni_ifup_hire_nanny(child)) ni_error("%s: unable to apply configuration to nanny", child->name); } rv = TRUE; error: if (!rv) ni_ifworker_fail(w, "%s: unable to apply configuration to nanny", w->name); xml_node_free(policy); return rv; }
ni_bool_t xml_process_element_nested(xml_reader_t *xr, xml_node_t *cur, unsigned int nesting) { ni_stringbuf_t tokenValue, identifier; xml_token_type_t token; xml_node_t *child; ni_stringbuf_init(&tokenValue); ni_stringbuf_init(&identifier); while (1) { token = xml_get_token(xr, &tokenValue); switch (token) { case CData: /* process element content */ xml_node_set_cdata(cur, tokenValue.string); break; case LeftAngleExclam: /* Most likely <!DOCTYPE ...> */ if (!xml_get_identifier(xr, &identifier)) { xml_parse_error(xr, "Bad element: tag open <! not followed by identifier"); goto error; } if (strcmp(identifier.string, "DOCTYPE")) { xml_parse_error(xr, "Unexpected element: <!%s ...> not supported", identifier.string); goto error; } while (1) { token = xml_get_token(xr, &identifier); if (token == RightAngle) break; if (token == Identifier && !xr->doctype) ni_string_dup(&xr->doctype, identifier.string); if (token != Identifier && token != QuotedString) { xml_parse_error(xr, "Error parsing <!DOCTYPE ...> attributes"); goto error; } } break; case LeftAngle: /* New element start */ if (!xml_get_identifier(xr, &identifier)) { xml_parse_error(xr, "Bad element: tag open < not followed by identifier"); goto error; } child = xml_node_new(identifier.string, cur); if (xr->shared_location) child->location = xml_location_new(xr->shared_location, xr->lineCount); token = xml_get_tag_attributes(xr, child); if (token == None) { xml_parse_error(xr, "Error parsing <%s ...> tag attributes", child->name); goto error; } else if (token == RightAngle) { /* Handle <foo>...</foo> */ xml_debug("%*.*s<%s>\n", nesting, nesting, "", child->name); if (!xml_process_element_nested(xr, child, nesting + 2)) goto error; } else if (token == RightAngleSlash) { /* We parsed a "<foo/>" element - nothing left to do, we're done */ xml_debug("%*.*s<%s/>\n", nesting, nesting, "", child->name); } else { xml_parse_error(xr, "Unexpected token %s at end of <%s ...", xml_token_name(token), child->name); goto error; } break; case LeftAngleSlash: /* Element end */ if (!xml_get_identifier(xr, &identifier)) { xml_parse_error(xr, "Bad element: end tag open </ not followed by identifier"); goto error; } if (xml_get_token(xr, &tokenValue) != RightAngle) { xml_parse_error(xr, "Bad element: </%s - missing tag close", identifier.string); goto error; } if (cur->parent == NULL) { xml_parse_error(xr, "Unexpected </%s> tag", identifier.string); goto error; } if (strcmp(cur->name, identifier.string)) { xml_parse_error(xr, "Closing tag </%s> does not match <%s>", identifier.string, cur->name); goto error; } xml_debug("%*.*s</%s>\n", nesting, nesting, "", cur->name); goto success; case LeftAngleQ: /* New PI node starts here */ if (!xml_get_identifier(xr, &identifier)) { xml_parse_error(xr, "Bad element: tag open <? not followed by identifier"); goto error; } child = xml_node_new(identifier.string, NULL); if (xr->shared_location) child->location = xml_location_new(xr->shared_location, xr->lineCount); token = xml_get_tag_attributes(xr, child); if (token == None) { xml_parse_error(xr, "Error parsing <?%s ...?> tag attributes", child->name); xml_node_free(child); goto error; } else if (token == RightAngleQ) { xml_debug("%*.*s<%s>\n", nesting, nesting, "", child->name); xml_process_pi_node(xr, child); xml_node_free(child); } else { xml_parse_error(xr, "Unexpected token %s at end of <?%s ...", xml_token_name(token), child->name); xml_node_free(child); goto error; } break; case EndOfDocument: if (cur->parent) { xml_parse_error(xr, "End of document while processing element <%s>", cur->name); goto error; } goto success; case None: /* parser error */ goto error; default: xml_parse_error(xr, "Unexpected token %s", xml_token_name(token)); goto error; } } success: ni_stringbuf_destroy(&tokenValue); ni_stringbuf_destroy(&identifier); return TRUE; error: ni_stringbuf_destroy(&tokenValue); ni_stringbuf_destroy(&identifier); return FALSE; }
static int process(struct hs20_svc *ctx) { int dmacc = 0; xml_node_t *soap, *spp, *resp; char *user, *realm, *post, *str; ctx->addr = getenv("HS20ADDR"); if (ctx->addr) debug_print(ctx, 1, "Connection from %s", ctx->addr); user = getenv("HS20USER"); if (user && strlen(user) == 0) user = NULL; realm = getenv("HS20REALM"); if (realm == NULL) { debug_print(ctx, 1, "HS20REALM not set"); return -1; } post = getenv("HS20POST"); if (post == NULL) { debug_print(ctx, 1, "HS20POST not set"); return -1; } soap = xml_node_from_buf(ctx->xml, post); if (soap == NULL) { debug_print(ctx, 1, "Could not parse SOAP data"); return -1; } debug_dump_node(ctx, "Received SOAP message", soap); spp = soap_get_body(ctx->xml, soap); if (spp == NULL) { debug_print(ctx, 1, "Could not get SPP message"); xml_node_free(ctx->xml, soap); return -1; } debug_dump_node(ctx, "Received SPP message", spp); resp = hs20_spp_server_process(ctx, spp, user, realm, dmacc); xml_node_free(ctx->xml, soap); if (resp == NULL && user == NULL) { debug_print(ctx, 1, "Request HTTP authentication"); return 2; /* Request authentication */ } if (resp == NULL) { debug_print(ctx, 1, "No response"); return -1; } soap = soap_build_envelope(ctx->xml, resp); if (soap == NULL) { debug_print(ctx, 1, "SOAP envelope building failed"); return -1; } str = xml_node_to_str(ctx->xml, soap); xml_node_free(ctx->xml, soap); if (str == NULL) { debug_print(ctx, 1, "Could not get node string"); return -1; } printf("%s", str); free(str); return 0; }
/****************************************************************************** **函数名称: xml_mark_get_attr **功 能: 解析有属性的标签 **输入参数: ** ** stack: XML栈 ** parse: 解析文件缓存信息 **输出参数: **返 回: 0: 成功 !0: 失败 **实现描述: **注意事项: ** 1. 属性值可使用双引号或单引号确定属性值范围 ** 2. 转义符号的转换对应关系如下: ** < < 小于 ** > > 大于 ** & & 和号 ** ' ' 单引号 ** " " 引号 **作 者: # Qifeng.zou # 2013.02.18 # **修 改: # Qifeng.zou # 2014.01.06 # ******************************************************************************/ static int xml_mark_get_attr(xml_tree_t *xml, Stack_t *stack, xml_parse_t *parse) { char border = '"'; xml_node_t *node, *top; int len, errflg = 0; const char *ptr = parse->ptr; #if defined(__XML_ESC_PARSE__) int ret, size; xml_esc_split_t split; const xml_esc_t *esc = NULL; memset(&split, 0, sizeof(split)); #endif /*__XML_ESC_PARSE__*/ /* 1. 获取正在处理的标签 */ top = (xml_node_t*)stack_gettop(stack); if (NULL == top) { log_error(xml->log, "Get stack top failed!"); return XML_ERR_STACK; } /* 3. 将属性节点依次加入标签子节点链表 */ do { /* 3.1 新建节点,并初始化 */ node = xml_node_creat(xml, XML_NODE_ATTR); if (NULL == node) { log_error(xml->log, "Create xml node failed!"); return XML_ERR_CREAT_NODE; } /* 3.2 获取属性名 */ while (XmlIsIgnoreChar(*ptr)) { ++ptr; }/* 跳过属性名之前无意义的空格 */ parse->ptr = ptr; while (XmlIsMarkChar(*ptr)) { ++ptr; } /* 查找属性名的边界 */ len = ptr - parse->ptr; node->name.str = (char *)xml->alloc(xml->pool, (len+1)*sizeof(char)); if (NULL == node->name.str) { errflg = 1; log_error(xml->log, "Calloc failed!"); break; } memcpy(node->name.str, parse->ptr, len); node->name.len = len; node->name.str[len] = '\0'; /* 3.3 获取属性值 */ while (XmlIsIgnoreChar(*ptr)) { ++ptr; } /* 跳过=之前的无意义字符 */ if (!XmlIsEqualChar(*ptr)) { /* 不为等号,则格式错误 */ errflg = 1; log_error(xml->log, "Attribute format is incorrect![%-.32s]", parse->ptr); break; } ptr++; /* 跳过"=" */ while (XmlIsIgnoreChar(*ptr)) { ++ptr; }/* 跳过=之后的无意义字符 */ /* 判断是单引号(')还是双引号(")为属性的边界 */ if (XmlIsQuotChar(*ptr) || XmlIsSQuotChar(*ptr)) { border = *ptr; } else { /* 不为 双/单 引号,则格式错误 */ errflg = 1; log_error(xml->log, "XML format is wrong![%-.32s]", parse->ptr); break; } ptr++; parse->ptr = ptr; while ((*ptr != border) && !XmlIsStrEndChar(*ptr))/* 计算 双/单 引号之间的数据长度 */ { #if defined(__XML_ESC_PARSE__) if (XmlIsAndChar(*ptr)) { /* 判断并获取转义字串类型及相关信息 */ esc = xml_esc_get(ptr); /* 对包含有转义字串的字串进行切割 */ ret = xml_esc_split(xml, esc, parse->ptr, ptr-parse->ptr+1, &split); if (XML_OK != ret) { errflg = 1; log_error(xml->log, "Parse forwad string failed!"); break; } ptr += esc->len; parse->ptr = ptr; } else #endif /*__XML_ESC_PARSE__*/ { ptr++; } } if (*ptr != border) { errflg = 1; log_error(xml->log, "Mismatch border [%c]![%-.32s]", border, parse->ptr); break; } len = ptr - parse->ptr; ptr++; /* 跳过" */ #if defined(__XML_ESC_PARSE__) if (NULL != split.head) { size = xml_esc_size(&split); size += len+1; node->value = (char *)xml->alloc(xml->pool, size); if (NULL == node->value) { errflg = 1; log_error(xml->log, "Alloc memory failed!"); break; } xml_esc_merge(&split, node->value); strncat(node->value, parse->ptr, len); xml_esc_free(&split); } else #endif /*__XML_ESC_PARSE__*/ { node->value.str = (char *)xml->alloc(xml->pool, len+1); if (NULL == node->value.str) { errflg = 1; log_error(xml->log, "Calloc failed!"); break; } memcpy(node->value.str, parse->ptr, len); node->value.len = len; node->value.str[len] = '\0'; } /* 3.4 将节点加入属性链表 */ if (NULL == top->tail) { /* 还没有孩子节点 */ top->child = node; } else { top->tail->next = node; } node->parent = top; top->tail = node; /* 3.5 指针向后移动 */ while (XmlIsIgnoreChar(*ptr)) { ++ptr; } }while (XmlIsMarkChar(*ptr)); #if defined(__XML_ESC_PARSE__) xml_esc_free(&split); #endif /*__XML_ESC_PARSE__*/ if (1 == errflg) { /* 防止内存泄漏 */ xml_node_free(xml, node); node = NULL; return XML_ERR_GET_ATTR; } parse->ptr = ptr; xml_set_attr_flag(top); return XML_OK; }