Пример #1
0
xmlNodeSetPtr getXNodes(xmlXPathContextPtr context, const gchar *xpath) {
  xmlXPathObjectPtr xobj = xmlXPathEvalExpression(BAD_CAST(xpath), context);
  xmlNodeSetPtr ret = xobj->nodesetval;
  xmlXPathFreeNodeSetList(xobj);

  return ret;
}
Пример #2
0
/**
 * @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;
}
Пример #3
0
/**
 * 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;
}
Пример #6
0
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]);
}