Merge branch 'collectd-4.10' into collectd-5.3
authorMarc Fournier <marc.fournier@camptocamp.com>
Tue, 19 May 2015 16:37:19 +0000 (18:37 +0200)
committerMarc Fournier <marc.fournier@camptocamp.com>
Tue, 19 May 2015 16:37:19 +0000 (18:37 +0200)
1  2 
src/curl_xml.c

diff --combined src/curl_xml.c
@@@ -28,7 -28,6 +28,7 @@@
  #include <libxml/parser.h>
  #include <libxml/tree.h>
  #include <libxml/xpath.h>
 +#include <libxml/xpathInternals.h>
  
  #include <curl/curl.h>
  
@@@ -59,14 -58,6 +59,14 @@@ struct cx_xpath_s /* {{{ *
  typedef struct cx_xpath_s cx_xpath_t;
  /* }}} */
  
 +struct cx_namespace_s /* {{{ */
 +{
 +  char *prefix;
 +  char *url;
 +};
 +typedef struct cx_namespace_s cx_namespace_t;
 +/* }}} */
 +
  struct cx_s /* {{{ */
  {
    char *instance;
    _Bool verify_peer;
    _Bool verify_host;
    char *cacert;
 +  char *post_body;
 +  struct curl_slist *headers;
 +
 +  cx_namespace_t *namespaces;
 +  size_t namespaces_num;
  
    CURL *curl;
    char curl_errbuf[CURL_ERROR_SIZE];
@@@ -174,7 -160,6 +174,7 @@@ static void cx_list_free (llist_t *list
  static void cx_free (void *arg) /* {{{ */
  {
    cx_t *db;
 +  size_t i;
  
    DEBUG ("curl_xml plugin: cx_free (arg = %p);", arg);
  
    sfree (db->pass);
    sfree (db->credentials);
    sfree (db->cacert);
 +  sfree (db->post_body);
 +  curl_slist_free_all (db->headers);
 +
 +  for (i = 0; i < db->namespaces_num; i++)
 +  {
 +    sfree (db->namespaces[i].prefix);
 +    sfree (db->namespaces[i].url);
 +  }
 +  sfree (db->namespaces);
  
    sfree (db);
  } /* }}} void cx_free */
  
 +static int cx_config_append_string (const char *name, struct curl_slist **dest, /* {{{ */
 +    oconfig_item_t *ci)
 +{
 +  if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
 +  {
 +    WARNING ("curl_xml plugin: `%s' needs exactly one string argument.", name);
 +    return (-1);
 +  }
 +
 +  *dest = curl_slist_append(*dest, ci->values[0].value.string);
 +  if (*dest == NULL)
 +    return (-1);
 +
 +  return (0);
 +} /* }}} int cx_config_append_string */
 +
  static int cx_check_type (const data_set_t *ds, cx_xpath_t *xpath) /* {{{ */
  {
    if (!ds)
@@@ -265,8 -225,7 +265,8 @@@ static xmlXPathObjectPtr cx_evaluate_xp
  
  static int cx_if_not_text_node (xmlNodePtr node) /* {{{ */
  {
 -  if (node->type == XML_TEXT_NODE || node->type == XML_ATTRIBUTE_NODE)
 +  if (node->type == XML_TEXT_NODE || node->type == XML_ATTRIBUTE_NODE ||
 +      node->type == XML_ELEMENT_NODE)
      return (0);
  
    WARNING ("curl_xml plugin: "
@@@ -341,6 -300,7 +341,7 @@@ static int cx_handle_single_value_xpat
  
    /* free up object */
    xmlXPathFreeObject (values_node_obj);
+   sfree (node_value);
  
    /* We have reached here which means that
     * we have got something to work */
@@@ -383,9 -343,9 +384,9 @@@ static int cx_handle_instance_xpath (xm
    memset (vl->type_instance, 0, sizeof (vl->type_instance));
  
    /* If the base xpath returns more than one block, the result is assumed to be
 -   * a table. The `Instnce' option is not optional in this case. Check for the
 +   * a table. The `Instance' option is not optional in this case. Check for the
     * condition and inform the user. */
-   if (is_table)
+   if (is_table && (xpath->instance == NULL))
    {
      WARNING ("curl_xml plugin: "
          "Base-XPath %s is a table (more than one result was returned), "
    if (xpath->instance_prefix != NULL)
    {
      if (instance_node != NULL)
+     {
+       char *node_value = (char *) xmlNodeGetContent(instance_node->nodeTab[0]);
        ssnprintf (vl->type_instance, sizeof (vl->type_instance),"%s%s",
-           xpath->instance_prefix, (char *) xmlNodeGetContent(instance_node->nodeTab[0]));
+           xpath->instance_prefix, node_value);
+       sfree (node_value);
+     }
      else
        sstrncpy (vl->type_instance, xpath->instance_prefix,
            sizeof (vl->type_instance));
      /* If instance_prefix and instance_node are NULL, then
       * don't set the type_instance */
      if (instance_node != NULL)
-       sstrncpy (vl->type_instance, (char *) xmlNodeGetContent(instance_node->nodeTab[0]),
-           sizeof (vl->type_instance));
+     {
+       char *node_value = (char *) xmlNodeGetContent(instance_node->nodeTab[0]);
+       sstrncpy (vl->type_instance, node_value, sizeof (vl->type_instance));
+       sfree (node_value);
+     }
    }
  
    /* Free `instance_node_obj' this late, because `instance_node' points to
@@@ -561,7 -528,6 +569,7 @@@ static int cx_parse_stats_xml(xmlChar* 
    int status;
    xmlDocPtr doc;
    xmlXPathContextPtr xpath_ctx;
 +  size_t i;
  
    /* Load the XML */
    doc = xmlParseDoc(xml);
      return (-1);
    }
  
 +  for (i = 0; i < db->namespaces_num; i++)
 +  {
 +    cx_namespace_t const *ns = db->namespaces + i;
 +    status = xmlXPathRegisterNs (xpath_ctx,
 +        BAD_CAST ns->prefix, BAD_CAST ns->url);
 +    if (status != 0)
 +    {
 +      ERROR ("curl_xml plugin: "
 +          "unable to register NS with prefix=\"%s\" and href=\"%s\"\n",
 +          ns->prefix, ns->url);
 +      xmlXPathFreeContext(xpath_ctx);
 +      xmlFreeDoc (doc);
 +      return (status);
 +    }
 +  }
 +
    status = cx_handle_parsed_xml (doc, xpath_ctx, db);
    /* Cleanup */
    xmlXPathFreeContext(xpath_ctx);
@@@ -785,46 -735,6 +793,46 @@@ static int cx_config_add_xpath (cx_t *d
    return (status);
  } /* }}} int cx_config_add_xpath */
  
 +static int cx_config_add_namespace (cx_t *db, /* {{{ */
 +    oconfig_item_t *ci)
 +{
 +  cx_namespace_t *ns;
 +
 +  if ((ci->values_num != 2)
 +      || (ci->values[0].type != OCONFIG_TYPE_STRING)
 +      || (ci->values[1].type != OCONFIG_TYPE_STRING))
 +  {
 +    WARNING ("curl_xml plugin: The `Namespace' option "
 +             "needs exactly two string arguments.");
 +    return (EINVAL);
 +  }
 +
 +  ns = realloc (db->namespaces, sizeof (*db->namespaces)
 +      * (db->namespaces_num + 1));
 +  if (ns == NULL)
 +  {
 +    ERROR ("curl_xml plugin: realloc failed.");
 +    return (ENOMEM);
 +  }
 +  db->namespaces = ns;
 +  ns = db->namespaces + db->namespaces_num;
 +  memset (ns, 0, sizeof (*ns));
 +
 +  ns->prefix = strdup (ci->values[0].value.string);
 +  ns->url = strdup (ci->values[1].value.string);
 +
 +  if ((ns->prefix == NULL) || (ns->url == NULL))
 +  {
 +    sfree (ns->prefix);
 +    sfree (ns->url);
 +    ERROR ("curl_xml plugin: strdup failed.");
 +    return (ENOMEM);
 +  }
 +
 +  db->namespaces_num++;
 +  return (0);
 +} /* }}} int cx_config_add_namespace */
 +
  /* Initialize db->curl */
  static int cx_init_curl (cx_t *db) /* {{{ */
  {
                      db->verify_host ? 2L : 0L);
    if (db->cacert != NULL)
      curl_easy_setopt (db->curl, CURLOPT_CAINFO, db->cacert);
 +  if (db->headers != NULL)
 +    curl_easy_setopt (db->curl, CURLOPT_HTTPHEADER, db->headers);
 +  if (db->post_body != NULL)
 +    curl_easy_setopt (db->curl, CURLOPT_POSTFIELDS, db->post_body);
  
    return (0);
  } /* }}} int cx_init_curl */
@@@ -935,12 -841,6 +943,12 @@@ static int cx_config_add_url (oconfig_i
        status = cf_util_get_string (child, &db->cacert);
      else if (strcasecmp ("xpath", child->key) == 0)
        status = cx_config_add_xpath (db, child);
 +    else if (strcasecmp ("Header", child->key) == 0)
 +      status = cx_config_append_string ("Header", &db->headers, child);
 +    else if (strcasecmp ("Post", child->key) == 0)
 +      status = cf_util_get_string (child, &db->post_body);
 +    else if (strcasecmp ("Namespace", child->key) == 0)
 +      status = cx_config_add_namespace (db, child);
      else
      {
        WARNING ("curl_xml plugin: Option `%s' not allowed here.", child->key);