xmlNodeSetPtr getXNodes(xmlXPathContextPtr context, const gchar *xpath) { xmlXPathObjectPtr xobj = xmlXPathEvalExpression(BAD_CAST(xpath), context); xmlNodeSetPtr ret = xobj->nodesetval; xmlXPathFreeNodeSetList(xobj); return ret; }
/** * @arg xpath XPath expression to evaluate * @doc document over which to evaluate * @arg pctxt can be NULL * @return list of matching nodes. The caller will have to free it using xmlXPathFreeNodeSet(). */ xmlNodeSetPtr find_node_set(const char *xpath, const xmlDocPtr doc, xmlXPathParserContextPtr *pctxt) { xmlXPathContextPtr ctxt = xmlXPathNewContext(doc); if(!ctxt) { g_printerr(G_STRLOC ": Failed to allocate XPathContext!\n"); return NULL; } if(xmlXPathRegisterNs(ctxt, (xmlChar *) FREEDICT_EDITOR_NAMESPACE_PREFIX, (xmlChar *) FREEDICT_EDITOR_NAMESPACE)) { g_printerr("Warning: Unable to register XSLT-Namespace prefix \"%s\"" " for URI \"%s\"\n", FREEDICT_EDITOR_NAMESPACE_PREFIX, FREEDICT_EDITOR_NAMESPACE); } if(xmlXPathRegisterFuncNS(ctxt, (xmlChar *) "unbalanced-braces", (xmlChar *) FREEDICT_EDITOR_NAMESPACE, freedict_xpath_extension_unbalanced_braces)) g_printerr("Warning: Unable to register XPath extension function " "\"unbalanced-braces\" for URI \"%s\"\n", FREEDICT_EDITOR_NAMESPACE); xmlXPathParserContextPtr pctxt2; if(!pctxt) pctxt = &pctxt2; xmlXPathObjectPtr xpobj = my_xmlXPathEvalExpression((xmlChar *) xpath, ctxt, pctxt); if(!xpobj) { g_printerr(G_STRLOC ": No XPathObject!\n"); xmlXPathFreeContext(ctxt); return NULL; } if(!(xpobj->nodesetval)) { g_printerr(G_STRLOC ": No nodeset!\n"); xmlXPathFreeObject(xpobj); xmlXPathFreeContext(ctxt); return NULL; } if(!(xpobj->nodesetval->nodeNr)) { //g_printerr("0 nodes!\n"); xmlXPathFreeObject(xpobj); xmlXPathFreeContext(ctxt); return NULL; } xmlXPathFreeContext(ctxt); xmlNodeSetPtr nodes = xmlMalloc(sizeof(xmlNodeSet)); // XXX copying is slow... memcpy(nodes, xpobj->nodesetval, sizeof(xmlNodeSet)); // I don't understand the naming of this function. According to the // documentation, it frees xpobj, but not its nodelist, if it // contained one. So it should be called xmlXPathFreeObjectButNotNodeSetList(). xmlXPathFreeNodeSetList(xpobj); return nodes; }
/** * Evaluates an XPath expression on the passed-in context. * * @param pContext Pointer to the context. * @param pczExpression The XPath expression to evaluate * * @return xmlNodeSetPtr pointing to the resulting node set, must be * freed by the caller. */ static xmlNodeSetPtr evaluateXPathExpression(xmlXPathContextPtr pContext, const char * pczExpression) { xmlXPathObjectPtr pObject = xmlXPathEval(CONSTXMLCHAR_P(pczExpression), pContext); if (!pObject || !pObject->nodesetval) { return NULL; } xmlNodeSetPtr pNodeSet = pObject->nodesetval; xmlXPathFreeNodeSetList(pObject); return pNodeSet; }
static void ruby_funcall(xmlXPathParserContextPtr ctx, int nargs) { VALUE xpath_handler = Qnil; VALUE result; VALUE *argv; VALUE doc; VALUE node_set = Qnil; xmlNodeSetPtr xml_node_set = NULL; xmlXPathObjectPtr obj; int i; nokogiriNodeSetTuple *node_set_tuple; assert(ctx); assert(ctx->context); assert(ctx->context->userData); assert(ctx->context->doc); assert(DOC_RUBY_OBJECT_TEST(ctx->context->doc)); xpath_handler = (VALUE)(ctx->context->userData); argv = (VALUE *)calloc((size_t)nargs, sizeof(VALUE)); for (i = 0 ; i < nargs ; ++i) { rb_gc_register_address(&argv[i]); } doc = DOC_RUBY_OBJECT(ctx->context->doc); if (nargs > 0) { i = nargs - 1; do { obj = valuePop(ctx); switch(obj->type) { case XPATH_STRING: argv[i] = NOKOGIRI_STR_NEW2(obj->stringval); break; case XPATH_BOOLEAN: argv[i] = obj->boolval == 1 ? Qtrue : Qfalse; break; case XPATH_NUMBER: argv[i] = rb_float_new(obj->floatval); break; case XPATH_NODESET: argv[i] = Nokogiri_wrap_xml_node_set(obj->nodesetval, doc); break; default: argv[i] = NOKOGIRI_STR_NEW2(xmlXPathCastToString(obj)); } xmlXPathFreeNodeSetList(obj); } while(i-- > 0); } result = rb_funcall2( xpath_handler, rb_intern((const char *)ctx->context->function), nargs, argv ); for (i = 0 ; i < nargs ; ++i) { rb_gc_unregister_address(&argv[i]); } free(argv); switch(TYPE(result)) { case T_FLOAT: case T_BIGNUM: case T_FIXNUM: xmlXPathReturnNumber(ctx, NUM2DBL(result)); break; case T_STRING: xmlXPathReturnString( ctx, (xmlChar *)xmlXPathWrapCString(StringValuePtr(result)) ); break; case T_TRUE: xmlXPathReturnTrue(ctx); break; case T_FALSE: xmlXPathReturnFalse(ctx); break; case T_NIL: break; case T_ARRAY: { VALUE args[2]; args[0] = doc; args[1] = result; node_set = rb_class_new_instance(2, args, cNokogiriXmlNodeSet); Data_Get_Struct(node_set, nokogiriNodeSetTuple, node_set_tuple); xml_node_set = node_set_tuple->node_set; xmlXPathReturnNodeSet(ctx, xmlXPathNodeSetMerge(NULL, xml_node_set)); } break; case T_DATA: if(rb_obj_is_kind_of(result, cNokogiriXmlNodeSet)) { Data_Get_Struct(result, nokogiriNodeSetTuple, node_set_tuple); xml_node_set = node_set_tuple->node_set; /* Copy the node set, otherwise it will get GC'd. */ xmlXPathReturnNodeSet(ctx, xmlXPathNodeSetMerge(NULL, xml_node_set)); break; } default: rb_raise(rb_eRuntimeError, "Invalid return type"); } }
/* * call-seq: * evaluate(search_path, handler = nil) * * Evaluate the +search_path+ returning an XML::XPath object. */ static VALUE evaluate(int argc, VALUE *argv, VALUE self) { VALUE search_path, xpath_handler; VALUE thing = Qnil; xmlXPathContextPtr ctx; xmlXPathObjectPtr xpath; xmlChar *query; Data_Get_Struct(self, xmlXPathContext, ctx); if(rb_scan_args(argc, argv, "11", &search_path, &xpath_handler) == 1) xpath_handler = Qnil; query = (xmlChar *)StringValuePtr(search_path); if(Qnil != xpath_handler) { /* FIXME: not sure if this is the correct place to shove private data. */ ctx->userData = (void *)xpath_handler; xmlXPathRegisterFuncLookup(ctx, lookup, (void *)xpath_handler); } xmlResetLastError(); xmlSetStructuredErrorFunc(NULL, xpath_exception_handler); /* For some reason, xmlXPathEvalExpression will blow up with a generic error */ /* when there is a non existent function. */ xmlSetGenericErrorFunc(NULL, xpath_generic_exception_handler); xpath = xmlXPathEvalExpression(query, ctx); xmlSetStructuredErrorFunc(NULL, NULL); xmlSetGenericErrorFunc(NULL, NULL); if(xpath == NULL) { VALUE xpath = rb_const_get(mNokogiriXml, rb_intern("XPath")); VALUE klass = rb_const_get(xpath, rb_intern("SyntaxError")); xmlErrorPtr error = xmlGetLastError(); rb_exc_raise(Nokogiri_wrap_xml_syntax_error(klass, error)); } assert(ctx->doc); assert(DOC_RUBY_OBJECT_TEST(ctx->doc)); switch(xpath->type) { case XPATH_STRING: thing = NOKOGIRI_STR_NEW2(xpath->stringval); break; case XPATH_NODESET: if(NULL == xpath->nodesetval) { thing = Nokogiri_wrap_xml_node_set(xmlXPathNodeSetCreate(NULL), DOC_RUBY_OBJECT(ctx->doc)); } else { thing = Nokogiri_wrap_xml_node_set(xpath->nodesetval, DOC_RUBY_OBJECT(ctx->doc)); } break; case XPATH_NUMBER: thing = rb_float_new(xpath->floatval); break; case XPATH_BOOLEAN: thing = xpath->boolval == 1 ? Qtrue : Qfalse; break; default: thing = Nokogiri_wrap_xml_node_set(xmlXPathNodeSetCreate(NULL), DOC_RUBY_OBJECT(ctx->doc)); } xmlXPathFreeNodeSetList(xpath); return thing; }
int cloudfs_connect() { long response = -1; curl_slist *headers = NULL; CURL *curl = curl_easy_init(); char postdata[8192] = ""; xmlNode *top_node = NULL, *service_node = NULL, *endpoint_node = NULL; xmlParserCtxtPtr xmlctx = NULL; if(reconnect_args.token[0] != '\0' && reconnect_args.endpoint[0] != '\0') { strncpy(storage_token, reconnect_args.token, sizeof(storage_token)); strncpy(storage_url, reconnect_args.endpoint, sizeof(storage_url)); return 1; } pthread_mutex_lock(&pool_mut); storage_token[0] = storage_url[0] = '\0'; if (reconnect_args.auth_version == 2) { if (reconnect_args.username[0] && reconnect_args.tenant[0] && reconnect_args.password[0]) { snprintf(postdata, sizeof(postdata), "<?xml version=\"1.0\" encoding" "=\"UTF-8\"?><auth xmlns=\"http://docs.openstack.org/identity/ap" "i/v2.0\" tenantName=\"%s\"><passwordCredentials username=\"%s\"" " password=\"%s\"/></auth>", reconnect_args.tenant, reconnect_args.username, reconnect_args.password); } else if (reconnect_args.username[0] && reconnect_args.password[0]) { snprintf(postdata, sizeof(postdata), "<?xml version=\"1.0\" encoding" "=\"UTF-8\"?><auth><apiKeyCredentials xmlns=\"http://docs.racksp" "ace.com/identity/api/ext/RAX-KSKEY/v1.0\" username=\"%s\" apiKe" "y=\"%s\"/></auth>", reconnect_args.username, reconnect_args.password); } else { debugf("Unable to determine auth scheme."); abort(); } debugf("%s", postdata); add_header(&headers, "Content-Type", "application/xml"); add_header(&headers, "Accept", "application/xml"); curl_easy_setopt(curl, CURLOPT_POST, 1); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postdata); curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strlen(postdata)); xmlctx = xmlCreatePushParserCtxt(NULL, NULL, "", 0, NULL); curl_easy_setopt(curl, CURLOPT_WRITEDATA, xmlctx); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &xml_dispatch); } else { add_header(&headers, "X-Auth-User", reconnect_args.username); add_header(&headers, "X-Auth-Key", reconnect_args.password); curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, &header_dispatch); } curl_easy_setopt(curl, CURLOPT_VERBOSE, debug); curl_easy_setopt(curl, CURLOPT_URL, reconnect_args.authurl); curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(curl, CURLOPT_USERAGENT, USER_AGENT); curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, verify_ssl); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, verify_ssl); curl_easy_setopt(curl, CURLOPT_TIMEOUT, 10); curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 10); curl_easy_setopt(curl, CURLOPT_FORBID_REUSE, 1); debugf("Sending authentication request."); curl_easy_perform(curl); curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response); curl_slist_free_all(headers); curl_easy_cleanup(curl); if (reconnect_args.auth_version == 2) { xmlParseChunk(xmlctx, "", 0, 1); if (xmlctx->wellFormed && response >= 200 && response < 300) { xmlXPathContextPtr xpctx = xmlXPathNewContext(xmlctx->myDoc); xmlXPathRegisterNs(xpctx, "id", "http://docs.openstack.org/identity/api/v2.0"); xmlXPathObjectPtr obj; /* Determine default region if not configured */ if (!reconnect_args.region[0]) { obj = xmlXPathEval("/id:access/id:user", xpctx); if (obj && obj->nodesetval && obj->nodesetval->nodeNr > 0) { xmlChar *default_region = xmlGetProp(obj->nodesetval->nodeTab[0], "defaultRegion"); if (default_region && *default_region) { strncpy(reconnect_args.region, default_region, sizeof(reconnect_args.region)); xmlFree(default_region); } } xmlXPathFreeNodeSetList(obj); } debugf("Using region: %s", reconnect_args.region); if (reconnect_args.region[0]) { char path[1024]; snprintf(path, sizeof(path), "/id:access/id:serviceCatalog/id:service" "[@type='object-store']/id:endpoint[@region='%s']", reconnect_args.region); obj = xmlXPathEval(path, xpctx); } else obj = xmlXPathEval("/id:access/id:serviceCatalog/id:service" "[@type='object-store']/id:endpoint", xpctx); if (obj->nodesetval && obj->nodesetval->nodeNr > 0) { xmlChar *url; if (reconnect_args.use_snet) url = xmlGetProp(obj->nodesetval->nodeTab[0], "internalURL"); else url = xmlGetProp(obj->nodesetval->nodeTab[0], "publicURL"); strncpy(storage_url, url, sizeof(storage_url)); xmlFree(url); } else debugf("Unable to find endpoint"); xmlXPathFreeNodeSetList(obj); obj = xmlXPathEval("/id:access/id:token", xpctx); if (obj->nodesetval && obj->nodesetval->nodeNr > 0) { xmlChar *token_id = xmlGetProp(obj->nodesetval->nodeTab[0], "id"); strncpy(storage_token, token_id, sizeof(storage_token)); xmlFree(token_id); } xmlXPathFreeNodeSetList(obj); xmlXPathFreeContext(xpctx); debugf("storage_url: %s", storage_url); debugf("storage_token: %s", storage_token); } xmlFreeParserCtxt(xmlctx); } else if (reconnect_args.use_snet && storage_url[0]) rewrite_url_snet(storage_url); pthread_mutex_unlock(&pool_mut); return (response >= 200 && response < 300 && storage_token[0] && storage_url[0]); }