*/
#include "xmlrpc.h"
+#include "internal.h"
#include <libxml/nanohttp.h>
2) xmlRpcValueToSexpr
*/
-#define TODO do { } while (0)
-
static xmlNodePtr xmlFirstElement(xmlNodePtr node);
static xmlNodePtr xmlNextElement(xmlNodePtr node);
char *faultMessage;
};
+static void xmlRpcError(virErrorNumber error, const char *info, int value)
+{
+ const char *errmsg;
+
+ if (error == VIR_ERR_OK)
+ return;
+
+ errmsg = __virErrorMsg(error, info);
+ __virRaiseError(NULL, NULL, VIR_FROM_RPC, error, VIR_ERR_ERROR,
+ errmsg, info, NULL, value, 0, errmsg, info, value);
+}
+
static xmlRpcValuePtr xmlRpcValueNew(xmlRpcValueType type)
{
xmlRpcValuePtr ret = malloc(sizeof(*ret));
- if (ret)
- ret->kind = type;
+
+ if (!ret)
+ xmlRpcError(VIR_ERR_NO_MEMORY, "allocate value", sizeof(*ret));
+ else
+ ret->kind = type;
return ret;
}
static char *xmlGetText(xmlNodePtr node)
{
for (node = node->children; node; node = node->next)
- if (node->type == XML_TEXT_NODE)
- return strdup((const char *)node->content);
+ if (node->type == XML_TEXT_NODE) {
+ char *x = strdup((const char *)node->content);
+ if (!x)
+ xmlRpcError(VIR_ERR_NO_MEMORY, "copying node content",
+ strlen((const char *)node->content));
+ return x;
+ }
return NULL;
}
static xmlRpcValuePtr xmlRpcValueUnmarshalDateTime(xmlNodePtr node ATTRIBUTE_UNUSED)
{
/* we don't need this */
- TODO;
+ TODO
return NULL;
}
static xmlRpcValuePtr xmlRpcValueUnmarshalString(xmlNodePtr node)
{
xmlRpcValuePtr ret = xmlRpcValueNew(XML_RPC_STRING);
- ret->value.string = xmlGetText(node);
+
+ if (ret)
+ ret->value.string = xmlGetText(node);
return ret;
}
static xmlRpcValuePtr xmlRpcValueUnmarshalBase64(xmlNodePtr node ATTRIBUTE_UNUSED)
{
/* we don't need this */
- TODO;
+ TODO
return NULL;
}
{
xmlRpcValuePtr ret = xmlRpcValueNew(XML_RPC_INTEGER);
char *value = xmlGetText(node);
-
- ret->value.integer = atoi(value);
-
- free(value);
-
+
+ if (ret && value)
+ ret->value.integer = atoi(value);
+ if (value)
+ free(value);
return ret;
}
xmlRpcValuePtr ret = xmlRpcValueNew(XML_RPC_BOOLEAN);
char *value = xmlGetText(node);
- if (atoi(value))
+ if (!ret)
+ return NULL;
+ if (value && atoi(value))
ret->value.boolean = true;
else
ret->value.boolean = false;
-
- free(value);
-
+ if (value)
+ free(value);
return ret;
}
xmlRpcValuePtr ret = xmlRpcValueNew(XML_RPC_DOUBLE);
char *value = xmlGetText(node);
- ret->value.real = atof(value);
-
- free(value);
-
+ if (ret && value)
+ ret->value.real = atof(value);
+ if (value)
+ free(value);
return ret;
}
xmlNodePtr cur;
int n_elements = 0;
+ if (!ret)
+ return NULL;
+
for (cur = xmlFirstElement(node); cur; cur = xmlNextElement(cur))
n_elements += 1;
ret->value.array.elements = malloc(n_elements * sizeof(xmlRpcValue));
-
+ if (!ret->value.array.elements) {
+ xmlRpcError(VIR_ERR_NO_MEMORY, "allocate value array",
+ n_elements * sizeof(xmlRpcValue));
+ free(ret);
+ return NULL;
+ }
n_elements = 0;
for (cur = xmlFirstElement(node); cur; cur = xmlNextElement(cur)) {
ret->value.array.elements[n_elements] = xmlRpcValueUnmarshal(cur);
xmlRpcValueDictElementPtr ret = malloc(sizeof(*ret));
xmlNodePtr cur;
+ if (!ret) {
+ xmlRpcError(VIR_ERR_NO_MEMORY, "allocate dict", sizeof(*ret));
+ return NULL;
+ }
memset(ret, 0, sizeof(*ret));
for (cur = xmlFirstElement(node); cur; cur = xmlNextElement(cur)) {
} else if (xmlStrEqual(cur->name, BAD_CAST "value")) {
ret->value = xmlRpcValueUnmarshal(cur);
} else {
- /* What? */
+ xmlRpcError(VIR_ERR_XML_ERROR, "unexpected dict node", 0);
+ if (ret->name)
+ free(ret->name);
+ if (ret->value)
+ xmlRpcValueFree(ret->value);
+ free(ret);
+ return NULL;
}
}
xmlRpcValuePtr ret = xmlRpcValueNew(XML_RPC_STRUCT);
xmlNodePtr cur;
+ if (!ret)
+ return NULL;
+
+ ret->value.dict.root = root;
+
for (cur = xmlFirstElement(node); cur; cur = xmlNextElement(cur)) {
*elem = xmlRpcValueUnmarshalDictElement(cur);
+ if (*elem==NULL) {
+ xmlRpcValueFree(ret);
+ return NULL;
+ }
elem = &(*elem)->next;
}
- ret->value.dict.root = root;
-
return ret;
}
} else if (xmlStrEqual(node->name, BAD_CAST "nil")) {
ret = xmlRpcValueNew(XML_RPC_NIL);
} else {
- /* bug */
+ xmlRpcError(VIR_ERR_XML_ERROR, "unexpected value node", 0);
}
return ret;
break;
case XML_RPC_DATE_TIME:
/* FIXME */
- TODO;
+ TODO
break;
case XML_RPC_BASE64:
/* FIXME */
- TODO;
+ TODO
break;
case XML_RPC_STRING:
virBufferStrcat(buf,
xmlRpcValuePtr xmlRpcUnmarshalResponse(xmlNodePtr node, bool *is_fault)
{
+ if (!node)
+ return NULL;
+
if (!xmlStrEqual(node->name, BAD_CAST "methodResponse"))
return NULL;
return xmlRpcValueUnmarshal(xmlFirstElement(node));
} else
return NULL;
-
}
static char *xmlRpcCallRaw(const char *url, const char *request)
NULL,
strlen(request));
- if (cxt == NULL)
+ if (cxt == NULL) {
+ xmlRpcError(VIR_ERR_POST_FAILED, "send request", 0);
goto error;
+ }
if (contentType && strcmp(contentType, "text/xml") != 0) {
errno = EINVAL;
+ xmlRpcError(VIR_ERR_POST_FAILED, "unexpected mime type", 0);
goto error;
}
len = xmlNanoHTTPContentLength(cxt);
response = malloc(len + 1);
- if (response == NULL)
+ if (response == NULL) {
+ xmlRpcError(VIR_ERR_NO_MEMORY, "allocate response", len);
goto error;
-
+ }
ret = xmlNanoHTTPRead(cxt, response, len);
if (ret != len) {
errno = EINVAL;
free(response);
response = NULL;
+ xmlRpcError(VIR_ERR_POST_FAILED, "read response", 0);
}
response[len] = 0;
if (value->value.array.elements[i]->kind == XML_RPC_STRING)
size += strlen(value->value.array.elements[i]->value.string) + 1;
- ptr = malloc(size);
-
+ if (!(ptr = malloc(size))) {
+ xmlRpcError(VIR_ERR_NO_MEMORY, "allocate string array", size);
+ return NULL;
+ }
ret = (char **)ptr;
ptr += sizeof(char *) * (value->value.array.n_elements + 1);
int i;
*argc = strlen(fmt);
- argv = malloc(sizeof(*argv) * *argc);
-
+ if (!(argv = malloc(sizeof(*argv) * *argc))) {
+ xmlRpcError(VIR_ERR_NO_MEMORY, "read response", sizeof(*argv) * *argc);
+ return NULL;
+ }
i = 0;
for (ptr = fmt; *ptr; ptr++) {
switch (*ptr) {
case 'i':
- argv[i] = xmlRpcValueNew(XML_RPC_INTEGER);
- argv[i]->value.integer = va_arg(ap, int32_t);
+ if ((argv[i] = xmlRpcValueNew(XML_RPC_INTEGER)))
+ argv[i]->value.integer = va_arg(ap, int32_t);
break;
case 'f':
- argv[i] = xmlRpcValueNew(XML_RPC_DOUBLE);
- argv[i]->value.real = va_arg(ap, double);
+ if ((argv[i] = xmlRpcValueNew(XML_RPC_DOUBLE)))
+ argv[i]->value.real = va_arg(ap, double);
break;
case 'b':
- argv[i] = xmlRpcValueNew(XML_RPC_BOOLEAN);
- argv[i]->value.boolean = va_arg(ap, int);
+ if ((argv[i] = xmlRpcValueNew(XML_RPC_BOOLEAN)))
+ argv[i]->value.boolean = va_arg(ap, int);
break;
case 's':
- argv[i] = xmlRpcValueNew(XML_RPC_STRING);
- argv[i]->value.string = strdup(va_arg(ap, const char *));
+ if ((argv[i] = xmlRpcValueNew(XML_RPC_STRING)))
+ argv[i]->value.string = strdup(va_arg(ap, const char *));
break;
default:
- xmlRpcArgvFree(i, argv);
+ argv[i] = NULL;
+ break;
+ }
+ if (argv[i]==NULL) {
+ xmlRpcArgvFree(i, argv);
return NULL;
}
i++;
xmlRpcArgvFree(int argc, xmlRpcValuePtr *argv)
{
int i;
+ if (!argv)
+ return;
for (i = 0; i < argc; i++)
xmlRpcValueFree(argv[i]);
if (retfmt && *retfmt)
retval = va_arg(ap, void *);
- argv = xmlRpcArgvNew(fmt, ap, &argc);
+ if (!(argv = xmlRpcArgvNew(fmt, ap, &argc)))
+ return -1;
va_end(ap);
xmlRpcArgvFree(argc, argv);
+ if (!buf)
+ return -1;
+
ret = xmlRpcCallRaw(context->uri, buf->content);
virBufferFree(buf);
+ if (!ret)
+ return -1;
+
xml = xmlReadDoc((const xmlChar *)ret, "response.xml", NULL,
XML_PARSE_NOENT | XML_PARSE_NONET |
XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
if (xml == NULL) {
errno = EINVAL;
+ xmlRpcError(VIR_ERR_XML_ERROR, "parse server response failed", 0);
return -1;
}
xmlFreeDoc(xml);
- if (fault) { /* FIXME we need generic dict routines */
+ if (fault) {
+ /* FIXME we need generic dict routines */
+ /* FIXME we need faultMessage propagate to libvirt error API */
context->faultCode = value->value.dict.root->value->value.integer;
context->faultMessage = strdup(value->value.dict.root->next->value->value.string);
xmlRpcValueFree(value);
if (ret) {
ret->uri = strdup(uri);
ret->faultMessage = NULL;
- }
+ } else
+ xmlRpcError(VIR_ERR_NO_MEMORY, "allocate new context", sizeof(*ret));
return ret;
}